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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.config/rail.toml +26 -0
  3. data/.release-please-manifest.json +1 -1
  4. data/.ruby-version +1 -1
  5. data/.taplo.toml +1 -1
  6. data/AGENTS.md +29 -15
  7. data/CHANGELOG.md +7 -0
  8. data/CONFIGURATION.md +19 -16
  9. data/Cargo.lock +254 -235
  10. data/Cargo.toml +11 -8
  11. data/README.md +100 -23
  12. data/examples/keyed_state.rb +10 -2
  13. data/examples/keyed_state.rbs +1 -0
  14. data/ext/prosody/Cargo.toml +1 -1
  15. data/ext/prosody/src/admin.rs +36 -36
  16. data/ext/prosody/src/bridge/mod.rs +5 -10
  17. data/ext/prosody/src/client/config/connections.rs +170 -0
  18. data/ext/prosody/src/client/config/middleware.rs +184 -0
  19. data/ext/prosody/src/client/config/mod.rs +396 -0
  20. data/ext/prosody/src/client/config/state.rs +323 -0
  21. data/ext/prosody/src/client/mod.rs +31 -117
  22. data/ext/prosody/src/client/readers.rs +106 -0
  23. data/ext/prosody/src/client/request.rs +2 -2
  24. data/ext/prosody/src/client/support.rs +13 -32
  25. data/ext/prosody/src/gvl.rs +8 -6
  26. data/ext/prosody/src/handler/{context.rs → context/mod.rs} +36 -150
  27. data/ext/prosody/src/handler/context/vending.rs +138 -0
  28. data/ext/prosody/src/handler/message.rs +36 -0
  29. data/ext/prosody/src/handler/mod.rs +18 -8
  30. data/ext/prosody/src/handler/state/deque.rs +144 -0
  31. data/ext/prosody/src/handler/state/mod.rs +163 -268
  32. data/ext/prosody/src/handler/state/query.rs +264 -0
  33. data/ext/prosody/src/handler/state/registration.rs +15 -86
  34. data/ext/prosody/src/handler/state/scan.rs +33 -141
  35. data/ext/prosody/src/handler/state/set.rs +98 -0
  36. data/ext/prosody/src/lib.rs +54 -36
  37. data/ext/prosody/src/logging.rs +6 -6
  38. data/ext/prosody/src/published.rs +171 -152
  39. data/ext/prosody/src/scheduler/result.rs +2 -1
  40. data/ext/prosody/src/util.rs +65 -3
  41. data/lib/prosody/client.rb +32 -0
  42. data/lib/prosody/configuration.rb +20 -12
  43. data/lib/prosody/demand.rb +27 -0
  44. data/lib/prosody/native_stubs/client.rb +157 -0
  45. data/lib/prosody/native_stubs/context.rb +178 -0
  46. data/lib/prosody/native_stubs/message.rb +133 -0
  47. data/lib/prosody/native_stubs.rb +11 -956
  48. data/lib/prosody/state/deque.rb +253 -0
  49. data/lib/prosody/state/map.rb +313 -0
  50. data/lib/prosody/state/set.rb +121 -0
  51. data/lib/prosody/state/value.rb +58 -0
  52. data/lib/prosody/state.rb +157 -677
  53. data/lib/prosody/version.rb +1 -1
  54. data/lib/prosody.rb +2 -1
  55. data/sig/configuration.rbs +19 -10
  56. data/sig/prosody.rbs +37 -4
  57. data/sig/published.rbs +102 -0
  58. data/sig/state.rbs +109 -122
  59. data/typecheck/payload_types.rb +12 -0
  60. data/typecheck/payload_types.rbs +1 -0
  61. metadata +30 -11
  62. data/ext/prosody/src/client/config.rs +0 -1300
@@ -43,8 +43,8 @@ mod state;
43
43
  mod trigger;
44
44
 
45
45
  pub(crate) use state::{
46
- NativeJsonDequeScan, NativeJsonMapScan, NativeMapKeyScan, parse_direction,
47
- published_deque_scan, published_map_key_scan, published_map_scan,
46
+ NativeJsonDequeScan, NativeJsonMapScan, NativeMapKeyScan, key_query, position_query, run_state,
47
+ state_error,
48
48
  };
49
49
 
50
50
  /// A handler that bridges between Kafka messages and Ruby message processing
@@ -95,6 +95,7 @@ impl RubyHandler {
95
95
  &self,
96
96
  context: C,
97
97
  message: ConsumerMessage<P>,
98
+ demand: DemandType,
98
99
  method: &'static str,
99
100
  event_type: &'static str,
100
101
  span: Span,
@@ -123,6 +124,7 @@ impl RubyHandler {
123
124
  context.boxed(),
124
125
  self.bridge.clone(),
125
126
  self.propagator.clone(),
127
+ demand,
126
128
  );
127
129
  let response_requested = message.response_requested();
128
130
  let message = M::from(message);
@@ -188,7 +190,7 @@ impl FallibleHandler for RubyHandler {
188
190
  &self,
189
191
  context: C,
190
192
  message: ConsumerMessage<Self::Payload>,
191
- _demand_type: DemandType,
193
+ demand: DemandType,
192
194
  ) -> Result<Self::Output, Self::Error>
193
195
  where
194
196
  C: EventContext<Payload = Self::Payload>,
@@ -201,7 +203,7 @@ impl FallibleHandler for RubyHandler {
201
203
  offset = message.offset(),
202
204
  key = %message.key()
203
205
  );
204
- self.handle_record::<_, _, Message>(context, message, "on_message", "message", span)
206
+ self.handle_record::<_, _, Message>(context, message, demand, "on_message", "message", span)
205
207
  .await
206
208
  }
207
209
 
@@ -209,7 +211,7 @@ impl FallibleHandler for RubyHandler {
209
211
  &self,
210
212
  context: C,
211
213
  message: ConsumerMessage<()>,
212
- _demand_type: DemandType,
214
+ demand: DemandType,
213
215
  ) -> Result<Self::Output, Self::Error>
214
216
  where
215
217
  C: EventContext<Payload = Self::Payload>,
@@ -222,15 +224,22 @@ impl FallibleHandler for RubyHandler {
222
224
  offset = message.offset(),
223
225
  key = %message.key()
224
226
  );
225
- self.handle_record::<_, _, ExciseMessage>(context, message, "on_excise", "excise", span)
226
- .await
227
+ self.handle_record::<_, _, ExciseMessage>(
228
+ context,
229
+ message,
230
+ demand,
231
+ "on_excise",
232
+ "excise",
233
+ span,
234
+ )
235
+ .await
227
236
  }
228
237
 
229
238
  async fn on_timer<C>(
230
239
  &self,
231
240
  context: C,
232
241
  trigger: ProsodyTrigger,
233
- _demand_type: DemandType,
242
+ demand: DemandType,
234
243
  ) -> Result<Self::Output, Self::Error>
235
244
  where
236
245
  C: EventContext<Payload = Self::Payload>,
@@ -269,6 +278,7 @@ impl FallibleHandler for RubyHandler {
269
278
  context.boxed(),
270
279
  self.bridge.clone(),
271
280
  self.propagator.clone(),
281
+ demand,
272
282
  );
273
283
  let timer: Timer = trigger.into();
274
284
 
@@ -0,0 +1,144 @@
1
+ //! Native deque handles for JSON and message payloads.
2
+
3
+ use super::{
4
+ NativeJsonDequeScan, NativeMessageDequeScan, json_write_item, message_or_nil,
5
+ message_write_item, outcome_symbol, position_query, run_state, wrapped_class,
6
+ };
7
+ use crate::bridge::Bridge;
8
+ use magnus::{Error, Module, RHash, RModule, Ruby, StaticSymbol, Value, method};
9
+ use opentelemetry::propagation::TextMapCompositePropagator;
10
+ use prosody::consumer::event_context::DynDequeState;
11
+ use prosody::consumer::message::ConsumerMessage;
12
+ use serde_json::Value as JsonValue;
13
+ use serde_magnus::serialize;
14
+ use std::sync::Arc;
15
+
16
+ macro_rules! deque_state {
17
+ ($name:ident, $class:literal, $item:ty, $scan:ident, $prepare:expr, $restore:expr) => {
18
+ /// Native deque handle with one payload type.
19
+ #[magnus::wrap(class = $class)]
20
+ pub struct $name {
21
+ state: Arc<dyn DynDequeState<$item>>,
22
+ bridge: Bridge,
23
+ propagator: Arc<TextMapCompositePropagator>,
24
+ }
25
+
26
+ impl $name {
27
+ pub(crate) fn new(
28
+ state: Arc<dyn DynDequeState<$item>>,
29
+ bridge: Bridge,
30
+ propagator: Arc<TextMapCompositePropagator>,
31
+ ) -> Self {
32
+ Self {
33
+ state,
34
+ bridge,
35
+ propagator,
36
+ }
37
+ }
38
+
39
+ fn len(ruby: &Ruby, this: &Self) -> Result<usize, Error> {
40
+ run_op!(ruby, this, &this.state, len())
41
+ }
42
+
43
+ fn is_empty(ruby: &Ruby, this: &Self) -> Result<bool, Error> {
44
+ run_op!(ruby, this, &this.state, is_empty())
45
+ }
46
+
47
+ fn get(ruby: &Ruby, this: &Self, index: usize) -> Result<Value, Error> {
48
+ ($restore)(ruby, run_op!(ruby, this, &this.state, get(index))?)
49
+ }
50
+
51
+ fn peek_front(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
52
+ ($restore)(ruby, run_op!(ruby, this, &this.state, peek_front())?)
53
+ }
54
+
55
+ fn peek_back(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
56
+ ($restore)(ruby, run_op!(ruby, this, &this.state, peek_back())?)
57
+ }
58
+
59
+ fn push_back(ruby: &Ruby, this: &Self, value: Value) -> Result<(), Error> {
60
+ let item = ($prepare)(ruby, value)?;
61
+ run_op!(ruby, this, &this.state, push_back(item))
62
+ }
63
+
64
+ fn push_front(ruby: &Ruby, this: &Self, value: Value) -> Result<(), Error> {
65
+ let item = ($prepare)(ruby, value)?;
66
+ run_op!(ruby, this, &this.state, push_front(item))
67
+ }
68
+
69
+ fn pop_front(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
70
+ ($restore)(ruby, run_op!(ruby, this, &this.state, pop_front())?)
71
+ }
72
+
73
+ fn pop_back(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
74
+ ($restore)(ruby, run_op!(ruby, this, &this.state, pop_back())?)
75
+ }
76
+
77
+ fn clear(ruby: &Ruby, this: &Self) -> Result<(), Error> {
78
+ run_op!(ruby, this, &this.state, clear())
79
+ }
80
+
81
+ fn scan(
82
+ ruby: &Ruby,
83
+ this: &Self,
84
+ direction: StaticSymbol,
85
+ options: RHash,
86
+ ) -> Result<$scan, Error> {
87
+ let query = position_query(ruby, direction, options)?;
88
+ Ok($scan::new(
89
+ this.state.values().with_query(query).stream(),
90
+ this.bridge.clone(),
91
+ Arc::clone(&this.propagator),
92
+ ))
93
+ }
94
+
95
+ fn commit(ruby: &Ruby, this: &Self) -> Result<StaticSymbol, Error> {
96
+ let outcome = run_op!(ruby, this, &this.state, commit())?;
97
+ Ok(outcome_symbol(ruby, outcome))
98
+ }
99
+
100
+ fn rollback(ruby: &Ruby, this: &Self) -> Result<StaticSymbol, Error> {
101
+ let state = Arc::clone(&this.state);
102
+ let outcome = run_state(ruby, &this.bridge, &this.propagator, async move {
103
+ Ok(state.rollback().await)
104
+ })?;
105
+ Ok(outcome_symbol(ruby, outcome))
106
+ }
107
+
108
+ pub(super) fn register(ruby: &Ruby, module: RModule) -> Result<(), Error> {
109
+ let class = wrapped_class(ruby, module, $class)?;
110
+ class.define_method("len", method!($name::len, 0))?;
111
+ class.define_method("is_empty", method!($name::is_empty, 0))?;
112
+ class.define_method("get", method!($name::get, 1))?;
113
+ class.define_method("peek_front", method!($name::peek_front, 0))?;
114
+ class.define_method("peek_back", method!($name::peek_back, 0))?;
115
+ class.define_method("push_back", method!($name::push_back, 1))?;
116
+ class.define_method("push_front", method!($name::push_front, 1))?;
117
+ class.define_method("pop_front", method!($name::pop_front, 0))?;
118
+ class.define_method("pop_back", method!($name::pop_back, 0))?;
119
+ class.define_method("clear", method!($name::clear, 0))?;
120
+ class.define_method("scan", method!($name::scan, 2))?;
121
+ class.define_method("commit", method!($name::commit, 0))?;
122
+ class.define_method("rollback", method!($name::rollback, 0))?;
123
+ Ok(())
124
+ }
125
+ }
126
+ };
127
+ }
128
+
129
+ deque_state!(
130
+ NativeJsonDequeState,
131
+ "Prosody::NativeJsonDequeState",
132
+ JsonValue,
133
+ NativeJsonDequeScan,
134
+ json_write_item,
135
+ |ruby, item| serialize::<_, Value>(ruby, &item)
136
+ );
137
+ deque_state!(
138
+ NativeMessageDequeState,
139
+ "Prosody::NativeMessageDequeState",
140
+ ConsumerMessage<JsonValue>,
141
+ NativeMessageDequeScan,
142
+ |ruby, value| message_write_item(ruby, value, " to push into a message deque"),
143
+ |ruby, item| Ok::<_, Error>(message_or_nil(ruby, item))
144
+ );