restate-sdk 0.4.3

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.
data/lib/restate/vm.rb ADDED
@@ -0,0 +1,325 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'restate_internal'
5
+
6
+ module Restate
7
+ # Ruby-side data types for VM results
8
+ Invocation = Struct.new(:invocation_id, :random_seed, :headers, :input_buffer, :key, keyword_init: true)
9
+ Failure = Struct.new(:code, :message, :stacktrace, keyword_init: true)
10
+
11
+ class NotReady; end
12
+ class Suspended; end
13
+
14
+ NOT_READY = T.let(NotReady.new.freeze, NotReady)
15
+ SUSPENDED = T.let(Suspended.new.freeze, Suspended)
16
+ CANCEL_HANDLE = T.let(Internal::CANCEL_NOTIFICATION_HANDLE, Integer)
17
+
18
+ # Progress loop result types
19
+ class DoProgressAnyCompleted; end
20
+ class DoProgressReadFromInput; end
21
+ class DoProgressCancelSignalReceived; end
22
+ class DoWaitPendingRun; end
23
+
24
+ DO_PROGRESS_ANY_COMPLETED = T.let(DoProgressAnyCompleted.new.freeze, DoProgressAnyCompleted)
25
+ DO_PROGRESS_READ_FROM_INPUT = T.let(DoProgressReadFromInput.new.freeze, DoProgressReadFromInput)
26
+ DO_PROGRESS_CANCEL_SIGNAL_RECEIVED = T.let(DoProgressCancelSignalReceived.new.freeze, DoProgressCancelSignalReceived)
27
+ DO_WAIT_PENDING_RUN = T.let(DoWaitPendingRun.new.freeze, DoWaitPendingRun)
28
+
29
+ DoProgressExecuteRun = Struct.new(:handle, keyword_init: true)
30
+
31
+ # User-facing retry policy for ctx.run
32
+ RunRetryPolicy = Struct.new(
33
+ :initial_interval, :max_attempts, :max_duration,
34
+ :max_interval, :interval_factor,
35
+ keyword_init: true
36
+ )
37
+
38
+ # Exponential retry configuration for run
39
+ RunRetryConfig = Struct.new(
40
+ :initial_interval, :max_attempts, :max_duration,
41
+ :max_interval, :interval_factor,
42
+ keyword_init: true
43
+ )
44
+
45
+ # Wraps the native Restate::Internal::VM, mapping native types to Ruby types.
46
+ class VMWrapper
47
+ extend T::Sig
48
+
49
+ sig { params(headers: T.untyped).void }
50
+ def initialize(headers)
51
+ @vm = T.let(Internal::VM.new(headers), Internal::VM)
52
+ end
53
+
54
+ sig { returns([Integer, T.untyped]) }
55
+ def get_response_head
56
+ result = @vm.get_response_head
57
+ [result.status_code, result.headers]
58
+ end
59
+
60
+ sig { params(buf: String).void }
61
+ def notify_input(buf)
62
+ @vm.notify_input(buf)
63
+ end
64
+
65
+ sig { void }
66
+ def notify_input_closed
67
+ @vm.notify_input_closed
68
+ end
69
+
70
+ sig { params(error: String, stacktrace: T.nilable(String)).void }
71
+ def notify_error(error, stacktrace = nil)
72
+ @vm.notify_error(error, stacktrace)
73
+ end
74
+
75
+ sig { returns(T.nilable(String)) }
76
+ def take_output
77
+ @vm.take_output
78
+ end
79
+
80
+ sig { returns(T::Boolean) }
81
+ def is_ready_to_execute
82
+ @vm.is_ready_to_execute
83
+ end
84
+
85
+ sig { params(handle: Integer).returns(T::Boolean) }
86
+ def is_completed(handle)
87
+ @vm.is_completed(handle)
88
+ end
89
+
90
+ sig { params(handles: T::Array[Integer]).returns(T.untyped) }
91
+ def do_progress(handles)
92
+ result = @vm.do_progress(handles)
93
+ map_do_progress(result)
94
+ rescue Internal::VMError => e
95
+ e
96
+ end
97
+
98
+ sig { params(handle: Integer).returns(T.untyped) }
99
+ def take_notification(handle)
100
+ result = @vm.take_notification(handle)
101
+ map_notification(result)
102
+ rescue Internal::VMError => e
103
+ e
104
+ end
105
+
106
+ sig { returns(T.untyped) }
107
+ def sys_input
108
+ inp = @vm.sys_input
109
+ headers = inp.headers.map { |h| [h.key, h.value] }
110
+ Invocation.new(
111
+ invocation_id: inp.invocation_id,
112
+ random_seed: inp.random_seed,
113
+ headers: headers,
114
+ input_buffer: inp.input.b,
115
+ key: inp.key
116
+ )
117
+ end
118
+
119
+ sig { params(name: String).returns(Integer) }
120
+ def sys_get_state(name)
121
+ @vm.sys_get_state(name)
122
+ end
123
+
124
+ sig { returns(Integer) }
125
+ def sys_get_state_keys
126
+ @vm.sys_get_state_keys
127
+ end
128
+
129
+ sig { params(name: String, value: String).void }
130
+ def sys_set_state(name, value)
131
+ @vm.sys_set_state(name, value)
132
+ end
133
+
134
+ sig { params(name: String).void }
135
+ def sys_clear_state(name)
136
+ @vm.sys_clear_state(name)
137
+ end
138
+
139
+ sig { void }
140
+ def sys_clear_all_state
141
+ @vm.sys_clear_all_state
142
+ end
143
+
144
+ sig { params(millis: Integer, name: T.nilable(String)).returns(Integer) }
145
+ def sys_sleep(millis, name = nil)
146
+ # Rust side always expects 2 args: (millis, name_or_nil)
147
+ @vm.sys_sleep(millis, name)
148
+ end
149
+
150
+ sig do
151
+ params(
152
+ service: String,
153
+ handler: String,
154
+ parameter: String,
155
+ key: T.nilable(String),
156
+ idempotency_key: T.nilable(String),
157
+ headers: T.nilable(T::Hash[String, String])
158
+ ).returns(Internal::CallHandle)
159
+ end
160
+ def sys_call(service:, handler:, parameter:, key: nil, idempotency_key: nil, headers: nil)
161
+ # Rust side expects 6 args: (service, handler, buffer, key_or_nil, idem_key_or_nil, headers_or_nil)
162
+ hdr_array = headers&.map { |k, v| [k, v] }
163
+ @vm.sys_call(service, handler, parameter, key, idempotency_key, hdr_array)
164
+ end
165
+
166
+ sig do
167
+ params(
168
+ service: String,
169
+ handler: String,
170
+ parameter: String,
171
+ key: T.nilable(String),
172
+ delay: T.nilable(Integer),
173
+ idempotency_key: T.nilable(String),
174
+ headers: T.nilable(T::Hash[String, String])
175
+ ).returns(Integer)
176
+ end
177
+ def sys_send(service:, handler:, parameter:, key: nil, delay: nil, idempotency_key: nil, headers: nil)
178
+ # Rust side expects 7 args
179
+ hdr_array = headers&.map { |k, v| [k, v] }
180
+ @vm.sys_send(service, handler, parameter, key, delay, idempotency_key, hdr_array)
181
+ end
182
+
183
+ sig { params(name: String).returns(Integer) }
184
+ def sys_run(name)
185
+ @vm.sys_run(name)
186
+ end
187
+
188
+ sig { params(handle: Integer, output: String).void }
189
+ def propose_run_completion_success(handle, output)
190
+ @vm.propose_run_completion_success(handle, output)
191
+ end
192
+
193
+ sig { params(handle: Integer, failure: T.untyped).void }
194
+ def propose_run_completion_failure(handle, failure)
195
+ native_failure = Internal::Failure.new(failure.code, failure.message, nil)
196
+ @vm.propose_run_completion_failure(handle, native_failure)
197
+ end
198
+
199
+ sig do
200
+ params(
201
+ handle: Integer,
202
+ failure: T.untyped,
203
+ attempt_duration_ms: Integer,
204
+ config: T.untyped
205
+ ).void
206
+ end
207
+ def propose_run_completion_transient(handle, failure:, attempt_duration_ms:, config:)
208
+ native_failure = Internal::Failure.new(failure.code, failure.message, failure.stacktrace)
209
+ native_config = Internal::ExponentialRetryConfig.new(
210
+ config.initial_interval, config.max_attempts,
211
+ config.max_duration, config.max_interval,
212
+ config.interval_factor
213
+ )
214
+ @vm.propose_run_completion_failure_transient(handle, native_failure, attempt_duration_ms, native_config)
215
+ end
216
+
217
+ sig { params(output: String).void }
218
+ def sys_write_output_success(output)
219
+ @vm.sys_write_output_success(output)
220
+ end
221
+
222
+ sig { params(failure: T.untyped).void }
223
+ def sys_write_output_failure(failure)
224
+ native_failure = Internal::Failure.new(failure.code, failure.message, nil)
225
+ @vm.sys_write_output_failure(native_failure)
226
+ end
227
+
228
+ sig { void }
229
+ def sys_end
230
+ @vm.sys_end
231
+ end
232
+
233
+ sig { returns(T::Boolean) }
234
+ def is_replaying
235
+ @vm.is_replaying
236
+ end
237
+
238
+ # Returns [awakeable_id (String), notification_handle (Integer)]
239
+ sig { returns([String, Integer]) }
240
+ def sys_awakeable
241
+ @vm.sys_awakeable
242
+ end
243
+
244
+ sig { params(awakeable_id: String, value: String).void }
245
+ def sys_complete_awakeable_success(awakeable_id, value)
246
+ @vm.sys_complete_awakeable_success(awakeable_id, value)
247
+ end
248
+
249
+ sig { params(awakeable_id: String, failure: T.untyped).void }
250
+ def sys_complete_awakeable_failure(awakeable_id, failure)
251
+ native_failure = Internal::Failure.new(failure.code, failure.message, nil)
252
+ @vm.sys_complete_awakeable_failure(awakeable_id, native_failure)
253
+ end
254
+
255
+ sig { params(key: String).returns(Integer) }
256
+ def sys_get_promise(key)
257
+ @vm.sys_get_promise(key)
258
+ end
259
+
260
+ sig { params(key: String).returns(Integer) }
261
+ def sys_peek_promise(key)
262
+ @vm.sys_peek_promise(key)
263
+ end
264
+
265
+ sig { params(key: String, value: String).returns(Integer) }
266
+ def sys_complete_promise_success(key, value)
267
+ @vm.sys_complete_promise_success(key, value)
268
+ end
269
+
270
+ sig { params(key: String, failure: T.untyped).returns(Integer) }
271
+ def sys_complete_promise_failure(key, failure)
272
+ native_failure = Internal::Failure.new(failure.code, failure.message, nil)
273
+ @vm.sys_complete_promise_failure(key, native_failure)
274
+ end
275
+
276
+ sig { params(invocation_id: String).void }
277
+ def sys_cancel_invocation(invocation_id)
278
+ @vm.sys_cancel_invocation(invocation_id)
279
+ end
280
+
281
+ private
282
+
283
+ sig { params(result: T.untyped).returns(T.untyped) }
284
+ def map_do_progress(result)
285
+ case result
286
+ when Internal::Suspended
287
+ SUSPENDED
288
+ when Internal::DoProgressAnyCompleted
289
+ DO_PROGRESS_ANY_COMPLETED
290
+ when Internal::DoProgressReadFromInput
291
+ DO_PROGRESS_READ_FROM_INPUT
292
+ when Internal::DoProgressExecuteRun
293
+ DoProgressExecuteRun.new(handle: result.handle)
294
+ when Internal::DoProgressCancelSignalReceived
295
+ DO_PROGRESS_CANCEL_SIGNAL_RECEIVED
296
+ when Internal::DoWaitForPendingRun
297
+ DO_WAIT_PENDING_RUN
298
+ else
299
+ raise "Unknown progress type: #{result.class}"
300
+ end
301
+ end
302
+
303
+ sig { params(result: T.untyped).returns(T.untyped) }
304
+ def map_notification(result)
305
+ case result
306
+ when Internal::Suspended
307
+ SUSPENDED
308
+ when NilClass
309
+ NOT_READY
310
+ when Internal::Void
311
+ nil
312
+ when String
313
+ # Could be bytes (success) or invocation_id string.
314
+ # The native layer returns RString for both.
315
+ result
316
+ when Internal::Failure
317
+ Failure.new(code: result.code, message: result.message)
318
+ when Internal::StateKeys
319
+ result.keys
320
+ else
321
+ raise "Unknown notification type: #{result.class}"
322
+ end
323
+ end
324
+ end
325
+ end
@@ -0,0 +1,57 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Restate
5
+ # A durable workflow with a main entry point and shared handlers.
6
+ #
7
+ # @example
8
+ # class Signup < Restate::Workflow
9
+ # main def run(email)
10
+ # # workflow logic
11
+ # end
12
+ #
13
+ # handler def status
14
+ # ctx = Restate.current_workflow_context
15
+ # ctx.get("status")
16
+ # end
17
+ # end
18
+ class Workflow
19
+ extend T::Sig
20
+ extend ServiceDSL
21
+
22
+ # Register the main workflow entry point.
23
+ # Use as: +main def run(arg)+ or +main :run, input: String+
24
+ #
25
+ # @param method_name [Symbol] name of the method to register
26
+ # @param opts [Hash] handler options (+input:+, +output:+, +accept:+, +content_type:+)
27
+ # @return [Symbol] the method name
28
+ def self.main(method_name = nil, **opts)
29
+ if method_name.is_a?(String)
30
+ raise ArgumentError,
31
+ "handler expects a Symbol (use `main def #{method_name}(...)` or `main :#{method_name}`)"
32
+ end
33
+ return method_name unless method_name.is_a?(Symbol)
34
+
35
+ _register_handler(method_name, **T.unsafe({ kind: 'workflow', **opts }))
36
+ end
37
+
38
+ # Register a shared handler on this workflow.
39
+ #
40
+ # @param method_name [Symbol] name of the method to register
41
+ # @param opts [Hash] handler options (+input:+, +output:+, +accept:+, +content_type:+)
42
+ # @return [Symbol] the method name
43
+ def self.handler(method_name = nil, **opts)
44
+ if method_name.is_a?(String)
45
+ raise ArgumentError,
46
+ "handler expects a Symbol (use `handler def #{method_name}(...)` or `handler :#{method_name}`)"
47
+ end
48
+ return method_name unless method_name.is_a?(Symbol)
49
+
50
+ _register_handler(method_name, **T.unsafe({ kind: 'shared', **opts }))
51
+ end
52
+
53
+ def self._service_kind
54
+ 'workflow'
55
+ end
56
+ end
57
+ end
data/lib/restate.rb ADDED
@@ -0,0 +1,130 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require 'sorbet-runtime'
5
+ require_relative 'restate/version'
6
+ require_relative 'restate/errors'
7
+ require_relative 'restate/serde'
8
+ require_relative 'restate/vm'
9
+ require_relative 'restate/context'
10
+ require_relative 'restate/handler'
11
+ require_relative 'restate/service_dsl'
12
+ require_relative 'restate/service'
13
+ require_relative 'restate/virtual_object'
14
+ require_relative 'restate/workflow'
15
+ require_relative 'restate/server_context'
16
+ require_relative 'restate/durable_future'
17
+ require_relative 'restate/discovery'
18
+ require_relative 'restate/endpoint'
19
+
20
+ # Restate Ruby SDK — build resilient applications with durable execution.
21
+ module Restate
22
+ extend T::Sig
23
+
24
+ module_function
25
+
26
+ # Create an endpoint, optionally binding services.
27
+ # Returns an Endpoint that can be further configured before calling +.app+.
28
+ #
29
+ # @param services [Array<Class>] service classes or instances to bind
30
+ # @return [Endpoint]
31
+ sig do
32
+ params(
33
+ services: T.untyped,
34
+ protocol: T.nilable(String),
35
+ identity_keys: T.nilable(T::Array[String])
36
+ ).returns(Endpoint)
37
+ end
38
+ def endpoint(*services, protocol: nil, identity_keys: nil)
39
+ ep = Endpoint.new
40
+ ep.streaming_protocol if protocol == 'bidi'
41
+ ep.request_response_protocol if protocol == 'request_response'
42
+ services.each { |s| ep.bind(s) }
43
+ identity_keys&.each { |k| ep.identity_key(k) }
44
+ ep
45
+ end
46
+
47
+ # ── Fiber-local context accessors ──
48
+ #
49
+ # The SDK stores the current handler context in fiber-local storage
50
+ # (Thread.current[], which is fiber-scoped in Ruby). These methods
51
+ # retrieve it with the appropriate type for IDE completion.
52
+ #
53
+ # Use these instead of the +ctx+ parameter when you need the context
54
+ # from a nested method that doesn't have +ctx+ in scope.
55
+
56
+ # Returns the current context for a Service handler.
57
+ # Raises if called outside a Restate handler.
58
+ #
59
+ # @return [Context]
60
+ sig { returns(Context) }
61
+ def current_context
62
+ fetch_context!
63
+ end
64
+
65
+ # Returns the current context for a VirtualObject exclusive handler.
66
+ # Raises if not inside a VirtualObject exclusive handler.
67
+ #
68
+ # @return [ObjectContext]
69
+ sig { returns(ObjectContext) }
70
+ def current_object_context
71
+ fetch_context!(service_kind: 'object', handler_kind: 'exclusive')
72
+ end
73
+
74
+ # Returns the current context for a VirtualObject shared handler.
75
+ # Read-only state: +get+ and +state_keys+ only, no +set+/+clear+.
76
+ # Raises if not inside a VirtualObject shared handler.
77
+ #
78
+ # @return [ObjectSharedContext]
79
+ sig { returns(ObjectSharedContext) }
80
+ def current_shared_context
81
+ fetch_context!(service_kind: 'object', handler_kind: 'shared')
82
+ end
83
+
84
+ # Returns the current context for a Workflow main handler.
85
+ # Raises if not inside a Workflow main handler.
86
+ #
87
+ # @return [WorkflowContext]
88
+ sig { returns(WorkflowContext) }
89
+ def current_workflow_context
90
+ fetch_context!(service_kind: 'workflow', handler_kind: 'workflow')
91
+ end
92
+
93
+ # Returns the current context for a Workflow shared handler.
94
+ # Read-only state: +get+ and +state_keys+ only, no +set+/+clear+.
95
+ # Raises if not inside a Workflow shared handler.
96
+ #
97
+ # @return [WorkflowSharedContext]
98
+ sig { returns(WorkflowSharedContext) }
99
+ def current_shared_workflow_context
100
+ fetch_context!(service_kind: 'workflow', handler_kind: 'shared')
101
+ end
102
+
103
+ # @!visibility private
104
+ sig do
105
+ params(service_kind: T.nilable(String), handler_kind: T.nilable(String)).returns(ServerContext)
106
+ end
107
+ def fetch_context!(service_kind: nil, handler_kind: nil) # rubocop:disable Metrics
108
+ ctx = Thread.current[:restate_context]
109
+ unless ctx
110
+ Kernel.raise 'Not inside a Restate handler. ' \
111
+ 'Context accessors can only be called during handler execution.'
112
+ end
113
+
114
+ if service_kind
115
+ actual_service = Thread.current[:restate_service_kind]
116
+ unless actual_service == service_kind
117
+ Kernel.raise "Expected a #{service_kind} handler, but current handler is #{actual_service || 'unknown'}."
118
+ end
119
+ end
120
+
121
+ if handler_kind
122
+ actual_handler = Thread.current[:restate_handler_kind]
123
+ unless actual_handler == handler_kind
124
+ Kernel.raise "Expected a #{handler_kind} handler, but current handler kind is #{actual_handler || 'unknown'}."
125
+ end
126
+ end
127
+
128
+ T.cast(ctx, ServerContext)
129
+ end
130
+ end
@@ -0,0 +1,45 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ return unless defined?(Tapioca::Dsl::Compiler)
5
+
6
+ module Tapioca
7
+ module Dsl
8
+ module Compilers
9
+ # Generates Sorbet sigs for Restate handler methods.
10
+ #
11
+ # Handlers no longer receive +ctx+ as a parameter — context is accessed
12
+ # via fiber-local +Restate.current_context+ (or typed variants). This
13
+ # compiler generates sigs reflecting the actual handler arity (0 or 1).
14
+ #
15
+ # Usage:
16
+ # bundle exec tapioca dsl
17
+ class Restate < Compiler
18
+ ConstantType = type_member { { fixed: Module } }
19
+
20
+ class << self
21
+ def gather_constants
22
+ all_classes.select do |klass|
23
+ klass.is_a?(Class) && (
24
+ klass < ::Restate::Service ||
25
+ klass < ::Restate::VirtualObject ||
26
+ klass < ::Restate::Workflow
27
+ )
28
+ rescue TypeError
29
+ false
30
+ end
31
+ end
32
+ end
33
+
34
+ def decorate
35
+ root.create_path(constant) do |klass|
36
+ constant.handlers.each do |name, handler|
37
+ params = handler.arity == 1 ? [create_param('input', type: 'T.untyped')] : []
38
+ klass.create_method(name, parameters: params, return_type: 'T.untyped')
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: restate-sdk
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.3
5
+ platform: ruby
6
+ authors:
7
+ - Restate Developers
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-03-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: async
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: falcon
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.47'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.47'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sorbet-runtime
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Build resilient applications with distributed durable async/await using
70
+ Restate
71
+ email:
72
+ - code@restate.dev
73
+ executables: []
74
+ extensions:
75
+ - ext/restate_internal/extconf.rb
76
+ extra_rdoc_files: []
77
+ files:
78
+ - Cargo.lock
79
+ - Cargo.toml
80
+ - LICENSE
81
+ - README.md
82
+ - ext/restate_internal/Cargo.toml
83
+ - ext/restate_internal/extconf.rb
84
+ - ext/restate_internal/src/lib.rs
85
+ - lib/restate.rb
86
+ - lib/restate/context.rb
87
+ - lib/restate/discovery.rb
88
+ - lib/restate/durable_future.rb
89
+ - lib/restate/endpoint.rb
90
+ - lib/restate/errors.rb
91
+ - lib/restate/handler.rb
92
+ - lib/restate/serde.rb
93
+ - lib/restate/server.rb
94
+ - lib/restate/server_context.rb
95
+ - lib/restate/service.rb
96
+ - lib/restate/service_dsl.rb
97
+ - lib/restate/testing.rb
98
+ - lib/restate/version.rb
99
+ - lib/restate/virtual_object.rb
100
+ - lib/restate/vm.rb
101
+ - lib/restate/workflow.rb
102
+ - lib/tapioca/dsl/compilers/restate.rb
103
+ homepage: https://github.com/restatedev/sdk-ruby
104
+ licenses:
105
+ - MIT
106
+ metadata:
107
+ rubygems_mfa_required: 'true'
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '3.1'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubygems_version: 3.5.22
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Restate SDK for Ruby
127
+ test_files: []