State Management & Store
Relevant source files
The following files were used as context for generating this wiki page:
State management in the RoundingWell frontend is built upon Backbone, Marionette, and Backbone.Store. The architecture ensures data consistency by enforcing a "single instance" rule for models in memory, preventing synchronization issues across different parts of the application.
The system distinguishes between Server Models (representing backend data) and State Models (representing UI or application state). While server data is routed through the entities-service, application-level communication is handled via Backbone.Radio, facilitating a decoupled pub/sub architecture.
Sources: README.md:126-136, CLAUDE.md:21-25
Core Components
Backbone.Store
Backbone.Store is a critical library used to ensure that only one instance of a model with a specific ID exists in memory. This is used for both server models and to sync state models across various applications. When a new instance is requested with an existing ID, the store returns the existing instance rather than creating a duplicate.
Sources: README.md:126-140
// Example of Store usage in the project
const MyModel = Backbone.Model.extend({...});
const MyUniqueModel = Backbone.Store(MyModel);
const myUniqueModel = new MyUniqueModel({ id: '1', foo: 'bar' });
const sameModel = new MyUniqueModel({ id: '1' });
// sameModel.get('foo') === 'bar' is true because they point to the same object
Sources: README.md:131-140
Entities Service
The entities-service acts as the primary boundary for data access and AJAX operations. It centralizes the logic for fetching, saving, and managing the lifecycle of domain entities like Actions and Flows. Direct fetch calls or ad hoc AJAX logic outside this service are discouraged.
Sources: CLAUDE.md:21-25, src/js/entities-service/entities/actions.js:192-205
Model Architecture
Models in the system often extend a BaseModel and utilize a messages hash to handle real-time updates (typically via WebSockets). This allows models to update their own attributes when server-side changes occur.
Sources: src/js/entities-service/entities/actions.js:15-55
Key Model Features
| Feature | Description |
|---|---|
| Type Definition | Every model belongs to a specific TYPE string (e.g., patient-actions, flows) for store indexing. |
| Relationship Management | Helpers like getRelationship() or Radio.request are used to resolve linked entities (e.g., getPatient, getOwner). |
| Computed States | Methods like isDone(), isOverdue(), and canEdit() provide business logic based on model attributes. |
| Persistence | Methods like saveState() and saveOwner() handle specific attribute updates and their corresponding API relationships. |
| Sources: src/js/entities-service/entities/actions.js:15-188, src/js/entities-service/entities/flows.js:10-85 |
Data Flow Diagram
The following diagram illustrates how data flows from the UI through the Store and Entities Service to the API.
State Synchronization
Pub/Sub via Backbone.Radio
The application utilizes Backbone.Radio to decouple modules. Components can "reply" to requests for data or "trigger" events that other modules listen for. This is frequently used to share global state, such as the current workspace or the currentUser.
Sources: src/js/README.md:92-94, src/js/views/patients/shared/components/state_component.test.js:46-50
State Components
Generic encapsulated components (using Marionette.Toolkit) manage their own state models. For example, a StateComponent handles the selection of a "Done", "Started", or "Queued" status for an action.
Sources: README.md:113-124, src/js/views/patients/shared/components/state_component.test.js:34-45
Implementation Standards
- Single Instance Rule: Always wrap models in
Backbone.Storeto ensure data consistency across the UI. Sources: README.md:131-140 - Encapsulation: Store state on a dedicated state model rather than appending properties directly to a class instance. Sources: README.md:183-184
- Validation: Models implement a
validatemethod (e.g., ensuring a name is present before saving). Sources: src/js/entities-service/entities/program-flows.js:20-22 - Batch Operations: Collections provide
batchInvokemethods to handle multiple model updates (e.g., saving a group of actions) efficiently. Sources: src/js/entities-service/entities/actions.js:195-197
Summary
The state management system prioritizes a "Single Source of Truth" by combining Backbone's event-driven models with a global Store. This architecture prevents UI inconsistencies and centralizes business logic within the entities-service, while Backbone.Radio provides the necessary glue for cross-component communication.