Skip to content

Commit f9ea8ea

Browse files
Discovery protocol v3 (#62)
* Add ServiceOptions and HandlerOptions * Expose new fields * Implement negotiation * Go to builder style, it's generally better looking * Bump minimum rust version
1 parent d897ac0 commit f9ea8ea

File tree

6 files changed

+476
-21
lines changed

6 files changed

+476
-21
lines changed

endpoint_manifest_schema.json

Lines changed: 111 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
"$schema": "https://json-schema.org/draft/2020-12/schema",
44
"type": "object",
55
"title": "Endpoint",
6-
"description": "Restate endpoint manifest v1",
6+
"description": "Restate endpoint manifest v3",
77
"properties": {
88
"protocolMode": {
99
"title": "ProtocolMode",
10-
"enum": ["BIDI_STREAM", "REQUEST_RESPONSE"]
10+
"enum": [
11+
"BIDI_STREAM",
12+
"REQUEST_RESPONSE"
13+
]
1114
},
1215
"minProtocolVersion": {
1316
"type": "integer",
@@ -31,9 +34,17 @@
3134
"type": "string",
3235
"pattern": "^([a-zA-Z]|_[a-zA-Z0-9])[a-zA-Z0-9._-]*$"
3336
},
37+
"documentation": {
38+
"type": "string",
39+
"description": "Documentation for this service definition. No format is enforced, but generally Markdown is assumed."
40+
},
3441
"ty": {
3542
"title": "ServiceType",
36-
"enum": ["VIRTUAL_OBJECT", "SERVICE", "WORKFLOW"]
43+
"enum": [
44+
"VIRTUAL_OBJECT",
45+
"SERVICE",
46+
"WORKFLOW"
47+
]
3748
},
3849
"handlers": {
3950
"type": "array",
@@ -45,9 +56,17 @@
4556
"type": "string",
4657
"pattern": "^([a-zA-Z]|_[a-zA-Z0-9])[a-zA-Z0-9_]*$"
4758
},
59+
"documentation": {
60+
"type": "string",
61+
"description": "Documentation for this handler definition. No format is enforced, but generally Markdown is assumed."
62+
},
4863
"ty": {
4964
"title": "HandlerType",
50-
"enum": ["WORKFLOW", "EXCLUSIVE", "SHARED"],
65+
"enum": [
66+
"WORKFLOW",
67+
"EXCLUSIVE",
68+
"SHARED"
69+
],
5170
"description": "If unspecified, defaults to EXCLUSIVE for Virtual Object or WORKFLOW for Workflows. This should be unset for Services."
5271
},
5372
"input": {
@@ -122,18 +141,103 @@
122141
"setContentTypeIfEmpty": true
123142
}
124143
}
144+
},
145+
"inactivityTimeout": {
146+
"type": "integer",
147+
"minimum": 0,
148+
"description": "Inactivity timeout duration, expressed in milliseconds."
149+
},
150+
"abortTimeout": {
151+
"type": "integer",
152+
"minimum": 0,
153+
"description": "Abort timeout duration, expressed in milliseconds."
154+
},
155+
"journalRetention": {
156+
"type": "integer",
157+
"minimum": 0,
158+
"description": "Journal retention duration, expressed in milliseconds."
159+
},
160+
"idempotencyRetention": {
161+
"type": "integer",
162+
"minimum": 0,
163+
"description": "Idempotency retention duration, expressed in milliseconds. This is NOT VALID when HandlerType == WORKFLOW"
164+
},
165+
"workflowCompletionRetention": {
166+
"type": "integer",
167+
"minimum": 0,
168+
"description": "Workflow completion retention duration, expressed in milliseconds. This is valid ONLY when HandlerType == WORKFLOW"
169+
},
170+
"enableLazyState": {
171+
"type": "boolean",
172+
"description": "If true, lazy state is enabled."
173+
},
174+
"ingressPrivate": {
175+
"type": "boolean",
176+
"description": "If true, the service cannot be invoked from the HTTP nor Kafka ingress."
177+
},
178+
"metadata": {
179+
"type": "object",
180+
"description": "Custom metadata of this handler definition. This metadata is shown on the Admin API when querying the service/handler definition.",
181+
"additionalProperties": {
182+
"type": "string"
183+
}
125184
}
126185
},
127-
"required": ["name"],
186+
"required": [
187+
"name"
188+
],
128189
"additionalProperties": false
129190
}
191+
},
192+
"inactivityTimeout": {
193+
"type": "integer",
194+
"minimum": 0,
195+
"description": "Inactivity timeout duration, expressed in milliseconds."
196+
},
197+
"abortTimeout": {
198+
"type": "integer",
199+
"minimum": 0,
200+
"description": "Abort timeout duration, expressed in milliseconds."
201+
},
202+
"journalRetention": {
203+
"type": "integer",
204+
"minimum": 0,
205+
"description": "Journal retention duration, expressed in milliseconds."
206+
},
207+
"idempotencyRetention": {
208+
"type": "integer",
209+
"minimum": 0,
210+
"description": "Idempotency retention duration, expressed in milliseconds. When ServiceType == WORKFLOW, this option will be applied only to the shared handlers. See workflowCompletionRetention for more details."
211+
},
212+
"enableLazyState": {
213+
"type": "boolean",
214+
"description": "If true, lazy state is enabled."
215+
},
216+
"ingressPrivate": {
217+
"type": "boolean",
218+
"description": "If true, the service cannot be invoked from the HTTP nor Kafka ingress."
219+
},
220+
"metadata": {
221+
"type": "object",
222+
"description": "Custom metadata of this service definition. This metadata is shown on the Admin API when querying the service definition.",
223+
"additionalProperties": {
224+
"type": "string"
225+
}
130226
}
131227
},
132-
"required": ["name", "ty", "handlers"],
228+
"required": [
229+
"name",
230+
"ty",
231+
"handlers"
232+
],
133233
"additionalProperties": false
134234
}
135235
}
136236
},
137-
"required": ["minProtocolVersion", "maxProtocolVersion", "services"],
237+
"required": [
238+
"minProtocolVersion",
239+
"maxProtocolVersion",
240+
"services"
241+
],
138242
"additionalProperties": false
139243
}

macros/src/gen.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,15 @@ impl<'a> ServiceGenerator<'a> {
221221
input: #input_schema,
222222
output: #output_schema,
223223
ty: #handler_ty,
224+
documentation: None,
225+
metadata: Default::default(),
226+
abort_timeout: None,
227+
inactivity_timeout: None,
228+
journal_retention: None,
229+
idempotency_retention: None,
230+
workflow_completion_retention: None,
231+
enable_lazy_state: None,
232+
ingress_private: None,
224233
}
225234
}
226235
});
@@ -235,6 +244,14 @@ impl<'a> ServiceGenerator<'a> {
235244
name: ::restate_sdk::discovery::ServiceName::try_from(#service_literal.to_string())
236245
.expect("Service name valid"),
237246
handlers: vec![#( #handlers ),*],
247+
documentation: None,
248+
metadata: Default::default(),
249+
abort_timeout: None,
250+
inactivity_timeout: None,
251+
journal_retention: None,
252+
idempotency_retention: None,
253+
enable_lazy_state: None,
254+
ingress_private: None,
238255
}
239256
}
240257
}

rust-toolchain.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[toolchain]
2-
channel = "1.81.0"
2+
channel = "1.82.0"
33
profile = "minimal"
44
components = ["rustfmt", "clippy"]

src/discovery.rs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ mod generated {
77
include!(concat!(env!("OUT_DIR"), "/endpoint_manifest.rs"));
88
}
99

10-
pub use generated::*;
11-
10+
use crate::endpoint::{HandlerOptions, ServiceOptions};
1211
use crate::serde::PayloadMetadata;
12+
pub use generated::*;
1313

1414
impl InputPayload {
1515
pub fn empty() -> Self {
@@ -48,3 +48,43 @@ impl OutputPayload {
4848
}
4949
}
5050
}
51+
52+
impl Service {
53+
pub(crate) fn apply_options(&mut self, options: ServiceOptions) {
54+
// Apply service options
55+
self.metadata.extend(options.metadata);
56+
self.inactivity_timeout = options.inactivity_timeout.map(|d| d.as_millis() as u64);
57+
self.abort_timeout = options.abort_timeout.map(|d| d.as_millis() as u64);
58+
self.inactivity_timeout = options.inactivity_timeout.map(|d| d.as_millis() as u64);
59+
self.idempotency_retention = options.idempotency_retention.map(|d| d.as_millis() as u64);
60+
self.journal_retention = options.journal_retention.map(|d| d.as_millis() as u64);
61+
self.enable_lazy_state = options.enable_lazy_state;
62+
self.ingress_private = options.ingress_private;
63+
64+
// Apply handler specific options
65+
for (handler_name, handler_options) in options.handler_options {
66+
let handler = self
67+
.handlers
68+
.iter_mut()
69+
.find(|h| handler_name == h.name.as_str())
70+
.expect("Invalid handler name provided in the options");
71+
handler.apply_options(handler_options);
72+
}
73+
}
74+
}
75+
76+
impl Handler {
77+
pub(crate) fn apply_options(&mut self, options: HandlerOptions) {
78+
// Apply handler options
79+
self.metadata.extend(options.metadata);
80+
self.inactivity_timeout = options.inactivity_timeout.map(|d| d.as_millis() as u64);
81+
self.abort_timeout = options.abort_timeout.map(|d| d.as_millis() as u64);
82+
self.inactivity_timeout = options.inactivity_timeout.map(|d| d.as_millis() as u64);
83+
self.idempotency_retention = options.idempotency_retention.map(|d| d.as_millis() as u64);
84+
self.journal_retention = options.journal_retention.map(|d| d.as_millis() as u64);
85+
self.workflow_completion_retention =
86+
options.workflow_retention.map(|d| d.as_millis() as u64);
87+
self.enable_lazy_state = options.enable_lazy_state;
88+
self.ingress_private = options.ingress_private;
89+
}
90+
}

0 commit comments

Comments
 (0)