harmos_operations/storage/
mod.rs1mod abandon_file;
16mod append_file;
17mod capture_file;
18mod create_file;
19mod delete_file;
20#[cfg(feature = "runtime")]
21pub(crate) mod exchange;
22mod finish_file;
23mod follow_file;
24mod follow_objects;
25mod follow_production;
26mod follow_records;
27mod follow_stream;
28mod hash_file;
29mod list_directory;
30mod query;
31mod read_file;
32mod resume_file;
33mod storage_status;
34mod watch_directory;
35mod write_file;
36mod write_objects;
37mod write_records;
38mod write_schema;
39mod write_streams;
40
41pub use abandon_file::AbandonFile;
44pub use append_file::AppendFile;
45pub use capture_file::CaptureFile;
46pub use create_file::CreateFile;
47pub use delete_file::DeleteFile;
48pub use finish_file::FinishFile;
49pub use follow_file::FollowFile;
50pub use follow_objects::FollowObjects;
51pub use follow_production::FollowProduction;
52pub use follow_records::{FollowBoundaries, FollowRecords, Followed};
53pub use follow_stream::FollowStream;
54pub use hash_file::HashFile;
55pub use list_directory::ListDirectory;
56pub use query::Query;
57pub use read_file::ReadFile;
58pub use resume_file::ResumeFile;
59pub use storage_status::StorageStatus;
60pub use watch_directory::WatchDirectory;
61pub use write_file::WriteFile;
62pub use write_objects::WriteObjects;
63pub use write_records::WriteRecords;
64pub use write_schema::WriteSchema;
65pub use write_streams::WriteStreams;
66
67use std::time::Duration;
71use harmos_domain::operations::{Backoff, Jitter, OperationPolicy, RetryPolicy};
76
77pub const POLICY: OperationPolicy = OperationPolicy {
80 timeout: Duration::from_secs(60),
81 attempt_timeout: Duration::from_secs(15),
82 retries: RetryPolicy::OnTransient {
83 max_retries: 3,
84 backoff: Backoff::Exponential {
85 initial: Duration::from_millis(250),
86 maximum: Duration::from_secs(2),
87 jitter: Jitter::Deterministic,
88 },
89 },
90};
91
92pub const EVERY_SCHEMA: &str = "*";
93
94pub const STREAM_POLICY: OperationPolicy = OperationPolicy {
95 attempt_timeout: POLICY.timeout,
96 retries: RetryPolicy::Never,
97 ..POLICY
98};
99
100pub const IO_POLICY: OperationPolicy = OperationPolicy {
101 timeout: harmos_domain::operations::UNBOUNDED,
102 attempt_timeout: harmos_domain::operations::UNBOUNDED,
103 retries: RetryPolicy::Never,
104};
105
106#[harmos::catalog(harmos_path = crate)]
109pub enum Storage {
110 ListDirectory(ListDirectory),
111 WatchDirectory(WatchDirectory),
112 Query(Query),
113 ReadFile(ReadFile),
114 HashFile(HashFile),
115 CaptureFile(CaptureFile),
116 FollowProduction(FollowProduction),
117 FollowRecords(FollowRecords),
118 FollowStream(FollowStream),
119 FollowFile(FollowFile),
120 StorageStatus(StorageStatus),
121 ResumeFile(ResumeFile),
122 CreateFile(CreateFile),
123 AppendFile(AppendFile),
124 FinishFile(FinishFile),
125 AbandonFile(AbandonFile),
126 WriteRecords(WriteRecords),
127 WriteStreams(WriteStreams),
128 WriteFile(WriteFile),
129 DeleteFile(DeleteFile),
130 WriteSchema(WriteSchema),
131 WriteObjects(WriteObjects),
132 FollowObjects(FollowObjects),
133}
134
135#[cfg(feature = "runtime")]
152const IO_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30);
153#[cfg(feature = "runtime")]
154fn output_timeout() -> crate::Error {
155 harmos_storage::Error::backend(
156 "storage output",
157 harmos_storage::BackendFailure::Transient,
158 std::io::Error::new(std::io::ErrorKind::TimedOut, "consumer delivery deadline exceeded"),
159 )
160 .into()
161}
162
163#[cfg(feature = "runtime")]
164fn classify(error: &crate::Error) -> harmos_domain::operations::FailureKind {
165 match error {
166 crate::Error::Storage(source) if source.backend_failure() == Some(harmos_storage::BackendFailure::Transient) => {
167 harmos_domain::operations::FailureKind::Transient
168 }
169 _ => harmos_domain::operations::FailureKind::Permanent,
170 }
171}
172
173#[cfg(all(test, feature = "runtime"))]
174mod tests {
175 use super::classify;
176 use harmos_domain::operations::FailureKind;
177 use harmos_storage::{BackendFailure, Error as StorageError};
178
179 #[test]
180 fn persistence_preserves_failure_kind() {
181 for (backend, expected) in
182 [(BackendFailure::Transient, FailureKind::Transient), (BackendFailure::Permanent, FailureKind::Permanent)]
183 {
184 let source = StorageError::backend("write", backend, std::io::Error::other("backend failed"));
185 let error = StorageError::Persistence { source: std::sync::Arc::new(source) };
186 assert_eq!(classify(&crate::Error::Storage(error)), expected);
187 }
188 }
189}