1use anyhow::Result;
2use serde::{Deserialize, Serialize, ser::SerializeSeq};
3use smallvec::SmallVec;
4
5use crate::{
6 CellId, RawVc, TaskId,
7 backend::{CachedTaskType, CellContent},
8 task::shared_reference::TypedSharedReference,
9};
10
11#[derive(Clone, Debug)]
12pub enum TaskCell {
13 Content(CellContent),
14 NeedComputation,
15}
16
17impl Default for TaskCell {
18 fn default() -> Self {
19 TaskCell::Content(CellContent(None))
20 }
21}
22
23#[derive(Serialize, Deserialize, Debug)]
24pub struct TaskData {
25 pub children: SmallVec<[TaskId; 4]>,
26 pub dependencies: SmallVec<[RawVc; 1]>,
27 pub cells: TaskCells,
28 pub output: RawVc,
29}
30
31#[derive(Debug)]
38pub struct TaskCells(pub Vec<(CellId, TaskCell)>);
39
40#[derive(Serialize, Deserialize)]
43struct SerializableTaskCell(Option<Option<TypedSharedReference>>);
44impl From<SerializableTaskCell> for TaskCell {
45 fn from(val: SerializableTaskCell) -> Self {
46 match val.0 {
47 Some(d) => TaskCell::Content(d.map(TypedSharedReference::into_untyped).into()),
48 None => TaskCell::NeedComputation,
49 }
50 }
51}
52
53impl Serialize for TaskCells {
54 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
55 where
56 S: serde::Serializer,
57 {
58 let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
59 for (cell_id, cell) in &self.0 {
60 let task_cell = SerializableTaskCell(match cell {
61 TaskCell::Content(CellContent(opt)) => {
62 Some(opt.clone().map(|d| d.into_typed(cell_id.type_id)))
63 }
64 TaskCell::NeedComputation => None,
65 });
66 seq.serialize_element(&(cell_id, task_cell))?;
67 }
68 seq.end()
69 }
70}
71
72impl<'de> Deserialize<'de> for TaskCells {
73 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
74 where
75 D: serde::Deserializer<'de>,
76 {
77 let data: Vec<(CellId, SerializableTaskCell)> = Vec::deserialize(deserializer)?;
78 Ok(TaskCells(
79 data.into_iter()
80 .map(|(id, cell)| (id, cell.into()))
81 .collect(),
82 ))
83 }
84}
85
86pub struct ReadTaskState {
87 pub clean: bool,
88 pub keeps_external_active: bool,
89}
90
91pub struct PersistTaskState {
92 pub externally_active: bool,
93}
94
95#[derive(Debug)]
121pub struct ActivateResult {
122 pub keeps_external_active: bool,
124
125 pub external: bool,
128
129 pub dirty: bool,
131
132 pub more_tasks_to_activate: SmallVec<[TaskId; 4]>,
135}
136
137#[derive(Debug)]
138pub struct PersistResult {
139 pub tasks_to_activate: SmallVec<[TaskId; 4]>,
141
142 pub tasks_to_deactivate: SmallVec<[TaskId; 4]>,
144}
145
146#[derive(Debug)]
147pub struct DeactivateResult {
148 pub more_tasks_to_deactivate: SmallVec<[TaskId; 4]>,
151}
152
153pub type TaskIds = SmallVec<[TaskId; 4]>;
154
155pub trait PersistedGraph: Sync + Send {
156 fn read(
158 &self,
159 task: TaskId,
160 api: &dyn PersistedGraphApi,
161 ) -> Result<Option<(TaskData, ReadTaskState)>>;
162
163 fn lookup(
167 &self,
168 partial_task_type: &CachedTaskType,
169 api: &dyn PersistedGraphApi,
170 ) -> Result<bool>;
171
172 fn lookup_one(
174 &self,
175 task_type: &CachedTaskType,
176 api: &dyn PersistedGraphApi,
177 ) -> Result<Option<TaskId>>;
178
179 fn is_persisted(&self, task: TaskId, api: &dyn PersistedGraphApi) -> Result<bool>;
181
182 fn persist(
186 &self,
187 task: TaskId,
188 data: TaskData,
189 state: PersistTaskState,
190 api: &dyn PersistedGraphApi,
191 ) -> Result<Option<PersistResult>>;
192
193 fn activate_when_needed(
196 &self,
197 task: TaskId,
198 api: &dyn PersistedGraphApi,
199 ) -> Result<Option<ActivateResult>>;
200
201 fn deactivate_when_needed(
204 &self,
205 task: TaskId,
206 api: &dyn PersistedGraphApi,
207 ) -> Result<Option<DeactivateResult>>;
208
209 fn set_externally_active(&self, task: TaskId, api: &dyn PersistedGraphApi) -> Result<bool>;
213
214 fn unset_externally_active(&self, task: TaskId, api: &dyn PersistedGraphApi) -> Result<bool>;
218
219 fn remove_outdated_externally_active(
223 &self,
224 api: &dyn PersistedGraphApi,
225 ) -> Result<SmallVec<[TaskId; 4]>>;
226
227 fn make_dirty(&self, task: TaskId, api: &dyn PersistedGraphApi) -> Result<bool>;
230
231 fn make_clean(&self, task: TaskId, api: &dyn PersistedGraphApi) -> Result<()>;
233
234 fn make_dependent_dirty(
237 &self,
238 vc: RawVc,
239 api: &dyn PersistedGraphApi,
240 ) -> Result<SmallVec<[TaskId; 4]>>;
241
242 fn get_active_external_tasks(
246 &self,
247 api: &dyn PersistedGraphApi,
248 ) -> Result<SmallVec<[TaskId; 4]>>;
249
250 fn get_dirty_active_tasks(&self, api: &dyn PersistedGraphApi) -> Result<SmallVec<[TaskId; 4]>>;
253
254 fn get_pending_active_update(&self, api: &dyn PersistedGraphApi) -> Result<(TaskIds, TaskIds)>;
257
258 #[allow(unused_variables)]
260 fn stop(&self, api: &dyn PersistedGraphApi) -> Result<()> {
261 Ok(())
262 }
263}
264
265pub trait PersistedGraphApi {
266 fn get_or_create_task_type(&self, ty: CachedTaskType) -> TaskId;
267
268 fn lookup_task_type(&self, id: TaskId) -> &CachedTaskType;
269}
270
271impl PersistedGraph for () {
297 fn read(
298 &self,
299 _task: TaskId,
300 _api: &dyn PersistedGraphApi,
301 ) -> Result<Option<(TaskData, ReadTaskState)>> {
302 Ok(None)
303 }
304
305 fn lookup(
306 &self,
307 _partial_task_type: &CachedTaskType,
308 _api: &dyn PersistedGraphApi,
309 ) -> Result<bool> {
310 Ok(false)
311 }
312
313 fn lookup_one(
314 &self,
315 _task_type: &CachedTaskType,
316 _api: &dyn PersistedGraphApi,
317 ) -> Result<Option<TaskId>> {
318 Ok(None)
319 }
320
321 fn is_persisted(&self, _task: TaskId, _api: &dyn PersistedGraphApi) -> Result<bool> {
322 Ok(false)
323 }
324
325 fn persist(
326 &self,
327 _task: TaskId,
328 _data: TaskData,
329 _state: PersistTaskState,
330 _api: &dyn PersistedGraphApi,
331 ) -> Result<Option<PersistResult>> {
332 Ok(None)
333 }
334
335 fn activate_when_needed(
336 &self,
337 _task: TaskId,
338 _api: &dyn PersistedGraphApi,
339 ) -> Result<Option<ActivateResult>> {
340 Ok(None)
341 }
342
343 fn deactivate_when_needed(
344 &self,
345 _task: TaskId,
346 _api: &dyn PersistedGraphApi,
347 ) -> Result<Option<DeactivateResult>> {
348 Ok(None)
349 }
350
351 fn set_externally_active(&self, _task: TaskId, _api: &dyn PersistedGraphApi) -> Result<bool> {
352 Ok(false)
353 }
354
355 fn unset_externally_active(&self, _task: TaskId, _api: &dyn PersistedGraphApi) -> Result<bool> {
356 Ok(false)
357 }
358
359 fn remove_outdated_externally_active(
360 &self,
361 _api: &dyn PersistedGraphApi,
362 ) -> Result<SmallVec<[TaskId; 4]>> {
363 Ok(Default::default())
364 }
365
366 fn make_dirty(&self, _task: TaskId, _api: &dyn PersistedGraphApi) -> Result<bool> {
367 Ok(false)
368 }
369
370 fn make_clean(&self, _task: TaskId, _api: &dyn PersistedGraphApi) -> Result<()> {
371 Ok(())
372 }
373
374 fn make_dependent_dirty(
375 &self,
376 _vc: RawVc,
377 _api: &dyn PersistedGraphApi,
378 ) -> Result<SmallVec<[TaskId; 4]>> {
379 Ok(Default::default())
380 }
381
382 fn get_active_external_tasks(
383 &self,
384 _api: &dyn PersistedGraphApi,
385 ) -> Result<SmallVec<[TaskId; 4]>> {
386 Ok(Default::default())
387 }
388
389 fn get_dirty_active_tasks(
390 &self,
391 _api: &dyn PersistedGraphApi,
392 ) -> Result<SmallVec<[TaskId; 4]>> {
393 Ok(Default::default())
394 }
395
396 fn get_pending_active_update(
397 &self,
398 _api: &dyn PersistedGraphApi,
399 ) -> Result<(SmallVec<[TaskId; 4]>, SmallVec<[TaskId; 4]>)> {
400 Ok((Default::default(), Default::default()))
401 }
402}