harmos_domain/operations/common/
mod.rs1mod catalog;
13mod context;
14mod contract;
15mod direction;
16mod grpc;
17pub mod instance;
18mod key;
19pub(crate) mod payload;
20mod policy;
21
22pub use crate::observers;
25pub use catalog::{Declarations, Entry};
26pub use context::{CallContext, CallValue, ContextError, ContextValue, PORTABLE_BYTES, PORTABLE_VALUES};
27pub use contract::{Codec, Contract, ContractError, Contracts, WireDeclaration};
28pub use direction::{Direction, NoStream, Stream, item_types};
29pub use grpc::Grpc;
30pub use key::{CacheKey, CacheKeyError, MAX_CACHE_KEY_BYTES};
31pub use policy::{Backoff, FailureKind, Jitter, OperationPolicy, PolicyError, ReplaySafety, RestartPolicy, RetryPolicy};
32
33use serde::{Deserialize, Serialize};
39use crate::Identifier;
41
42pub const UNBOUNDED: std::time::Duration = std::time::Duration::from_secs(1 << 32);
46
47#[macro_export]
52macro_rules! declare {
53 ($ty:ty {
54 id: $id:expr,
55 version: $version:expr,
56 policy: $policy:expr,
57 response: $response:ty
58 $(, input: $input:ty)?
59 $(, output: $output:ty)?
60 $(, description: $description:expr)?
61 $(, visibility: $visibility:expr)?
62 $(, replay: $replay:expr)?
63 $(, grpc: ($package:expr, $service:expr, $method:expr))?
64 $(, grant: $grant:expr)?
65 $(, key: $key:expr)?
66 $(,)?
67 }) => {
68 impl $crate::operations::OperationDeclaration for $ty {
69 type Response = $response;
70 type Input = $crate::declare!(@direction $($input)?);
71 type Output = $crate::declare!(@direction $($output)?);
72 const ID: &'static str = $id;
73 const VERSION: u32 = $version;
74 const POLICY: $crate::operations::OperationPolicy = $policy;
75 $(const DESCRIPTION: &'static str = $description;)?
76 $(const VISIBILITY: $crate::operations::Visibility = $visibility;)?
77 $(const REPLAY: $crate::operations::ReplaySafety = $replay;)?
78 $(const GRPC: ::core::option::Option<$crate::operations::Grpc> =
79 ::core::option::Option::Some($crate::operations::Grpc::new($package, $service, $method));)?
80 $(fn grant(&self) -> ::core::option::Option<$crate::plugin::Grant> {
81 ($grant)(self)
82 })?
83 $(fn key(&self) -> ::core::option::Option<$crate::operations::CacheKey> {
84 ($key)(self)
85 })?
86 }
87 };
88 (@direction) => { $crate::operations::NoStream };
89 (@direction $item:ty) => { $crate::operations::Stream<$item> };
90}
91
92#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
97pub struct Definition {
98 pub id: Identifier,
99 pub description: String,
100 pub policy: OperationPolicy,
101 pub visibility: Visibility,
102 pub replay: ReplaySafety,
103}
104
105#[derive(Deserialize)]
108#[serde(remote = "Definition", deny_unknown_fields)]
109struct DecodedDefinition {
110 id: Identifier,
111 description: String,
112 policy: OperationPolicy,
113 visibility: Visibility,
114 replay: ReplaySafety,
115}
116
117#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
120#[serde(rename_all = "snake_case")]
121pub enum Visibility {
122 Private,
123 Shared,
124 Host,
125}
126
127pub trait OperationDeclaration: crate::Portable {
133 type Response: crate::Portable;
134 type Input: Direction;
135 type Output: Direction;
136
137 const ID: &'static str;
138 const VERSION: u32;
139 const POLICY: OperationPolicy;
140 const DESCRIPTION: &'static str = "";
141 const VISIBILITY: Visibility = Visibility::Private;
142 const REPLAY: ReplaySafety = ReplaySafety::Unknown;
143 const GRPC: Option<Grpc> = None;
144
145 fn grant(&self) -> Option<crate::plugin::Grant> {
146 None
147 }
148
149 fn key(&self) -> Option<CacheKey> {
150 None
151 }
152}
153
154pub trait Declares {
155 type Declaration: OperationDeclaration;
156}
157
158impl<O: OperationDeclaration> Declares for O {
161 type Declaration = O;
162}
163
164impl<'de> Deserialize<'de> for Definition {
165 fn deserialize<D: serde::Deserializer<'de>>(decoder: D) -> Result<Self, D::Error> {
166 let definition = DecodedDefinition::deserialize(decoder)?;
167 definition.validate().map_err(serde::de::Error::custom)?;
168 Ok(definition)
169 }
170}
171
172impl Definition {
173 pub fn validate(&self) -> crate::Result<()> {
174 if crate::reserved(self.id.as_str()) {
175 return Err(crate::Error::ReservedOperation { id: self.id.as_str().to_owned() });
176 }
177 self.policy.validate()?;
178 Ok(())
179 }
180
181 pub fn of<O: OperationDeclaration>() -> crate::Result<Self> {
182 Entry::of::<O>().definition()
183 }
184}
185
186