Skip to main content

ferrum_interfaces/model_executor/
prefix_restore.rs

1//! Publication of restored state before constructing a prefill batch.
2
3use super::{KvCacheHandle, PlanRuntimePrefillAuthority, PrefixCaptureLease};
4use ferrum_types::{FerrumError, RequestId, Result, TokenId};
5use std::{fmt, sync::Arc};
6
7/// Observation only: neither an index hit nor a completed copy authorizes use
8/// of restored state. `Restored` is emitted after publication acknowledgement.
9#[derive(Debug, serde::Serialize)]
10pub struct PrefixRestoreObservation<'a> {
11    pub request_id: &'a RequestId,
12    pub source: PrefixRestoreSource,
13    pub decision: PrefixRestoreDecision<'a>,
14}
15
16#[derive(Debug, Clone, Copy, serde::Serialize)]
17#[serde(rename_all = "snake_case")]
18pub enum PrefixRestoreSource {
19    Index,
20    Rendezvous,
21}
22
23/// Contains lengths and typed resource evidence, never prompt/token contents.
24#[derive(Debug, serde::Serialize)]
25#[serde(tag = "outcome", rename_all = "snake_case")]
26pub enum PrefixRestoreDecision<'a> {
27    NoReusableEntry,
28    SequenceCapacityNotReady {
29        candidate_prefix_tokens: usize,
30        capacity: &'a super::ExecutorExecutionCapacityDeferral,
31    },
32    RequestStateNotReady {
33        candidate_prefix_tokens: usize,
34        request_state: &'a super::ExecutorRequestStateDeferral,
35    },
36    NativeRestoreSkipped {
37        candidate_prefix_tokens: usize,
38    },
39    Restored {
40        candidate_prefix_tokens: usize,
41    },
42}
43
44/// The exact input already admitted by the plan runtime. Restoration does not
45/// replace admission or authorize a different request incarnation.
46#[derive(Debug, Clone, Copy)]
47pub struct PlanRuntimePrefixRestoreInput<'a> {
48    pub request_id: &'a RequestId,
49    pub input_tokens: &'a [TokenId],
50    pub maximum_sequence_tokens: usize,
51    /// An authenticated ready source retained by an earlier rendezvous. This
52    /// bypasses index lookup, never target admission or native compatibility.
53    pub checkpoint: Option<&'a dyn PrefixCaptureLease>,
54    /// Exact retained source from a prior capacity deferral; never reselect the index.
55    pub retry: Option<&'a PlanRuntimePrefixRestoreDeferral>,
56}
57
58/// A capacity deferral submits no restore and retains one immutable source. It
59/// grants neither target admission nor permission to wait without a progress
60/// source. Dropping it releases the optional checkpoint pin.
61#[derive(Debug)]
62pub struct PlanRuntimePrefixRestoreDeferral {
63    capacity: super::ExecutorExecutionCapacityDeferral,
64    checkpoint: Arc<dyn PrefixCaptureLease>,
65    source: PrefixRestoreSource,
66}
67
68impl PlanRuntimePrefixRestoreDeferral {
69    pub fn new(
70        capacity: super::ExecutorExecutionCapacityDeferral,
71        checkpoint: Arc<dyn PrefixCaptureLease>,
72        source: PrefixRestoreSource,
73    ) -> Self {
74        Self {
75            capacity,
76            checkpoint,
77            source,
78        }
79    }
80
81    pub fn capacity(&self) -> &super::ExecutorExecutionCapacityDeferral {
82        &self.capacity
83    }
84
85    pub fn checkpoint(&self) -> &Arc<dyn PrefixCaptureLease> {
86        &self.checkpoint
87    }
88
89    pub fn source(&self) -> PrefixRestoreSource {
90        self.source
91    }
92}
93
94#[derive(Debug)]
95#[must_use = "restore publication or a retained capacity deferral must be handled"]
96pub enum PlanRuntimePrefixRestoreOutcome {
97    Unavailable,
98    Restored(PlanRuntimePrefixRestoreOutput),
99    Deferred(PlanRuntimePrefixRestoreDeferral),
100}
101
102/// Independently restored state whose execution gate remains closed while the
103/// engine installs its physical cache authority and advances scheduler progress.
104///
105/// The executor callback owns the native publication guard. Dropping this value
106/// must drop that guard and cancel its exact target; the callback must never
107/// retain only a request id or a later registry lookup. No logits are cached:
108/// at least one remaining prompt token must execute before sampling.
109#[must_use = "publish matching progress and acknowledge, or drop to cancel the restored target"]
110pub struct PlanRuntimePrefixRestoreOutput {
111    authority: PlanRuntimePrefillAuthority,
112    prompt_tokens: usize,
113    acknowledge: Box<dyn FnOnce() -> Result<()> + Send>,
114}
115
116impl PlanRuntimePrefixRestoreOutput {
117    /// Implementer constructor. The callback must own and acknowledge the
118    /// exact native restoration, revalidating cancellation and target identity.
119    /// Rejected construction drops the callback and its retained guard.
120    pub fn new(
121        request_id: RequestId,
122        restored_tokens: usize,
123        prompt_tokens: usize,
124        kv_cache: Arc<dyn KvCacheHandle>,
125        acknowledge: impl FnOnce() -> Result<()> + Send + 'static,
126    ) -> Result<Self> {
127        let output = Self {
128            authority: PlanRuntimePrefillAuthority {
129                request_id,
130                committed_tokens: restored_tokens,
131                kv_cache,
132            },
133            prompt_tokens,
134            acknowledge: Box::new(acknowledge),
135        };
136        output.validate_for(output.request_id(), prompt_tokens)?;
137        Ok(output)
138    }
139
140    pub fn request_id(&self) -> &RequestId {
141        self.authority.request_id()
142    }
143
144    pub fn restored_tokens(&self) -> usize {
145        self.authority.committed_tokens()
146    }
147
148    pub fn kv_cache(&self) -> &Arc<dyn KvCacheHandle> {
149        self.authority.kv_cache()
150    }
151
152    pub fn validate_for(&self, request_id: &RequestId, prompt_tokens: usize) -> Result<()> {
153        if self.request_id() != request_id || self.prompt_tokens != prompt_tokens {
154            return Err(FerrumError::backend(
155                "prefix restore publication does not match the admitted request",
156            ));
157        }
158        let restored = self.restored_tokens();
159        if restored == 0 || restored >= prompt_tokens {
160            return Err(FerrumError::backend(
161                "prefix restore must leave a nonempty prompt suffix for execution",
162            ));
163        }
164        if self.kv_cache().num_tokens() != restored || !self.kv_cache().is_valid() {
165            return Err(FerrumError::backend(
166                "prefix restore cache authority does not match the restored extent",
167            ));
168        }
169        Ok(())
170    }
171
172    /// Opens the native execution gate only after outer progress is installed.
173    /// An error requires cancellation of the corresponding outer request; it
174    /// does not authorize falling back to execution on the restored target.
175    pub fn acknowledge(self) -> Result<PlanRuntimePrefillAuthority> {
176        let Self {
177            authority,
178            acknowledge,
179            ..
180        } = self;
181        acknowledge()?;
182        Ok(authority)
183    }
184}
185
186impl fmt::Debug for PlanRuntimePrefixRestoreOutput {
187    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188        f.debug_struct("PlanRuntimePrefixRestoreOutput")
189            .field("authority", &self.authority)
190            .field("prompt_tokens", &self.prompt_tokens)
191            .finish_non_exhaustive()
192    }
193}