A Ruby gem for streaming data from the Bluesky/ATProto firehose
1## [0.7.0] - 2026-02-13
2
3The main change in this version is that inline [YARD documentation](https://rubydoc.info/gems/skyfall/) has been added. This was also a good opportunity to review some APIs and tweak some things in order to get Skyfall a bit closer to 1.0.
4
5New APIs:
6
7- the `Skyfall::Firehose` initializer now allows skipping `:subscribe_repos`, i.e. `.new(host)` or `.new(host, cursor)`
8- added `Skyfall::Jetstream::CommitMessage#operation` (aliased as `op`) which returns the (always single) operation in the `operations` array
9- added `#kind` as alias for `#type` in both `Message` classes
10- added a base class for error types, `Skyfall::Error`
11- added `#blocks` to `Skyfall::Firehose::SyncMessage`
12- added `#rev`, `#since` and `#prev_data` to `Skyfall::Firehose::CommitMessage`
13
14Deprecated & removed APIs:
15
16- removed deprecated `HandleMessage` and `TombstoneMessage` message classes
17- removed deprecated `CommitMessage#prev`
18- deprecated `#path` in both `Operation` classes
19
20Optimizations:
21
22- much faster `Skyfall::Firehose::Message#time` parsing on Ruby 3.2+
23- lazy decoding of sections in `CarArchive` – saves quite a lot of work if sections are only accessed through `Operation#raw_record`
24- added `frozen_string_literal: true` in all files to reduce garbage collection
25
26Access level changes:
27
28- restricted `Stream#start_heartbeat_timer` & `Stream#stop_heartbeat_timer` methods' access to private
29- restricted `Stream#handle_message` method access to protected
30- restricted `Stream#last_update` to read-only access
31- restricted `#inspectable_variables` access to either private or protected
32- relaxed `Stream#build_websocket_url` & `Stream#build_websocket_client` access from private to protected
33- fixed private class method `Skyfall::Firehose::Message.decode_cbor_objects` which wasn't actually private
34
35Additional validations and other changes:
36
37- `Stream#connect` throws an error if neither `on_message` nor `on_raw_message` handlers have been configured
38- `Message` subclasses do additional checks if the fields they require to not be nil aren't nil
39- `Message` subclasses raise an error if `.new` is called on a subclass (and not on the base `Message`) passing the data of a wrong kind of message (instead of returning e.g. a `CommitMessage` from `AccountMessage.new` as it worked previously)
40- made `LabelsMessage` a subclass of `Firehose::Message`
41- fixed the `require`s config in some files so they can be loaded in any order
42
43
44## [0.6.1] - 2026-01-08
45
46- added `:bsky_notif_declaration` shortcode for `app.bsky.notification.declaration` collection
47- throw error when trying to run two streams in one process (see b4a1514f5da28983205765e55724b5c4abe6c5e4 for details)
48- added protected `#send_data` and `#socket` methods in `Stream` for use in `Stream` subclasses (currently for the Tapfall gem)
49- added a way to customize headers sent when connecting in `Stream` subclasses through the `#request_headers` method
50
51## [0.6.0] - 2025-06-25
52
53- significantly speeded up reading of events from the binary firehose (`Skyfall::Firehose`) – up to 4-5x faster than before
54- removed the `Skyfall::Stream.new` constructor deprecated in 0.5.0
55
56## [0.5.1] - 2025-05-18
57
58- added support for the new `#sync` message type
59- added `#unknown?` helper in `Skyfall::Firehose::Message` and `Skyfall::Jetstream::Message`, which returns true if the message type is `UnknownMessage`
60- added `:bsky_verification` and `:bsky_actor_status` lexicon type and shortcode
61- added one missing require
62
63## [0.5.0] - 2024-11-15
64
65Jetstream support! You can now connect to [Jetstream](https://github.com/bluesky-social/jetstream) sources using `Skyfall::Jetstream` (see readme).
66
67This required some breaking changes in the existing API:
68
69- `Skyfall::Stream` has been renamed to `Skyfall::Firehose`, `Skyfall::Stream` is now a base class of both `Firehose` and `Jetstream`; the existing `Skyfall::Stream` constructor works for now but will be removed soon
70- `Skyfall::WebsocketMessage` and its subclasses have been separated into two parallel families under `Skyfall::Firehose` and `Skyfall::Jetstream`, with the base classes just named `Message`
71- same thing happened with `Skyfall::Operation`
72- `data_object` and `type_object` properties in `WebsocketMessage` are considered semi-private API now ("nodoc")
73
74In most cases, you should only need to update the `Skyfall::Stream` class name in the constructor. If you've referenced message classes like `Skyfall::CommitMessage` directly, it's probably better to just check the `#type` property instead.
75
76Also, small change to the user agent API: `Skyfall::Stream` now has an additional metod `version_string`, which will always return `Skyfall/0.x.y` – it's recommended to use that instead of `default_user_agent` to build your own user agent string that includes the library version. `default_user_agent` now passes through to `version_string`, but it could be changed in future to return something else.
77
78## [0.4.1] - 2024-10-04
79
80- performance fix – don't decode CAR sections which aren't needed, which is most of them; this cuts the amount of memory that GC has to free up by about one third, and should speed up processing by around ~10%
81
82## [0.4.0] - 2024-09-23
83
84- (re)added a "hearbeat" feature (removed earlier in 0.2.0) to fix the occasional issue when the websocket stops receiving data, but doesn't disconnect (not enabled by default, turn it on by setting `check_heartbeat` to true)
85- added a way to set the user agent sent when connecting using the `user_agent` field (default is `"Skyfall/#{version}"`)
86- added `app.bsky.feed.postgate` record type
87
88## [0.3.1] - 2024-06-28
89
90- added `app.bsky.graph.starterpack` and `chat.bsky.actor.declaration` record types
91- added `#account` event type (`AccountMessage`)
92- added `handle` field to `IdentityMessage`
93- fixed param validation on `Stream` initialization
94- reverted the change that added Ruby stdlib dependencies explicitly to the gemspec, since this causes more problems than it's worth – only `base64` is left there, since it's the one now required to be listed
95
96## [0.3.0] - 2024-03-21
97
98- added support for labeller firehose, served by labeller services at the `com.atproto.label.subscribeLabels` endpoint (aliased as `:subscribe_labels`)
99- the `#labels` messages from the labeller firehose are parsed into a `LabelsMessage`, which includes a `labels` array of `Label` objects
100- `Stream` callbacks can now also be assigned via setters, e.g. `stream.on_message = proc { ... }`
101- added default error handler to `Stream` which logs the error to `$stdout` – set `stream.on_error = nil` to disable
102- added Ruby stdlib dependencies explicitly to the gemspec – fixes a warning in Ruby 3.3 when requiring `base64`, which will be extracted as an optional gem in 3.4
103
104## [0.2.5] - 2024-03-14
105
106- added `:bsky_labeler` record type symbol & collection constant
107
108## [0.2.4] - 2024-02-27
109
110- added support for `#identity` message type
111- added `Operation#did` as an alias of `#repo`
112- added `Stream#reconnect` method which forces the websocket to reconnect
113- added some validation for the `cursor` parameter in `Stream` initializer
114- the `server` parameter in `Stream` initializer can be a full URL with scheme, which lets you connect to e.g. `ws://localhost` (since by default, `wss://` is used)
115- tweaked `#inspect` output of `Stream` and `Operation`
116
117## [0.2.3] - 2023-09-28
118
119- fixed encoding of image CIDs again (they should be wrapped in a `$link` object)
120- binary strings are now correctly returned as `$bytes` objects
121- added `list`, `listblock` and `threadgate` to record type symbols and collection constants
122
123## [0.2.2] - 2023-09-06
124
125- fixed image CIDs returned in the record JSON as CBOR tag objects (they are now returned decoded to the string form)
126
127## [0.2.1] - 2023-08-19
128
129- optimized `WebsocketMessage` parsing performance – lazy parsing of most properties (message decoding should be over 50% faster on average)
130- added separate subclasses of `WebsocketMessage` for different message types
131- added support for `#handle`, `#info` and `#tombstone` message types
132- `UnknownMessage` is returned for unrecognized message types
133
134## [0.2.0] - 2023-07-24
135
136- switched the websocket library from `websocket-client-simple` to `faye-websocket`, which should make event parsing up to ~30× faster (!)
137- added `auto_reconnect` property to `Stream` (on by default) – if true, it will try to reconnect with an exponential backoff when the websocket disconnects, until you call `Stream#disconnect`
138
139Note:
140
141- calling `sleep` is no longer needed after connecting – call `connect` on a new thread instead to get previously default behavior of running the event loop asynchronously
142- the disconnect event no longer passes an error object in the argument
143- there is currently no "heartbeat" feature as in 0.1.x that checks for a stuck connection – but it doesn't seem to be needed
144
145## [0.1.3] - 2023-07-04
146
147- allow passing a previously saved cursor to websocket to replay any missed events
148- the cursor is also kept in memory and automatically used when reconnecting
149- added "connecting" callback with url as argument
150- fixed connecting to websocket when endpoint is given as a string
151- improved error handling during parsing
152
153## [0.1.2] - 2023-06-15
154
155- added rkey property for Operation
156
157## [0.1.1] - 2023-06-13
158
159- added heartbeat thread to restart websocket if it stops responding
160
161## [0.1.0] - 2023-06-01
162
163- connecting to the firehose websocket
164
165## [0.0.1] - 2023-05-31
166
167Initial release:
168
169- parsing CBOR objects from a websocket message
170- parsing CIDs, CAR archives and operation details from the objects