7.2 KiB
7.2 KiB
Architecture
Analysis Date: 2026-01-11
Pattern Overview
Overall: Hybrid Microservices with Shared Monolithic Database
Key Characteristics:
- Service-oriented architecture with distinct service boundaries
- Monolithic Rails backend transitioning to modern React frontend
- Shared PostgreSQL database across all services
- Real-time communication via WebSocket gateway with Protocol Buffers
- Async messaging via RabbitMQ/AMQP between services
Layers
Presentation Layer (Frontend):
- Purpose: User interface and client-side logic
- Contains: React 16 SPA with Redux Toolkit state management
- Location:
jam-ui/src/ - Entry Point:
jam-ui/src/index.js→Main.js(providers) →App.js(layout router) - Depends on: Rails API (
web/) via REST, WebSocket gateway for real-time - Used by: End users via browser at
http://beta.jamkazam.local:4000 - Current Status: Under development. This is mostly a UI update of the legacy front end (web)
API Layer (Backend):
- Purpose: REST API endpoints, request processing, authentication
- Contains: Rails 4.2.8 controllers, responders, error handling
- Location:
web/app/controllers/(83 API controller files) - Base Controller:
api_controller.rbprovides auth, error handling, response formatting - Depends on: Shared business logic gem (
ruby/), PostgreSQL - Used by: React frontend, mobile apps, third-party integrations
Real-time Communication Layer:
- Purpose: WebSocket connections for live session updates
- Contains: EventMachine-based WebSocket server with Protocol Buffer messaging
- Location:
websocket-gateway/ - Protocol: Protocol Buffers (
.protodefinitions inpb/src/client_container.proto) - Bridge:
jam-ui/src/jamClientProxy.jsmanages native C++ client communication via QWebChannel - Depends on: Shared Ruby gem, WebSocket protocol
- Used by: React frontend, native desktop client
Shared Business Logic Layer:
- Purpose: Centralized models, validations, domain logic
- Contains: ActiveRecord models (217 files), managers, message factory
- Location:
ruby/lib/jam_ruby/(shared gem embedded via local path) - Key Files:
ruby/lib/jam_ruby/models/(217 model files),message_factory.rb,connection_manager.rb - Depends on: Rails frameworks, PostgreSQL
- Used by: All services (web, admin, websocket-gateway)
Data Layer:
- Purpose: Persistent storage
- Contains: PostgreSQL schema, migrations
- Location:
db/up/(403+ migration files) - ORM: ActiveRecord models in
ruby/lib/jam_ruby/models/ - Depends on: PostgreSQL server
- Used by: All services via ActiveRecord
Data Flow
REST API Request (Example: Fetch User Profile):
- User action in React component (e.g.,
JKUserProfile.js) - Redux dispatch or direct API call via
apiFetch()(jam-ui/src/helpers/rest.js) - HTTP request to Rails controller (e.g.,
api_users_controller.rb) - Controller uses shared business logic (
ruby/lib/jam_ruby/models/user.rb) - ActiveRecord query to PostgreSQL database
- Response serialized (RABL template or JSON)
- Redux store updated (
jam-ui/src/store/features/*.js) - Component re-renders with new data
Real-time Session Flow (Example: Join Music Session):
- Native C++ desktop client sends message
- Proxied through
jamClientProxy.js(QWebChannel tunnel to frontend) - WebSocket message to gateway (
websocket-gateway/) - Protocol Buffer decoding → Rails backend logic
- Async processing via Resque jobs or AMQP messages
- State changes persisted to PostgreSQL
- Broadcast back to all session participants via WebSocket
- Protocol Buffer encoding → Frontend updates Redux state
State Management:
- Redux Toolkit for global app state (sessions, tracks, user, notifications)
- Context API for UI state (native client connection, media player, global settings)
- WebSocket for real-time state synchronization
Key Abstractions
Component (React):
- Purpose: UI building blocks with JK prefix for brand-specific components
- Examples:
JKDashboardMain.js,JKSessionModal.js,JKJamTrackPlayer.jsinjam-ui/src/components/ - Pattern: Functional components with hooks, prop destructuring, Redux integration
Hook (React):
- Purpose: Reusable stateful logic
- Examples:
useJamServer.js(26KB, WebSocket orchestration),useJamTrack.js,useGearUtils.jsinjam-ui/src/hooks/ - Pattern:
use*naming convention, returns state and handlers
Controller (Rails):
- Purpose: Handle HTTP requests, route to business logic
- Examples:
api_sessions_controller.rb,api_jam_tracks_controller.rb,api_users_controller.rbinweb/app/controllers/ - Pattern: RESTful actions, inherit from
api_controller.rb, use responders
Model (Rails/ActiveRecord):
- Purpose: Domain objects with validations and business rules
- Examples:
user.rb(3,078 lines),music_session.rb(1,481 lines),jam_track.rbinruby/lib/jam_ruby/models/ - Pattern: ActiveRecord associations, scopes, state machines (AASM)
API Service Function:
- Purpose: Frontend-to-backend communication abstractions
- Examples:
getSession(id),joinSession(options),updateUser(id, data)injam-ui/src/helpers/rest.js - Pattern: Promise-based, wraps
apiFetch(), returns resolved/rejected promises
Entry Points
Frontend Entry:
- Location:
jam-ui/src/index.js - Triggers: Browser loads page at
http://beta.jamkazam.local:4000 - Responsibilities: Render React app, wrap with providers (Redux, Context), route to layouts
Backend API Entry:
- Location:
web/config/routes.rb(51KB route definitions) - Triggers: HTTP request to
/api/*endpoints - Responsibilities: Route to controller actions, apply middleware, return JSON responses
WebSocket Gateway Entry:
- Location:
websocket-gateway/(EventMachine server) - Triggers: WebSocket connection from client
- Responsibilities: Maintain persistent connections, decode/encode Protocol Buffers, broadcast messages
Shared Library Entry:
- Location:
ruby/lib/jam_ruby.rb - Triggers: Required by Rails services
- Responsibilities: Load all models, managers, and shared utilities
Error Handling
Strategy: Exceptions bubble to top-level handler, logged and returned as JSON errors
Patterns:
- Controllers use
api_controller.rbbase class for centralized error handling - Frontend catches promise rejections from
apiFetch(), displays user-friendly errors - Background jobs (Resque) retry on transient failures, log permanent failures
- WebSocket errors logged server-side, client notified via error messages
Cross-Cutting Concerns
Logging:
- Rails logger for backend (stdout in development, files in production)
- Console logging in React frontend (removed in production builds)
- Bugsnag for error tracking (API key configured in
web/config/application.rb) - InfluxDB for time-series metrics (configured but disabled for production)
Validation:
- ActiveRecord validations in model layer (
ruby/lib/jam_ruby/models/*) - React Hook Form for frontend form validation
- API parameter validation in controllers
Authentication:
- Devise for user authentication (session-based cookies)
- OAuth via OmniAuth (Facebook, Google, Twitter)
- Session sharing between
www.jamkazam.local(Rails) andbeta.jamkazam.local(React) viaremember_tokencookie
Architecture analysis: 2026-01-11 Update when major patterns change