restate-sdk 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c57bd9821f10bb65901d7da4ad7f6a38f9e64f81f36bd6eece1f2a9efcb7d57
4
- data.tar.gz: c924c4d0f17f82012edaafba7d9867b2f78f2aecdd6fecc0a8f17cbd84c5f89a
3
+ metadata.gz: cc64f400fa1b48565474c9cc26c8bde6742e58b0c02f5090c0f633e16fd2b354
4
+ data.tar.gz: 7d72ad638b4dd6742c149d5314e8c67de919d198362d4a29e65d78da24146898
5
5
  SHA512:
6
- metadata.gz: 0153b6c412588938d243b1d806af7a4e38d9467a21296fd299b9a6c1da77296a208009a82ce264f7d2e6e722a03fcd7b33fa1e77525c736dde7f0286512ece83
7
- data.tar.gz: 4218cc6a283aa5ddf29eaed2ffd9935769a098e58fa98d476687509da45c9ddf4e4bfc871b873cfe234c1239b44f4d4ad6810975e89b61e90017463b0a0bf3d7
6
+ metadata.gz: 6180be88c64766e8537a59ce16c22ff591d9a0b6620301668b0c7759b981f2344a9d04f9e6d896b08a569168cd517e29e9202c69947f1311410911c1c2190f85
7
+ data.tar.gz: bfaa1a28cbfdbeafa95a10a428e7e0b7f17ebc033e0c28659ffeec059c980c4f1635827f40a799e517ccf31c6d143bd342fb6fdfa4b70f6f8dd9709d383af7a9
data/Cargo.lock CHANGED
@@ -569,7 +569,7 @@ dependencies = [
569
569
 
570
570
  [[package]]
571
571
  name = "restate_internal"
572
- version = "0.7.0"
572
+ version = "0.8.0"
573
573
  dependencies = [
574
574
  "magnus",
575
575
  "rb-sys",
data/README.md CHANGED
@@ -58,23 +58,28 @@ Or add the gem to an existing project:
58
58
  gem install restate-sdk
59
59
  ```
60
60
 
61
- ### Typed handlers with T::Struct
61
+ ### Typed handlers with Dry::Struct
62
62
 
63
- Use Sorbet's `T::Struct` for typed input/output with automatic JSON Schema generation:
63
+ Use [dry-struct](https://dry-rb.org/gems/dry-struct/) for typed input/output with automatic JSON Schema generation:
64
64
 
65
65
  ```ruby
66
66
  require 'restate'
67
+ require 'dry-struct'
67
68
 
68
- class RegistrationRequest < T::Struct
69
- const :event_name, String
70
- const :attendee, String
71
- const :num_guests, Integer
72
- const :note, T.nilable(String)
69
+ module Types
70
+ include Dry.Types()
73
71
  end
74
72
 
75
- class RegistrationResponse < T::Struct
76
- const :registration_id, String
77
- const :status, String
73
+ class RegistrationRequest < Dry::Struct
74
+ attribute :event_name, Types::String
75
+ attribute :attendee, Types::String
76
+ attribute :num_guests, Types::Integer
77
+ attribute? :note, Types::String # optional attribute
78
+ end
79
+
80
+ class RegistrationResponse < Dry::Struct
81
+ attribute :registration_id, Types::String
82
+ attribute :status, Types::String
78
83
  end
79
84
 
80
85
  class EventService < Restate::Service
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "restate_internal"
3
- version = "0.7.0"
3
+ version = "0.8.0"
4
4
  edition = "2021"
5
5
  publish = false
6
6
 
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: false
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'net/http'
@@ -31,13 +31,6 @@ module Restate
31
31
  # client.cancel_invocation(invocation_id)
32
32
  # client.create_deployment("http://localhost:9080")
33
33
  class Client
34
- extend T::Sig
35
-
36
- sig do
37
- params(ingress_url: String, admin_url: String,
38
- ingress_headers: T::Hash[String, String],
39
- admin_headers: T::Hash[String, String]).void
40
- end
41
34
  def initialize(ingress_url: 'http://localhost:8080', admin_url: 'http://localhost:9070',
42
35
  ingress_headers: {}, admin_headers: {})
43
36
  @ingress_url = ingress_url.chomp('/')
@@ -49,19 +42,16 @@ module Restate
49
42
  # ── Service invocation proxies ──
50
43
 
51
44
  # Returns a proxy for calling a stateless service.
52
- sig { params(service: T.any(String, T::Class[T.anything])).returns(ClientServiceProxy) }
53
45
  def service(service)
54
46
  ClientServiceProxy.new(@ingress_url, resolve_name(service), nil, @ingress_headers)
55
47
  end
56
48
 
57
49
  # Returns a proxy for calling a keyed virtual object.
58
- sig { params(service: T.any(String, T::Class[T.anything]), key: String).returns(ClientServiceProxy) }
59
50
  def object(service, key)
60
51
  ClientServiceProxy.new(@ingress_url, resolve_name(service), key, @ingress_headers)
61
52
  end
62
53
 
63
54
  # Returns a proxy for calling a workflow.
64
- sig { params(service: T.any(String, T::Class[T.anything]), key: String).returns(ClientServiceProxy) }
65
55
  def workflow(service, key)
66
56
  ClientServiceProxy.new(@ingress_url, resolve_name(service), key, @ingress_headers)
67
57
  end
@@ -69,13 +59,11 @@ module Restate
69
59
  # ── Awakeable operations ──
70
60
 
71
61
  # Resolve an awakeable from outside the Restate runtime.
72
- sig { params(awakeable_id: String, payload: T.untyped).void }
73
62
  def resolve_awakeable(awakeable_id, payload)
74
63
  post_ingress("/restate/awakeables/#{awakeable_id}/resolve", payload)
75
64
  end
76
65
 
77
66
  # Reject an awakeable from outside the Restate runtime.
78
- sig { params(awakeable_id: String, message: String, code: Integer).void }
79
67
  def reject_awakeable(awakeable_id, message, code: 500)
80
68
  post_ingress("/restate/awakeables/#{awakeable_id}/reject",
81
69
  { 'message' => message, 'code' => code })
@@ -84,57 +72,51 @@ module Restate
84
72
  # ── Invocation management ──
85
73
 
86
74
  # Cancel a running invocation.
87
- sig { params(invocation_id: String).void }
88
75
  def cancel_invocation(invocation_id)
89
76
  post_admin("/restate/invocations/#{invocation_id}/cancel", nil)
90
77
  end
91
78
 
92
79
  # Kill a running invocation (immediate termination, no cleanup).
93
- sig { params(invocation_id: String).void }
94
80
  def kill_invocation(invocation_id)
95
81
  post_admin("/restate/invocations/#{invocation_id}/kill", nil)
96
82
  end
97
83
 
98
84
  private
99
85
 
100
- sig { params(service: T.any(String, T::Class[T.anything])).returns(String) }
101
86
  def resolve_name(service)
102
87
  if service.is_a?(Class) && service.respond_to?(:service_name)
103
- T.unsafe(service).service_name
88
+ service.service_name # steep:ignore NoMethod
104
89
  else
105
90
  service.to_s
106
91
  end
107
92
  end
108
93
 
109
- sig { params(path: String, body: T.untyped).returns(T.untyped) }
110
94
  def post_ingress(path, body) # rubocop:disable Metrics/AbcSize
111
95
  uri = URI("#{@ingress_url}#{path}")
112
96
  request = Net::HTTP::Post.new(uri)
113
97
  request['Content-Type'] = 'application/json'
114
98
  @ingress_headers.each { |k, v| request[k] = v }
115
99
  request.body = JSON.generate(body) if body
116
- response = Net::HTTP.start(uri.hostname, uri.port,
100
+ response = Net::HTTP.start(uri.hostname, uri.port, # steep:ignore ArgumentTypeMismatch
117
101
  use_ssl: uri.scheme == 'https',
118
102
  read_timeout: 30) { |http| http.request(request) }
119
103
  Kernel.raise "Restate ingress error: #{response.code} #{response.body}" unless response.is_a?(Net::HTTPSuccess)
120
104
  parse_response(response)
121
105
  end
122
106
 
123
- sig { params(path: String, body: T.untyped).returns(T.untyped) }
124
107
  def post_admin(path, body) # rubocop:disable Metrics/AbcSize
125
108
  uri = URI("#{@admin_url}#{path}")
126
109
  request = Net::HTTP::Post.new(uri)
127
110
  request['Content-Type'] = 'application/json'
128
111
  @admin_headers.each { |k, v| request[k] = v }
129
112
  request.body = JSON.generate(body) if body
130
- response = Net::HTTP.start(uri.hostname, uri.port,
113
+ response = Net::HTTP.start(uri.hostname, uri.port, # steep:ignore ArgumentTypeMismatch
131
114
  use_ssl: uri.scheme == 'https',
132
115
  read_timeout: 30) { |http| http.request(request) }
133
116
  Kernel.raise "Restate admin error: #{response.code} #{response.body}" unless response.is_a?(Net::HTTPSuccess)
134
117
  parse_response(response)
135
118
  end
136
119
 
137
- sig { params(response: Net::HTTPResponse).returns(T.untyped) }
138
120
  def parse_response(response)
139
121
  body = response.body
140
122
  body && !body.empty? ? JSON.parse(body) : nil
@@ -146,12 +128,6 @@ module Restate
146
128
  #
147
129
  # @!visibility private
148
130
  class ClientServiceProxy
149
- extend T::Sig
150
-
151
- sig do
152
- params(base_url: String, service_name: String, key: T.nilable(String),
153
- headers: T::Hash[String, String]).void
154
- end
155
131
  def initialize(base_url, service_name, key, headers)
156
132
  @base_url = base_url
157
133
  @service_name = service_name
@@ -166,7 +142,7 @@ module Restate
166
142
  request['Content-Type'] = 'application/json'
167
143
  @headers.each { |k, v| request[k] = v }
168
144
  request.body = JSON.generate(arg)
169
- response = Net::HTTP.start(uri.hostname, uri.port,
145
+ response = Net::HTTP.start(uri.hostname, uri.port, # steep:ignore ArgumentTypeMismatch
170
146
  use_ssl: uri.scheme == 'https',
171
147
  read_timeout: 30) { |http| http.request(request) }
172
148
  Kernel.raise "Restate ingress error: #{response.code} #{response.body}" unless response.is_a?(Net::HTTPSuccess)
@@ -13,30 +13,23 @@ module Restate
13
13
  # # Then use the pre-configured client:
14
14
  # Restate.client.service(Greeter).greet("World")
15
15
  class Config
16
- extend T::Sig
17
-
18
16
  # Restate ingress URL (for invoking services).
19
- sig { returns(String) }
20
17
  attr_accessor :ingress_url
21
18
 
22
19
  # Restate admin URL (for deployments, invocation management).
23
- sig { returns(String) }
24
20
  attr_accessor :admin_url
25
21
 
26
22
  # Default headers sent with every ingress request.
27
- sig { returns(T::Hash[String, String]) }
28
23
  attr_accessor :ingress_headers
29
24
 
30
25
  # Default headers sent with every admin request.
31
- sig { returns(T::Hash[String, String]) }
32
26
  attr_accessor :admin_headers
33
27
 
34
- sig { void }
35
28
  def initialize
36
- @ingress_url = T.let('http://localhost:8080', String)
37
- @admin_url = T.let('http://localhost:9070', String)
38
- @ingress_headers = T.let({}, T::Hash[String, String])
39
- @admin_headers = T.let({}, T::Hash[String, String])
29
+ @ingress_url = 'http://localhost:8080'
30
+ @admin_url = 'http://localhost:9070'
31
+ @ingress_headers = {}
32
+ @admin_headers = {}
40
33
  end
41
34
  end
42
35
  end
@@ -1,7 +1,7 @@
1
- # typed: true
1
+ # typed: false
2
2
  # frozen_string_literal: true
3
3
 
4
- # rubocop:disable Metrics/ModuleLength,Metrics/ParameterLists,Style/EmptyMethod
4
+ # rubocop:disable Style/EmptyMethod
5
5
  module Restate
6
6
  # Signals when the current invocation attempt has finished — either the handler
7
7
  # completed, the connection was lost, or a transient error occurred.
@@ -17,27 +17,22 @@ module Restate
17
17
  # # poll event.set? periodically, or pass it to your HTTP client
18
18
  # end
19
19
  class AttemptFinishedEvent
20
- extend T::Sig
21
-
22
- sig { void }
23
20
  def initialize
24
- @mutex = T.let(Mutex.new, Mutex)
25
- @set = T.let(false, T::Boolean)
26
- @waiters = T.let([], T::Array[Thread::Queue])
21
+ @mutex = Mutex.new
22
+ @set = false
23
+ @waiters = []
27
24
  end
28
25
 
29
26
  # Returns true if the attempt has finished.
30
- sig { returns(T::Boolean) }
31
27
  def set?
32
28
  @set
33
29
  end
34
30
 
35
31
  # Blocks the current fiber/thread until the attempt finishes.
36
- sig { void }
37
32
  def wait
38
33
  return if @set
39
34
 
40
- waiter = T.let(nil, T.nilable(Thread::Queue))
35
+ waiter = nil
41
36
  @mutex.synchronize do
42
37
  unless @set
43
38
  waiter = Thread::Queue.new
@@ -49,7 +44,6 @@ module Restate
49
44
 
50
45
  # Marks the event as set and wakes all waiters.
51
46
  # Called internally by the SDK when the attempt ends.
52
- sig { void }
53
47
  def set!
54
48
  @mutex.synchronize do
55
49
  @set = true
@@ -79,258 +73,149 @@ module Restate
79
73
  # @see ObjectContext for VirtualObject handlers (adds state operations)
80
74
  # @see WorkflowContext for Workflow handlers (adds promise operations)
81
75
  module Context
82
- extend T::Sig
83
- extend T::Helpers
84
-
85
- abstract!
86
-
87
76
  # Execute a durable side effect. The block runs at most once; the result
88
77
  # is journaled and replayed on retries.
89
78
  #
90
79
  # Pass +background: true+ to offload the block to a real OS Thread,
91
80
  # keeping the fiber event loop responsive for CPU-intensive work.
92
- sig do
93
- abstract.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
81
  def run(name, serde: JsonSerde, retry_policy: nil, background: false, &action); end
99
82
 
100
83
  # Convenience shortcut for +run(...).await+. Returns the result directly.
101
84
  # Accepts all the same options as +run+, including +background: true+.
102
- sig do
103
- abstract.params(
104
- name: String, serde: T.untyped, retry_policy: T.nilable(RunRetryPolicy),
105
- background: T::Boolean, action: T.proc.returns(T.untyped)
106
- ).returns(T.untyped)
107
- end
108
85
  def run_sync(name, serde: JsonSerde, retry_policy: nil, background: false, &action); end
109
86
 
110
87
  # Durable timer that survives handler restarts.
111
- sig { params(seconds: Numeric).returns(DurableFuture) }
112
88
  def sleep(seconds) # rubocop:disable Lint/UnusedMethodArgument
113
89
  Kernel.raise NotImplementedError
114
90
  end
115
91
 
116
92
  # Durably call a handler on a Restate service.
117
- sig do
118
- abstract.params(
119
- service: T.any(String, T::Class[T.anything]), handler: T.any(String, Symbol),
120
- arg: T.untyped, key: T.nilable(String), idempotency_key: T.nilable(String),
121
- headers: T.nilable(T::Hash[String, String]), input_serde: T.untyped, output_serde: T.untyped
122
- ).returns(DurableCallFuture)
123
- end
124
93
  def service_call(service, handler, arg, key: nil, idempotency_key: nil, headers: nil,
125
94
  input_serde: NOT_SET, output_serde: NOT_SET)
126
95
  end
96
+
127
97
  # Fire-and-forget send to a Restate service handler.
128
- sig do
129
- abstract.params(
130
- service: T.any(String, T::Class[T.anything]), handler: T.any(String, Symbol),
131
- arg: T.untyped, key: T.nilable(String), delay: T.nilable(Numeric),
132
- idempotency_key: T.nilable(String), headers: T.nilable(T::Hash[String, String]),
133
- input_serde: T.untyped
134
- ).returns(SendHandle)
135
- end
136
98
  def service_send(service, handler, arg, key: nil, delay: nil, idempotency_key: nil,
137
99
  headers: nil, input_serde: NOT_SET)
138
100
  end
101
+
139
102
  # Durably call a handler on a Restate virtual object.
140
- sig do
141
- abstract.params(
142
- service: T.any(String, T::Class[T.anything]), handler: T.any(String, Symbol),
143
- key: String, arg: T.untyped, idempotency_key: T.nilable(String),
144
- headers: T.nilable(T::Hash[String, String]), input_serde: T.untyped, output_serde: T.untyped
145
- ).returns(DurableCallFuture)
146
- end
147
103
  def object_call(service, handler, key, arg, idempotency_key: nil, headers: nil,
148
104
  input_serde: NOT_SET, output_serde: NOT_SET)
149
105
  end
106
+
150
107
  # Fire-and-forget send to a Restate virtual object handler.
151
- sig do
152
- abstract.params(
153
- service: T.any(String, T::Class[T.anything]), handler: T.any(String, Symbol),
154
- key: String, arg: T.untyped, delay: T.nilable(Numeric),
155
- idempotency_key: T.nilable(String), headers: T.nilable(T::Hash[String, String]),
156
- input_serde: T.untyped
157
- ).returns(SendHandle)
158
- end
159
108
  def object_send(service, handler, key, arg, delay: nil, idempotency_key: nil,
160
109
  headers: nil, input_serde: NOT_SET)
161
110
  end
111
+
162
112
  # Durably call a handler on a Restate workflow.
163
- sig do
164
- abstract.params(
165
- service: T.any(String, T::Class[T.anything]), handler: T.any(String, Symbol),
166
- key: String, arg: T.untyped, idempotency_key: T.nilable(String),
167
- headers: T.nilable(T::Hash[String, String]), input_serde: T.untyped, output_serde: T.untyped
168
- ).returns(DurableCallFuture)
169
- end
170
113
  def workflow_call(service, handler, key, arg, idempotency_key: nil, headers: nil,
171
114
  input_serde: NOT_SET, output_serde: NOT_SET)
172
115
  end
116
+
173
117
  # Fire-and-forget send to a Restate workflow handler.
174
- sig do
175
- abstract.params(
176
- service: T.any(String, T::Class[T.anything]), handler: T.any(String, Symbol),
177
- key: String, arg: T.untyped, delay: T.nilable(Numeric),
178
- idempotency_key: T.nilable(String), headers: T.nilable(T::Hash[String, String]),
179
- input_serde: T.untyped
180
- ).returns(SendHandle)
181
- end
182
118
  def workflow_send(service, handler, key, arg, delay: nil, idempotency_key: nil,
183
119
  headers: nil, input_serde: NOT_SET)
184
120
  end
121
+
185
122
  # Durably call a handler using raw bytes (no serialization).
186
- sig do
187
- abstract.params(
188
- service: String, handler: String, arg: String,
189
- key: T.nilable(String), idempotency_key: T.nilable(String),
190
- headers: T.nilable(T::Hash[String, String])
191
- ).returns(DurableCallFuture)
192
- end
193
123
  def generic_call(service, handler, arg, key: nil, idempotency_key: nil, headers: nil); end
194
124
 
195
125
  # Fire-and-forget send using raw bytes (no serialization).
196
- sig do
197
- abstract.params(
198
- service: String, handler: String, arg: String,
199
- key: T.nilable(String), delay: T.nilable(Numeric),
200
- idempotency_key: T.nilable(String), headers: T.nilable(T::Hash[String, String])
201
- ).returns(SendHandle)
202
- end
203
126
  def generic_send(service, handler, arg, key: nil, delay: nil, idempotency_key: nil, headers: nil); end
204
127
 
205
128
  # Create an awakeable for external callbacks.
206
129
  # Returns [awakeable_id, DurableFuture].
207
- sig { abstract.params(serde: T.untyped).returns([String, DurableFuture]) }
208
130
  def awakeable(serde: JsonSerde); end
209
131
 
210
132
  # Resolve an awakeable with a success value.
211
- sig { abstract.params(awakeable_id: String, payload: T.untyped, serde: T.untyped).void }
212
133
  def resolve_awakeable(awakeable_id, payload, serde: JsonSerde); end
213
134
 
214
135
  # Reject an awakeable with a terminal failure.
215
- sig { abstract.params(awakeable_id: String, message: String, code: Integer).void }
216
136
  def reject_awakeable(awakeable_id, message, code: 500); end
217
137
 
218
138
  # Request cancellation of another invocation.
219
- sig { abstract.params(invocation_id: String).void }
220
139
  def cancel_invocation(invocation_id); end
221
140
 
222
141
  # Wait until any of the given futures completes.
223
142
  # Returns [completed, remaining].
224
- sig { abstract.params(futures: DurableFuture).returns([T::Array[DurableFuture], T::Array[DurableFuture]]) }
225
143
  def wait_any(*futures); end
226
144
 
227
145
  # Returns metadata about the current invocation.
228
- sig { abstract.returns(Request) }
229
146
  def request; end
230
147
 
231
148
  # Returns the key for this virtual object or workflow invocation.
232
- sig { abstract.returns(String) }
233
149
  def key; end
234
150
  end
235
151
 
236
152
  # Context interface for VirtualObject shared handlers (read-only state).
237
153
  # Extends {Context} with +get+, +state_keys+, and +key+ — but no mutations.
238
154
  module ObjectSharedContext
239
- extend T::Sig
240
- extend T::Helpers
241
-
242
- abstract!
243
155
  include Context
244
156
 
245
157
  # Durably retrieve a state entry. Returns nil if unset.
246
- sig { abstract.params(name: String, serde: T.untyped).returns(T.untyped) }
247
158
  def get(name, serde: JsonSerde); end
248
159
 
249
160
  # Durably retrieve a state entry, returning a DurableFuture instead of blocking.
250
- sig { abstract.params(name: String, serde: T.untyped).returns(DurableFuture) }
251
161
  def get_async(name, serde: JsonSerde); end
252
162
 
253
163
  # List all state entry names.
254
- sig { abstract.returns(T.untyped) }
255
164
  def state_keys; end
256
165
 
257
166
  # List all state entry names, returning a DurableFuture instead of blocking.
258
- sig { abstract.returns(DurableFuture) }
259
167
  def state_keys_async; end
260
168
  end
261
169
 
262
170
  # Context interface for VirtualObject exclusive handlers (full state access).
263
171
  # Extends {ObjectSharedContext} with mutating state operations.
264
172
  module ObjectContext
265
- extend T::Sig
266
- extend T::Helpers
267
-
268
- abstract!
269
173
  include ObjectSharedContext
270
174
 
271
175
  # Durably set a state entry.
272
- sig { abstract.params(name: String, value: T.untyped, serde: T.untyped).void }
273
176
  def set(name, value, serde: JsonSerde); end
274
177
 
275
178
  # Durably remove a single state entry.
276
- sig { abstract.params(name: String).void }
277
179
  def clear(name); end
278
180
 
279
181
  # Durably remove all state entries.
280
- sig { abstract.void }
281
182
  def clear_all; end
282
183
  end
283
184
 
284
185
  # Context interface for Workflow shared handlers (read-only state + promises).
285
186
  # Extends {ObjectSharedContext} with durable promise operations.
286
187
  module WorkflowSharedContext
287
- extend T::Sig
288
- extend T::Helpers
289
-
290
- abstract!
291
188
  include ObjectSharedContext
292
189
 
293
190
  # Get a durable promise value, blocking until resolved.
294
- sig { abstract.params(name: String, serde: T.untyped).returns(T.untyped) }
295
191
  def promise(name, serde: JsonSerde); end
296
192
 
297
193
  # Peek at a durable promise without blocking. Returns nil if not yet resolved.
298
- sig { abstract.params(name: String, serde: T.untyped).returns(T.untyped) }
299
194
  def peek_promise(name, serde: JsonSerde); end
300
195
 
301
196
  # Resolve a durable promise with a value.
302
- sig { abstract.params(name: String, payload: T.untyped, serde: T.untyped).void }
303
197
  def resolve_promise(name, payload, serde: JsonSerde); end
304
198
 
305
199
  # Reject a durable promise with a terminal failure.
306
- sig { abstract.params(name: String, message: String, code: Integer).void }
307
200
  def reject_promise(name, message, code: 500); end
308
201
  end
309
202
 
310
203
  # Context interface for Workflow main handler (full state + promises).
311
204
  # Extends {ObjectContext} with durable promise operations.
312
205
  module WorkflowContext
313
- extend T::Sig
314
- extend T::Helpers
315
-
316
- abstract!
317
206
  include ObjectContext
318
207
 
319
208
  # Get a durable promise value, blocking until resolved.
320
- sig { abstract.params(name: String, serde: T.untyped).returns(T.untyped) }
321
209
  def promise(name, serde: JsonSerde); end
322
210
 
323
211
  # Peek at a durable promise without blocking. Returns nil if not yet resolved.
324
- sig { abstract.params(name: String, serde: T.untyped).returns(T.untyped) }
325
212
  def peek_promise(name, serde: JsonSerde); end
326
213
 
327
214
  # Resolve a durable promise with a value.
328
- sig { abstract.params(name: String, payload: T.untyped, serde: T.untyped).void }
329
215
  def resolve_promise(name, payload, serde: JsonSerde); end
330
216
 
331
217
  # Reject a durable promise with a terminal failure.
332
- sig { abstract.params(name: String, message: String, code: Integer).void }
333
218
  def reject_promise(name, message, code: 500); end
334
219
  end
335
220
  end
336
- # rubocop:enable Metrics/ModuleLength,Metrics/ParameterLists,Style/EmptyMethod
221
+ # rubocop:enable Style/EmptyMethod
@@ -5,36 +5,32 @@ require 'json'
5
5
 
6
6
  module Restate
7
7
  module Discovery # rubocop:disable Metrics/ModuleLength
8
- extend T::Sig
9
-
10
- PROTOCOL_MODES = T.let({
8
+ PROTOCOL_MODES = {
11
9
  'bidi' => 'BIDI_STREAM',
12
10
  'request_response' => 'REQUEST_RESPONSE'
13
- }.freeze, T::Hash[String, String])
11
+ }.freeze
14
12
 
15
- SERVICE_TYPES = T.let({
13
+ SERVICE_TYPES = {
16
14
  'service' => 'SERVICE',
17
15
  'object' => 'VIRTUAL_OBJECT',
18
16
  'workflow' => 'WORKFLOW'
19
- }.freeze, T::Hash[String, String])
17
+ }.freeze
20
18
 
21
- HANDLER_TYPES = T.let({
19
+ HANDLER_TYPES = {
22
20
  'exclusive' => 'EXCLUSIVE',
23
21
  'shared' => 'SHARED',
24
22
  'workflow' => 'WORKFLOW'
25
- }.freeze, T::Hash[String, String])
23
+ }.freeze
26
24
 
27
25
  module_function
28
26
 
29
27
  # Generate the discovery JSON for the given endpoint.
30
- sig { params(endpoint: Endpoint, _version: Integer, discovered_as: String).returns(String) }
31
28
  def compute_discovery_json(endpoint, _version, discovered_as)
32
29
  ep = compute_discovery(endpoint, discovered_as)
33
30
  JSON.generate(ep, allow_nan: false)
34
31
  end
35
32
 
36
33
  # Build the discovery hash for the endpoint.
37
- sig { params(endpoint: Endpoint, discovered_as: String).returns(T::Hash[Symbol, T.untyped]) }
38
34
  def compute_discovery(endpoint, discovered_as)
39
35
  services = endpoint.services.values.map do |service|
40
36
  build_service(service)
@@ -50,7 +46,6 @@ module Restate
50
46
  )
51
47
  end
52
48
 
53
- sig { params(service: T.untyped).returns(T::Hash[Symbol, T.untyped]) }
54
49
  def build_service(service) # rubocop:disable Metrics/AbcSize
55
50
  service_type = SERVICE_TYPES.fetch(service.service_tag.kind)
56
51
 
@@ -80,7 +75,6 @@ module Restate
80
75
  result
81
76
  end
82
77
 
83
- sig { params(handler: T.untyped).returns(T::Hash[Symbol, T.untyped]) }
84
78
  def build_handler(handler) # rubocop:disable Metrics/AbcSize
85
79
  ty = handler.kind ? HANDLER_TYPES.fetch(handler.kind) : nil
86
80
 
@@ -118,7 +112,6 @@ module Restate
118
112
  end
119
113
 
120
114
  # Convert seconds to milliseconds (integer). Returns nil if input is nil.
121
- sig { params(seconds: T.nilable(Numeric)).returns(T.nilable(Integer)) }
122
115
  def seconds_to_ms(seconds)
123
116
  return nil if seconds.nil?
124
117
 
@@ -126,7 +119,6 @@ module Restate
126
119
  end
127
120
 
128
121
  # Merge retry policy fields (flattened) into the target hash.
129
- sig { params(target: T::Hash[Symbol, T.untyped], policy: T.nilable(T::Hash[Symbol, T.untyped])).void }
130
122
  def merge_retry_policy!(target, policy) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity
131
123
  return if policy.nil? || policy.empty?
132
124
 
@@ -138,7 +130,6 @@ module Restate
138
130
  end
139
131
 
140
132
  # Remove nil values from a hash (non-recursive for top level, recursive for nested).
141
- sig { params(kwargs: T.untyped).returns(T::Hash[Symbol, T.untyped]) }
142
133
  def compact(**kwargs)
143
134
  kwargs.each_with_object({}) do |(k, v), result|
144
135
  next if v.nil?