prosody 0.5.1 → 0.6.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/.config/rail.toml +26 -0
- data/.release-please-manifest.json +1 -1
- data/.ruby-version +1 -1
- data/.taplo.toml +1 -1
- data/AGENTS.md +29 -15
- data/CHANGELOG.md +7 -0
- data/CONFIGURATION.md +19 -16
- data/Cargo.lock +254 -235
- data/Cargo.toml +11 -8
- data/README.md +100 -23
- data/examples/keyed_state.rb +10 -2
- data/examples/keyed_state.rbs +1 -0
- data/ext/prosody/Cargo.toml +1 -1
- data/ext/prosody/src/admin.rs +36 -36
- data/ext/prosody/src/bridge/mod.rs +5 -10
- data/ext/prosody/src/client/config/connections.rs +170 -0
- data/ext/prosody/src/client/config/middleware.rs +184 -0
- data/ext/prosody/src/client/config/mod.rs +396 -0
- data/ext/prosody/src/client/config/state.rs +323 -0
- data/ext/prosody/src/client/mod.rs +31 -117
- data/ext/prosody/src/client/readers.rs +106 -0
- data/ext/prosody/src/client/request.rs +2 -2
- data/ext/prosody/src/client/support.rs +13 -32
- data/ext/prosody/src/gvl.rs +8 -6
- data/ext/prosody/src/handler/{context.rs → context/mod.rs} +36 -150
- data/ext/prosody/src/handler/context/vending.rs +138 -0
- data/ext/prosody/src/handler/message.rs +36 -0
- data/ext/prosody/src/handler/mod.rs +18 -8
- data/ext/prosody/src/handler/state/deque.rs +144 -0
- data/ext/prosody/src/handler/state/mod.rs +163 -268
- data/ext/prosody/src/handler/state/query.rs +264 -0
- data/ext/prosody/src/handler/state/registration.rs +15 -86
- data/ext/prosody/src/handler/state/scan.rs +33 -141
- data/ext/prosody/src/handler/state/set.rs +98 -0
- data/ext/prosody/src/lib.rs +54 -36
- data/ext/prosody/src/logging.rs +6 -6
- data/ext/prosody/src/published.rs +171 -152
- data/ext/prosody/src/scheduler/result.rs +2 -1
- data/ext/prosody/src/util.rs +65 -3
- data/lib/prosody/client.rb +32 -0
- data/lib/prosody/configuration.rb +20 -12
- data/lib/prosody/demand.rb +27 -0
- data/lib/prosody/native_stubs/client.rb +157 -0
- data/lib/prosody/native_stubs/context.rb +178 -0
- data/lib/prosody/native_stubs/message.rb +133 -0
- data/lib/prosody/native_stubs.rb +11 -956
- data/lib/prosody/state/deque.rb +253 -0
- data/lib/prosody/state/map.rb +313 -0
- data/lib/prosody/state/set.rb +121 -0
- data/lib/prosody/state/value.rb +58 -0
- data/lib/prosody/state.rb +157 -677
- data/lib/prosody/version.rb +1 -1
- data/lib/prosody.rb +2 -1
- data/sig/configuration.rbs +19 -10
- data/sig/prosody.rbs +37 -4
- data/sig/published.rbs +102 -0
- data/sig/state.rbs +109 -122
- data/typecheck/payload_types.rb +12 -0
- data/typecheck/payload_types.rbs +1 -0
- metadata +30 -11
- data/ext/prosody/src/client/config.rs +0 -1300
data/sig/state.rbs
CHANGED
|
@@ -1,43 +1,38 @@
|
|
|
1
1
|
module Prosody
|
|
2
2
|
type state_config_value = String | Integer | bool
|
|
3
3
|
|
|
4
|
+
# The effect of commit or rollback: :applied when buffered operations were
|
|
5
|
+
# drained, :no_op when nothing was buffered.
|
|
6
|
+
type store_outcome = :applied | :no_op
|
|
7
|
+
|
|
8
|
+
# Query keywords as the traversal methods collect them.
|
|
9
|
+
type query_options = Hash[Symbol, String | Integer | Range[String?] | Range[Integer?] | nil]
|
|
10
|
+
|
|
4
11
|
# --- error taxonomy -----------------------------------------------------
|
|
5
12
|
# Raised for keyed-state failures a retry cannot resolve (unregistered
|
|
6
|
-
# collection, identity mismatch, duplicate registration, bad TTL
|
|
13
|
+
# collection, identity mismatch, duplicate registration, bad TTL, JSON null
|
|
14
|
+
# write; use clear/delete to remove a value). Never
|
|
7
15
|
# Terminal: core folds Terminal into Transient.
|
|
8
16
|
class PermanentStateError < PermanentError
|
|
9
17
|
end
|
|
10
18
|
|
|
11
19
|
# Raised for keyed-state failures that may succeed on retry, plus every
|
|
12
|
-
# caller mistake
|
|
13
|
-
# direction). Never Terminal.
|
|
20
|
+
# caller mistake the client detects (wrong item shape, invalid index,
|
|
21
|
+
# invalid direction). Never Terminal.
|
|
14
22
|
class TransientStateError < TransientError
|
|
15
23
|
end
|
|
16
24
|
|
|
17
|
-
# Raised when a JSON null is written to a collection. Null is not storable
|
|
18
|
-
# (indistinguishable from absence); use clear/delete instead.
|
|
19
|
-
class NullValueError < TransientStateError
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
class StateAccess < Data
|
|
23
|
-
attr_reader vend_method: Symbol
|
|
24
|
-
attr_reader wrapper: Symbol
|
|
25
|
-
attr_reader published_vend_method: Symbol?
|
|
26
|
-
attr_reader published_wrapper: Symbol?
|
|
27
|
-
end
|
|
28
|
-
|
|
29
25
|
# Concrete immutable definition object returned by the constructor helpers.
|
|
30
26
|
class StateDefinition < Data
|
|
31
27
|
attr_reader name: String
|
|
32
28
|
attr_reader kind: String
|
|
33
|
-
attr_reader payload: String
|
|
29
|
+
attr_reader payload: String?
|
|
34
30
|
attr_reader ttl_seconds: Integer?
|
|
35
31
|
attr_reader read_uncommitted: bool?
|
|
36
32
|
attr_reader published: bool?
|
|
37
33
|
attr_reader read_cache: (Numeric | false)?
|
|
38
34
|
attr_reader keyset_limit: Integer?
|
|
39
35
|
attr_reader capacity: Integer?
|
|
40
|
-
attr_reader access: StateAccess
|
|
41
36
|
|
|
42
37
|
def to_state_config: () -> Hash[Symbol, state_config_value]
|
|
43
38
|
end
|
|
@@ -61,6 +56,14 @@ module Prosody
|
|
|
61
56
|
def to_state_config: () -> Hash[Symbol, state_config_value]
|
|
62
57
|
end
|
|
63
58
|
|
|
59
|
+
interface _SetDefinition
|
|
60
|
+
def name: () -> String
|
|
61
|
+
def kind: () -> "set"
|
|
62
|
+
def payload: () -> nil
|
|
63
|
+
def read_cache: () -> (Numeric | false)?
|
|
64
|
+
def to_state_config: () -> Hash[Symbol, state_config_value]
|
|
65
|
+
end
|
|
66
|
+
|
|
64
67
|
interface _DequeDefinition[T = json_value]
|
|
65
68
|
def name: () -> String
|
|
66
69
|
def kind: () -> "deque"
|
|
@@ -96,6 +99,7 @@ module Prosody
|
|
|
96
99
|
# `[P]` type parameter is annotation-only, naming the message payload type.
|
|
97
100
|
def self.value: [T] (_ToS name, ?ttl: Integer?, ?read_uncommitted: bool?, ?published: bool?, ?read_cache: (Numeric | false)?) -> _ValueDefinition[T]
|
|
98
101
|
def self.map: [V] (_ToS name, ?ttl: Integer?, ?keyset_limit: Integer?, ?read_uncommitted: bool?, ?published: bool?, ?read_cache: (Numeric | false)?) -> _MapDefinition[V]
|
|
102
|
+
def self.set: (_ToS name, ?ttl: Integer?, ?keyset_limit: Integer?, ?read_uncommitted: bool?, ?published: bool?, ?read_cache: (Numeric | false)?) -> _SetDefinition
|
|
99
103
|
def self.deque: [T] (_ToS name, ?ttl: Integer?, ?capacity: Integer?, ?read_uncommitted: bool?, ?published: bool?, ?read_cache: (Numeric | false)?) -> _DequeDefinition[T]
|
|
100
104
|
def self.message_value: [P] (_ToS name, ?ttl: Integer?, ?read_uncommitted: bool?) -> _MessageValueDefinition[P]
|
|
101
105
|
def self.message_map: [P] (_ToS name, ?ttl: Integer?, ?keyset_limit: Integer?, ?read_uncommitted: bool?) -> _MessageMapDefinition[P]
|
|
@@ -104,12 +108,10 @@ module Prosody
|
|
|
104
108
|
# --- handles ------------------------------------------------------------
|
|
105
109
|
# A single-value keyed-state handle. Reads return the stored value or nil.
|
|
106
110
|
# Every op is fiber-yield async: it looks blocking but never blocks the thread.
|
|
107
|
-
class ValueState[T = json_value]
|
|
111
|
+
class ValueState[T = json_value] < State::Handle
|
|
108
112
|
def get: () -> T?
|
|
109
113
|
def set: (T value) -> void
|
|
110
114
|
def clear: () -> void
|
|
111
|
-
def commit: () -> nil
|
|
112
|
-
def rollback: () -> nil
|
|
113
115
|
|
|
114
116
|
# idiomatic conveniences
|
|
115
117
|
def value: () -> T? # alias of #get
|
|
@@ -120,35 +122,36 @@ module Prosody
|
|
|
120
122
|
end
|
|
121
123
|
|
|
122
124
|
# A String-keyed ordered-map keyed-state handle.
|
|
123
|
-
class MapState[V = json_value]
|
|
125
|
+
class MapState[V = json_value] < State::Handle
|
|
124
126
|
include State::Scanning
|
|
125
127
|
|
|
126
128
|
def get: (String key) -> V?
|
|
127
129
|
def get_many: (Array[String] keys) -> Array[V?]
|
|
130
|
+
def contains_many: (Array[String] keys) -> Array[bool]
|
|
131
|
+
def empty?: () -> bool
|
|
128
132
|
def set: (String key, V value) -> void
|
|
129
133
|
def delete: (String key) -> nil
|
|
130
134
|
def clear: () -> void
|
|
131
|
-
|
|
132
|
-
def
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
| () -> Enumerator[V, void]
|
|
135
|
+
# Traversals accept optional query keywords (see State::Scanning).
|
|
136
|
+
def each_pair: (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) { ([String, V]) -> void } -> void
|
|
137
|
+
| (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) -> Enumerator[[ String, V ], void]
|
|
138
|
+
def reverse_each_pair: (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) { ([String, V]) -> void } -> void
|
|
139
|
+
| (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) -> Enumerator[[ String, V ], void]
|
|
140
|
+
def each_key: (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) { (String) -> void } -> void
|
|
141
|
+
| (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) -> Enumerator[String, void]
|
|
142
|
+
def reverse_each_key: (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) { (String) -> void } -> void
|
|
143
|
+
| (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) -> Enumerator[String, void]
|
|
144
|
+
def each_value: (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) { (V) -> void } -> void
|
|
145
|
+
| (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) -> Enumerator[V, void]
|
|
146
|
+
def reverse_each_value: (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) { (V) -> void } -> void
|
|
147
|
+
| (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) -> Enumerator[V, void]
|
|
145
148
|
|
|
146
149
|
# idiomatic Hash-style conveniences (bounded reads only)
|
|
147
150
|
def []: (String key) -> V? # alias of #get
|
|
148
151
|
def []=: (String key, V value) -> V # alias of #set (assignment yields value)
|
|
149
152
|
def store: (String key, V value) -> V # wrapper over #set, returns value
|
|
150
|
-
def each: () { (String, V) -> void } -> void # alias of #each_pair
|
|
151
|
-
| () -> Enumerator[[ String, V ], void]
|
|
153
|
+
def each: (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) { ([String, V]) -> void } -> void # alias of #each_pair
|
|
154
|
+
| (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) -> Enumerator[[ String, V ], void]
|
|
152
155
|
def values_at: (*String keys) -> Array[V?]
|
|
153
156
|
def fetch: (String key) -> V
|
|
154
157
|
| [D] (String key, D default) -> (V | D)
|
|
@@ -164,14 +167,32 @@ module Prosody
|
|
|
164
167
|
|
|
165
168
|
private
|
|
166
169
|
def initialize: ((NativeJsonMapState | NativeMessageMapState) native) -> void
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# A presence-only ordered set of String members. Mirrors Ruby's Set.
|
|
173
|
+
class SetState < State::Handle
|
|
174
|
+
include State::Scanning
|
|
175
|
+
|
|
176
|
+
def add: (String member) -> self
|
|
177
|
+
def <<: (String member) -> self
|
|
178
|
+
def delete: (String member) -> self
|
|
179
|
+
def include?: (String member) -> bool
|
|
180
|
+
def member?: (String member) -> bool
|
|
181
|
+
def contains_many: (Array[String] members) -> Array[bool]
|
|
182
|
+
def empty?: () -> bool
|
|
183
|
+
def clear: () -> self
|
|
184
|
+
# Traversals accept optional query keywords (see State::Scanning).
|
|
185
|
+
def each: (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) { (String) -> void } -> void
|
|
186
|
+
| (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) -> Enumerator[String, void]
|
|
187
|
+
def reverse_each: (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) { (String) -> void } -> void
|
|
188
|
+
| (?from: String?, ?after: String?, ?to: String?, ?before: String?, ?range: Range[String?]?, ?prefix: String?, ?limit: Integer?) -> Enumerator[String, void]
|
|
189
|
+
|
|
190
|
+
private
|
|
191
|
+
def initialize: (NativeSetState native) -> void
|
|
171
192
|
end
|
|
172
193
|
|
|
173
194
|
# A deque keyed-state handle.
|
|
174
|
-
class DequeState[T = json_value]
|
|
195
|
+
class DequeState[T = json_value] < State::Handle
|
|
175
196
|
include State::Scanning
|
|
176
197
|
|
|
177
198
|
def push: (T value) -> void
|
|
@@ -182,13 +203,12 @@ module Prosody
|
|
|
182
203
|
def size: () -> Integer
|
|
183
204
|
def empty?: () -> bool
|
|
184
205
|
def clear: () -> void
|
|
185
|
-
def commit: () -> nil
|
|
186
|
-
def rollback: () -> nil
|
|
187
206
|
def get: (Integer index) -> T?
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
207
|
+
# Traversals accept optional position keywords (see State::Scanning).
|
|
208
|
+
def each: (?from: Integer?, ?after: Integer?, ?to: Integer?, ?before: Integer?, ?range: Range[Integer?]?, ?limit: Integer?) { (T) -> void } -> void
|
|
209
|
+
| (?from: Integer?, ?after: Integer?, ?to: Integer?, ?before: Integer?, ?range: Range[Integer?]?, ?limit: Integer?) -> Enumerator[T, void]
|
|
210
|
+
def reverse_each: (?from: Integer?, ?after: Integer?, ?to: Integer?, ?before: Integer?, ?range: Range[Integer?]?, ?limit: Integer?) { (T) -> void } -> void
|
|
211
|
+
| (?from: Integer?, ?after: Integer?, ?to: Integer?, ?before: Integer?, ?range: Range[Integer?]?, ?limit: Integer?) -> Enumerator[T, void]
|
|
192
212
|
|
|
193
213
|
# idiomatic Array-style conveniences (bounded reads only). #get and #fetch
|
|
194
214
|
# take a single Integer index (negatives resolve from the back, Array-style);
|
|
@@ -206,16 +226,14 @@ module Prosody
|
|
|
206
226
|
private
|
|
207
227
|
def initialize: ((NativeJsonDequeState | NativeMessageDequeState) native) -> void
|
|
208
228
|
def at_negative: (Integer index) -> T?
|
|
209
|
-
def traverse: (Symbol direction) { (T) -> void } -> void
|
|
210
|
-
| (Symbol direction) -> Enumerator[T, void]
|
|
211
229
|
end
|
|
212
230
|
|
|
213
231
|
interface _NativeValueHandle[T]
|
|
214
232
|
def get: () -> T?
|
|
215
233
|
def set: (T value) -> void
|
|
216
234
|
def clear: () -> void
|
|
217
|
-
def commit: () ->
|
|
218
|
-
def rollback: () ->
|
|
235
|
+
def commit: () -> store_outcome
|
|
236
|
+
def rollback: () -> store_outcome
|
|
219
237
|
end
|
|
220
238
|
|
|
221
239
|
class NativeJsonValueState
|
|
@@ -229,14 +247,16 @@ module Prosody
|
|
|
229
247
|
interface _NativeMapHandle[V, S]
|
|
230
248
|
def get: (String key) -> V?
|
|
231
249
|
def contains_key: (String key) -> bool
|
|
250
|
+
def is_empty: () -> bool
|
|
232
251
|
def get_many: (Array[String] keys) -> Array[V?]
|
|
252
|
+
def contains_many: (Array[String] keys) -> Array[bool]
|
|
233
253
|
def set: (String key, V value) -> void
|
|
234
254
|
def remove: (String key) -> void
|
|
235
255
|
def clear: () -> void
|
|
236
|
-
def scan: (Symbol direction) -> S
|
|
237
|
-
def keys: (Symbol direction) -> NativeMapKeyScan
|
|
238
|
-
def commit: () ->
|
|
239
|
-
def rollback: () ->
|
|
256
|
+
def scan: (Symbol direction, query_options query) -> S
|
|
257
|
+
def keys: (Symbol direction, query_options query) -> NativeMapKeyScan
|
|
258
|
+
def commit: () -> store_outcome
|
|
259
|
+
def rollback: () -> store_outcome
|
|
240
260
|
end
|
|
241
261
|
|
|
242
262
|
class NativeJsonMapState
|
|
@@ -247,6 +267,18 @@ module Prosody
|
|
|
247
267
|
include _NativeMapHandle[Message[json_value], NativeMessageMapScan]
|
|
248
268
|
end
|
|
249
269
|
|
|
270
|
+
class NativeSetState
|
|
271
|
+
def contains: (String member) -> bool
|
|
272
|
+
def contains_many: (Array[String] members) -> Array[bool]
|
|
273
|
+
def is_empty: () -> bool
|
|
274
|
+
def insert: (String member) -> void
|
|
275
|
+
def remove: (String member) -> void
|
|
276
|
+
def clear: () -> void
|
|
277
|
+
def keys: (Symbol direction, query_options query) -> NativeMapKeyScan
|
|
278
|
+
def commit: () -> store_outcome
|
|
279
|
+
def rollback: () -> store_outcome
|
|
280
|
+
end
|
|
281
|
+
|
|
250
282
|
interface _NativeDequeHandle[T, S]
|
|
251
283
|
def len: () -> Integer
|
|
252
284
|
def is_empty: () -> bool
|
|
@@ -258,9 +290,9 @@ module Prosody
|
|
|
258
290
|
def pop_front: () -> T?
|
|
259
291
|
def pop_back: () -> T?
|
|
260
292
|
def clear: () -> void
|
|
261
|
-
def scan: (Symbol direction) -> S
|
|
262
|
-
def commit: () ->
|
|
263
|
-
def rollback: () ->
|
|
293
|
+
def scan: (Symbol direction, query_options query) -> S
|
|
294
|
+
def commit: () -> store_outcome
|
|
295
|
+
def rollback: () -> store_outcome
|
|
264
296
|
end
|
|
265
297
|
|
|
266
298
|
class NativeJsonDequeState
|
|
@@ -272,7 +304,7 @@ module Prosody
|
|
|
272
304
|
end
|
|
273
305
|
|
|
274
306
|
interface _NativeScan[T]
|
|
275
|
-
def
|
|
307
|
+
def next_chunk: () -> Array[T]?
|
|
276
308
|
def close: () -> void
|
|
277
309
|
end
|
|
278
310
|
|
|
@@ -296,72 +328,19 @@ module Prosody
|
|
|
296
328
|
include _NativeScan[String]
|
|
297
329
|
end
|
|
298
330
|
|
|
299
|
-
class NativePublishedValue
|
|
300
|
-
def get: (String key) -> json_value?
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
class NativePublishedMap
|
|
304
|
-
def get: (String key, String map_key) -> json_value?
|
|
305
|
-
def get_many: (String key, Array[String] map_keys) -> Array[json_value?]
|
|
306
|
-
def contains_key: (String key, String map_key) -> bool
|
|
307
|
-
def scan: (String key, Symbol direction) -> NativeJsonMapScan
|
|
308
|
-
def keys: (String key, Symbol direction) -> NativeMapKeyScan
|
|
309
|
-
end
|
|
310
|
-
|
|
311
|
-
class NativePublishedDeque
|
|
312
|
-
def get: (String key, Integer index) -> json_value?
|
|
313
|
-
def length: (String key) -> Integer
|
|
314
|
-
def is_empty: (String key) -> bool
|
|
315
|
-
def peek_front: (String key) -> json_value?
|
|
316
|
-
def peek_back: (String key) -> json_value?
|
|
317
|
-
def scan: (String key, Symbol direction) -> NativeJsonDequeScan
|
|
318
|
-
end
|
|
319
|
-
|
|
320
|
-
class PublishedValue[T = json_value]
|
|
321
|
-
def get: (_ToS key) -> T?
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
class PublishedMap[V = json_value]
|
|
325
|
-
def get: (_ToS key, _ToS map_key) -> V?
|
|
326
|
-
def get_many: (_ToS key, Array[_ToS] map_keys) -> Array[V?]
|
|
327
|
-
def key?: (_ToS key, _ToS map_key) -> bool
|
|
328
|
-
alias has_key? key?
|
|
329
|
-
alias include? key?
|
|
330
|
-
alias member? key?
|
|
331
|
-
def each_pair: (_ToS key) { (String, V) -> void } -> void
|
|
332
|
-
| (_ToS key) -> Enumerator[[String, V], void]
|
|
333
|
-
def reverse_each_pair: (_ToS key) { (String, V) -> void } -> void
|
|
334
|
-
| (_ToS key) -> Enumerator[[String, V], void]
|
|
335
|
-
def each_key: (_ToS key) { (String) -> void } -> void
|
|
336
|
-
| (_ToS key) -> Enumerator[String, void]
|
|
337
|
-
def reverse_each_key: (_ToS key) { (String) -> void } -> void
|
|
338
|
-
| (_ToS key) -> Enumerator[String, void]
|
|
339
|
-
def each_value: (_ToS key) { (V) -> void } -> void
|
|
340
|
-
| (_ToS key) -> Enumerator[V, void]
|
|
341
|
-
def reverse_each_value: (_ToS key) { (V) -> void } -> void
|
|
342
|
-
| (_ToS key) -> Enumerator[V, void]
|
|
343
|
-
alias each each_pair
|
|
344
|
-
end
|
|
345
|
-
|
|
346
|
-
class PublishedDeque[T = json_value]
|
|
347
|
-
def get: (_ToS key, Integer index) -> T?
|
|
348
|
-
def length: (_ToS key) -> Integer
|
|
349
|
-
alias size length
|
|
350
|
-
def empty?: (_ToS key) -> bool
|
|
351
|
-
def first: (_ToS key) -> T?
|
|
352
|
-
def last: (_ToS key) -> T?
|
|
353
|
-
def each: (_ToS key) { (T) -> void } -> void
|
|
354
|
-
| (_ToS key) -> Enumerator[T, void]
|
|
355
|
-
def reverse_each: (_ToS key) { (T) -> void } -> void
|
|
356
|
-
| (_ToS key) -> Enumerator[T, void]
|
|
357
|
-
end
|
|
358
|
-
|
|
359
331
|
# --- shared state modules ------------------------------------------------
|
|
360
332
|
module State
|
|
333
|
+
# The base class of the owned handles.
|
|
334
|
+
class Handle
|
|
335
|
+
def commit: () -> store_outcome
|
|
336
|
+
def rollback: () -> store_outcome
|
|
337
|
+
end
|
|
338
|
+
|
|
361
339
|
# Adds keyed-state vending to the native context.
|
|
362
340
|
module Vending
|
|
363
341
|
def state: [T] (_ValueDefinition[T]) -> ValueState[T]
|
|
364
342
|
| [V] (_MapDefinition[V]) -> MapState[V]
|
|
343
|
+
| (_SetDefinition) -> SetState
|
|
365
344
|
| [T] (_DequeDefinition[T]) -> DequeState[T]
|
|
366
345
|
| [P] (_MessageValueDefinition[P]) -> ValueState[Message[P]]
|
|
367
346
|
| [P] (_MessageMapDefinition[P]) -> MapState[Message[P]]
|
|
@@ -369,10 +348,15 @@ module Prosody
|
|
|
369
348
|
end
|
|
370
349
|
|
|
371
350
|
# Shared native-scan driving mixed into the traversal handles.
|
|
351
|
+
# Query keywords apply in iteration order and narrow the selection. Map
|
|
352
|
+
# and set traversals take String keys and `prefix:`. Deque traversals take
|
|
353
|
+
# non-negative positions from the front.
|
|
372
354
|
module Scanning
|
|
373
355
|
private
|
|
374
|
-
def
|
|
375
|
-
|
|
356
|
+
def traverse: (Symbol opener, *untyped args) { (untyped) -> void } -> void
|
|
357
|
+
| (Symbol opener, *untyped args) -> Enumerator[untyped, void]
|
|
358
|
+
def traverse_values: (*untyped args) { (untyped) -> void } -> void
|
|
359
|
+
| (*untyped args) -> Enumerator[untyped, void]
|
|
376
360
|
end
|
|
377
361
|
end
|
|
378
362
|
|
|
@@ -380,8 +364,11 @@ module Prosody
|
|
|
380
364
|
class Context
|
|
381
365
|
include State::Vending
|
|
382
366
|
|
|
367
|
+
private
|
|
368
|
+
|
|
383
369
|
def value_state: (String name) -> NativeJsonValueState
|
|
384
370
|
def map_state: (String name) -> NativeJsonMapState
|
|
371
|
+
def set_state: (String name) -> NativeSetState
|
|
385
372
|
def deque_state: (String name) -> NativeJsonDequeState
|
|
386
373
|
def message_value_state: (String name) -> NativeMessageValueState
|
|
387
374
|
def message_map_state: (String name) -> NativeMessageMapState
|
data/typecheck/payload_types.rb
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
ORDER_BACKLOG = Prosody.message_deque("order-backlog")
|
|
7
7
|
ORDER_TOTALS = Prosody.map("order-totals")
|
|
8
|
+
ORDER_IDS = Prosody.set("order-ids")
|
|
8
9
|
|
|
9
10
|
class TypedOrderHandler < Prosody::EventHandler
|
|
10
11
|
def on_excise(_context, message)
|
|
@@ -15,17 +16,25 @@ class TypedOrderHandler < Prosody::EventHandler
|
|
|
15
16
|
def on_message(context, message)
|
|
16
17
|
payload = message.payload
|
|
17
18
|
order_id = payload["order_id"]
|
|
19
|
+
demand = context.demand
|
|
20
|
+
consume_order(order_id, demand.retries) if demand.failure?
|
|
18
21
|
total = payload["total"]
|
|
19
22
|
|
|
20
23
|
# Message-backed state preserves the handler's payload type.
|
|
21
24
|
backlog = context.state(ORDER_BACKLOG)
|
|
22
25
|
backlog.push(message)
|
|
23
26
|
oldest = backlog.first
|
|
27
|
+
backlog.reverse_each(range: 0..9, limit: 2) { |pending| pending.payload["order_id"].upcase }
|
|
24
28
|
|
|
25
29
|
# This call is a regression constraint: state(ORDER_TOTALS) must infer as
|
|
26
30
|
# MapState[Integer], not untyped or a generic JSON-valued state handle.
|
|
27
31
|
consume_totals(context.state(ORDER_TOTALS))
|
|
28
32
|
|
|
33
|
+
# A set handle takes and yields String members.
|
|
34
|
+
order_ids = context.state(ORDER_IDS)
|
|
35
|
+
order_ids << order_id unless order_ids.include?(order_id)
|
|
36
|
+
order_ids.each(prefix: "order-", limit: 5) { |id| id.upcase }
|
|
37
|
+
|
|
29
38
|
consume_order(order_id, total)
|
|
30
39
|
oldest_payload = oldest&.payload
|
|
31
40
|
consume_order(oldest_payload["order_id"], oldest_payload["total"]) if oldest_payload
|
|
@@ -43,6 +52,9 @@ class TypedOrderHandler < Prosody::EventHandler
|
|
|
43
52
|
|
|
44
53
|
def consume_totals(totals)
|
|
45
54
|
totals.set("latest", 1)
|
|
55
|
+
# Query keywords keep the item types.
|
|
56
|
+
totals.each_key(prefix: "order:", after: "order:1", limit: 10) { |key| key.upcase }
|
|
57
|
+
totals.reverse_each_value(range: "a"..."m").each { |total| total + 1 }
|
|
46
58
|
nil
|
|
47
59
|
end
|
|
48
60
|
end
|
data/typecheck/payload_types.rbs
CHANGED
|
@@ -6,6 +6,7 @@ type handler_response = { "accepted" => bool }
|
|
|
6
6
|
|
|
7
7
|
ORDER_BACKLOG: Prosody::_MessageDequeDefinition[order_event]
|
|
8
8
|
ORDER_TOTALS: Prosody::_MapDefinition[Integer]
|
|
9
|
+
ORDER_IDS: Prosody::_SetDefinition
|
|
9
10
|
|
|
10
11
|
class TypedOrderHandler < Prosody::EventHandler[order_event, handler_response]
|
|
11
12
|
def on_message: (Prosody::Context context, Prosody::Message[order_event] message) -> handler_response
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: prosody
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joshua Griffith
|
|
@@ -43,14 +43,14 @@ dependencies:
|
|
|
43
43
|
requirements:
|
|
44
44
|
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: 0.9.
|
|
46
|
+
version: 0.9.130
|
|
47
47
|
type: :runtime
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: 0.9.
|
|
53
|
+
version: 0.9.130
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
55
|
name: async-rspec
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -71,42 +71,42 @@ dependencies:
|
|
|
71
71
|
requirements:
|
|
72
72
|
- - "~>"
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
|
-
version: '1.
|
|
74
|
+
version: '1.13'
|
|
75
75
|
type: :development
|
|
76
76
|
prerelease: false
|
|
77
77
|
version_requirements: !ruby/object:Gem::Requirement
|
|
78
78
|
requirements:
|
|
79
79
|
- - "~>"
|
|
80
80
|
- !ruby/object:Gem::Version
|
|
81
|
-
version: '1.
|
|
81
|
+
version: '1.13'
|
|
82
82
|
- !ruby/object:Gem::Dependency
|
|
83
83
|
name: opentelemetry-exporter-otlp
|
|
84
84
|
requirement: !ruby/object:Gem::Requirement
|
|
85
85
|
requirements:
|
|
86
86
|
- - "~>"
|
|
87
87
|
- !ruby/object:Gem::Version
|
|
88
|
-
version: '0.
|
|
88
|
+
version: '0.37'
|
|
89
89
|
type: :development
|
|
90
90
|
prerelease: false
|
|
91
91
|
version_requirements: !ruby/object:Gem::Requirement
|
|
92
92
|
requirements:
|
|
93
93
|
- - "~>"
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
|
-
version: '0.
|
|
95
|
+
version: '0.37'
|
|
96
96
|
- !ruby/object:Gem::Dependency
|
|
97
97
|
name: sentry-ruby
|
|
98
98
|
requirement: !ruby/object:Gem::Requirement
|
|
99
99
|
requirements:
|
|
100
100
|
- - "~>"
|
|
101
101
|
- !ruby/object:Gem::Version
|
|
102
|
-
version: '
|
|
102
|
+
version: '7.0'
|
|
103
103
|
type: :development
|
|
104
104
|
prerelease: false
|
|
105
105
|
version_requirements: !ruby/object:Gem::Requirement
|
|
106
106
|
requirements:
|
|
107
107
|
- - "~>"
|
|
108
108
|
- !ruby/object:Gem::Version
|
|
109
|
-
version: '
|
|
109
|
+
version: '7.0'
|
|
110
110
|
description: |
|
|
111
111
|
Prosody offers Ruby bindings to the Prosody Kafka client, providing features
|
|
112
112
|
for message production and consumption, including configurable retry
|
|
@@ -118,6 +118,7 @@ extensions:
|
|
|
118
118
|
extra_rdoc_files: []
|
|
119
119
|
files:
|
|
120
120
|
- ".cargo/config.toml"
|
|
121
|
+
- ".config/rail.toml"
|
|
121
122
|
- ".release-please-manifest.json"
|
|
122
123
|
- ".rspec"
|
|
123
124
|
- ".ruby-version"
|
|
@@ -144,17 +145,25 @@ files:
|
|
|
144
145
|
- ext/prosody/src/admin.rs
|
|
145
146
|
- ext/prosody/src/bridge/callback.rs
|
|
146
147
|
- ext/prosody/src/bridge/mod.rs
|
|
147
|
-
- ext/prosody/src/client/config.rs
|
|
148
|
+
- ext/prosody/src/client/config/connections.rs
|
|
149
|
+
- ext/prosody/src/client/config/middleware.rs
|
|
150
|
+
- ext/prosody/src/client/config/mod.rs
|
|
151
|
+
- ext/prosody/src/client/config/state.rs
|
|
148
152
|
- ext/prosody/src/client/mod.rs
|
|
153
|
+
- ext/prosody/src/client/readers.rs
|
|
149
154
|
- ext/prosody/src/client/request.rs
|
|
150
155
|
- ext/prosody/src/client/support.rs
|
|
151
156
|
- ext/prosody/src/gvl.rs
|
|
152
|
-
- ext/prosody/src/handler/context.rs
|
|
157
|
+
- ext/prosody/src/handler/context/mod.rs
|
|
158
|
+
- ext/prosody/src/handler/context/vending.rs
|
|
153
159
|
- ext/prosody/src/handler/message.rs
|
|
154
160
|
- ext/prosody/src/handler/mod.rs
|
|
161
|
+
- ext/prosody/src/handler/state/deque.rs
|
|
155
162
|
- ext/prosody/src/handler/state/mod.rs
|
|
163
|
+
- ext/prosody/src/handler/state/query.rs
|
|
156
164
|
- ext/prosody/src/handler/state/registration.rs
|
|
157
165
|
- ext/prosody/src/handler/state/scan.rs
|
|
166
|
+
- ext/prosody/src/handler/state/set.rs
|
|
158
167
|
- ext/prosody/src/handler/trigger.rs
|
|
159
168
|
- ext/prosody/src/lib.rs
|
|
160
169
|
- ext/prosody/src/logging.rs
|
|
@@ -167,19 +176,29 @@ files:
|
|
|
167
176
|
- ext/prosody/src/tracing_util.rs
|
|
168
177
|
- ext/prosody/src/util.rs
|
|
169
178
|
- lib/prosody.rb
|
|
179
|
+
- lib/prosody/client.rb
|
|
170
180
|
- lib/prosody/configuration.rb
|
|
181
|
+
- lib/prosody/demand.rb
|
|
171
182
|
- lib/prosody/handler.rb
|
|
172
183
|
- lib/prosody/native_stubs.rb
|
|
184
|
+
- lib/prosody/native_stubs/client.rb
|
|
185
|
+
- lib/prosody/native_stubs/context.rb
|
|
186
|
+
- lib/prosody/native_stubs/message.rb
|
|
173
187
|
- lib/prosody/processor.rb
|
|
174
188
|
- lib/prosody/request.rb
|
|
175
189
|
- lib/prosody/sentry.rb
|
|
176
190
|
- lib/prosody/state.rb
|
|
191
|
+
- lib/prosody/state/deque.rb
|
|
192
|
+
- lib/prosody/state/map.rb
|
|
193
|
+
- lib/prosody/state/set.rb
|
|
194
|
+
- lib/prosody/state/value.rb
|
|
177
195
|
- lib/prosody/version.rb
|
|
178
196
|
- release-please-config.json
|
|
179
197
|
- sig/configuration.rbs
|
|
180
198
|
- sig/handler.rbs
|
|
181
199
|
- sig/processor.rbs
|
|
182
200
|
- sig/prosody.rbs
|
|
201
|
+
- sig/published.rbs
|
|
183
202
|
- sig/request.rbs
|
|
184
203
|
- sig/sentry.rbs
|
|
185
204
|
- sig/state.rbs
|