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
|
@@ -14,52 +14,36 @@ use crate::ROOT_MOD;
|
|
|
14
14
|
use crate::bridge::Bridge;
|
|
15
15
|
use crate::handler::message::Message;
|
|
16
16
|
use crate::tracing_util::extract_opentelemetry_context;
|
|
17
|
-
use magnus::value::
|
|
18
|
-
use magnus::{
|
|
17
|
+
use magnus::value::ReprValue;
|
|
18
|
+
use magnus::{
|
|
19
|
+
Error, ExceptionClass, IntoValue, Module, RClass, RHash, RModule, Ruby, StaticSymbol,
|
|
20
|
+
TryConvert, Value, method,
|
|
21
|
+
};
|
|
19
22
|
use opentelemetry::propagation::TextMapCompositePropagator;
|
|
20
23
|
use opentelemetry::trace::FutureExt;
|
|
21
24
|
use prosody::consumer::event_context::{
|
|
22
|
-
|
|
25
|
+
DynMapState, DynValueState, ErasedCategory, ErasedStateError,
|
|
23
26
|
};
|
|
24
27
|
use prosody::consumer::message::ConsumerMessage;
|
|
25
|
-
use prosody::state::
|
|
28
|
+
use prosody::state::StoreOutcome;
|
|
26
29
|
use serde_json::Value as JsonValue;
|
|
27
30
|
use serde_magnus::{deserialize, serialize};
|
|
28
31
|
use std::sync::Arc;
|
|
29
32
|
use tracing::Span;
|
|
30
33
|
|
|
31
|
-
///
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
.const_get(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
clippy::expect_used,
|
|
45
|
-
reason = "mirrors bridge.rs QUEUE_CLASS Lazy pattern"
|
|
46
|
-
)]
|
|
47
|
-
static TRANSIENT_STATE_ERROR: Lazy<ExceptionClass> = Lazy::new(|ruby| {
|
|
48
|
-
ruby.get_inner(&ROOT_MOD)
|
|
49
|
-
.const_get("TransientStateError")
|
|
50
|
-
.expect("Prosody::TransientStateError")
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
/// Lazily resolved `Prosody::NullValueError` class (defined in Ruby).
|
|
54
|
-
#[allow(
|
|
55
|
-
clippy::expect_used,
|
|
56
|
-
reason = "mirrors bridge.rs QUEUE_CLASS Lazy pattern"
|
|
57
|
-
)]
|
|
58
|
-
static NULL_VALUE_ERROR: Lazy<ExceptionClass> = Lazy::new(|ruby| {
|
|
59
|
-
ruby.get_inner(&ROOT_MOD)
|
|
60
|
-
.const_get("NullValueError")
|
|
61
|
-
.expect("Prosody::NullValueError")
|
|
62
|
-
});
|
|
34
|
+
/// Builds an error of the Ruby-defined `Prosody::<class>` exception class.
|
|
35
|
+
///
|
|
36
|
+
/// A failed class lookup returns the lookup error in place of the state
|
|
37
|
+
/// error.
|
|
38
|
+
fn ruby_error(ruby: &Ruby, class: &str, message: String) -> Error {
|
|
39
|
+
match ruby
|
|
40
|
+
.get_inner(&ROOT_MOD)
|
|
41
|
+
.const_get::<_, ExceptionClass>(class)
|
|
42
|
+
{
|
|
43
|
+
Ok(class) => Error::new(class, message),
|
|
44
|
+
Err(error) => error,
|
|
45
|
+
}
|
|
46
|
+
}
|
|
63
47
|
|
|
64
48
|
/// Maps an erased state error to the matching Ruby state-error class.
|
|
65
49
|
///
|
|
@@ -68,60 +52,32 @@ static NULL_VALUE_ERROR: Lazy<ExceptionClass> = Lazy::new(|ruby| {
|
|
|
68
52
|
/// `#permanent?` path reclassifies a rethrown error with no change.
|
|
69
53
|
pub(crate) fn state_error(ruby: &Ruby, error: &ErasedStateError) -> Error {
|
|
70
54
|
let class = match error.category() {
|
|
71
|
-
ErasedCategory::Permanent =>
|
|
72
|
-
ErasedCategory::Transient =>
|
|
55
|
+
ErasedCategory::Permanent => "PermanentStateError",
|
|
56
|
+
ErasedCategory::Transient => "TransientStateError",
|
|
73
57
|
};
|
|
74
|
-
|
|
58
|
+
ruby_error(ruby, class, error.message().to_owned())
|
|
75
59
|
}
|
|
76
60
|
|
|
77
61
|
/// Builds a transient state error for a caller-caused condition the glue
|
|
78
62
|
/// detects (a wrong item shape, an invalid direction token, an unrepresentable
|
|
79
63
|
/// value).
|
|
80
64
|
fn transient_state_error(ruby: &Ruby, message: String) -> Error {
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/// Builds a null-value error for a rejected JSON-null write.
|
|
85
|
-
fn null_value_error(ruby: &Ruby, message: String) -> Error {
|
|
86
|
-
Error::new(ruby.get_inner(&NULL_VALUE_ERROR), message)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/// Converts an optional JSON item into a Ruby value or `nil`.
|
|
90
|
-
fn json_or_nil(ruby: &Ruby, item: Option<JsonValue>) -> Result<Value, Error> {
|
|
91
|
-
match item {
|
|
92
|
-
Some(value) => serialize(ruby, &value),
|
|
93
|
-
None => Ok(ruby.qnil().as_value()),
|
|
94
|
-
}
|
|
65
|
+
ruby_error(ruby, "TransientStateError", message)
|
|
95
66
|
}
|
|
96
67
|
|
|
97
68
|
/// Converts an optional message item into a `Prosody::Message` or `nil`.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
reason = "parity with json_or_nil for uniform call sites"
|
|
101
|
-
)]
|
|
102
|
-
fn message_or_nil(ruby: &Ruby, item: Option<ConsumerMessage<JsonValue>>) -> Result<Value, Error> {
|
|
103
|
-
match item {
|
|
104
|
-
Some(message) => Ok(Message::from(message).into_value_with(ruby)),
|
|
105
|
-
None => Ok(ruby.qnil().as_value()),
|
|
106
|
-
}
|
|
69
|
+
fn message_or_nil(ruby: &Ruby, item: Option<ConsumerMessage<JsonValue>>) -> Value {
|
|
70
|
+
item.map(Message::from).into_value_with(ruby)
|
|
107
71
|
}
|
|
108
72
|
|
|
109
|
-
/// Converts a Ruby argument into a
|
|
73
|
+
/// Converts a Ruby argument into a JSON item.
|
|
110
74
|
///
|
|
111
75
|
/// A value with no JSON representation is a caller mistake and rejects
|
|
112
|
-
/// transient. JSON `null`
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
let value: JsonValue = deserialize(ruby, value).map_err(|error| {
|
|
76
|
+
/// transient. Core rejects a JSON `null` write as permanent.
|
|
77
|
+
fn json_write_item(ruby: &Ruby, value: Value) -> Result<JsonValue, Error> {
|
|
78
|
+
deserialize(ruby, value).map_err(|error| {
|
|
116
79
|
transient_state_error(ruby, format!("value is not representable as JSON: {error}"))
|
|
117
|
-
})
|
|
118
|
-
if value.is_null() {
|
|
119
|
-
return Err(null_value_error(
|
|
120
|
-
ruby,
|
|
121
|
-
format!("JSON null is not a storable value{null_advice}"),
|
|
122
|
-
));
|
|
123
|
-
}
|
|
124
|
-
Ok(value)
|
|
80
|
+
})
|
|
125
81
|
}
|
|
126
82
|
|
|
127
83
|
/// Converts a Ruby argument into a storable message item.
|
|
@@ -140,49 +96,48 @@ fn message_write_item(
|
|
|
140
96
|
Ok(message.consumer_message())
|
|
141
97
|
}
|
|
142
98
|
|
|
143
|
-
///
|
|
99
|
+
/// Maps a core [`StoreOutcome`] to `:applied` or `:no_op`.
|
|
144
100
|
///
|
|
145
|
-
///
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
ruby,
|
|
152
|
-
format!("direction: expected :forward or :backward, got :{other}"),
|
|
153
|
-
)),
|
|
101
|
+
/// `:applied` means the call drained buffered operations. `:no_op` means
|
|
102
|
+
/// nothing was buffered.
|
|
103
|
+
fn outcome_symbol(ruby: &Ruby, outcome: StoreOutcome) -> StaticSymbol {
|
|
104
|
+
match outcome {
|
|
105
|
+
StoreOutcome::Applied => ruby.sym_new("applied"),
|
|
106
|
+
StoreOutcome::NoOp => ruby.sym_new("no_op"),
|
|
154
107
|
}
|
|
155
108
|
}
|
|
156
109
|
|
|
157
|
-
///
|
|
158
|
-
///
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
($ruby:expr, $this:expr, $handle:expr, $call:ident ( $($arg:expr),* )) => {{
|
|
162
|
-
let handle = Arc::clone($handle);
|
|
163
|
-
let context = extract_opentelemetry_context($ruby, &$this.propagator)?;
|
|
164
|
-
$this
|
|
165
|
-
.bridge
|
|
166
|
-
.wait_for(
|
|
167
|
-
$ruby,
|
|
168
|
-
async move { handle.$call($($arg),*).with_context(context).await },
|
|
169
|
-
Span::current(),
|
|
170
|
-
)?
|
|
171
|
-
.map_err(|error| state_error($ruby, &error))
|
|
172
|
-
}};
|
|
110
|
+
/// Defines the class that a `magnus::wrap` path such as
|
|
111
|
+
/// `"Prosody::NativeSetState"` names.
|
|
112
|
+
fn wrapped_class(ruby: &Ruby, module: RModule, path: &str) -> Result<RClass, Error> {
|
|
113
|
+
module.define_class(path.trim_start_matches("Prosody::"), ruby.class_object())
|
|
173
114
|
}
|
|
174
115
|
|
|
175
|
-
///
|
|
176
|
-
/// [`
|
|
177
|
-
|
|
178
|
-
|
|
116
|
+
/// Waits for one state operation in the caller's trace. An
|
|
117
|
+
/// [`ErasedStateError`] raises its matching Ruby class.
|
|
118
|
+
pub(crate) fn run_state<F, T>(
|
|
119
|
+
ruby: &Ruby,
|
|
120
|
+
bridge: &Bridge,
|
|
121
|
+
propagator: &Arc<TextMapCompositePropagator>,
|
|
122
|
+
operation: F,
|
|
123
|
+
) -> Result<T, Error>
|
|
124
|
+
where
|
|
125
|
+
F: Future<Output = Result<T, ErasedStateError>> + Send + 'static,
|
|
126
|
+
T: Send + 'static,
|
|
127
|
+
{
|
|
128
|
+
let context = extract_opentelemetry_context(ruby, propagator)?;
|
|
129
|
+
bridge
|
|
130
|
+
.wait_for(ruby, operation.with_context(context), Span::current())?
|
|
131
|
+
.map_err(|error| state_error(ruby, &error))
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/// Calls one method of an erased handle through [`run_state`].
|
|
135
|
+
macro_rules! run_op {
|
|
136
|
+
($ruby:expr, $this:expr, $handle:expr, $call:ident ( $($arg:expr),* )) => {{
|
|
179
137
|
let handle = Arc::clone($handle);
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
async move { handle.$call().with_context(context).await },
|
|
184
|
-
Span::current(),
|
|
185
|
-
)?
|
|
138
|
+
run_state($ruby, &$this.bridge, &$this.propagator, async move {
|
|
139
|
+
handle.$call($($arg),*).await
|
|
140
|
+
})
|
|
186
141
|
}};
|
|
187
142
|
}
|
|
188
143
|
|
|
@@ -213,25 +168,36 @@ macro_rules! value_state {
|
|
|
213
168
|
($restore)(ruby, run_op!(ruby, this, &this.state, get())?)
|
|
214
169
|
}
|
|
215
170
|
|
|
216
|
-
fn set(ruby: &Ruby, this: &Self, value: Value) -> Result<
|
|
171
|
+
fn set(ruby: &Ruby, this: &Self, value: Value) -> Result<(), Error> {
|
|
217
172
|
let item = ($prepare)(ruby, value)?;
|
|
218
|
-
run_op!(ruby, this, &this.state, set(item))
|
|
219
|
-
|
|
173
|
+
run_op!(ruby, this, &this.state, set(item))
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
fn clear(ruby: &Ruby, this: &Self) -> Result<(), Error> {
|
|
177
|
+
run_op!(ruby, this, &this.state, clear())
|
|
220
178
|
}
|
|
221
179
|
|
|
222
|
-
fn
|
|
223
|
-
run_op!(ruby, this, &this.state,
|
|
224
|
-
Ok(ruby
|
|
180
|
+
fn commit(ruby: &Ruby, this: &Self) -> Result<StaticSymbol, Error> {
|
|
181
|
+
let outcome = run_op!(ruby, this, &this.state, commit())?;
|
|
182
|
+
Ok(outcome_symbol(ruby, outcome))
|
|
225
183
|
}
|
|
226
184
|
|
|
227
|
-
fn
|
|
228
|
-
|
|
229
|
-
|
|
185
|
+
fn rollback(ruby: &Ruby, this: &Self) -> Result<StaticSymbol, Error> {
|
|
186
|
+
let state = Arc::clone(&this.state);
|
|
187
|
+
let outcome = run_state(ruby, &this.bridge, &this.propagator, async move {
|
|
188
|
+
Ok(state.rollback().await)
|
|
189
|
+
})?;
|
|
190
|
+
Ok(outcome_symbol(ruby, outcome))
|
|
230
191
|
}
|
|
231
192
|
|
|
232
|
-
fn
|
|
233
|
-
|
|
234
|
-
|
|
193
|
+
pub(super) fn register(ruby: &Ruby, module: RModule) -> Result<(), Error> {
|
|
194
|
+
let class = wrapped_class(ruby, module, $class)?;
|
|
195
|
+
class.define_method("get", method!($name::get, 0))?;
|
|
196
|
+
class.define_method("set", method!($name::set, 1))?;
|
|
197
|
+
class.define_method("clear", method!($name::clear, 0))?;
|
|
198
|
+
class.define_method("commit", method!($name::commit, 0))?;
|
|
199
|
+
class.define_method("rollback", method!($name::rollback, 0))?;
|
|
200
|
+
Ok(())
|
|
235
201
|
}
|
|
236
202
|
}
|
|
237
203
|
};
|
|
@@ -241,8 +207,8 @@ value_state!(
|
|
|
241
207
|
NativeJsonValueState,
|
|
242
208
|
"Prosody::NativeJsonValueState",
|
|
243
209
|
JsonValue,
|
|
244
|
-
|
|
245
|
-
|
|
210
|
+
json_write_item,
|
|
211
|
+
|ruby, item| serialize::<_, Value>(ruby, &item)
|
|
246
212
|
);
|
|
247
213
|
value_state!(
|
|
248
214
|
NativeMessageValueState,
|
|
@@ -253,7 +219,7 @@ value_state!(
|
|
|
253
219
|
value,
|
|
254
220
|
"; use clear to delete a message value collection"
|
|
255
221
|
),
|
|
256
|
-
message_or_nil
|
|
222
|
+
|ruby, item| Ok::<_, Error>(message_or_nil(ruby, item))
|
|
257
223
|
);
|
|
258
224
|
|
|
259
225
|
macro_rules! map_state {
|
|
@@ -283,8 +249,12 @@ macro_rules! map_state {
|
|
|
283
249
|
($restore)(ruby, run_op!(ruby, this, &this.state, get(key))?)
|
|
284
250
|
}
|
|
285
251
|
|
|
286
|
-
fn contains_key(ruby: &Ruby, this: &Self, key: String) -> Result<
|
|
287
|
-
|
|
252
|
+
fn contains_key(ruby: &Ruby, this: &Self, key: String) -> Result<bool, Error> {
|
|
253
|
+
run_op!(ruby, this, &this.state, contains_key(key))
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
fn is_empty(ruby: &Ruby, this: &Self) -> Result<bool, Error> {
|
|
257
|
+
run_op!(ruby, this, &this.state, is_empty())
|
|
288
258
|
}
|
|
289
259
|
|
|
290
260
|
fn get_many(ruby: &Ruby, this: &Self, keys: Vec<String>) -> Result<Value, Error> {
|
|
@@ -294,56 +264,83 @@ macro_rules! map_state {
|
|
|
294
264
|
Ok(array.as_value())
|
|
295
265
|
}
|
|
296
266
|
|
|
297
|
-
fn
|
|
267
|
+
fn contains_many(
|
|
268
|
+
ruby: &Ruby,
|
|
269
|
+
this: &Self,
|
|
270
|
+
keys: Vec<String>,
|
|
271
|
+
) -> Result<Vec<bool>, Error> {
|
|
272
|
+
run_op!(ruby, this, &this.state, contains_many(keys))
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
fn set(ruby: &Ruby, this: &Self, key: String, value: Value) -> Result<(), Error> {
|
|
298
276
|
let item = ($prepare)(ruby, value)?;
|
|
299
|
-
run_op!(ruby, this, &this.state, set(key, item))
|
|
300
|
-
Ok(ruby.qnil().as_value())
|
|
277
|
+
run_op!(ruby, this, &this.state, set(key, item))
|
|
301
278
|
}
|
|
302
279
|
|
|
303
|
-
fn remove(ruby: &Ruby, this: &Self, key: String) -> Result<
|
|
304
|
-
run_op!(ruby, this, &this.state, remove(key))
|
|
305
|
-
Ok(ruby.qnil().as_value())
|
|
280
|
+
fn remove(ruby: &Ruby, this: &Self, key: String) -> Result<(), Error> {
|
|
281
|
+
run_op!(ruby, this, &this.state, remove(key))
|
|
306
282
|
}
|
|
307
283
|
|
|
308
|
-
fn clear(ruby: &Ruby, this: &Self) -> Result<
|
|
309
|
-
run_op!(ruby, this, &this.state, clear())
|
|
310
|
-
Ok(ruby.qnil().as_value())
|
|
284
|
+
fn clear(ruby: &Ruby, this: &Self) -> Result<(), Error> {
|
|
285
|
+
run_op!(ruby, this, &this.state, clear())
|
|
311
286
|
}
|
|
312
287
|
|
|
313
|
-
fn scan(
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
288
|
+
fn scan(
|
|
289
|
+
ruby: &Ruby,
|
|
290
|
+
this: &Self,
|
|
291
|
+
direction: StaticSymbol,
|
|
292
|
+
options: RHash,
|
|
293
|
+
) -> Result<$scan, Error> {
|
|
294
|
+
let query = key_query(ruby, direction, options)?;
|
|
295
|
+
Ok($scan::new(
|
|
296
|
+
this.state.entries().with_query(query).stream(),
|
|
319
297
|
this.bridge.clone(),
|
|
320
298
|
Arc::clone(&this.propagator),
|
|
321
|
-
)
|
|
299
|
+
))
|
|
322
300
|
}
|
|
323
301
|
|
|
324
302
|
fn keys(
|
|
325
303
|
ruby: &Ruby,
|
|
326
304
|
this: &Self,
|
|
327
305
|
direction: StaticSymbol,
|
|
306
|
+
options: RHash,
|
|
328
307
|
) -> Result<NativeMapKeyScan, Error> {
|
|
329
|
-
let
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
ruby,
|
|
333
|
-
this.state.keys(direction),
|
|
308
|
+
let query = key_query(ruby, direction, options)?;
|
|
309
|
+
Ok(NativeMapKeyScan::new(
|
|
310
|
+
this.state.keys().with_query(query).stream(),
|
|
334
311
|
this.bridge.clone(),
|
|
335
312
|
Arc::clone(&this.propagator),
|
|
336
|
-
)
|
|
313
|
+
))
|
|
337
314
|
}
|
|
338
315
|
|
|
339
|
-
fn commit(ruby: &Ruby, this: &Self) -> Result<
|
|
340
|
-
run_op!(ruby, this, &this.state, commit())?;
|
|
341
|
-
Ok(ruby
|
|
316
|
+
fn commit(ruby: &Ruby, this: &Self) -> Result<StaticSymbol, Error> {
|
|
317
|
+
let outcome = run_op!(ruby, this, &this.state, commit())?;
|
|
318
|
+
Ok(outcome_symbol(ruby, outcome))
|
|
342
319
|
}
|
|
343
320
|
|
|
344
|
-
fn rollback(ruby: &Ruby, this: &Self) -> Result<
|
|
345
|
-
|
|
346
|
-
|
|
321
|
+
fn rollback(ruby: &Ruby, this: &Self) -> Result<StaticSymbol, Error> {
|
|
322
|
+
let state = Arc::clone(&this.state);
|
|
323
|
+
let outcome = run_state(ruby, &this.bridge, &this.propagator, async move {
|
|
324
|
+
Ok(state.rollback().await)
|
|
325
|
+
})?;
|
|
326
|
+
Ok(outcome_symbol(ruby, outcome))
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
pub(super) fn register(ruby: &Ruby, module: RModule) -> Result<(), Error> {
|
|
330
|
+
let class = wrapped_class(ruby, module, $class)?;
|
|
331
|
+
class.define_method("get", method!($name::get, 1))?;
|
|
332
|
+
class.define_method("contains_key", method!($name::contains_key, 1))?;
|
|
333
|
+
class.define_method("is_empty", method!($name::is_empty, 0))?;
|
|
334
|
+
class.define_method("get_many", method!($name::get_many, 1))?;
|
|
335
|
+
class.define_method("contains_many", method!($name::contains_many, 1))?;
|
|
336
|
+
class.define_method("set", method!($name::set, 2))?;
|
|
337
|
+
class.define_method("remove", method!($name::remove, 1))?;
|
|
338
|
+
class.define_method("clear", method!($name::clear, 0))?;
|
|
339
|
+
class.define_method("scan", method!($name::scan, 2))?;
|
|
340
|
+
class.define_method("keys", method!($name::keys, 2))?;
|
|
341
|
+
class.define_method("commit", method!($name::commit, 0))?;
|
|
342
|
+
class.define_method("rollback", method!($name::rollback, 0))?;
|
|
343
|
+
Ok(())
|
|
347
344
|
}
|
|
348
345
|
}
|
|
349
346
|
};
|
|
@@ -354,8 +351,8 @@ map_state!(
|
|
|
354
351
|
"Prosody::NativeJsonMapState",
|
|
355
352
|
JsonValue,
|
|
356
353
|
NativeJsonMapScan,
|
|
357
|
-
|
|
358
|
-
|
|
354
|
+
json_write_item,
|
|
355
|
+
|ruby, item| serialize::<_, Value>(ruby, &item)
|
|
359
356
|
);
|
|
360
357
|
map_state!(
|
|
361
358
|
NativeMessageMapState,
|
|
@@ -367,122 +364,20 @@ map_state!(
|
|
|
367
364
|
value,
|
|
368
365
|
"; use delete(key) to remove a message map entry"
|
|
369
366
|
),
|
|
370
|
-
message_or_nil
|
|
371
|
-
);
|
|
372
|
-
macro_rules! deque_state {
|
|
373
|
-
($name:ident, $class:literal, $item:ty, $scan:ident, $prepare:expr, $restore:expr) => {
|
|
374
|
-
/// Native deque handle with one payload type.
|
|
375
|
-
#[magnus::wrap(class = $class)]
|
|
376
|
-
pub struct $name {
|
|
377
|
-
state: Arc<dyn DynDequeState<$item>>,
|
|
378
|
-
bridge: Bridge,
|
|
379
|
-
propagator: Arc<TextMapCompositePropagator>,
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
impl $name {
|
|
383
|
-
pub(crate) fn new(
|
|
384
|
-
state: Arc<dyn DynDequeState<$item>>,
|
|
385
|
-
bridge: Bridge,
|
|
386
|
-
propagator: Arc<TextMapCompositePropagator>,
|
|
387
|
-
) -> Self {
|
|
388
|
-
Self {
|
|
389
|
-
state,
|
|
390
|
-
bridge,
|
|
391
|
-
propagator,
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
fn len(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
|
|
396
|
-
Ok(run_op!(ruby, this, &this.state, len())?.into_value_with(ruby))
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
fn is_empty(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
|
|
400
|
-
Ok(run_op!(ruby, this, &this.state, is_empty())?.into_value_with(ruby))
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
fn get(ruby: &Ruby, this: &Self, index: usize) -> Result<Value, Error> {
|
|
404
|
-
($restore)(ruby, run_op!(ruby, this, &this.state, get(index))?)
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
fn peek_front(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
|
|
408
|
-
($restore)(ruby, run_op!(ruby, this, &this.state, peek_front())?)
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
fn peek_back(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
|
|
412
|
-
($restore)(ruby, run_op!(ruby, this, &this.state, peek_back())?)
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
fn push_back(ruby: &Ruby, this: &Self, value: Value) -> Result<Value, Error> {
|
|
416
|
-
let item = ($prepare)(ruby, value)?;
|
|
417
|
-
run_op!(ruby, this, &this.state, push_back(item))?;
|
|
418
|
-
Ok(ruby.qnil().as_value())
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
fn push_front(ruby: &Ruby, this: &Self, value: Value) -> Result<Value, Error> {
|
|
422
|
-
let item = ($prepare)(ruby, value)?;
|
|
423
|
-
run_op!(ruby, this, &this.state, push_front(item))?;
|
|
424
|
-
Ok(ruby.qnil().as_value())
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
fn pop_front(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
|
|
428
|
-
($restore)(ruby, run_op!(ruby, this, &this.state, pop_front())?)
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
fn pop_back(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
|
|
432
|
-
($restore)(ruby, run_op!(ruby, this, &this.state, pop_back())?)
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
fn clear(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
|
|
436
|
-
run_op!(ruby, this, &this.state, clear())?;
|
|
437
|
-
Ok(ruby.qnil().as_value())
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
fn scan(ruby: &Ruby, this: &Self, direction: StaticSymbol) -> Result<$scan, Error> {
|
|
441
|
-
let direction = parse_direction(ruby, direction)?;
|
|
442
|
-
let _guard = extract_opentelemetry_context(ruby, &this.propagator)?.attach();
|
|
443
|
-
$scan::new(
|
|
444
|
-
ruby,
|
|
445
|
-
this.state.scan(direction),
|
|
446
|
-
this.bridge.clone(),
|
|
447
|
-
Arc::clone(&this.propagator),
|
|
448
|
-
)
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
fn commit(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
|
|
452
|
-
run_op!(ruby, this, &this.state, commit())?;
|
|
453
|
-
Ok(ruby.qnil().as_value())
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
fn rollback(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
|
|
457
|
-
run_infallible!(ruby, this, &this.state, rollback());
|
|
458
|
-
Ok(ruby.qnil().as_value())
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
deque_state!(
|
|
465
|
-
NativeJsonDequeState,
|
|
466
|
-
"Prosody::NativeJsonDequeState",
|
|
467
|
-
JsonValue,
|
|
468
|
-
NativeJsonDequeScan,
|
|
469
|
-
|ruby, value| json_write_item(ruby, value, " in a deque"),
|
|
470
|
-
json_or_nil
|
|
471
|
-
);
|
|
472
|
-
deque_state!(
|
|
473
|
-
NativeMessageDequeState,
|
|
474
|
-
"Prosody::NativeMessageDequeState",
|
|
475
|
-
ConsumerMessage<JsonValue>,
|
|
476
|
-
NativeMessageDequeScan,
|
|
477
|
-
|ruby, value| message_write_item(ruby, value, " to push into a message deque"),
|
|
478
|
-
message_or_nil
|
|
367
|
+
|ruby, item| Ok::<_, Error>(message_or_nil(ruby, item))
|
|
479
368
|
);
|
|
369
|
+
mod deque;
|
|
370
|
+
mod query;
|
|
480
371
|
mod scan;
|
|
372
|
+
mod set;
|
|
481
373
|
|
|
374
|
+
pub(crate) use deque::{NativeJsonDequeState, NativeMessageDequeState};
|
|
375
|
+
pub(crate) use query::{key_query, position_query};
|
|
482
376
|
pub(crate) use scan::{
|
|
483
377
|
NativeJsonDequeScan, NativeJsonMapScan, NativeMapKeyScan, NativeMessageDequeScan,
|
|
484
|
-
NativeMessageMapScan,
|
|
378
|
+
NativeMessageMapScan,
|
|
485
379
|
};
|
|
380
|
+
pub(crate) use set::NativeSetState;
|
|
486
381
|
mod registration;
|
|
487
382
|
|
|
488
383
|
pub(crate) use registration::register;
|