|
| 1 | +# Campfire Architecture Overview |
| 2 | +Note: ChatGPT Codex autogenerated with edits |
| 3 | + |
| 4 | +## Rails stack |
| 5 | +- Campfire is a Rails application loaded from `config/application.rb`, running against the main Rails branch with Puma as the Rack server (`Gemfile`). |
| 6 | +- The Process model defined in `Procfile` runs a web process (`thrust bin/start-app`), a Redis instance, and a Resque worker pool, mirroring the production topology. |
| 7 | + |
| 8 | +## Server components |
| 9 | +### HTTP layer & concerns |
| 10 | +- Routes in `config/routes.rb` expose REST-style resources for accounts, rooms, messages, searches, and user onboarding, with controller logic under `app/controllers`. |
| 11 | +- `ApplicationController` wires in shared concerns for authentication, authorization, request context, and Turbo support (`app/controllers/application_controller.rb`), while scoped controllers (e.g. `accounts`, `rooms`, `sessions`) encapsulate feature-specific flows. |
| 12 | + |
| 13 | +### Domain models |
| 14 | +- Active Record models under `app/models` capture the chat domain: `Room` orchestrates membership grants and message fan-out, `Message` stores Action Text content and triggers broadcasts, and `Membership` tracks unread state and presence (`app/models/room.rb`, `app/models/message.rb`, `app/models/membership.rb`). |
| 15 | +- Users own push subscriptions, webhook endpoints, and other associations (`app/models/user.rb`, `app/models/user/bot.rb`), enabling bots and notifications with minimal coupling. |
| 16 | + |
| 17 | +### Real-time delivery |
| 18 | +- Turbo Streams allow immediate updates when messages post, via `Message::Broadcasts` (`app/models/message/broadcasts.rb`). |
| 19 | +- Action Cable channels handle live room traffic, typing state, presence, and heartbeat pings (`app/channels/**/*`). `RoomChannel` scopes streams to authorized users, while `PresenceChannel` updates connection counters and fires read receipts. |
| 20 | + |
| 21 | +### Background jobs & integrations |
| 22 | +- Active Job dispatches asynchronous work; production runs jobs through Resque (`config/environments/production.rb`). Examples include `Room::PushMessageJob` (web push fan-out) and `Bot::WebhookJob` (outbound bot integrations) under `app/jobs`. |
| 23 | +- Web push delivery is handled by a dedicated thread pool (`lib/web_push/pool.rb`), which coalesces HTTP connections and asynchronously invalidates expired subscriptions. |
| 24 | +- The PWA surface is served through `PwaController` and the custom service worker script in `app/views/pwa/service_worker.js` to manage push notifications and badge counts. |
| 25 | + |
| 26 | +## Redis-backed storage |
| 27 | +- Action Cable uses Redis for its pub/sub adapter (`config/cable.yml`), enabling multi-process fan-out of channel traffic and presence updates. |
| 28 | +- Resque persists job queues and worker state in Redis; the pool is configured via `config/resque-pool.yml`, and each worker reconnects to Postgres while closing Redis connections before forking (`lib/tasks/resque.rake`). |
| 29 | +- Rails caching switches to `:redis_cache_store` in production (and when dev caching is enabled), so fragment and view caches are stored alongside queue data (`config/environments/production.rb`, `config/environments/development.rb`). |
| 30 | +- Local development optionally launches a bundled Redis server through `Procfile` and `bin/setup` if one is not already running, keeping all Redis-backed concerns co-located. |
| 31 | + |
| 32 | +## VAPID keys and push delivery |
| 33 | +- VAPID keys are loaded at boot from credentials or environment variables into `Rails.configuration.x.vapid` (`config/initializers/vapid.rb`). |
| 34 | +- The layout exposes the public key through a `<meta>` tag (`app/views/layouts/application.html.erb`), so the Stimulus notifications controller can subscribe the service worker with the proper `applicationServerKey` (`app/javascript/controllers/notifications_controller.js`). |
| 35 | +- When a message arrives, `Room::MessagePusher` builds payloads for relevant subscribers and queues them on the shared `WebPush::Pool`, which signs each request using the configured VAPID credentials (`app/models/room/message_pusher.rb`, `lib/web_push/notification.rb`). |
| 36 | +- Administrators can mint or rotate key pairs with `script/admin/create-vapid-key`, which shells into the Rails environment and prints the new values for storage in credentials or environment. |
0 commit comments