harmos_operations/storage/
follow_objects.rs1use super::STREAM_POLICY;
22use harmos_domain::MemorySize;
23use harmos_domain::model::storage::codec::{Nested, Optional, product};
24use harmos_domain::model::storage::{ObjectEntry, ObjectSelection, StorageCursor};
25#[cfg(feature = "runtime")]
26use harmos_storage::{ErasedCatalog, StorageManager};
27
28product!(FollowObjects {
33 after: Optional<Nested<StorageCursor>> => 1,
34 selection: Nested<ObjectSelection> => 2,
35});
36
37#[harmos::operation(harmos_path = crate, resources = [StorageManager<ErasedCatalog>], codec = manual,
42 id = "storage.follow_objects",
43 response = StorageCursor,
44 policy = STREAM_POLICY,
45 output = ObjectEntry,
46 visibility = Host)]
47#[derive(Clone, Debug, PartialEq, Eq)]
48pub struct FollowObjects {
49 pub after: Option<StorageCursor>,
50 pub selection: ObjectSelection,
51}
52
53impl MemorySize for FollowObjects {
60 fn memory_size(&self) -> usize {
61 std::mem::size_of::<Self>()
62 .saturating_add(self.after.memory_size().saturating_sub(std::mem::size_of_val(&self.after)))
63 .saturating_add(self.selection.memory_size().saturating_sub(std::mem::size_of_val(&self.selection)))
64 }
65}
66
67#[cfg(feature = "runtime")]
68mod execution {
69
70 use harmos_sdk::operations::Operation;
77
78 use harmos_storage::{ObjectEntry, StorageCursor};
79
80 use crate::{Error, MemorySize, Result};
81
82 impl Operation for super::FollowObjects {
83 type Error = Error;
84
85 async fn run(self, context: harmos_sdk::Context<'_, Self>) -> Result<harmos_sdk::operations::Response<StorageCursor>> {
86 let storage = context.resource::<harmos_storage::StorageManager<harmos_storage::ErasedCatalog>>();
87 let output = context.streams();
88
89 if !self.selection.follows_revisions() {
90 return Err(Error::InvalidInput {
91 field: "storage follow",
92 reason: "following delivers every object revision",
93 });
94 }
95 let mut follower = storage.follow::<ObjectEntry>(self.after.as_ref(), self.selection.clone()).await?;
96 loop {
97 let page = follower.next().await?;
98 for entry in page.entries() {
99 output.send_with(entry.memory_size(), || Ok(entry.clone())).await?;
100 }
101 }
102 }
103 }
104}
105
106