restate-sdk 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Cargo.lock +1 -1
- data/README.md +31 -14
- data/ext/restate_internal/Cargo.toml +1 -1
- data/lib/restate/client.rb +157 -0
- data/lib/restate/config.rb +35 -0
- data/lib/restate/context.rb +13 -128
- data/lib/restate/discovery.rb +6 -15
- data/lib/restate/durable_future.rb +15 -39
- data/lib/restate/endpoint.rb +5 -22
- data/lib/restate/errors.rb +2 -15
- data/lib/restate/handler.rb +21 -20
- data/lib/restate/serde.rb +14 -130
- data/lib/restate/server.rb +10 -26
- data/lib/restate/server_context.rb +50 -248
- data/lib/restate/service.rb +24 -3
- data/lib/restate/service_dsl.rb +70 -6
- data/lib/restate/service_proxy.rb +73 -0
- data/lib/restate/testing.rb +1 -1
- data/lib/restate/version.rb +2 -2
- data/lib/restate/virtual_object.rb +27 -4
- data/lib/restate/vm.rb +9 -74
- data/lib/restate/workflow.rb +27 -4
- data/lib/restate.rb +222 -62
- data/sig/restate.rbs +196 -0
- metadata +6 -18
- data/lib/tapioca/dsl/compilers/restate.rb +0 -116
- data/rbi/restate-sdk.rbi +0 -307
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
# typed: false
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
return unless defined?(Tapioca::Dsl::Compiler)
|
|
5
|
-
|
|
6
|
-
require 'restate'
|
|
7
|
-
|
|
8
|
-
module Tapioca
|
|
9
|
-
module Dsl
|
|
10
|
-
module Compilers
|
|
11
|
-
# Generates Sorbet sigs for Restate handler methods.
|
|
12
|
-
#
|
|
13
|
-
# Every handler receives +ctx+ as its first parameter. Handlers that
|
|
14
|
-
# accept input receive it as the second parameter (arity 2).
|
|
15
|
-
#
|
|
16
|
-
# Usage:
|
|
17
|
-
# bundle exec tapioca dsl
|
|
18
|
-
class Restate < Compiler
|
|
19
|
-
ConstantType = type_member { { fixed: Module } }
|
|
20
|
-
|
|
21
|
-
class << self
|
|
22
|
-
def gather_constants
|
|
23
|
-
# Load service files so they're visible to all_classes.
|
|
24
|
-
# In non-Rails apps, Tapioca doesn't auto-load application code.
|
|
25
|
-
load_service_files
|
|
26
|
-
|
|
27
|
-
all_classes.select do |klass|
|
|
28
|
-
klass.is_a?(Class) && (
|
|
29
|
-
klass < ::Restate::Service ||
|
|
30
|
-
klass < ::Restate::VirtualObject ||
|
|
31
|
-
klass < ::Restate::Workflow
|
|
32
|
-
)
|
|
33
|
-
rescue TypeError
|
|
34
|
-
false
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
private
|
|
39
|
-
|
|
40
|
-
def load_service_files # rubocop:disable Metrics/MethodLength
|
|
41
|
-
root = Bundler.root.to_s
|
|
42
|
-
patterns = [
|
|
43
|
-
"#{root}/*.rb",
|
|
44
|
-
"#{root}/app/**/*.rb",
|
|
45
|
-
"#{root}/services/**/*.rb",
|
|
46
|
-
"#{root}/examples/**/*.rb"
|
|
47
|
-
]
|
|
48
|
-
Dir.glob(patterns).each do |file|
|
|
49
|
-
next if file.end_with?('config.ru', 'Rakefile')
|
|
50
|
-
|
|
51
|
-
require file
|
|
52
|
-
rescue LoadError, StandardError
|
|
53
|
-
nil # skip files that can't be loaded
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def decorate # rubocop:disable Metrics/MethodLength
|
|
59
|
-
root.create_path(constant) do |klass|
|
|
60
|
-
constant.handlers.each do |name, handler|
|
|
61
|
-
ctx_type = resolve_context_type(constant, handler)
|
|
62
|
-
params = [create_param('ctx', type: ctx_type)]
|
|
63
|
-
if handler.arity == 2
|
|
64
|
-
input_type = resolve_input_type(handler)
|
|
65
|
-
params << create_param('input', type: input_type)
|
|
66
|
-
end
|
|
67
|
-
output_type = resolve_output_type(handler)
|
|
68
|
-
klass.create_method(name, parameters: params, return_type: output_type)
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
private
|
|
74
|
-
|
|
75
|
-
# Maps (service kind, handler kind) to the correct context module.
|
|
76
|
-
def resolve_context_type(klass, handler)
|
|
77
|
-
if klass < ::Restate::Workflow
|
|
78
|
-
handler.kind == 'workflow' ? 'Restate::WorkflowContext' : 'Restate::WorkflowSharedContext'
|
|
79
|
-
elsif klass < ::Restate::VirtualObject
|
|
80
|
-
handler.kind == 'shared' ? 'Restate::ObjectSharedContext' : 'Restate::ObjectContext'
|
|
81
|
-
else
|
|
82
|
-
'Restate::Context'
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
# Resolves the Sorbet type string for the handler's input serde.
|
|
87
|
-
def resolve_input_type(handler)
|
|
88
|
-
type_class = handler.handler_io&.input_serde
|
|
89
|
-
sorbet_type_name(type_class) || 'T.untyped'
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
# Resolves the Sorbet type string for the handler's output serde.
|
|
93
|
-
def resolve_output_type(handler)
|
|
94
|
-
type_class = handler.handler_io&.output_serde
|
|
95
|
-
sorbet_type_name(type_class) || 'T.untyped'
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# Returns a Sorbet type string if the serde wraps a known type, nil otherwise.
|
|
99
|
-
def sorbet_type_name(serde)
|
|
100
|
-
return nil if serde.nil?
|
|
101
|
-
|
|
102
|
-
# TStructSerde exposes .struct_class (T::Struct subclasses are visible to Sorbet)
|
|
103
|
-
return serde.struct_class.name if serde.is_a?(::Restate::TStructSerde)
|
|
104
|
-
|
|
105
|
-
# TypeSerde wraps a primitive type in .type_class
|
|
106
|
-
if serde.respond_to?(:type_class)
|
|
107
|
-
name = serde.type_class.name
|
|
108
|
-
return name if %w[String Integer Float].include?(name)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
nil
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
end
|
data/rbi/restate-sdk.rbi
DELETED
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
# typed: true
|
|
2
|
-
|
|
3
|
-
# RBI shipped with the restate-sdk gem.
|
|
4
|
-
# Tapioca merges this automatically when users run `tapioca gems`.
|
|
5
|
-
|
|
6
|
-
module Restate
|
|
7
|
-
# Create an endpoint, optionally binding services.
|
|
8
|
-
sig do
|
|
9
|
-
params(
|
|
10
|
-
services: T.untyped,
|
|
11
|
-
protocol: T.nilable(String),
|
|
12
|
-
identity_keys: T.nilable(T::Array[String])
|
|
13
|
-
).returns(Restate::Endpoint)
|
|
14
|
-
end
|
|
15
|
-
def self.endpoint(*services, protocol: nil, identity_keys: nil); end
|
|
16
|
-
|
|
17
|
-
# Returns the current context (any handler).
|
|
18
|
-
sig { returns(Restate::Context) }
|
|
19
|
-
def self.current_context; end
|
|
20
|
-
|
|
21
|
-
# Returns the current context for a VirtualObject exclusive handler.
|
|
22
|
-
sig { returns(Restate::ObjectContext) }
|
|
23
|
-
def self.current_object_context; end
|
|
24
|
-
|
|
25
|
-
# Returns the current context for a VirtualObject shared handler.
|
|
26
|
-
sig { returns(Restate::ObjectSharedContext) }
|
|
27
|
-
def self.current_shared_context; end
|
|
28
|
-
|
|
29
|
-
# Returns the current context for a Workflow main handler.
|
|
30
|
-
sig { returns(Restate::WorkflowContext) }
|
|
31
|
-
def self.current_workflow_context; end
|
|
32
|
-
|
|
33
|
-
# Returns the current context for a Workflow shared handler.
|
|
34
|
-
sig { returns(Restate::WorkflowSharedContext) }
|
|
35
|
-
def self.current_shared_workflow_context; end
|
|
36
|
-
|
|
37
|
-
class TerminalError < StandardError
|
|
38
|
-
sig { returns(Integer) }
|
|
39
|
-
def status_code; end
|
|
40
|
-
|
|
41
|
-
sig { params(message: String, status_code: Integer).void }
|
|
42
|
-
def initialize(message = '', status_code: 500); end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
class AttemptFinishedEvent
|
|
46
|
-
sig { returns(T::Boolean) }
|
|
47
|
-
def set?; end
|
|
48
|
-
|
|
49
|
-
sig { void }
|
|
50
|
-
def wait; end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
Request = T.type_alias { T.untyped }
|
|
54
|
-
|
|
55
|
-
class RunRetryPolicy < T::Struct
|
|
56
|
-
const :initial_interval, T.nilable(Integer)
|
|
57
|
-
const :max_attempts, T.nilable(Integer)
|
|
58
|
-
const :max_duration, T.nilable(Integer)
|
|
59
|
-
const :max_interval, T.nilable(Integer)
|
|
60
|
-
const :interval_factor, T.nilable(Float)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
class DurableFuture
|
|
64
|
-
sig { returns(T.untyped) }
|
|
65
|
-
def await; end
|
|
66
|
-
|
|
67
|
-
sig { returns(T::Boolean) }
|
|
68
|
-
def completed?; end
|
|
69
|
-
|
|
70
|
-
sig { returns(Integer) }
|
|
71
|
-
def handle; end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
class DurableCallFuture < DurableFuture
|
|
75
|
-
sig { returns(String) }
|
|
76
|
-
def invocation_id; end
|
|
77
|
-
|
|
78
|
-
sig { void }
|
|
79
|
-
def cancel; end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
class SendHandle
|
|
83
|
-
sig { returns(String) }
|
|
84
|
-
def invocation_id; end
|
|
85
|
-
|
|
86
|
-
sig { void }
|
|
87
|
-
def cancel; end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Base context interface for all Restate handlers.
|
|
91
|
-
module Context
|
|
92
|
-
sig do
|
|
93
|
-
params(
|
|
94
|
-
name: String, serde: T.untyped, retry_policy: T.nilable(RunRetryPolicy),
|
|
95
|
-
background: T::Boolean, action: T.proc.returns(T.untyped)
|
|
96
|
-
).returns(DurableFuture)
|
|
97
|
-
end
|
|
98
|
-
def run(name, serde: Restate::JsonSerde, retry_policy: nil, background: false, &action); end
|
|
99
|
-
|
|
100
|
-
sig do
|
|
101
|
-
params(
|
|
102
|
-
name: String, serde: T.untyped, retry_policy: T.nilable(RunRetryPolicy),
|
|
103
|
-
background: T::Boolean, action: T.proc.returns(T.untyped)
|
|
104
|
-
).returns(T.untyped)
|
|
105
|
-
end
|
|
106
|
-
def run_sync(name, serde: Restate::JsonSerde, retry_policy: nil, background: false, &action); end
|
|
107
|
-
|
|
108
|
-
sig { params(seconds: Numeric).returns(DurableFuture) }
|
|
109
|
-
def sleep(seconds); end
|
|
110
|
-
|
|
111
|
-
sig do
|
|
112
|
-
params(
|
|
113
|
-
service: T.any(String, T::Class[T.anything]), handler: T.any(String, Symbol),
|
|
114
|
-
arg: T.untyped, key: T.nilable(String), idempotency_key: T.nilable(String),
|
|
115
|
-
headers: T.nilable(T::Hash[String, String]), input_serde: T.untyped, output_serde: T.untyped
|
|
116
|
-
).returns(DurableCallFuture)
|
|
117
|
-
end
|
|
118
|
-
def service_call(service, handler, arg, key: nil, idempotency_key: nil, headers: nil,
|
|
119
|
-
input_serde: T.unsafe(nil), output_serde: T.unsafe(nil)); end
|
|
120
|
-
|
|
121
|
-
sig do
|
|
122
|
-
params(
|
|
123
|
-
service: T.any(String, T::Class[T.anything]), handler: T.any(String, Symbol),
|
|
124
|
-
arg: T.untyped, key: T.nilable(String), delay: T.nilable(Numeric),
|
|
125
|
-
idempotency_key: T.nilable(String), headers: T.nilable(T::Hash[String, String]),
|
|
126
|
-
input_serde: T.untyped
|
|
127
|
-
).returns(SendHandle)
|
|
128
|
-
end
|
|
129
|
-
def service_send(service, handler, arg, key: nil, delay: nil, idempotency_key: nil,
|
|
130
|
-
headers: nil, input_serde: T.unsafe(nil)); end
|
|
131
|
-
|
|
132
|
-
sig do
|
|
133
|
-
params(
|
|
134
|
-
service: T.any(String, T::Class[T.anything]), handler: T.any(String, Symbol),
|
|
135
|
-
key: String, arg: T.untyped, idempotency_key: T.nilable(String),
|
|
136
|
-
headers: T.nilable(T::Hash[String, String]), input_serde: T.untyped, output_serde: T.untyped
|
|
137
|
-
).returns(DurableCallFuture)
|
|
138
|
-
end
|
|
139
|
-
def object_call(service, handler, key, arg, idempotency_key: nil, headers: nil,
|
|
140
|
-
input_serde: T.unsafe(nil), output_serde: T.unsafe(nil)); end
|
|
141
|
-
|
|
142
|
-
sig do
|
|
143
|
-
params(
|
|
144
|
-
service: T.any(String, T::Class[T.anything]), handler: T.any(String, Symbol),
|
|
145
|
-
key: String, arg: T.untyped, delay: T.nilable(Numeric),
|
|
146
|
-
idempotency_key: T.nilable(String), headers: T.nilable(T::Hash[String, String]),
|
|
147
|
-
input_serde: T.untyped
|
|
148
|
-
).returns(SendHandle)
|
|
149
|
-
end
|
|
150
|
-
def object_send(service, handler, key, arg, delay: nil, idempotency_key: nil,
|
|
151
|
-
headers: nil, input_serde: T.unsafe(nil)); end
|
|
152
|
-
|
|
153
|
-
sig do
|
|
154
|
-
params(
|
|
155
|
-
service: T.any(String, T::Class[T.anything]), handler: T.any(String, Symbol),
|
|
156
|
-
key: String, arg: T.untyped, idempotency_key: T.nilable(String),
|
|
157
|
-
headers: T.nilable(T::Hash[String, String]), input_serde: T.untyped, output_serde: T.untyped
|
|
158
|
-
).returns(DurableCallFuture)
|
|
159
|
-
end
|
|
160
|
-
def workflow_call(service, handler, key, arg, idempotency_key: nil, headers: nil,
|
|
161
|
-
input_serde: T.unsafe(nil), output_serde: T.unsafe(nil)); end
|
|
162
|
-
|
|
163
|
-
sig do
|
|
164
|
-
params(
|
|
165
|
-
service: T.any(String, T::Class[T.anything]), handler: T.any(String, Symbol),
|
|
166
|
-
key: String, arg: T.untyped, delay: T.nilable(Numeric),
|
|
167
|
-
idempotency_key: T.nilable(String), headers: T.nilable(T::Hash[String, String]),
|
|
168
|
-
input_serde: T.untyped
|
|
169
|
-
).returns(SendHandle)
|
|
170
|
-
end
|
|
171
|
-
def workflow_send(service, handler, key, arg, delay: nil, idempotency_key: nil,
|
|
172
|
-
headers: nil, input_serde: T.unsafe(nil)); end
|
|
173
|
-
|
|
174
|
-
sig do
|
|
175
|
-
params(
|
|
176
|
-
service: String, handler: String, arg: String,
|
|
177
|
-
key: T.nilable(String), idempotency_key: T.nilable(String),
|
|
178
|
-
headers: T.nilable(T::Hash[String, String])
|
|
179
|
-
).returns(DurableCallFuture)
|
|
180
|
-
end
|
|
181
|
-
def generic_call(service, handler, arg, key: nil, idempotency_key: nil, headers: nil); end
|
|
182
|
-
|
|
183
|
-
sig do
|
|
184
|
-
params(
|
|
185
|
-
service: String, handler: String, arg: String,
|
|
186
|
-
key: T.nilable(String), delay: T.nilable(Numeric),
|
|
187
|
-
idempotency_key: T.nilable(String), headers: T.nilable(T::Hash[String, String])
|
|
188
|
-
).returns(SendHandle)
|
|
189
|
-
end
|
|
190
|
-
def generic_send(service, handler, arg, key: nil, delay: nil, idempotency_key: nil, headers: nil); end
|
|
191
|
-
|
|
192
|
-
sig { params(serde: T.untyped).returns([String, DurableFuture]) }
|
|
193
|
-
def awakeable(serde: Restate::JsonSerde); end
|
|
194
|
-
|
|
195
|
-
sig { params(awakeable_id: String, payload: T.untyped, serde: T.untyped).void }
|
|
196
|
-
def resolve_awakeable(awakeable_id, payload, serde: Restate::JsonSerde); end
|
|
197
|
-
|
|
198
|
-
sig { params(awakeable_id: String, message: String, code: Integer).void }
|
|
199
|
-
def reject_awakeable(awakeable_id, message, code: 500); end
|
|
200
|
-
|
|
201
|
-
sig { params(invocation_id: String).void }
|
|
202
|
-
def cancel_invocation(invocation_id); end
|
|
203
|
-
|
|
204
|
-
sig { params(futures: DurableFuture).returns([T::Array[DurableFuture], T::Array[DurableFuture]]) }
|
|
205
|
-
def wait_any(*futures); end
|
|
206
|
-
|
|
207
|
-
sig { returns(T.untyped) }
|
|
208
|
-
def request; end
|
|
209
|
-
|
|
210
|
-
sig { returns(String) }
|
|
211
|
-
def key; end
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
# VirtualObject shared handler context (read-only state).
|
|
215
|
-
module ObjectSharedContext
|
|
216
|
-
include Context
|
|
217
|
-
|
|
218
|
-
sig { params(name: String, serde: T.untyped).returns(T.untyped) }
|
|
219
|
-
def get(name, serde: Restate::JsonSerde); end
|
|
220
|
-
|
|
221
|
-
sig { params(name: String, serde: T.untyped).returns(DurableFuture) }
|
|
222
|
-
def get_async(name, serde: Restate::JsonSerde); end
|
|
223
|
-
|
|
224
|
-
sig { returns(T.untyped) }
|
|
225
|
-
def state_keys; end
|
|
226
|
-
|
|
227
|
-
sig { returns(DurableFuture) }
|
|
228
|
-
def state_keys_async; end
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
# VirtualObject exclusive handler context (full state access).
|
|
232
|
-
module ObjectContext
|
|
233
|
-
include ObjectSharedContext
|
|
234
|
-
|
|
235
|
-
sig { params(name: String, value: T.untyped, serde: T.untyped).void }
|
|
236
|
-
def set(name, value, serde: Restate::JsonSerde); end
|
|
237
|
-
|
|
238
|
-
sig { params(name: String).void }
|
|
239
|
-
def clear(name); end
|
|
240
|
-
|
|
241
|
-
sig { void }
|
|
242
|
-
def clear_all; end
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
# Workflow shared handler context (read-only state + promises).
|
|
246
|
-
module WorkflowSharedContext
|
|
247
|
-
include ObjectSharedContext
|
|
248
|
-
|
|
249
|
-
sig { params(name: String, serde: T.untyped).returns(T.untyped) }
|
|
250
|
-
def promise(name, serde: Restate::JsonSerde); end
|
|
251
|
-
|
|
252
|
-
sig { params(name: String, serde: T.untyped).returns(T.untyped) }
|
|
253
|
-
def peek_promise(name, serde: Restate::JsonSerde); end
|
|
254
|
-
|
|
255
|
-
sig { params(name: String, payload: T.untyped, serde: T.untyped).void }
|
|
256
|
-
def resolve_promise(name, payload, serde: Restate::JsonSerde); end
|
|
257
|
-
|
|
258
|
-
sig { params(name: String, message: String, code: Integer).void }
|
|
259
|
-
def reject_promise(name, message, code: 500); end
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
# Workflow main handler context (full state + promises).
|
|
263
|
-
module WorkflowContext
|
|
264
|
-
include ObjectContext
|
|
265
|
-
|
|
266
|
-
sig { params(name: String, serde: T.untyped).returns(T.untyped) }
|
|
267
|
-
def promise(name, serde: Restate::JsonSerde); end
|
|
268
|
-
|
|
269
|
-
sig { params(name: String, serde: T.untyped).returns(T.untyped) }
|
|
270
|
-
def peek_promise(name, serde: Restate::JsonSerde); end
|
|
271
|
-
|
|
272
|
-
sig { params(name: String, payload: T.untyped, serde: T.untyped).void }
|
|
273
|
-
def resolve_promise(name, payload, serde: Restate::JsonSerde); end
|
|
274
|
-
|
|
275
|
-
sig { params(name: String, message: String, code: Integer).void }
|
|
276
|
-
def reject_promise(name, message, code: 500); end
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
# Stateless service base class.
|
|
280
|
-
class Service; end
|
|
281
|
-
|
|
282
|
-
# Keyed virtual object base class.
|
|
283
|
-
class VirtualObject; end
|
|
284
|
-
|
|
285
|
-
# Durable workflow base class.
|
|
286
|
-
class Workflow; end
|
|
287
|
-
|
|
288
|
-
class Endpoint
|
|
289
|
-
sig { params(services: T.untyped).void }
|
|
290
|
-
def bind(*services); end
|
|
291
|
-
|
|
292
|
-
sig { void }
|
|
293
|
-
def streaming_protocol; end
|
|
294
|
-
|
|
295
|
-
sig { void }
|
|
296
|
-
def request_response_protocol; end
|
|
297
|
-
|
|
298
|
-
sig { params(key: String).void }
|
|
299
|
-
def identity_key(key); end
|
|
300
|
-
|
|
301
|
-
sig { returns(T.untyped) }
|
|
302
|
-
def app; end
|
|
303
|
-
end
|
|
304
|
-
|
|
305
|
-
module JsonSerde; end
|
|
306
|
-
module BytesSerde; end
|
|
307
|
-
end
|