summaryrefslogtreecommitdiff
path: root/crates/arti-rpcserver/src/objmap/methods.rs
blob: f611862d153c1da97c212586a1da4be3274d185c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//! Implementations for rpc methods that interact with
//! object IDs directly.
//!
//! (These methods do not use the regular dispatch system
//! because they interact with the object map system in special ways.)

use derive_deftly::Deftly;
use futures::FutureExt as _;
use std::sync::Arc;
use tor_rpcbase::{self as rpc, templates::*};

/// Release a single ObjectID.
///
/// Only works if the ObjectID is strong reference (also known as a "handle"):
/// see RPC specification for more information on the distinction.
/// (We intend to relax this requirement in the future.)
///
/// After calling this method, the provided ObjectID will no longer be usable,
/// but other ObjectIDs for the same object may still exist.
///
/// TODO RPC: Releasing a weak reference is perilous and hard-to-define
/// based on how we have implemented our object ids.  If you tell the objmap
/// to "release" a single name for a weak reference, you are releasing every
/// name for that weak reference, which may have surprising results.
/// See also #838.
#[derive(Debug, serde::Deserialize, Deftly)]
#[derive_deftly(DynMethod)]
#[deftly(rpc(method_name = "rpc:release", bypass_method_dispatch))]
struct RpcRelease {}

impl rpc::RpcMethod for RpcRelease {
    type Output = rpc::Nil;
    type Update = rpc::NoUpdates;
}

impl rpc::DynMethod for RpcRelease {
    fn invoke_without_dispatch(
        &self,
        ctx: Arc<dyn rpc::Context>,
        obj_id: &rpc::ObjectId,
    ) -> Result<tor_rpcbase::dispatch::RpcResultFuture, tor_rpcbase::InvokeError> {
        let result = match ctx.release_owned(obj_id) {
            Ok(()) => Ok(Box::new(rpc::NIL) as _),
            Err(e) => Err(rpc::RpcError::from(e)),
        };
        Ok(futures::future::ready(result).boxed())
    }
}