yrby-rails 0.4.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 +7 -0
- data/CHANGELOG-rails.md +123 -0
- data/LICENSE +21 -0
- data/README.md +753 -0
- data/app/models/y/document.rb +182 -0
- data/app/models/y/document_update.rb +10 -0
- data/lib/generators/yrby/install/USAGE +11 -0
- data/lib/generators/yrby/install/install_generator.rb +44 -0
- data/lib/generators/yrby/install/templates/document_channel.rb +36 -0
- data/lib/generators/yrby/tables/tables_generator.rb +41 -0
- data/lib/generators/yrby/tables/templates/create_y_tables.rb +24 -0
- data/lib/y/action_cable/sync.rb +333 -0
- data/lib/y/action_cable.rb +23 -0
- data/lib/yrby/engine.rb +11 -0
- data/lib/yrby/rails/version.rb +7 -0
- data/lib/yrby-rails.rb +6 -0
- metadata +175 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 1fe04378813fb80d02f8a7044258741096d7db25ddfca9d15451055bb00893a0
|
|
4
|
+
data.tar.gz: fa3f4d4f4b5bd62884c56235addb80c38c0c6b2185ffeb8f7862b83389bbcbd0
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 4e1226ee5c5de50fb97cd8712f2e9dd4ac0730be26449d0053e177910516308caf7021b0b0e192b63ae19f693c417455fcdab53d45135434acae72352064550e
|
|
7
|
+
data.tar.gz: 5a47202000292a09671ce92791b5accc72400eb13e035d26994c65bf490b0b1c8abddb30a69d0c73fb1876ff01db7736fe1fc18707367dbcf74ae822b37eca30
|
data/CHANGELOG-rails.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Changelog — yrby-rails
|
|
2
|
+
|
|
3
|
+
All notable changes to the `yrby-rails` gem (formerly `yrby-actioncable`) are
|
|
4
|
+
documented here. The
|
|
5
|
+
format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
|
6
|
+
this project aims to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.4.0] - 2026-08-04
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **The gem is now `yrby-rails`** (formerly `yrby-actioncable`) and a Rails
|
|
13
|
+
engine. `yrby-actioncable` stops at 0.3.1; `yrby-rails` starts at 0.4.0.
|
|
14
|
+
`Y::ActionCable` keeps its name as the public channel concern.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- `Y::Document`, engine-owned: a unique transport `key`, an optional
|
|
19
|
+
polymorphic `record` + `name` binding, and the compacted `state`
|
|
20
|
+
snapshot. It stores CRDT state only; derived data (rendered HTML,
|
|
21
|
+
search text) is the application's job. `load_state(key)` /
|
|
22
|
+
`append(key, update)` are the store calls the generated channel uses;
|
|
23
|
+
`locate`/`locate!` find by key.
|
|
24
|
+
- `Y::DocumentUpdate`, engine-owned: the uncompacted tail, one delta per
|
|
25
|
+
row, compacted into `state` and deleted at the threshold. A load reads
|
|
26
|
+
the snapshot plus the current tail. Compaction serializes on a
|
|
27
|
+
per-document row lock. Causally-gapped updates
|
|
28
|
+
are quarantined (`pending`), excluded from the compaction trigger, and
|
|
29
|
+
kept until they heal; a healed gap serves immediately and compacts away
|
|
30
|
+
on the next pass.
|
|
31
|
+
- `Y::Document.for(record, name)` finds or creates a record's document,
|
|
32
|
+
derives its key (`post/1/body`), and adopts a key-only row already
|
|
33
|
+
holding that key, so a channel writing first and a binding created
|
|
34
|
+
later end up on one row.
|
|
35
|
+
- `rails g yrby:tables` creates both tables. It is invoked by
|
|
36
|
+
`yrby:install` and usable directly by gems building on the same
|
|
37
|
+
storage.
|
|
38
|
+
- `include Y::ActionCable` now includes `Y::ActionCable::Sync` for you;
|
|
39
|
+
the long spelling keeps working.
|
|
40
|
+
- `rails generate yrby:install`: a `DocumentChannel` speaking the
|
|
41
|
+
y-websocket protocol over the gem-owned storage, plus the storage
|
|
42
|
+
migration.
|
|
43
|
+
|
|
44
|
+
## [0.3.1] - 2026-07-01
|
|
45
|
+
|
|
46
|
+
### Removed
|
|
47
|
+
|
|
48
|
+
- The unhealable-gap strike defense that shipped in 0.3.0. That release was
|
|
49
|
+
published prematurely, before the feature had been reviewed; 0.3.1 supersedes
|
|
50
|
+
it with the defense removed while review happens. 0.3.0 remains installable
|
|
51
|
+
and functional; the feature returns in a future release once reviewed.
|
|
52
|
+
|
|
53
|
+
## [0.3.0] - 2026-07-01
|
|
54
|
+
|
|
55
|
+
Published prematurely (see 0.3.1): shipped the unhealable-gap strike defense
|
|
56
|
+
(settle + drop a repeatedly-gapped update, `{ "ack" => id, "dropped" => true }`,
|
|
57
|
+
`gap_strike_limit`, istate-backed strikes under AnyCable) alongside the fixes
|
|
58
|
+
below. The fixes carry forward; the defense was withdrawn in 0.3.1 pending
|
|
59
|
+
review.
|
|
60
|
+
|
|
61
|
+
Fixes from a full source review:
|
|
62
|
+
|
|
63
|
+
### Fixed
|
|
64
|
+
|
|
65
|
+
- **A lost-ack retry now re-broadcasts.** If the original attempt recorded the
|
|
66
|
+
update and then crashed (or the pub/sub broadcast failed) before
|
|
67
|
+
distributing, the retry was previously settled as `:applied` without
|
|
68
|
+
re-broadcasting — live subscribers stayed stale until their next full resync,
|
|
69
|
+
and nothing else could reach them. The retry now re-broadcasts before acking;
|
|
70
|
+
idempotent CRDT apply makes the duplicate free for every receiver.
|
|
71
|
+
- **A missing document key now fails closed.** Under a transport that doesn't
|
|
72
|
+
keep the channel instance alive across actions (AnyCable), an app that forgot
|
|
73
|
+
to pass `key` to `sync_receive` silently recorded updates under a nil key,
|
|
74
|
+
broadcast them to a stream no one subscribes to, and still acked them. The
|
|
75
|
+
frame now raises `Y::Error` instead.
|
|
76
|
+
|
|
77
|
+
### Changed
|
|
78
|
+
|
|
79
|
+
- Raised the `yrby` floor to `>= 0.3.1`, whose `update_ready?` is exact
|
|
80
|
+
(trial-integration, not just per-client clocks). With an older core, a
|
|
81
|
+
cross-client-origin gap passed the ready check and the `update_advances?`
|
|
82
|
+
probe then acked-and-dropped real content.
|
|
83
|
+
|
|
84
|
+
## [0.2.3] - 2026-07-01
|
|
85
|
+
|
|
86
|
+
### Changed
|
|
87
|
+
- Raised the `yrby` floor to `>= 0.3.0`. That release makes
|
|
88
|
+
`Doc#handle_sync_message` answer `SyncStep1` with integrated-only (gap-free)
|
|
89
|
+
state — it no longer serves un-integrable pending structs, which previously
|
|
90
|
+
poisoned peers and drove endless resync traffic. The sync channel serves its
|
|
91
|
+
SyncStep2 response through that method, so with an older core a poisoned server
|
|
92
|
+
store would still hand the gap to clients. No code change here — pinning the
|
|
93
|
+
floor makes gap-free serving self-enforcing instead of dependent on the app
|
|
94
|
+
updating the core gem.
|
|
95
|
+
|
|
96
|
+
## [0.2.2] - 2026-07-01
|
|
97
|
+
|
|
98
|
+
### Changed
|
|
99
|
+
- Raised the `yrby` floor to `>= 0.2.3`. That release makes `Doc#update_advances?`
|
|
100
|
+
exact for **delete-bearing** updates. The sync channel gates durable
|
|
101
|
+
record-before-distribute on `update_advances?` (`return :applied unless
|
|
102
|
+
doc.update_advances?(update)`), so with an older core a lost-ack retry of a
|
|
103
|
+
deletion the server had already integrated was re-recorded and re-broadcast
|
|
104
|
+
each time. No code change here — pinning the floor just makes the gem's
|
|
105
|
+
exactly-once durable-recording guarantee self-enforcing instead of dependent on
|
|
106
|
+
the app updating the core gem.
|
|
107
|
+
|
|
108
|
+
## [0.2.1] - 2026-06-29
|
|
109
|
+
|
|
110
|
+
### Changed
|
|
111
|
+
- **Internal:** ActionCable stream-name prefix `y_ruby:` → `yrby:`.
|
|
112
|
+
Server-internal (broadcast + `stream_from` both use it) — no public API or
|
|
113
|
+
client-facing wire change. Depends on `yrby >= 0.2.1`.
|
|
114
|
+
|
|
115
|
+
## [0.2.0] - 2026-06-28
|
|
116
|
+
|
|
117
|
+
First release. The y-websocket sync channel concern is **`Y::ActionCable::Sync`**,
|
|
118
|
+
loaded with `require "y/action_cable"`. Depends on `yrby >= 0.2.0`.
|
|
119
|
+
|
|
120
|
+
### Notes
|
|
121
|
+
- Full y-websocket protocol over ActionCable/AnyCable: origin-filtered relay,
|
|
122
|
+
awareness, on_load/on_save persistence hooks, optional record-before-distribute
|
|
123
|
+
audit mode, and AnyCable `sync_backend :store`.
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|