Faye to ActionCable: broadcasting modernization #1

Merged
bterkuile merged 16 commits from feat/review-improve-and-document-the-broadcasting-model into master 2026-05-17 21:23:37 +02:00

16 Commits

Author SHA1 Message Date
BenClaw c48f4d9041 fix(action_cable): allow employee to subscribe to supplier channel
- Employee authenticates via auth_token, acts on behalf of a Supplier
- Connection now accepts ?supplier_id=ID query param
- identified_by :current_supplier_id added
- MozoChannel#authorized? allows :employee to subscribe to supplier_<id>
  when current_supplier_id matches
2026-05-17 21:08:38 +02:00
BenClaw 4a4e076416 fix(action_cable): use Redis adapter in development too
- async adapter is in-process — works in Puma request cycle
  but fails from Rails console (no event loop to deliver messages)
- Redis is shared-state, works from any context (console, jobs, requests)
- Dev uses Redis DB 2, separate channel_prefix from production
2026-05-17 20:16:01 +02:00
BenClaw 02df03282e Revert "fix(broadcasting): broadcast on mark_helped! even when already false"
This reverts commit 4ad701c1a5.
2026-05-17 20:12:22 +02:00
BenClaw 4ad701c1a5 fix(broadcasting): broadcast on mark_helped! even when already false
- mark_helped! gated broadcast on if save, but save returns false
  when needs_help is already false (no dirty attributes in CouchDB)
- Same fix applied to remove_needs_payment!
- Broadcast is the important side effect — save is just persistence
2026-05-17 19:48:19 +02:00
BenClaw bdd1d248db debug(action_cable): add server-side broadcast logging
- Log channel remapping and data on every broadcast
- Log warnings when channel format is unknown
- Helps trace whether broadcasts reach ActionCable.server
2026-05-17 19:41:00 +02:00
BenClaw 7c69f0a0bc fix(action_cable): accept both /user/123 and /user_123 channel formats
- Benjamin standardized on /user_123 in mozo.rb (underscore, no slash)
- Old remap regex ^/user/(.+)$ didn't match /user_123
- Fix: ^/user[/_](.+)$ accepts both separators → user_123
2026-05-17 19:27:30 +02:00
bterkuile 11ba8e7434 channel naming convention change 2026-05-17 12:24:07 -05:00
bterkuile 383872b800 require the action_cable engine instead of just the root 2026-05-17 12:07:15 -05:00
BenClaw ee8861355b fix(action_cable): add missing ApplicationCable::Channel base class
- MozoChannel < ApplicationCable::Channel was failing with
  NameError: uninitialized constant ApplicationCable::Channel
- Standard Rails convention requires both connection.rb and channel.rb
2026-05-17 19:06:00 +02:00
BenClaw df04e99447 fix(action_cable): ensure logger is set for upgraded Rails app
- ActionCable::TaggedLoggerProxy crashes with NoMethodError when
  logger is nil (common in apps upgraded from older Rails)
- Add after_initialize hook to guarantee ActionCable.server.config.logger
  falls back to Rails.logger or
2026-05-17 18:49:13 +02:00
bterkuile 4bee13aae7 activate ActionCable messaging instead of Faye 2026-05-17 11:44:53 -05:00
bterkuile 12836dd14b Switch to Redis counter 2026-05-17 10:48:05 -05:00
bterkuile 5dbb6dbeae Explicitly require action_cable 2026-05-17 09:42:48 -05:00
BenClaw 3e4bcc80c8 feat(counter): add Redis counter adapter, replace DrbCounter
- Add Mozo::Counter::Redis with same get/set/incr/decr interface
- Add redis gem (~> 5.0) to Gemfile
- Update cable.yml to use Redis adapter in production (shared with counters)
- Document DrbCounter → Redis migration in broadcasting-migration.md
- Redis installed and running on vmi3300327
- Leave Faye as current broadcaster; both switches are one-line changes

DrbCounter problems solved:
  - In-memory → persistent (RDB + AOF)
  - Single-process DRb → multi-process safe Redis
  - Atomic INCR/DECR across Puma workers
  - One less custom process to manage
2026-05-17 16:42:09 +02:00
BenClaw a755d8a205 refactor(broadcasting): add Broadcastable to List + Order, remove monkey-patch
- include Broadcastable in app/models/list.rb
- include Broadcastable in app/models/order.rb
- Remove config/initializers/model_broadcast.rb (ApplicationController.new anti-pattern)
- Broadcasting now goes through Mozo.broadcast_* directly, not via controller hack
2026-05-17 16:36:28 +02:00
root 1f52448253 feat(broadcasting): add ActionCable adapter + fix model broadcast anti-pattern
- Add Mozo::Broadcaster::ActionCable as drop-in Faye replacement
- Fix model_broadcast.rb: delegate to Mozo directly instead of
  ApplicationController.new (memory-unsafe anti-pattern)
- Add Broadcastable concern for clean model-side broadcasting
- ActionCable config: async adapter, cable.yml, WebSocket endpoint
- MozoChannel with per-entity authorization (user/supplier/employee)
- Connection auth via auth_token (matches existing auth pattern)
- Mount /cable WebSocket in routes
- Add broadcasting-migration.md with Faye→ActionCable guide
2026-05-17 15:25:49 +02:00