- Example implementation of the SAM pattern (home).
- Uses the Cerebral framework (home).
- Project folder structure follows the Control-Entity-Boundary (ECB) pattern (blog post).
npm
installs all dependencies.npm run build
sets up static dependencies for the website.npm start
starts the Budo development-webserver and serves the directory (watch + rebuild + autoreload).npm run lint
formats the code with Prettier and checks few Eslint rules.
- A Cerebral module may be implemented as a SAM container. Each Cerebral signal is a SAM-step action, and this ensures that the model is updated in a precisely defined step (as in TLA+).
- Triggering an action may execute a step, if there is a proposal.
- A proposal in turn may trigger an indeterminate (see Actor Model) amount of automatic next-actions via the next-action-predicate function.
- Only the accept function has write access to the model.
- The computeStateRepresentation function derives the state-representation (view-model). It also gives a hint in form of a list of allowed actions, so that buttons, etc. can be disabled in the UI.
- Although technically wrong, in this implementation, the model is saved in the Cerebral state-tree as well, just to be visible in Cerebral's debugger. This also allows the model or parts of it to be used as view-model, which requires less code for this exercise.
- Helper functions allow communication between SAM-step-containers. If one container calls an action of another, it should wait for the other to compute its state-representation, which is the (asynchronous) return value of the action-call.
The SAM pattern maps to the ECB pattern too:
boundary --> View component
control --> Cerebral module, actions, third party APIs
entity --> model (accept), compute state, compute next action
-
App features
-
Add blog post example (conflict-free example). No replies without parent should be shown because of eventual consistency.
- post posts
- reply to posts
- like posts and show counter per user (publicly visible)
-
Add Git-like example (with conflict management)? Track concurrent changes and show causal chain for conflict resolution by user.
-
Use control state for page change (routing) example?
-
Add session control state example (log in <-> log out on authenticated route)?
-
Use security token.
-
Add notification service when remote changes arrive.
-
Prevent automatic example post by more than one user?
-
-
Storage layer
- Add PouchDB provider to Cerebral context
- Save model to DB
- Specify Bolt-on Shim Layer in TLA+
- Implement Bolt-on Shim Layer
- Globally unique identifier for local store
- Local Lamport time-stamp sequence number for writes
- As external service?
- Remove SAM container semantics?
- Refactor shim module to be sub-module?
-
SAM container
- Allow for next action to not block step until complete (blockStep = true)? -> No
- Queue action to NAP when in progress (optionally)
- Compute: Mark action specific cancel buttons as disabled.
-
Check allowed action in step.
-
Add tests.
-
Create Proxy to hide state API?
-
Defer updating the view until end of SAM step? (State updates may trigger rerending immediately currently.)
- Prevent or at least warn about concurrent mutations while a step is in progress?
- Async Ticker is not a simple next action example. Ticker could be a singleton.