A Gleam WebSocket consumer for AT Protocol Jetstream events.
1# goose
2
3[](https://hex.pm/packages/goose)
4[](https://hexdocs.pm/goose/)
5
6A Gleam WebSocket consumer for AT Protocol Jetstream events.
7
8```sh
9gleam add goose
10```
11
12## Quick Start
13
14```gleam
15import goose
16import gleam/io
17
18pub fn main() {
19 // Use default config with automatic retry logic
20 let config = goose.default_config()
21
22 goose.start_consumer(config, fn(json_event) {
23 let event = goose.parse_event(json_event)
24
25 case event {
26 goose.CommitEvent(did, time_us, commit) -> {
27 io.println("Commit: " <> commit.operation <> " in " <> commit.collection)
28 }
29 goose.IdentityEvent(did, time_us, identity) -> {
30 io.println("Identity: " <> identity.handle)
31 }
32 goose.AccountEvent(did, time_us, account) -> {
33 io.println("Account updated: " <> did)
34 }
35 goose.UnknownEvent(_) -> {
36 io.println("Unknown event type")
37 }
38 }
39 })
40}
41```
42
43### Custom Configuration
44
45```gleam
46import goose
47import gleam/option
48
49pub fn main() {
50 let config = goose.JetstreamConfig(
51 endpoint: "wss://jetstream2.us-east.bsky.network/subscribe",
52 wanted_collections: ["app.bsky.feed.post", "app.bsky.feed.like"],
53 wanted_dids: [],
54 cursor: option.None,
55 max_message_size_bytes: option.None,
56 compress: True,
57 require_hello: False,
58 )
59
60 goose.start_consumer(config, handle_event)
61}
62```
63
64## Configuration Options
65
66**Note:** Goose automatically handles connection failures with exponential backoff retry logic (1s, 2s, 4s, 8s, 16s, 32s, capped at 60s). All connections automatically retry on failure and reconnect on disconnection.
67
68### `wanted_collections`
69An array of Collection NSIDs to filter which records you receive (default: empty = all collections)
70
71- Supports NSID path prefixes like `app.bsky.graph.*` or `app.bsky.*`
72- The prefix before `.*` must pass NSID validation
73- Incomplete prefixes like `app.bsky.graph.fo*` are not supported
74- Account and Identity events are always received regardless of this filter
75- Maximum 100 collections/prefixes
76
77**Example:**
78```gleam
79wanted_collections: ["app.bsky.feed.post", "app.bsky.graph.*"]
80```
81
82### `wanted_dids`
83An array of Repo DIDs to filter which records you receive (default: empty = all repos)
84
85- Maximum 10,000 DIDs
86
87**Example:**
88```gleam
89wanted_dids: ["did:plc:example123", "did:plc:example456"]
90```
91
92### `cursor`
93A unix microseconds timestamp to begin playback from
94
95- Absent cursor or future timestamp results in live-tail operation
96- When reconnecting, use `time_us` from your most recently processed event
97- Consider subtracting a few seconds as a buffer to ensure gapless playback
98
99**Example:**
100```gleam
101cursor: option.Some(1234567890123456)
102```
103
104### `max_message_size_bytes`
105The maximum size of a payload that this client would like to receive
106
107- Zero means no limit
108- Negative values are treated as zero
109- Default: 0 (no maximum size)
110
111**Example:**
112```gleam
113max_message_size_bytes: option.Some(1048576) // 1MB limit
114```
115
116### `compress`
117Enable zstd compression for WebSocket frames
118
119- Set to `True` to enable compression
120- Default: `False`
121- Uses zstandard compression with Jetstream's custom dictionary
122- Reduces bandwidth by approximately 50%
123- Messages are automatically decompressed before reaching your callback
124- Requires the `ezstd` library (automatically handled as a dependency)
125
126**Example:**
127```gleam
128compress: True
129```
130
131**Note:** Compression is transparent to your application - compressed messages are automatically decompressed before being passed to your event handler. The bandwidth savings occur on the wire between the server and your client.
132
133### `require_hello`
134Pause replay/live-tail until server receives a `SubscriberOptionsUpdatePayload`
135
136- Set to `True` to require initial handshake
137- Default: `False`
138
139**Example:**
140```gleam
141require_hello: True
142```
143
144## Full Configuration Example
145
146```gleam
147import goose
148import gleam/option
149
150let config = goose.JetstreamConfig(
151 endpoint: "wss://jetstream2.us-east.bsky.network/subscribe",
152 wanted_collections: ["app.bsky.feed.post", "app.bsky.graph.*"],
153 wanted_dids: ["did:plc:example123"],
154 cursor: option.Some(1234567890123456),
155 max_message_size_bytes: option.Some(2097152), // 2MB
156 compress: True,
157 require_hello: False,
158)
159
160goose.start_consumer(config, handle_event)
161```
162
163Further documentation can be found at <https://hexdocs.pm/goose>.
164
165## Development
166
167```sh
168gleam build # Build the project
169gleam test # Run the tests
170```