restate-sdk 0.9.0 → 0.10.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 +9 -17
- data/ext/restate_internal/Cargo.toml +1 -1
- data/lib/restate/client.rb +27 -0
- data/lib/restate/introspection.rb +127 -0
- data/lib/restate/railtie.rb +17 -0
- data/lib/restate/version.rb +1 -1
- data/lib/restate.rb +1 -0
- data/sig/restate.rbs +3 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 40a987e80017804da9524cecb061cb5dd798f63d78b7b9d5297eafd0f7a3f08c
|
|
4
|
+
data.tar.gz: 7911f4dc802ffc13b5065ee3d7c0447c04a0741dee2df87aa023b7dfd8196cee
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8ed57c28f1a19c800602f98d47f8956850fa72962b8a35f6fe80f1d9e27c28d16de8803d504e0000455d8bfdfe45e0e402e063ea330307f4ace1c13c19196316
|
|
7
|
+
data.tar.gz: e48404e2aa84ee83852b65015fd70330d6407ad3874da6f639af741e623133bb59007294cffdc526ec5b0c1bfe35b20dbe4d9557ae4c1e3f0a92df7c603f6ba8
|
data/Cargo.lock
CHANGED
|
@@ -31,16 +31,14 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
|
|
31
31
|
|
|
32
32
|
[[package]]
|
|
33
33
|
name = "bindgen"
|
|
34
|
-
version = "0.
|
|
34
|
+
version = "0.72.1"
|
|
35
35
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
36
|
-
checksum = "
|
|
36
|
+
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
|
|
37
37
|
dependencies = [
|
|
38
38
|
"bitflags",
|
|
39
39
|
"cexpr",
|
|
40
40
|
"clang-sys",
|
|
41
41
|
"itertools 0.12.1",
|
|
42
|
-
"lazy_static",
|
|
43
|
-
"lazycell",
|
|
44
42
|
"proc-macro2",
|
|
45
43
|
"quote",
|
|
46
44
|
"regex",
|
|
@@ -278,12 +276,6 @@ version = "1.5.0"
|
|
|
278
276
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
279
277
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|
280
278
|
|
|
281
|
-
[[package]]
|
|
282
|
-
name = "lazycell"
|
|
283
|
-
version = "1.3.0"
|
|
284
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
285
|
-
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|
286
|
-
|
|
287
279
|
[[package]]
|
|
288
280
|
name = "libc"
|
|
289
281
|
version = "0.2.183"
|
|
@@ -489,18 +481,18 @@ dependencies = [
|
|
|
489
481
|
|
|
490
482
|
[[package]]
|
|
491
483
|
name = "rb-sys"
|
|
492
|
-
version = "0.9.
|
|
484
|
+
version = "0.9.128"
|
|
493
485
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
494
|
-
checksum = "
|
|
486
|
+
checksum = "45ca28513560e56cfb79a62b1fce363c73af170a182024ce880c77ee9429920a"
|
|
495
487
|
dependencies = [
|
|
496
488
|
"rb-sys-build",
|
|
497
489
|
]
|
|
498
490
|
|
|
499
491
|
[[package]]
|
|
500
492
|
name = "rb-sys-build"
|
|
501
|
-
version = "0.9.
|
|
493
|
+
version = "0.9.128"
|
|
502
494
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
503
|
-
checksum = "
|
|
495
|
+
checksum = "ce04b2c55eff3a21aaa623fcc655d94373238e72cac6b3e1a3641ff31649f99a"
|
|
504
496
|
dependencies = [
|
|
505
497
|
"bindgen",
|
|
506
498
|
"lazy_static",
|
|
@@ -569,7 +561,7 @@ dependencies = [
|
|
|
569
561
|
|
|
570
562
|
[[package]]
|
|
571
563
|
name = "restate_internal"
|
|
572
|
-
version = "0.
|
|
564
|
+
version = "0.10.0"
|
|
573
565
|
dependencies = [
|
|
574
566
|
"magnus",
|
|
575
567
|
"rb-sys",
|
|
@@ -593,9 +585,9 @@ dependencies = [
|
|
|
593
585
|
|
|
594
586
|
[[package]]
|
|
595
587
|
name = "rustc-hash"
|
|
596
|
-
version = "
|
|
588
|
+
version = "2.1.2"
|
|
597
589
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
598
|
-
checksum = "
|
|
590
|
+
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
|
|
599
591
|
|
|
600
592
|
[[package]]
|
|
601
593
|
name = "rustversion"
|
data/lib/restate/client.rb
CHANGED
|
@@ -81,6 +81,33 @@ module Restate
|
|
|
81
81
|
post_admin("/restate/invocations/#{invocation_id}/kill", nil)
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
+
# ── Introspection queries ──
|
|
85
|
+
|
|
86
|
+
# Execute a SQL query against Restate's introspection API (DataFusion).
|
|
87
|
+
# The admin API exposes system tables (sys_invocation, sys_journal, state,
|
|
88
|
+
# etc.) that can be queried with standard SQL.
|
|
89
|
+
#
|
|
90
|
+
# @param sql [String] a SQL query string
|
|
91
|
+
# @return [Array<Hash>] rows returned by the query
|
|
92
|
+
#
|
|
93
|
+
# @example
|
|
94
|
+
# client.execute_query("SELECT id, status FROM sys_invocation LIMIT 10")
|
|
95
|
+
def execute_query(sql) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
96
|
+
uri = URI("#{@admin_url}/query")
|
|
97
|
+
request = Net::HTTP::Post.new(uri)
|
|
98
|
+
request['Content-Type'] = 'application/json'
|
|
99
|
+
request['Accept'] = 'application/json'
|
|
100
|
+
@admin_headers.each { |k, v| request[k] = v }
|
|
101
|
+
request.body = JSON.generate({ query: sql })
|
|
102
|
+
response = Net::HTTP.start(uri.hostname, uri.port, # steep:ignore ArgumentTypeMismatch
|
|
103
|
+
use_ssl: uri.scheme == 'https',
|
|
104
|
+
open_timeout: 5,
|
|
105
|
+
read_timeout: 30) { |http| http.request(request) }
|
|
106
|
+
Kernel.raise "Restate query error: #{response.code} #{response.body}" unless response.is_a?(Net::HTTPSuccess)
|
|
107
|
+
body = response.body
|
|
108
|
+
body && !body.empty? ? (JSON.parse(body)['rows'] || []) : []
|
|
109
|
+
end
|
|
110
|
+
|
|
84
111
|
private
|
|
85
112
|
|
|
86
113
|
def resolve_name(service)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# typed: false
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'active_record'
|
|
5
|
+
|
|
6
|
+
module Restate
|
|
7
|
+
# Arel table references for Restate's SQL introspection tables.
|
|
8
|
+
#
|
|
9
|
+
# Restate exposes a DataFusion-powered SQL endpoint at +/query+ on the admin
|
|
10
|
+
# API. These tables let you build queries using Arel's composable, type-safe
|
|
11
|
+
# predicate API — the same one ActiveRecord uses under the hood.
|
|
12
|
+
#
|
|
13
|
+
# @example Query running invocations for a service
|
|
14
|
+
# i = Restate::Sys::Invocation
|
|
15
|
+
# query = i.project(i[:id], i[:status], i[:created_at])
|
|
16
|
+
# .where(i[:target_service_name].eq("MyService"))
|
|
17
|
+
# .where(i[:status].eq("running"))
|
|
18
|
+
# .order(i[:created_at].desc)
|
|
19
|
+
# .take(50)
|
|
20
|
+
# Restate.query(query)
|
|
21
|
+
#
|
|
22
|
+
# @example Join invocations with their journal input
|
|
23
|
+
# i = Restate::Sys::Invocation
|
|
24
|
+
# j = Restate::Sys::Journal
|
|
25
|
+
# query = i.project(i[:id], i[:target], i[:status], j[:entry_json])
|
|
26
|
+
# .join(j, Arel::Nodes::OuterJoin)
|
|
27
|
+
# .on(j[:id].eq(i[:id]).and(j[:index].eq(0)))
|
|
28
|
+
# .where(i[:target_service_name].eq("CrawlPipeline"))
|
|
29
|
+
# .order(i[:created_at].desc)
|
|
30
|
+
# .take(20)
|
|
31
|
+
# Restate.query(query)
|
|
32
|
+
#
|
|
33
|
+
# @example Query virtual object state
|
|
34
|
+
# s = Restate::Sys::State
|
|
35
|
+
# query = s.project(s[:service_name], s[:service_key], s[:key], s[:value_utf8])
|
|
36
|
+
# .where(s[:service_name].eq("Counter"))
|
|
37
|
+
# Restate.query(query)
|
|
38
|
+
module Sys
|
|
39
|
+
Invocation = Arel::Table.new(:sys_invocation)
|
|
40
|
+
Journal = Arel::Table.new(:sys_journal)
|
|
41
|
+
JournalEvents = Arel::Table.new(:sys_journal_events)
|
|
42
|
+
Inbox = Arel::Table.new(:sys_inbox)
|
|
43
|
+
KeyedStatus = Arel::Table.new(:sys_keyed_service_status)
|
|
44
|
+
Service = Arel::Table.new(:sys_service)
|
|
45
|
+
Deployment = Arel::Table.new(:sys_deployment)
|
|
46
|
+
Idempotency = Arel::Table.new(:sys_idempotency)
|
|
47
|
+
Promise = Arel::Table.new(:sys_promise)
|
|
48
|
+
State = Arel::Table.new(:state)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Minimal quoting adapter for Arel's ToSql visitor. Emits ANSI SQL
|
|
52
|
+
# (double-quoted identifiers, single-quoted strings) which DataFusion expects.
|
|
53
|
+
# Allows Arel query generation without an ActiveRecord database connection.
|
|
54
|
+
#
|
|
55
|
+
# @!visibility private
|
|
56
|
+
class DataFusionQuoting
|
|
57
|
+
def quote_table_name(name)
|
|
58
|
+
"\"#{name}\""
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def quote_column_name(name)
|
|
62
|
+
"\"#{name}\""
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def quote(value)
|
|
66
|
+
case value
|
|
67
|
+
when String then "'#{value.gsub("'", "''")}'"
|
|
68
|
+
when nil then 'NULL'
|
|
69
|
+
when true then 'TRUE'
|
|
70
|
+
when false then 'FALSE'
|
|
71
|
+
else value.to_s
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def schema_cache
|
|
76
|
+
self
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def columns_hash(_table)
|
|
80
|
+
{}
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def data_source_exists?(_table)
|
|
84
|
+
true
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Arel visitor that generates ANSI SQL compatible with DataFusion.
|
|
89
|
+
# Uses DataFusionQuoting for identifier/value quoting without requiring
|
|
90
|
+
# a live database connection.
|
|
91
|
+
#
|
|
92
|
+
# @!visibility private
|
|
93
|
+
class DataFusionVisitor < Arel::Visitors::ToSql
|
|
94
|
+
def initialize
|
|
95
|
+
super(DataFusionQuoting.new)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
class << self
|
|
100
|
+
# Convert an Arel AST to a SQL string without requiring an AR connection.
|
|
101
|
+
# Uses a standalone visitor that emits ANSI SQL (DataFusion-compatible).
|
|
102
|
+
#
|
|
103
|
+
# @param arel [Arel::SelectManager] an Arel query
|
|
104
|
+
# @return [String] SQL string
|
|
105
|
+
def arel_to_sql(arel)
|
|
106
|
+
collector = Arel::Collectors::SQLString.new
|
|
107
|
+
DataFusionVisitor.new.accept(arel.ast, collector).value
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Execute an Arel query or raw SQL string against the Restate admin
|
|
111
|
+
# introspection API. Returns an array of row hashes.
|
|
112
|
+
#
|
|
113
|
+
# @param arel_or_sql [Arel::SelectManager, String] an Arel query or raw SQL
|
|
114
|
+
# @return [Array<Hash>] rows returned by Restate
|
|
115
|
+
#
|
|
116
|
+
# @example With Arel
|
|
117
|
+
# i = Restate::Sys::Invocation
|
|
118
|
+
# Restate.query(i.project(Arel.star).take(10))
|
|
119
|
+
#
|
|
120
|
+
# @example With raw SQL
|
|
121
|
+
# Restate.query("SELECT id, status FROM sys_invocation LIMIT 10")
|
|
122
|
+
def query(arel_or_sql)
|
|
123
|
+
sql = arel_or_sql.respond_to?(:ast) ? arel_to_sql(arel_or_sql) : arel_or_sql.to_s
|
|
124
|
+
client.execute_query(sql)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# typed: false
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Restate
|
|
5
|
+
# Rails integration for the Restate SDK. Automatically loads the
|
|
6
|
+
# introspection module which provides Arel-based query support for
|
|
7
|
+
# Restate's SQL introspection API (powered by DataFusion).
|
|
8
|
+
#
|
|
9
|
+
# When Rails is present, +Restate::Sys+ table constants become available
|
|
10
|
+
# for building type-safe, composable queries against system tables like
|
|
11
|
+
# +sys_invocation+, +sys_journal+, and +state+.
|
|
12
|
+
class Railtie < Rails::Railtie
|
|
13
|
+
initializer 'restate.introspection' do
|
|
14
|
+
require_relative 'introspection'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/restate/version.rb
CHANGED
data/lib/restate.rb
CHANGED
|
@@ -18,6 +18,7 @@ require_relative 'restate/endpoint'
|
|
|
18
18
|
require_relative 'restate/service_proxy'
|
|
19
19
|
require_relative 'restate/config'
|
|
20
20
|
require_relative 'restate/client'
|
|
21
|
+
require_relative 'restate/railtie' if defined?(Rails::Railtie)
|
|
21
22
|
|
|
22
23
|
# Restate Ruby SDK — build resilient applications with durable execution.
|
|
23
24
|
#
|
data/sig/restate.rbs
CHANGED
|
@@ -8,6 +8,8 @@ module Restate
|
|
|
8
8
|
def self.configure: () { (Config) -> void } -> void
|
|
9
9
|
def self.config: () -> Config
|
|
10
10
|
def self.client: () -> Client
|
|
11
|
+
def self.query: (untyped arel_or_sql) -> Array[Hash[String, untyped]]
|
|
12
|
+
def self.arel_to_sql: (untyped arel) -> String
|
|
11
13
|
|
|
12
14
|
# ── Durable execution ──
|
|
13
15
|
|
|
@@ -118,6 +120,7 @@ module Restate
|
|
|
118
120
|
def reject_awakeable: (String awakeable_id, String message, ?code: Integer) -> void
|
|
119
121
|
def cancel_invocation: (String invocation_id) -> void
|
|
120
122
|
def kill_invocation: (String invocation_id) -> void
|
|
123
|
+
def execute_query: (String sql) -> Array[Hash[String, untyped]]
|
|
121
124
|
|
|
122
125
|
private
|
|
123
126
|
|
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.10.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Restate Developers
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-05-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: async
|
|
@@ -63,6 +63,8 @@ files:
|
|
|
63
63
|
- lib/restate/endpoint.rb
|
|
64
64
|
- lib/restate/errors.rb
|
|
65
65
|
- lib/restate/handler.rb
|
|
66
|
+
- lib/restate/introspection.rb
|
|
67
|
+
- lib/restate/railtie.rb
|
|
66
68
|
- lib/restate/serde.rb
|
|
67
69
|
- lib/restate/server.rb
|
|
68
70
|
- lib/restate/server_context.rb
|