Skip to main content

active_rpc/
promise.rs

1//! Promises: results that exist before they are ready.
2//!
3//! A promise is a slot the kernel fills later. Passing one as an argument makes
4//! a call *pipelined*: the kernel keeps the dependent call at the provider and
5//! dispatches it in the same batch that resolves the promise, so a chain costs
6//! one provider round-trip instead of one per step (spec §5).
7//!
8//! A promise can be resolved once, rejected once, or cancelled; every state
9//! transition is checked, and awaiting a cancelled promise is an error rather
10//! than a hang.
11
12use std::fmt;
13
14use crate::error::{Error, Result};
15use crate::value::Value;
16
17/// Identity of a promise inside one kernel.
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
19pub struct PromiseId(pub u64);
20
21impl fmt::Display for PromiseId {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        write!(f, "p{}", self.0)
24    }
25}
26
27/// Lifecycle of a promise.
28#[derive(Debug, Clone, PartialEq)]
29pub enum PromiseState {
30    /// Waiting for its producing call.
31    Pending,
32    /// Resolved with a value.
33    Resolved(Value),
34    /// Failed; the original error is preserved so the class survives the hop.
35    Rejected(crate::error::Error),
36    /// Cancelled by the caller; never resolves.
37    Cancelled,
38}
39
40impl PromiseState {
41    pub fn is_settled(&self) -> bool {
42        !matches!(self, PromiseState::Pending)
43    }
44}
45
46/// Provider-side record of one promise.
47#[derive(Debug, Clone, PartialEq)]
48pub struct PromiseRecord {
49    pub id: PromiseId,
50    pub state: PromiseState,
51    /// Calls waiting on this promise (derived, informational).
52    pub waiters: u32,
53    /// Lane that issued the producing call.
54    pub lane: u64,
55}
56
57impl PromiseRecord {
58    pub fn new(id: PromiseId, lane: u64) -> Self {
59        Self {
60            id,
61            state: PromiseState::Pending,
62            waiters: 0,
63            lane,
64        }
65    }
66
67    /// Resolve once.
68    pub fn resolve(&mut self, value: Value) -> Result<()> {
69        match self.state {
70            PromiseState::Pending => {
71                self.state = PromiseState::Resolved(value);
72                Ok(())
73            }
74            _ => Err(Error::PromiseAlreadyResolved(self.id.0)),
75        }
76    }
77
78    /// Reject once.
79    pub fn reject(&mut self, error: crate::error::Error) -> Result<()> {
80        match self.state {
81            PromiseState::Pending => {
82                self.state = PromiseState::Rejected(error);
83                Ok(())
84            }
85            _ => Err(Error::PromiseAlreadyResolved(self.id.0)),
86        }
87    }
88
89    /// Cancel a pending promise.
90    pub fn cancel(&mut self) -> Result<()> {
91        match self.state {
92            PromiseState::Pending => {
93                self.state = PromiseState::Cancelled;
94                Ok(())
95            }
96            _ => Err(Error::PromiseAlreadyResolved(self.id.0)),
97        }
98    }
99
100    /// The settled value, or an error describing why it is not available.
101    pub fn value(&self) -> Result<Value> {
102        match &self.state {
103            PromiseState::Resolved(value) => Ok(value.clone()),
104            PromiseState::Pending => Err(Error::UnresolvablePromise(self.id.0)),
105            PromiseState::Rejected(error) => Err(error.clone()),
106            PromiseState::Cancelled => Err(Error::PromiseCancelled(self.id.0)),
107        }
108    }
109}