wicked-bus 1.0.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.
- package/README.md +153 -0
- package/commands/cli.js +129 -0
- package/commands/cmd-ack.js +31 -0
- package/commands/cmd-cleanup.js +44 -0
- package/commands/cmd-deregister.js +26 -0
- package/commands/cmd-emit.js +52 -0
- package/commands/cmd-init.js +30 -0
- package/commands/cmd-list.js +39 -0
- package/commands/cmd-register.js +29 -0
- package/commands/cmd-replay.js +65 -0
- package/commands/cmd-status.js +70 -0
- package/commands/cmd-subscribe.js +102 -0
- package/install.mjs +83 -0
- package/lib/config.js +87 -0
- package/lib/db.js +72 -0
- package/lib/emit.js +111 -0
- package/lib/errors.js +45 -0
- package/lib/index.cjs +20 -0
- package/lib/index.js +13 -0
- package/lib/paths.js +69 -0
- package/lib/poll.js +212 -0
- package/lib/register.js +164 -0
- package/lib/schema.sql +68 -0
- package/lib/sweep.js +71 -0
- package/lib/validate.js +156 -0
- package/package.json +56 -0
- package/scripts/postinstall.js +14 -0
- package/skills/wicked-bus/emit/SKILL.md +147 -0
- package/skills/wicked-bus/init/SKILL.md +94 -0
- package/skills/wicked-bus/naming/SKILL.md +151 -0
- package/skills/wicked-bus/query/SKILL.md +177 -0
- package/skills/wicked-bus/subscribe/SKILL.md +164 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Subscribe to wicked-bus events. Use when consuming events from the bus, setting up event listeners, polling for new events, or integrating as a subscriber. Covers registration, polling, acknowledgment, and filter patterns.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# wicked-bus:subscribe
|
|
6
|
+
|
|
7
|
+
Guide for consuming events from the wicked-bus.
|
|
8
|
+
|
|
9
|
+
## When to use
|
|
10
|
+
|
|
11
|
+
- User wants to listen for events
|
|
12
|
+
- User asks "how do I subscribe to the bus" or "how do I consume events"
|
|
13
|
+
- Setting up a new subscriber integration
|
|
14
|
+
- User needs help with filter patterns
|
|
15
|
+
|
|
16
|
+
## Prerequisites
|
|
17
|
+
|
|
18
|
+
Check that wicked-bus is initialized. If not, trigger `wicked-bus-init`.
|
|
19
|
+
|
|
20
|
+
## CLI Usage (quickest way to start)
|
|
21
|
+
|
|
22
|
+
### Subscribe to events (streaming)
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# All run events from any source
|
|
26
|
+
npx wicked-bus subscribe --filter 'wicked.run.*'
|
|
27
|
+
|
|
28
|
+
# Only from a specific domain
|
|
29
|
+
npx wicked-bus subscribe --filter 'wicked.run.*@wicked-testing'
|
|
30
|
+
|
|
31
|
+
# Everything from a domain
|
|
32
|
+
npx wicked-bus subscribe --filter '*@wicked-brain'
|
|
33
|
+
|
|
34
|
+
# Without auto-acknowledgment
|
|
35
|
+
npx wicked-bus subscribe --filter 'wicked.phase.*' --no-ack
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Output is NDJSON — one JSON object per line per event.
|
|
39
|
+
|
|
40
|
+
### Register then poll manually
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Register as subscriber
|
|
44
|
+
npx wicked-bus register \
|
|
45
|
+
--role subscriber \
|
|
46
|
+
--plugin my-consumer \
|
|
47
|
+
--filter 'wicked.run.*' \
|
|
48
|
+
--cursor-init latest
|
|
49
|
+
|
|
50
|
+
# Poll (uses cursor from registration)
|
|
51
|
+
npx wicked-bus subscribe --plugin my-consumer --filter 'wicked.run.*'
|
|
52
|
+
|
|
53
|
+
# Manual ack
|
|
54
|
+
npx wicked-bus ack --cursor-id {cursor_id} --event-id {event_id}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Programmatic Usage (Node.js)
|
|
58
|
+
|
|
59
|
+
### Basic poll loop
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
import { poll, ack } from 'wicked-bus';
|
|
63
|
+
import { loadConfig } from 'wicked-bus/lib/config.js';
|
|
64
|
+
import { openDb } from 'wicked-bus/lib/db.js';
|
|
65
|
+
import { register } from 'wicked-bus/lib/register.js';
|
|
66
|
+
|
|
67
|
+
const config = loadConfig();
|
|
68
|
+
const db = openDb(config);
|
|
69
|
+
|
|
70
|
+
// Register (idempotent — safe to call on every startup)
|
|
71
|
+
const sub = register(db, {
|
|
72
|
+
plugin: 'my-consumer',
|
|
73
|
+
role: 'subscriber',
|
|
74
|
+
event_type_filter: 'wicked.run.*',
|
|
75
|
+
cursor_init: 'latest',
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Poll for new events
|
|
79
|
+
const events = poll(db, config, {
|
|
80
|
+
cursor_id: sub.cursor_id,
|
|
81
|
+
filter: 'wicked.run.*',
|
|
82
|
+
batch_size: 10,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
for (const event of events.events) {
|
|
86
|
+
console.log(event.event_type, event.payload);
|
|
87
|
+
// Process the event...
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Acknowledge (advances the cursor)
|
|
91
|
+
if (events.events.length > 0) {
|
|
92
|
+
const lastId = events.events[events.events.length - 1].event_id;
|
|
93
|
+
ack(db, { cursor_id: sub.cursor_id, event_id: lastId });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
db.close();
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Fire-and-forget subscriber (for integrations)
|
|
100
|
+
|
|
101
|
+
Plugins that react to bus events but should never block:
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
async function checkBusEvents() {
|
|
105
|
+
try {
|
|
106
|
+
const { poll, ack } = await import('wicked-bus');
|
|
107
|
+
const { loadConfig } = await import('wicked-bus/lib/config.js');
|
|
108
|
+
const { openDb } = await import('wicked-bus/lib/db.js');
|
|
109
|
+
|
|
110
|
+
const config = loadConfig();
|
|
111
|
+
const db = openDb(config);
|
|
112
|
+
|
|
113
|
+
const result = poll(db, config, {
|
|
114
|
+
cursor_id: myCursorId,
|
|
115
|
+
filter: 'wicked.phase.*@wicked-garden',
|
|
116
|
+
batch_size: 50,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
for (const event of result.events) {
|
|
120
|
+
// React to the event (non-blocking)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (result.events.length > 0) {
|
|
124
|
+
const lastId = result.events[result.events.length - 1].event_id;
|
|
125
|
+
ack(db, { cursor_id: myCursorId, event_id: lastId });
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
db.close();
|
|
129
|
+
} catch (_) {
|
|
130
|
+
// Bus unavailable — degrade gracefully
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Filter Patterns
|
|
136
|
+
|
|
137
|
+
| Pattern | Matches |
|
|
138
|
+
|---------|---------|
|
|
139
|
+
| `wicked.run.completed` | Exact match only |
|
|
140
|
+
| `wicked.run.*` | All `wicked.run.` events (single-level wildcard) |
|
|
141
|
+
| `*@wicked-brain` | All events from the `wicked-brain` domain |
|
|
142
|
+
| `wicked.memory.*@wicked-brain` | Memory events from brain only |
|
|
143
|
+
|
|
144
|
+
### Filter rules
|
|
145
|
+
|
|
146
|
+
1. `*` matches exactly one segment (single-level wildcard)
|
|
147
|
+
2. `@domain` suffix scopes by the `domain` column
|
|
148
|
+
3. Wildcards and `@domain` can combine: `wicked.run.*@my-plugin`
|
|
149
|
+
4. `*` alone (catch-all) is valid but noisy
|
|
150
|
+
|
|
151
|
+
## Delivery Semantics
|
|
152
|
+
|
|
153
|
+
- **At-least-once**: unacked events are re-delivered on next poll
|
|
154
|
+
- **Cursor-based**: each subscriber has its own cursor position
|
|
155
|
+
- **Batch polling**: use `batch_size` to control how many events per poll
|
|
156
|
+
- **Visibility filter**: events past `expires_at` are invisible to poll
|
|
157
|
+
- **WB-003 warning**: if your cursor is behind the oldest event, you may have missed events
|
|
158
|
+
|
|
159
|
+
## Error Handling
|
|
160
|
+
|
|
161
|
+
| Error | Code | Meaning |
|
|
162
|
+
|-------|------|---------|
|
|
163
|
+
| WB-003 | CURSOR_BEHIND | Cursor is behind oldest available event — events may have been missed |
|
|
164
|
+
| WB-006 | CURSOR_NOT_FOUND | Cursor ID doesn't exist or was deregistered |
|