where_is_waldo 0.1.10 → 0.1.11
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/CHANGELOG.md +55 -0
- data/README.md +21 -0
- data/VERSION +1 -1
- data/lib/generators/where_is_waldo/install/install_generator.rb +35 -3
- data/lib/generators/where_is_waldo/install/templates/migration.rb.tt +6 -1
- metadata +11 -9
- data/lib/generators/where_is_waldo/install/templates/create_presences.rb.tt +0 -44
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5bd28c86d109c69fc976eaab788972106493a78b3fbd8e8e2370bae5dc936986
|
|
4
|
+
data.tar.gz: fd49e94bf3a08dd4350fdc1b8b413ec5d66916ef1ada8c74162044b3ccbdc428
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 620c8ce6c899937a25ab39f2858e45c5fa6ac68dc3510cf0e47a5739b36a8f95c24bb3daf385974600ffa652ad32f176a79ac0389286520af7a291bc48cda1e7
|
|
7
|
+
data.tar.gz: 0ecf65ed538cbffc439428ed3f5acc690e178430ba62a9568fb1b4a1d4cb48f33303aaa9724979f8c1c0ebfc44da5eb35133665345a2dfc2d4a3a224373784d7
|
data/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,61 @@
|
|
|
3
3
|
Notable changes to where_is_waldo. Format loosely follows
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/).
|
|
5
5
|
|
|
6
|
+
## Unreleased
|
|
7
|
+
|
|
8
|
+
## 0.1.11 - 2026-10-27
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **The install generator emitted the pre-0.1.5 schema.** It wrote a unique
|
|
13
|
+
index on the session column alone, while 0.1.5 moved presence rows to being
|
|
14
|
+
keyed by `(subject, session)` precisely so two authenticated subjects who
|
|
15
|
+
collide on a session id cannot upsert onto each other's row — session ids are
|
|
16
|
+
client-supplied in some setups, and a reused JWT `jti` is enough. The adapter
|
|
17
|
+
has scoped every session lookup by both columns since; only the generator
|
|
18
|
+
lagged, so every app installed after 0.1.5 got a schema the library had
|
|
19
|
+
already moved away from and needed a follow-up migration to correct. An
|
|
20
|
+
unused second migration template carrying the right index (and a hardcoded
|
|
21
|
+
`Migration[7.0]`) has been removed rather than left as a second answer.
|
|
22
|
+
|
|
23
|
+
- **The install generator overwrote an existing ActionCable connection.**
|
|
24
|
+
Installing into an app that already authenticates its own cable connection
|
|
25
|
+
replaced that file with the turnkey one, silently dropping whatever the app
|
|
26
|
+
did beyond what this library needs — container scoping and token bookkeeping
|
|
27
|
+
in the cases seen. Existing channel files are now kept, and the post-install
|
|
28
|
+
message names them and states what the channel requires of a connection
|
|
29
|
+
(`current_user` and `session_id`).
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- **The Redis adapter is now tested against a real server, on both redis-rb 5
|
|
34
|
+
and 6.** Its existing spec runs against `MockRedis`, a pure-Ruby fake with no
|
|
35
|
+
protocol layer, so it could not see wire-format changes at all. redis-rb 6
|
|
36
|
+
defaults to RESP3, which types several replies differently from RESP2 —
|
|
37
|
+
`SMEMBERS` among them, and this adapter feeds that result straight into
|
|
38
|
+
`filter_map` and `all?`. Nothing in the adapter's command set behaves
|
|
39
|
+
differently between the two, but that was previously unverified rather than
|
|
40
|
+
known.
|
|
41
|
+
|
|
42
|
+
- New integration spec drives the adapter against a live Redis. It skips when
|
|
43
|
+
no server is reachable, so contributors are not required to run one.
|
|
44
|
+
- CI adds an `rspec-redis` job with a Redis service, run as a matrix over
|
|
45
|
+
redis-rb 5.x and 6.x, and fails rather than skips if the service is missing
|
|
46
|
+
— a silent skip would read as a pass.
|
|
47
|
+
- Development dependency widened from `~> 5.0` to `>= 5.0, < 7`. The gem has
|
|
48
|
+
no runtime dependency on `redis` and never has, so this constrains nothing
|
|
49
|
+
for consumers; it only lets the library test what consumers actually use.
|
|
50
|
+
- README documents supported client versions, and that `protocol: 2` is not
|
|
51
|
+
needed.
|
|
52
|
+
|
|
53
|
+
The committed lockfile stays on redis 5.x, which keeps `mock_redis` at
|
|
54
|
+
0.53.0 for every existing spec. `mock_redis` 0.53.0 depends on `redis ~> 5`,
|
|
55
|
+
so resolving against redis 6 forces it down to 0.48.1 — that happens only
|
|
56
|
+
inside the redis 6 CI leg, which runs the real-server spec alone and never
|
|
57
|
+
touches MockRedis. No mock-based spec changed the double it runs against.
|
|
58
|
+
|
|
59
|
+
No runtime code changed.
|
|
60
|
+
|
|
6
61
|
## 0.1.10
|
|
7
62
|
|
|
8
63
|
### Added
|
data/README.md
CHANGED
|
@@ -41,6 +41,13 @@ rails generate where_is_waldo:install --adapter=redis --subject_column=user_id
|
|
|
41
41
|
npm install @byscott-io/where-is-waldo @rails/actioncable
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
+
Installing into an app that already has `app/channels/application_cable/`?
|
|
45
|
+
Those files are kept, never overwritten — the generator only adds what is
|
|
46
|
+
missing, and says which it left alone. The presence channel needs the
|
|
47
|
+
connection to identify **`current_user`** and **`session_id`**; add them to
|
|
48
|
+
your own connection, or `include WhereIsWaldo::JwtConnection` (corebyscott
|
|
49
|
+
apps) to get both from the JWT.
|
|
50
|
+
|
|
44
51
|
### 2. Configure
|
|
45
52
|
|
|
46
53
|
```ruby
|
|
@@ -148,6 +155,20 @@ WhereIsWaldo.configure do |config|
|
|
|
148
155
|
end
|
|
149
156
|
```
|
|
150
157
|
|
|
158
|
+
#### Redis adapter and client versions
|
|
159
|
+
|
|
160
|
+
The gem does not depend on `redis`. Choosing `:redis` means supplying your own
|
|
161
|
+
client, so you pick the version.
|
|
162
|
+
|
|
163
|
+
`redis-rb` 5.x and 6.x are both supported and both run in CI against a real
|
|
164
|
+
server. Version 6 switched to RESP3 by default, which changes reply types for
|
|
165
|
+
some commands; none of the commands this adapter uses behave differently, and
|
|
166
|
+
the integration spec exists to keep that true. Nothing here needs `protocol: 2`.
|
|
167
|
+
|
|
168
|
+
The adapter stores presence under keys prefixed by `config.redis_prefix`
|
|
169
|
+
(default `where_is_waldo`) and sets a TTL on session keys, so it does not need a
|
|
170
|
+
cleanup job the way the database adapter does.
|
|
171
|
+
|
|
151
172
|
### Querying Presence
|
|
152
173
|
|
|
153
174
|
```ruby
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.11
|
|
@@ -32,9 +32,17 @@ module WhereIsWaldo
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def create_channels
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
# NEVER overwrite an app's existing cable connection or channel base.
|
|
36
|
+
# A host app that already authenticates ActionCable has its auth,
|
|
37
|
+
# container scoping and session identity in those files, and the
|
|
38
|
+
# turnkey versions here provide only what this library needs -- so
|
|
39
|
+
# replacing them silently drops whatever else they did. Installing
|
|
40
|
+
# into an existing app is the common case, not the exception.
|
|
41
|
+
@kept_channels = []
|
|
42
|
+
|
|
43
|
+
copy_channel "connection.rb.tt", "app/channels/application_cable/connection.rb"
|
|
44
|
+
copy_channel "channel.rb.tt", "app/channels/application_cable/channel.rb"
|
|
45
|
+
copy_channel "presence_channel.rb.tt", "app/channels/presence_channel.rb"
|
|
38
46
|
end
|
|
39
47
|
|
|
40
48
|
def show_post_install_message
|
|
@@ -54,10 +62,34 @@ module WhereIsWaldo
|
|
|
54
62
|
say " <App />"
|
|
55
63
|
say " </PresenceProvider>"
|
|
56
64
|
say ""
|
|
65
|
+
report_kept_channels
|
|
57
66
|
end
|
|
58
67
|
|
|
59
68
|
private
|
|
60
69
|
|
|
70
|
+
# Say plainly what was left alone. A silent skip is as confusing as a
|
|
71
|
+
# silent overwrite: the install looks complete and presence then fails
|
|
72
|
+
# because the app's own connection exposes no session identity.
|
|
73
|
+
def report_kept_channels
|
|
74
|
+
return if @kept_channels.blank?
|
|
75
|
+
|
|
76
|
+
say "Kept your existing files (not overwritten):", :yellow
|
|
77
|
+
@kept_channels.each { |f| say " - #{f}" }
|
|
78
|
+
say ""
|
|
79
|
+
say " WhereIsWaldo's channel reads connection.current_user and"
|
|
80
|
+
say " connection.session_id. If your connection does not identify"
|
|
81
|
+
say " both, add them -- or include WhereIsWaldo::JwtConnection."
|
|
82
|
+
say ""
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def copy_channel(source, destination)
|
|
86
|
+
if File.exist?(File.join(destination_root, destination))
|
|
87
|
+
@kept_channels << destination
|
|
88
|
+
else
|
|
89
|
+
template source, destination
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
61
93
|
def migration_version
|
|
62
94
|
"[#{ActiveRecord::VERSION::STRING.to_f}]"
|
|
63
95
|
end
|
|
@@ -14,7 +14,12 @@ class CreatePresences < ActiveRecord::Migration<%= migration_version %>
|
|
|
14
14
|
t.timestamps
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
# (subject, session) must be unique TOGETHER, never session alone. Session
|
|
18
|
+
# ids are not globally unique -- they are client-supplied in some setups,
|
|
19
|
+
# and a reused JWT jti is enough -- so keying on the session alone lets two
|
|
20
|
+
# authenticated subjects upsert onto each other's presence row. This is the
|
|
21
|
+
# keying the adapter uses: every session lookup scopes by both columns.
|
|
22
|
+
add_index :presences, [ :<%= subject_column %>, :<%= session_column %> ], unique: true
|
|
18
23
|
add_index :presences, :last_heartbeat
|
|
19
24
|
end
|
|
20
25
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: where_is_waldo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.11
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Scott Gibson
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: rails
|
|
@@ -84,16 +83,22 @@ dependencies:
|
|
|
84
83
|
name: redis
|
|
85
84
|
requirement: !ruby/object:Gem::Requirement
|
|
86
85
|
requirements:
|
|
87
|
-
- - "
|
|
86
|
+
- - ">="
|
|
88
87
|
- !ruby/object:Gem::Version
|
|
89
88
|
version: '5.0'
|
|
89
|
+
- - "<"
|
|
90
|
+
- !ruby/object:Gem::Version
|
|
91
|
+
version: '7'
|
|
90
92
|
type: :development
|
|
91
93
|
prerelease: false
|
|
92
94
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
95
|
requirements:
|
|
94
|
-
- - "
|
|
96
|
+
- - ">="
|
|
95
97
|
- !ruby/object:Gem::Version
|
|
96
98
|
version: '5.0'
|
|
99
|
+
- - "<"
|
|
100
|
+
- !ruby/object:Gem::Version
|
|
101
|
+
version: '7'
|
|
97
102
|
- !ruby/object:Gem::Dependency
|
|
98
103
|
name: rspec-rails
|
|
99
104
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -210,7 +215,6 @@ files:
|
|
|
210
215
|
- lib/generators/where_is_waldo/install/install_generator.rb
|
|
211
216
|
- lib/generators/where_is_waldo/install/templates/channel.rb.tt
|
|
212
217
|
- lib/generators/where_is_waldo/install/templates/connection.rb.tt
|
|
213
|
-
- lib/generators/where_is_waldo/install/templates/create_presences.rb.tt
|
|
214
218
|
- lib/generators/where_is_waldo/install/templates/initializer.rb.tt
|
|
215
219
|
- lib/generators/where_is_waldo/install/templates/migration.rb.tt
|
|
216
220
|
- lib/generators/where_is_waldo/install/templates/presence_channel.rb.tt
|
|
@@ -228,7 +232,6 @@ metadata:
|
|
|
228
232
|
changelog_uri: https://github.com/byscott-io/where_is_waldo/blob/master/CHANGELOG.md
|
|
229
233
|
allowed_push_host: https://rubygems.org
|
|
230
234
|
rubygems_mfa_required: 'true'
|
|
231
|
-
post_install_message:
|
|
232
235
|
rdoc_options: []
|
|
233
236
|
require_paths:
|
|
234
237
|
- lib
|
|
@@ -243,8 +246,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
243
246
|
- !ruby/object:Gem::Version
|
|
244
247
|
version: '0'
|
|
245
248
|
requirements: []
|
|
246
|
-
rubygems_version:
|
|
247
|
-
signing_key:
|
|
249
|
+
rubygems_version: 4.0.16
|
|
248
250
|
specification_version: 4
|
|
249
251
|
summary: Real-time presence tracking for Rails + React applications
|
|
250
252
|
test_files: []
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
class Create<%= table_name.camelize %> < ActiveRecord::Migration[7.0]
|
|
4
|
-
def change
|
|
5
|
-
create_table :<%= table_name %> do |t|
|
|
6
|
-
# Identifiers - column names are configurable
|
|
7
|
-
t.string :<%= session_column %>, null: false # Unique session/connection identifier
|
|
8
|
-
t.bigint :<%= subject_column %>, null: false # Who (user, member, student, etc.)
|
|
9
|
-
|
|
10
|
-
# Timestamps
|
|
11
|
-
t.datetime :connected_at, null: false
|
|
12
|
-
t.datetime :last_heartbeat, null: false
|
|
13
|
-
t.datetime :last_activity
|
|
14
|
-
|
|
15
|
-
# Activity state
|
|
16
|
-
t.boolean :tab_visible, default: true, null: false
|
|
17
|
-
t.boolean :subject_active, default: true, null: false
|
|
18
|
-
|
|
19
|
-
# Extensible metadata
|
|
20
|
-
t.<%= json_column_type %> :metadata
|
|
21
|
-
|
|
22
|
-
t.timestamps
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# (subject, session) must be unique together. Keying by session alone
|
|
26
|
-
# would let two authenticated subjects that happen to collide on a
|
|
27
|
-
# session id (client-supplied values, JWT jti reuse, etc.) upsert onto
|
|
28
|
-
# each other's row.
|
|
29
|
-
add_index :<%= table_name %>, [:<%= subject_column %>, :<%= session_column %>], unique: true
|
|
30
|
-
|
|
31
|
-
# Session lookups (heartbeat, disconnect, session_status) always scope
|
|
32
|
-
# by (subject, session); the composite unique index above serves those.
|
|
33
|
-
# Query by subject alone
|
|
34
|
-
add_index :<%= table_name %>, :<%= subject_column %>
|
|
35
|
-
|
|
36
|
-
# Cleanup old records
|
|
37
|
-
add_index :<%= table_name %>, :last_heartbeat
|
|
38
|
-
|
|
39
|
-
<% if subject_table.present? -%>
|
|
40
|
-
# Foreign key to subject table
|
|
41
|
-
add_foreign_key :<%= table_name %>, :<%= subject_table %>, column: :<%= subject_column %>
|
|
42
|
-
<% end -%>
|
|
43
|
-
end
|
|
44
|
-
end
|