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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f51af8dfb50cdab48f5a2a60c0ae761f26ce082ce3be41c538c1642a7147871e
|
|
4
|
+
data.tar.gz: 293c854498dbb467a1ea5aaccb774bc4d4db997e432f03b407cc7b6518de15e7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4f7f4a6ec8fb471110213bcf7ba47d38bd06393f0a072afe403fe25a1ed8ee3924444ecd91e26a06207807916c22f4d0c1e803679f9aa75dec80e35f3d64c361
|
|
7
|
+
data.tar.gz: 584bd14a5ea9e2e806434ee06eea31ace62930b53f7e8c926e8536193d6500389b86f40fe4c7702b9fe06913d347c16f82a1e280c7bff381d2c0d46b14fb2d12
|
data/.config/rail.toml
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
[plan.work.ci]
|
|
2
|
+
paths = [".config/rail.toml", ".github/**", ".taplo.toml", "Makefile"]
|
|
3
|
+
scope = "repository"
|
|
4
|
+
|
|
5
|
+
[plan.work.ruby]
|
|
6
|
+
paths = [
|
|
7
|
+
".rspec",
|
|
8
|
+
".ruby-version",
|
|
9
|
+
".standard.yml",
|
|
10
|
+
"Gemfile",
|
|
11
|
+
"Gemfile.lock",
|
|
12
|
+
"Rakefile",
|
|
13
|
+
"Steepfile",
|
|
14
|
+
"bin/**",
|
|
15
|
+
"examples/**",
|
|
16
|
+
"ext/prosody/extconf.rb",
|
|
17
|
+
"lib/**",
|
|
18
|
+
"prosody.gemspec",
|
|
19
|
+
"sig-private/**",
|
|
20
|
+
"sig/**",
|
|
21
|
+
"spec/**",
|
|
22
|
+
"steep_expectations.yml",
|
|
23
|
+
"typecheck/**",
|
|
24
|
+
"typecheck_negative/**",
|
|
25
|
+
]
|
|
26
|
+
scope = "repository"
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.3.
|
|
1
|
+
3.3.12
|
data/.taplo.toml
CHANGED
data/AGENTS.md
CHANGED
|
@@ -10,11 +10,11 @@ Ruby/Rust bridge in depth — read it before touching the extension.
|
|
|
10
10
|
|
|
11
11
|
These come before everything else. Every change is judged against them.
|
|
12
12
|
|
|
13
|
-
**Write code that is simple, clear, well-factored,
|
|
14
|
-
understand, correct, and idiomatic.** A reader should grasp the intent
|
|
15
|
-
effort. If a change makes the code harder to read, the change is
|
|
16
|
-
if it is faster or shorter. If two designs are correct, pick the
|
|
17
|
-
easier to delete.
|
|
13
|
+
**Write code that is simple, clear, well-factored, DRY, performant, elegant,
|
|
14
|
+
easy to understand, correct, and idiomatic.** A reader should grasp the intent
|
|
15
|
+
without effort. If a change makes the code harder to read, the change is
|
|
16
|
+
wrong, even if it is faster or shorter. If two designs are correct, pick the
|
|
17
|
+
one that is easier to delete.
|
|
18
18
|
|
|
19
19
|
**Make invalid states unrepresentable in the type system.** When a compiler
|
|
20
20
|
or type checker can prove a contract, no test, comment, or convention has to.
|
|
@@ -26,9 +26,10 @@ uncompilable, do that instead of writing a runtime check.
|
|
|
26
26
|
**Delete more than you add.** Every change should leave the codebase smaller,
|
|
27
27
|
simpler, or both. If you must add code, look first for duplication you can
|
|
28
28
|
fold, abstractions that no longer pay rent, dead branches, and stale comments.
|
|
29
|
-
The end-state diff should net negative whenever the task allows.
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
The end-state diff should net negative whenever the task allows. Each added
|
|
30
|
+
line must be inherent to the problem, not incidental to the solution. Line
|
|
31
|
+
count is not the only axis: plain duplicated arms often read better than
|
|
32
|
+
generic machinery.
|
|
32
33
|
|
|
33
34
|
**Identify, document, and enforce invariants.** For every load-bearing piece
|
|
34
35
|
of state: name the invariant, write it down near the type or function that
|
|
@@ -40,6 +41,15 @@ not yet understand the code well enough to change it.
|
|
|
40
41
|
encouraged when they are scoped to the area you are already touching. Do not
|
|
41
42
|
sprawl — but do not walk past obvious cleanup either.
|
|
42
43
|
|
|
44
|
+
**Do not break users without a reason.** The published package has real
|
|
45
|
+
users. A release can break them only for a clear improvement that the
|
|
46
|
+
owner decided on: a fixed defect, an invalid state that the types now
|
|
47
|
+
prevent, or a need of a new feature. "Nothing in this repo calls it" is
|
|
48
|
+
not a reason to remove, rename, or narrow a public member, an error
|
|
49
|
+
class, a log text, or a dependency floor. When you are not sure, keep
|
|
50
|
+
the old shape. List each break under `## Breaking changes` in the PR
|
|
51
|
+
body.
|
|
52
|
+
|
|
43
53
|
## Definition of Done
|
|
44
54
|
|
|
45
55
|
No change is complete until every line below holds. These are acts, not
|
|
@@ -60,7 +70,8 @@ aspirations — perform each one; do not merely agree with it:
|
|
|
60
70
|
vocabulary (see Redesign hygiene). "The new thing works" is half done.
|
|
61
71
|
7. Every claim written this session — doc cross-reference, "covered by" note,
|
|
62
72
|
exemplar path — was verified to resolve, not recalled from memory.
|
|
63
|
-
8. The diff is net-negative, or each addition is individually justified
|
|
73
|
+
8. The diff is net-negative, or each addition is individually justified as
|
|
74
|
+
inherent to the problem.
|
|
64
75
|
|
|
65
76
|
## Development Setup
|
|
66
77
|
|
|
@@ -216,6 +227,8 @@ half-deleted designs are where bloat and bug re-introduction live:
|
|
|
216
227
|
|
|
217
228
|
**Style:**
|
|
218
229
|
|
|
230
|
+
- Structure function bodies as logical paragraphs. Keep statements for one
|
|
231
|
+
operation together. Add a blank line before a new concept or operation.
|
|
219
232
|
- Prefer `use` statements over fully qualified prefixes
|
|
220
233
|
- Methods without `self` should be functions (except `new` and similar)
|
|
221
234
|
- Ask before large structural changes
|
|
@@ -295,12 +308,13 @@ Constants → Statics → Types → Implementations → Functions → Errors (bo
|
|
|
295
308
|
|
|
296
309
|
- `sig/` — public RBS signatures; `sig-private/` — internal signatures.
|
|
297
310
|
Every API change updates the signatures in the same commit.
|
|
298
|
-
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
311
|
+
- Public API docs are YARD comments on the public Ruby classes. A public
|
|
312
|
+
class that the Rust extension implements (`Client`, `Context`, `Message`,
|
|
313
|
+
`Timer`) keeps a documented stub in `lib/prosody/native_stubs/`. Do not
|
|
314
|
+
write stubs for internal native classes or private methods; `sig/` and
|
|
315
|
+
`sig-private/` type them. The runtime does not load the stubs, and Steep
|
|
316
|
+
ignores them. When a public native method changes, update its stub in the
|
|
317
|
+
same commit.
|
|
304
318
|
- Steep targets (`Steepfile`): `lib` checks the implementation;
|
|
305
319
|
`consumer_types` (`typecheck/`) verifies a payload type flows through the
|
|
306
320
|
public API; `typed_examples` checks every runnable example;
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.6.0](https://github.com/prosody-events/prosody-rb/compare/prosody/v0.5.1...prosody/v0.6.0) (2026-10-02)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **deps:** upgrade prosody to 0.7.0 ([#51](https://github.com/prosody-events/prosody-rb/issues/51)) ([c9f265c](https://github.com/prosody-events/prosody-rb/commit/c9f265c7c5353c989886d2333afca2142e06763c))
|
|
9
|
+
|
|
3
10
|
## [0.5.1](https://github.com/prosody-events/prosody-rb/compare/prosody/v0.5.0...prosody/v0.5.1) (2026-08-20)
|
|
4
11
|
|
|
5
12
|
|
data/CONFIGURATION.md
CHANGED
|
@@ -10,12 +10,14 @@ The Ruby client reports values it cannot convert to Prosody types. Prosody valid
|
|
|
10
10
|
|-----------------------------------------|---------------------------------------------------|--------------|
|
|
11
11
|
| `bootstrap_servers` / `PROSODY_BOOTSTRAP_SERVERS` | Kafka servers to connect to | - |
|
|
12
12
|
| `group_id` / `PROSODY_GROUP_ID` | Consumer group name | - |
|
|
13
|
-
| `subscribed_topics` / `PROSODY_SUBSCRIBED_TOPICS` | Topics to read from
|
|
13
|
+
| `subscribed_topics` / `PROSODY_SUBSCRIBED_TOPICS` | Topics to read from; a client that only reads published state needs none | - |
|
|
14
14
|
| `allowed_events` / `PROSODY_ALLOWED_EVENTS` | Only process events matching these prefixes | (all) |
|
|
15
15
|
| `source_system` / `PROSODY_SOURCE_SYSTEM` | Tag for outgoing messages (prevents reprocessing)| `<group_id>` |
|
|
16
16
|
| `mock` / `PROSODY_MOCK` | Use in-memory Kafka for testing | false |
|
|
17
17
|
| `mode` / - | Processing mode: `pipeline`, `low_latency`, or `best_effort` | `pipeline` |
|
|
18
|
-
| - / `PROSODY_LOG` | Rust log filter, such as `info` or `prosody=debug` | `info` |
|
|
18
|
+
| - / `PROSODY_LOG` | Rust log filter, such as `info` or `prosody=debug` | `info`, with `warn` for `scylla` and `opentelemetry` |
|
|
19
|
+
|
|
20
|
+
`PROSODY_LOG` directives apply on top of the defaults above. A value that names only targets, such as `prosody=debug`, keeps other targets at `info`. Set `PROSODY_LOG=opentelemetry=info` to restore the OpenTelemetry info events.
|
|
19
21
|
|
|
20
22
|
## Requests
|
|
21
23
|
|
|
@@ -45,9 +47,9 @@ Set `subsystem` to make this client answer requests. Without it, the client cons
|
|
|
45
47
|
| `shutdown_timeout` / `PROSODY_SHUTDOWN_TIMEOUT` | Shutdown budget; handlers run freely until cancellation fires near the end of the timeout | 30s |
|
|
46
48
|
| `stall_threshold` / `PROSODY_STALL_THRESHOLD` | Report unhealthy if no progress for this long | 5m |
|
|
47
49
|
| `probe_port` / `PROSODY_PROBE_PORT` | HTTP port for health checks; use `false`, `:disabled`, or the environment value `none` to disable | 8000 |
|
|
48
|
-
|
|
|
50
|
+
| `statistics_interval` / `PROSODY_STATISTICS_INTERVAL` | How often librdkafka reports client statistics; must be between 1ms and 24h | 5s |
|
|
49
51
|
| `failure_topic` / `PROSODY_FAILURE_TOPIC` | Send unprocessable messages here (dead letter queue) | - |
|
|
50
|
-
| `idempotence_cache_size` / `PROSODY_IDEMPOTENCE_CACHE_SIZE` |
|
|
52
|
+
| `idempotence_cache_size` / `PROSODY_IDEMPOTENCE_CACHE_SIZE` | Capacity of the producer idempotence cache and of the consumer deduplication cache. Consumer deduplication cannot be turned off, so the value must be at least 1 | 8192 |
|
|
51
53
|
| `idempotence_version` / `PROSODY_IDEMPOTENCE_VERSION` | Version string for cache-busting dedup hashes | 1 |
|
|
52
54
|
| `idempotence_ttl` / `PROSODY_IDEMPOTENCE_TTL` | TTL for dedup records in Cassandra | 7d (604800 seconds) |
|
|
53
55
|
| `slab_size` / `PROSODY_SLAB_SIZE` | Timer storage granularity (rarely needs changing) | 1h |
|
|
@@ -141,27 +143,28 @@ Register keyed-state collections before you subscribe. Persistence is backed by
|
|
|
141
143
|
| Option / Environment Variable | Description | Default |
|
|
142
144
|
|-------------------------------|-------------|---------|
|
|
143
145
|
| `state_collections` / - | Keyed-state collections to register before subscribe (array of definitions or config hashes; duplicate names rejected) | (none) |
|
|
144
|
-
| `subsystem` / `PROSODY_SUBSYSTEM` | Subsystem name used to advertise JSON collections whose definitions set `published: true` | (none) |
|
|
145
|
-
| `state_cache_dir` / `PROSODY_STATE_CACHE_DIR` |
|
|
146
|
+
| `subsystem` / `PROSODY_SUBSYSTEM` | Subsystem name used to advertise JSON and set collections whose definitions set `published: true` | (none) |
|
|
147
|
+
| `state_cache_dir` / `PROSODY_STATE_CACHE_DIR` | Directory for the local keyed-state caches. Each consumer opens its cache in a new subdirectory and removes it when the consumer stops, so clients can share the directory. Set a mounted path in production | `<temp>/prosody/keyed-state` |
|
|
146
148
|
| `state_owned_cache_size` / `PROSODY_STATE_OWNED_CACHE_SIZE` | Capacity of the owning keyed-state cache; accepts sizes such as `64 MiB` or `500 MB` | storage-engine default |
|
|
149
|
+
| `state_memtable_size` / `PROSODY_STATE_MEMTABLE_SIZE` | Bytes of in-memory writes the local keyed-state cache holds for each assigned partition before it flushes them to disk; accepts sizes such as `16 MiB`. Memory use scales with the number of assigned partitions | storage-engine default of 64 MiB |
|
|
147
150
|
| `state_read_cache_size` / `PROSODY_STATE_READ_CACHE_SIZE` | Capacity of the published-state read cache; accepts sizes such as `1 MiB` | `state_owned_cache_size` or `PROSODY_STATE_OWNED_CACHE_SIZE` when set; otherwise 1 MiB |
|
|
148
151
|
| `state_read_cache` / `PROSODY_STATE_READ_CACHE_TTL` | Default published-read cache TTL. Use `false` or the environment value `none` to bypass the cache | 5s |
|
|
149
|
-
| `state_recovery_delay` / `PROSODY_STATE_RECOVERY_DELAY` | Whole-second delay between staging a provisional cell and the recovery sweep; every collection TTL must strictly exceed it | 30s |
|
|
150
|
-
|
|
151
|
-
Prefer the definition constructors from the [API reference](README.md#api-reference). They serialize into `state_collections`, so you can reuse the same object with `context.state`. Each entry has these fields:
|
|
152
152
|
|
|
153
153
|
Published collections require `subsystem`. Keep it configured for one deployment after removing `published: true` so readers can observe the collection's retirement.
|
|
154
154
|
|
|
155
|
+
Prefer the definition constructors from the [API reference](README.md#api-reference). They serialize into `state_collections`, so you can reuse the same object with `context.state`. Each entry has these fields:
|
|
156
|
+
|
|
155
157
|
| Field | Description | Default |
|
|
156
158
|
|-------|-------------|---------|
|
|
157
159
|
| `name` | Collection name; non-empty and unique within the client | (required) |
|
|
158
|
-
| `kind` | `"value"`, `"map"`, or `"deque"` | (required) |
|
|
159
|
-
| `payload` | `"json"` (JSON values) or `"message"` (the full Kafka message the handler received) | (required) |
|
|
160
|
-
| `ttl_seconds` | Per-write TTL in whole seconds (at least 1
|
|
160
|
+
| `kind` | `"value"`, `"map"`, `"set"`, or `"deque"` | (required) |
|
|
161
|
+
| `payload` | `"json"` (JSON values) or `"message"` (the full Kafka message the handler received). Omit it for a set, which stores membership only | (required for a value, map, or deque) |
|
|
162
|
+
| `ttl_seconds` | Per-write TTL in whole seconds (at least 1) | (none) |
|
|
161
163
|
| `read_uncommitted` | Opt out of transactional staging | false |
|
|
162
|
-
| `published` | Allow read-only access from other consumer groups; JSON collections only | false |
|
|
163
|
-
| `
|
|
164
|
-
| `keyset_limit` | Map-only; ordered-scan bound in `0..=4096` (`0` disables ordered-scan tracking) | 128 |
|
|
164
|
+
| `published` | Allow read-only access from other consumer groups; JSON and set collections only | false |
|
|
165
|
+
| `keyset_limit` | Map and set only; ordered-scan bound in `0..=4096` (`0` disables ordered-scan tracking) | 128 |
|
|
165
166
|
| `capacity` | Deque-only window bound (at least 1); keeps at most N slots, enforced lazily on push. Runtime-only and mutable across deploys — not persisted | unbounded |
|
|
166
167
|
|
|
167
|
-
Constructors set these via keyword arguments (`ttl:`, `keyset_limit:`, `capacity:`, `read_uncommitted:`, `published
|
|
168
|
+
Constructors set these via keyword arguments (`ttl:`, `keyset_limit:`, `capacity:`, `read_uncommitted:`, `published:`).
|
|
169
|
+
|
|
170
|
+
A JSON or set constructor also takes `read_cache:`. It is not a registration field: it applies only to the readers that `client.state` opens with the definition. `read_cache` is a positive duration in seconds, `false` to bypass the cache, or `nil` to inherit the client default.
|