pub struct DurableFuture<T> { /* private fields */ }Expand description
A wrapper around scheduled futures that supports cancellation on drop.
When a DurableFuture is dropped without completing (e.g., as a select loser,
or when going out of scope without being awaited), the underlying scheduled work
is cancelled:
- Activities: Lock stealing via provider (removes from worker queue)
- Sub-orchestrations:
CancelInstancework item enqueued for child - Timers/External waits: No-op (virtual constructs with no external state)
§Examples
// Activity scheduled - if timer wins, activity gets cancelled
let activity = ctx.schedule_activity("SlowWork", "input");
let timeout = ctx.schedule_timer(Duration::from_secs(5));
match ctx.select2(activity, timeout).await {
duroxide::Either2::First(result) => result,
duroxide::Either2::Second(()) => Err("Timed out - activity cancelled".to_string()),
}§Drop Semantics
Unlike regular Rust futures which are inert on drop, DurableFuture has
meaningful drop semantics similar to File (closes on drop) or MutexGuard
(releases lock on drop). This is intentional - we want unobserved scheduled
work to be cancelled rather than leaked.
Note: Using std::mem::forget() on a DurableFuture will bypass
cancellation, causing the scheduled work to run but its result to be lost.
Implementations§
Source§impl<T: Send + 'static> DurableFuture<T>
impl<T: Send + 'static> DurableFuture<T>
Sourcepub fn map<U: Send + 'static>(
self,
f: impl FnOnce(T) -> U + Send + 'static,
) -> DurableFuture<U> ⓘ
pub fn map<U: Send + 'static>( self, f: impl FnOnce(T) -> U + Send + 'static, ) -> DurableFuture<U> ⓘ
Transform the output of this DurableFuture while preserving its
identity for cancellation, join, and select composability.
The mapping function runs synchronously after the underlying future
completes. Cancellation semantics are fully preserved: dropping the
returned DurableFuture cancels the original scheduled work.
§Example
// Map an activity result to extract a field
let length = ctx.schedule_activity("Greet", "World")
.map(|r| r.map(|s| s.len().to_string()));
let len_result = length.await?;Sourcepub fn with_tag(self, tag: impl Into<String>) -> Self
pub fn with_tag(self, tag: impl Into<String>) -> Self
Set a routing tag on this scheduled activity.
Tags direct activities to specialized workers. A worker configured with
crate::providers::TagFilter::tags(["gpu"]) will only process activities
tagged "gpu".
This method uses mutate-after-emit: the action has already been emitted to
the context’s action list, and with_tag reaches back to modify it in place.
This is safe because actions are not drained until the replay engine polls
the orchestration future (which hasn’t happened yet — we’re still inside the
user’s async block).
§Panics
Panics if called on a non-activity DurableFuture (e.g., timer or sub-orchestration).
§Example
let result = ctx.schedule_activity("CompileRelease", "repo-url")
.with_tag("build-machine")
.await?;Trait Implementations§
Source§impl<T> Drop for DurableFuture<T>
impl<T> Drop for DurableFuture<T>
Source§impl<T> Future for DurableFuture<T>
impl<T> Future for DurableFuture<T>
impl<T: Send> Send for DurableFuture<T>
Auto Trait Implementations§
impl<T> Freeze for DurableFuture<T>
impl<T> !RefUnwindSafe for DurableFuture<T>
impl<T> !Sync for DurableFuture<T>
impl<T> Unpin for DurableFuture<T>
impl<T> UnsafeUnpin for DurableFuture<T>
impl<T> !UnwindSafe for DurableFuture<T>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_cancellation_token(
self,
cancellation_token: &CancellationToken,
) -> WithCancellationTokenFuture<'_, Self>where
Self: Sized,
fn with_cancellation_token(
self,
cancellation_token: &CancellationToken,
) -> WithCancellationTokenFuture<'_, Self>where
Self: Sized,
CancellationToken::run_until_cancelled,
but with the advantage that it is easier to write fluent call chains. Read moreSource§fn with_cancellation_token_owned(
self,
cancellation_token: CancellationToken,
) -> WithCancellationTokenFutureOwned<Self>where
Self: Sized,
fn with_cancellation_token_owned(
self,
cancellation_token: CancellationToken,
) -> WithCancellationTokenFutureOwned<Self>where
Self: Sized,
CancellationToken::run_until_cancelled_owned,
but with the advantage that it is easier to write fluent call chains. Read moreSource§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn map<U, F>(self, f: F) -> Map<Self, F>
fn map<U, F>(self, f: F) -> Map<Self, F>
Source§fn map_into<U>(self) -> MapInto<Self, U>
fn map_into<U>(self) -> MapInto<Self, U>
Source§fn then<Fut, F>(self, f: F) -> Then<Self, Fut, F>
fn then<Fut, F>(self, f: F) -> Then<Self, Fut, F>
f. Read moreSource§fn left_future<B>(self) -> Either<Self, B>
fn left_future<B>(self) -> Either<Self, B>
Source§fn right_future<A>(self) -> Either<A, Self>
fn right_future<A>(self) -> Either<A, Self>
Source§fn into_stream(self) -> IntoStream<Self>where
Self: Sized,
fn into_stream(self) -> IntoStream<Self>where
Self: Sized,
Source§fn flatten(self) -> Flatten<Self>
fn flatten(self) -> Flatten<Self>
Source§fn flatten_stream(self) -> FlattenStream<Self>
fn flatten_stream(self) -> FlattenStream<Self>
Source§fn fuse(self) -> Fuse<Self>where
Self: Sized,
fn fuse(self) -> Fuse<Self>where
Self: Sized,
poll will never again be called once it has
completed. This method can be used to turn any Future into a
FusedFuture. Read moreSource§fn inspect<F>(self, f: F) -> Inspect<Self, F>
fn inspect<F>(self, f: F) -> Inspect<Self, F>
Source§fn catch_unwind(self) -> CatchUnwind<Self>where
Self: Sized + UnwindSafe,
fn catch_unwind(self) -> CatchUnwind<Self>where
Self: Sized + UnwindSafe,
Source§fn remote_handle(self) -> (Remote<Self>, RemoteHandle<Self::Output>)where
Self: Sized,
fn remote_handle(self) -> (Remote<Self>, RemoteHandle<Self::Output>)where
Self: Sized,
() on completion and sends
its output to another future on a separate task. Read moreSource§fn boxed<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>
fn boxed<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>
Source§fn boxed_local<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + 'a>>where
Self: Sized + 'a,
fn boxed_local<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + 'a>>where
Self: Sized + 'a,
Source§fn unit_error(self) -> UnitError<Self>where
Self: Sized,
fn unit_error(self) -> UnitError<Self>where
Self: Sized,
Future<Output = T> into a
TryFuture<Ok = T, Error = ()>.Source§fn never_error(self) -> NeverError<Self>where
Self: Sized,
fn never_error(self) -> NeverError<Self>where
Self: Sized,
Future<Output = T> into a
TryFuture<Ok = T, Error = Never>.