restate-sdk 0.4.4-aarch64-linux → 0.5.0-aarch64-linux
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 +4 -5
- data/ext/restate_internal/Cargo.toml +1 -1
- data/lib/restate/3.2/restate_internal.so +0 -0
- data/lib/restate/3.3/restate_internal.so +0 -0
- data/lib/restate/3.4/restate_internal.so +0 -0
- data/lib/restate/4.0/restate_internal.so +0 -0
- data/lib/restate/handler.rb +7 -7
- data/lib/restate/serde.rb +10 -1
- data/lib/restate/server_context.rb +1 -1
- data/lib/restate/service.rb +3 -3
- data/lib/restate/service_dsl.rb +3 -4
- data/lib/restate/version.rb +1 -1
- data/lib/restate/virtual_object.rb +3 -5
- data/lib/restate/workflow.rb +3 -4
- data/lib/restate.rb +5 -5
- data/lib/tapioca/dsl/compilers/restate.rb +77 -6
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6c4926d9f1b3d398f990db7c8c1b69992d15dca6c4351b26ca2acdb544241dbb
|
|
4
|
+
data.tar.gz: fa7141828b226288c421d9fd3e7e312542996ba54f84fa3b8037b7f392143315
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 97997980254554521ee6b9a24244de9a8115664bef4585b1d856ac859b8c590ae20ed938208d06f245d1d019951ec7be51f73217c359e7ceaae43da24875f21b
|
|
7
|
+
data.tar.gz: 135673211c2a556bba886aefc3ce4b3d8b20312330a985d908a08d50b4e2d1c744514b3fec5918ecfe1fc89bb916adcc353649d28371365725913cf3872fce01
|
data/Cargo.lock
CHANGED
data/README.md
CHANGED
|
@@ -5,14 +5,15 @@
|
|
|
5
5
|
|
|
6
6
|
# Restate Ruby SDK
|
|
7
7
|
|
|
8
|
+
> **Note:** This SDK is currently under active development. APIs may change between releases.
|
|
9
|
+
|
|
8
10
|
[Restate](https://restate.dev/) is a system for easily building resilient applications using *distributed durable async/await*. This repository contains the Restate SDK for writing services in **Ruby**.
|
|
9
11
|
|
|
10
12
|
```ruby
|
|
11
13
|
require 'restate'
|
|
12
14
|
|
|
13
15
|
class Greeter < Restate::Service
|
|
14
|
-
handler def greet(name)
|
|
15
|
-
ctx = Restate.current_context
|
|
16
|
+
handler def greet(ctx, name)
|
|
16
17
|
ctx.run_sync('build-greeting') { "Hello, #{name}!" }
|
|
17
18
|
end
|
|
18
19
|
end
|
|
@@ -66,9 +67,7 @@ end
|
|
|
66
67
|
|
|
67
68
|
class EventService < Restate::Service
|
|
68
69
|
handler :register, input: RegistrationRequest, output: RegistrationResponse
|
|
69
|
-
def register(request)
|
|
70
|
-
ctx = Restate.current_context
|
|
71
|
-
|
|
70
|
+
def register(ctx, request)
|
|
72
71
|
registration_id = ctx.run_sync('create-registration') do
|
|
73
72
|
"reg_#{request.event_name}_#{rand(10_000)}"
|
|
74
73
|
end
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/lib/restate/handler.rb
CHANGED
|
@@ -31,20 +31,20 @@ module Restate
|
|
|
31
31
|
|
|
32
32
|
module_function
|
|
33
33
|
|
|
34
|
-
# Invoke a handler with raw input bytes.
|
|
35
|
-
#
|
|
34
|
+
# Invoke a handler with the context and raw input bytes.
|
|
35
|
+
# The context is passed as the first argument to every handler.
|
|
36
36
|
# Returns raw output bytes.
|
|
37
|
-
sig { params(handler: T.untyped, in_buffer: String).returns(String) }
|
|
38
|
-
def invoke_handler(handler:, in_buffer:)
|
|
39
|
-
if handler.arity ==
|
|
37
|
+
sig { params(handler: T.untyped, ctx: T.untyped, in_buffer: String).returns(String) }
|
|
38
|
+
def invoke_handler(handler:, ctx:, in_buffer:)
|
|
39
|
+
if handler.arity == 2
|
|
40
40
|
begin
|
|
41
41
|
in_arg = handler.handler_io.input_serde.deserialize(in_buffer)
|
|
42
42
|
rescue StandardError => e
|
|
43
43
|
Kernel.raise TerminalError, "Unable to parse input argument: #{e.message}"
|
|
44
44
|
end
|
|
45
|
-
out_arg = handler.callable.call(in_arg)
|
|
45
|
+
out_arg = handler.callable.call(ctx, in_arg)
|
|
46
46
|
else
|
|
47
|
-
out_arg = handler.callable.call
|
|
47
|
+
out_arg = handler.callable.call(ctx)
|
|
48
48
|
end
|
|
49
49
|
handler.handler_io.output_serde.serialize(out_arg)
|
|
50
50
|
end
|
data/lib/restate/serde.rb
CHANGED
|
@@ -212,10 +212,13 @@ module Restate
|
|
|
212
212
|
class TypeSerde
|
|
213
213
|
extend T::Sig
|
|
214
214
|
|
|
215
|
+
sig { returns(T.untyped) }
|
|
216
|
+
attr_reader :type_class
|
|
217
|
+
|
|
215
218
|
# Create a TypeSerde for the given type with a precomputed JSON Schema.
|
|
216
219
|
sig { params(type: T.untyped, schema: T.nilable(T::Hash[String, T.untyped])).void }
|
|
217
220
|
def initialize(type, schema)
|
|
218
|
-
@
|
|
221
|
+
@type_class = type
|
|
219
222
|
@schema = schema
|
|
220
223
|
end
|
|
221
224
|
|
|
@@ -243,6 +246,9 @@ module Restate
|
|
|
243
246
|
class DryStructSerde
|
|
244
247
|
extend T::Sig
|
|
245
248
|
|
|
249
|
+
sig { returns(T.untyped) }
|
|
250
|
+
attr_reader :struct_class
|
|
251
|
+
|
|
246
252
|
# Create a DryStructSerde for the given Dry::Struct class.
|
|
247
253
|
sig { params(struct_class: T.untyped).void }
|
|
248
254
|
def initialize(struct_class)
|
|
@@ -280,6 +286,9 @@ module Restate
|
|
|
280
286
|
class TStructSerde
|
|
281
287
|
extend T::Sig
|
|
282
288
|
|
|
289
|
+
sig { returns(T.class_of(T::Struct)) }
|
|
290
|
+
attr_reader :struct_class
|
|
291
|
+
|
|
283
292
|
# Create a TStructSerde for the given T::Struct subclass.
|
|
284
293
|
sig { params(struct_class: T.class_of(T::Struct)).void }
|
|
285
294
|
def initialize(struct_class)
|
|
@@ -48,7 +48,7 @@ module Restate
|
|
|
48
48
|
Thread.current[:restate_service_kind] = @handler.service_tag.kind
|
|
49
49
|
Thread.current[:restate_handler_kind] = @handler.kind
|
|
50
50
|
in_buffer = @invocation.input_buffer
|
|
51
|
-
out_buffer = Restate.invoke_handler(handler: @handler, in_buffer: in_buffer)
|
|
51
|
+
out_buffer = Restate.invoke_handler(handler: @handler, ctx: self, in_buffer: in_buffer)
|
|
52
52
|
@vm.sys_write_output_success(out_buffer.b)
|
|
53
53
|
@vm.sys_end
|
|
54
54
|
rescue TerminalError => e
|
data/lib/restate/service.rb
CHANGED
|
@@ -6,8 +6,8 @@ module Restate
|
|
|
6
6
|
#
|
|
7
7
|
# @example
|
|
8
8
|
# class Greeter < Restate::Service
|
|
9
|
-
# handler def greet(name)
|
|
10
|
-
# "Hello, #{name}!"
|
|
9
|
+
# handler def greet(ctx, name)
|
|
10
|
+
# ctx.run_sync('build-greeting') { "Hello, #{name}!" }
|
|
11
11
|
# end
|
|
12
12
|
# end
|
|
13
13
|
class Service
|
|
@@ -15,7 +15,7 @@ module Restate
|
|
|
15
15
|
extend ServiceDSL
|
|
16
16
|
|
|
17
17
|
# Register a handler method on this service.
|
|
18
|
-
# Use as: +handler def my_method(arg)+ or +handler :my_method, input: String+
|
|
18
|
+
# Use as: +handler def my_method(ctx, arg)+ or +handler :my_method, input: String+
|
|
19
19
|
#
|
|
20
20
|
# @param method_name [Symbol] name of the method to register
|
|
21
21
|
# @param opts [Hash] handler options (+input:+, +output:+, +accept:+, +content_type:+)
|
data/lib/restate/service_dsl.rb
CHANGED
|
@@ -9,8 +9,7 @@ module Restate
|
|
|
9
9
|
#
|
|
10
10
|
# @example
|
|
11
11
|
# class Counter < Restate::VirtualObject
|
|
12
|
-
# handler def add(addend)
|
|
13
|
-
# ctx = Restate.current_object_context
|
|
12
|
+
# handler def add(ctx, addend)
|
|
14
13
|
# old = ctx.get('counter') || 0
|
|
15
14
|
# ctx.set('counter', old + addend)
|
|
16
15
|
# old + addend
|
|
@@ -211,8 +210,8 @@ module Restate
|
|
|
211
210
|
|
|
212
211
|
um = T.unsafe(self).instance_method(name)
|
|
213
212
|
arity = um.arity.abs
|
|
214
|
-
unless [
|
|
215
|
-
Kernel.raise ArgumentError, "handler '#{name}' must accept
|
|
213
|
+
unless [1, 2].include?(arity)
|
|
214
|
+
Kernel.raise ArgumentError, "handler '#{name}' must accept 1 or 2 parameters (ctx[, input]), got #{arity}"
|
|
216
215
|
end
|
|
217
216
|
|
|
218
217
|
bound = um.bind(instance)
|
data/lib/restate/version.rb
CHANGED
|
@@ -6,15 +6,13 @@ module Restate
|
|
|
6
6
|
#
|
|
7
7
|
# @example
|
|
8
8
|
# class Counter < Restate::VirtualObject
|
|
9
|
-
# handler def add(addend)
|
|
10
|
-
# ctx = Restate.current_object_context
|
|
9
|
+
# handler def add(ctx, addend)
|
|
11
10
|
# old = ctx.get("count") || 0
|
|
12
11
|
# ctx.set("count", old + addend)
|
|
13
12
|
# old + addend
|
|
14
13
|
# end
|
|
15
14
|
#
|
|
16
|
-
# shared def get
|
|
17
|
-
# ctx = Restate.current_object_context
|
|
15
|
+
# shared def get(ctx)
|
|
18
16
|
# ctx.get("count") || 0
|
|
19
17
|
# end
|
|
20
18
|
# end
|
|
@@ -22,7 +20,7 @@ module Restate
|
|
|
22
20
|
extend T::Sig
|
|
23
21
|
extend ServiceDSL
|
|
24
22
|
|
|
25
|
-
# Register an exclusive handler. Use as: +handler def my_method(arg)+
|
|
23
|
+
# Register an exclusive handler. Use as: +handler def my_method(ctx, arg)+
|
|
26
24
|
#
|
|
27
25
|
# @param method_name [Symbol] name of the method to register
|
|
28
26
|
# @param kind [Symbol] concurrency mode (+:exclusive+ or +:shared+)
|
data/lib/restate/workflow.rb
CHANGED
|
@@ -6,12 +6,11 @@ module Restate
|
|
|
6
6
|
#
|
|
7
7
|
# @example
|
|
8
8
|
# class Signup < Restate::Workflow
|
|
9
|
-
# main def run(email)
|
|
9
|
+
# main def run(ctx, email)
|
|
10
10
|
# # workflow logic
|
|
11
11
|
# end
|
|
12
12
|
#
|
|
13
|
-
# handler def status
|
|
14
|
-
# ctx = Restate.current_workflow_context
|
|
13
|
+
# handler def status(ctx)
|
|
15
14
|
# ctx.get("status")
|
|
16
15
|
# end
|
|
17
16
|
# end
|
|
@@ -20,7 +19,7 @@ module Restate
|
|
|
20
19
|
extend ServiceDSL
|
|
21
20
|
|
|
22
21
|
# Register the main workflow entry point.
|
|
23
|
-
# Use as: +main def run(arg)+ or +main :run, input: String+
|
|
22
|
+
# Use as: +main def run(ctx, arg)+ or +main :run, input: String+
|
|
24
23
|
#
|
|
25
24
|
# @param method_name [Symbol] name of the method to register
|
|
26
25
|
# @param opts [Hash] handler options (+input:+, +output:+, +accept:+, +content_type:+)
|
data/lib/restate.rb
CHANGED
|
@@ -46,12 +46,12 @@ module Restate
|
|
|
46
46
|
|
|
47
47
|
# ── Fiber-local context accessors ──
|
|
48
48
|
#
|
|
49
|
-
# The SDK
|
|
50
|
-
# (Thread.current[], which is
|
|
51
|
-
# retrieve it with the appropriate
|
|
49
|
+
# The SDK passes the context as the first argument to every handler.
|
|
50
|
+
# It is also stored in fiber-local storage (Thread.current[], which is
|
|
51
|
+
# fiber-scoped in Ruby). These methods retrieve it with the appropriate
|
|
52
|
+
# type for IDE completion.
|
|
52
53
|
#
|
|
53
|
-
# Use these
|
|
54
|
-
# from a nested method that doesn't have +ctx+ in scope.
|
|
54
|
+
# Use these from nested helper methods that don't have +ctx+ in scope.
|
|
55
55
|
|
|
56
56
|
# Returns the current context for a Service handler.
|
|
57
57
|
# Raises if called outside a Restate handler.
|
|
@@ -3,14 +3,15 @@
|
|
|
3
3
|
|
|
4
4
|
return unless defined?(Tapioca::Dsl::Compiler)
|
|
5
5
|
|
|
6
|
+
require 'restate'
|
|
7
|
+
|
|
6
8
|
module Tapioca
|
|
7
9
|
module Dsl
|
|
8
10
|
module Compilers
|
|
9
11
|
# Generates Sorbet sigs for Restate handler methods.
|
|
10
12
|
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
# compiler generates sigs reflecting the actual handler arity (0 or 1).
|
|
13
|
+
# Every handler receives +ctx+ as its first parameter. Handlers that
|
|
14
|
+
# accept input receive it as the second parameter (arity 2).
|
|
14
15
|
#
|
|
15
16
|
# Usage:
|
|
16
17
|
# bundle exec tapioca dsl
|
|
@@ -19,6 +20,10 @@ module Tapioca
|
|
|
19
20
|
|
|
20
21
|
class << self
|
|
21
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
|
+
|
|
22
27
|
all_classes.select do |klass|
|
|
23
28
|
klass.is_a?(Class) && (
|
|
24
29
|
klass < ::Restate::Service ||
|
|
@@ -29,16 +34,82 @@ module Tapioca
|
|
|
29
34
|
false
|
|
30
35
|
end
|
|
31
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
|
|
32
56
|
end
|
|
33
57
|
|
|
34
|
-
def decorate
|
|
58
|
+
def decorate # rubocop:disable Metrics/MethodLength
|
|
35
59
|
root.create_path(constant) do |klass|
|
|
36
60
|
constant.handlers.each do |name, handler|
|
|
37
|
-
|
|
38
|
-
|
|
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)
|
|
39
69
|
end
|
|
40
70
|
end
|
|
41
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
|
|
42
113
|
end
|
|
43
114
|
end
|
|
44
115
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: restate-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Restate Developers
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-03-
|
|
11
|
+
date: 2026-03-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: async
|