/docs/diagrams.md
Machine Basics
Features are explained using Mermaid flow diagrams, and headers link to relevant sections of the manual.
Multi-state
Many states can be active at the same time.
flowchart LR
subgraph ActiveBefore[Before]
A1([A:1])
B1[B:0]
C1[C:0]
end
ActiveMutation([add B])
subgraph ActiveAfter[After]
A2([A:1])
B2([B:1])
C2[C:0]
end
ActiveBefore --> ActiveMutation
ActiveMutation --> ActiveAfter
Clock and state contexts
States have clocks that produce contexts (odd = active; even = inactive).
flowchart LR
subgraph ClockStep1[ ]
A1([A:1])
B1([B:1])
C1[C:0]
end
ClockMutation1[remove B]
subgraph ClockStep2[ ]
A2([A:1])
B2[B:2]
C2[C:0]
end
ClockMutation2([add B])
subgraph ClockStep3[ ]
A3([A:1])
B3([B:3])
C3[C:0]
end
subgraph ClockCtxs[State contexts of B]
CtxB1([B:1])
CtxB3([B:3])
end
ClockStep1 --> ClockMutation1 --> ClockStep2
ClockStep2 --> ClockMutation2 --> ClockStep3
%% B1 --> CtxB1
%% B2 --> CtxB2
%% B3 --> CtxB3
Queue
Queue of mutations enable lock-free Actor Model.
flowchart LR
Machine[[Machine]]
Add1([add A])
Add2([add A])
Add3([add B])
Add1 -- 1 --> Machine
Add2 -- 2 --> Machine
Add3 -- 3 --> Machine
subgraph Queue
direction LR
QAdd1([add A])
QAdd2([add A])
QAdd3([add B])
QAdd1 --> QAdd2 --> QAdd3
end
Machine --> Queue
AOP handlers
States are Aspects with Enter, State, Exit, and End handlers.
flowchart LR
subgraph HandlersBefore[ ]
A1([A:1])
B1[B:0]
C1[C:0]
end
subgraph HandlersAfter[ ]
A2([A:1])
B2([B:1])
C2[C:0]
end
HandlersMutation([add B])
HandlersBefore --> HandlersMutation
HandlersMutation --> HandlersAfter
HandlersMutation --> AnyB
HandlersMutation --> BEnter
HandlersMutation --> AB
HandlersMutation --> BState
subgraph Handlers
AnyB[["AnyB()"]]
BEnter[["BEnter()"]]
AB[["AB()"]]
BState[["BState()"]]
end
Negotiation
Transitions are cancellable (during the negotiation phase).
flowchart LR
subgraph NegotiationBefore[ ]
A1([A:1])
B1[B:0]
C1[C:0]
end
subgraph NegotiationAfter[ ]
A2([A:1])
B2[B:0]
C2[C:0]
end
NegotiationMutation([add B])
NegotiationBefore --> NegotiationMutation
NegotiationMutation --> NegotiationAfter
NegotiationMutation --> AnyB
NegotiationMutation --> BEnter
BEnter == return ==> false
NegotiationMutation -. canceled .-x AB
NegotiationMutation -. canceled .-x BState
subgraph Negotiation
false[[false]]
AnyB[["AnyB()"]]
BEnter[["BEnter()"]]
AB[["AB()"]]
BState[["BState()"]]
end
Relations
States are connected via Require, Remove, and Add relations.
flowchart LR
Wet(Wet)
Dry(Dry)
Water(Water)
Wet -- Require --> Water
Water -- Add --> Wet
Water -- Remove --> Dry
Dry -- Remove --> Water
Subscriptions
Channel-broadcast waiting on clock values.
flowchart LR
subgraph SubStates[ ]
direction LR
subgraph SubStep1[ ]
direction BT
A1([A:1])
B1([B:1])
C1[C:0]
end
SubMutation1[remove B]
subgraph SubStep2[ ]
A2([A:1])
B2[B:2]
C2[C:0]
end
SubMutation2([add B])
subgraph SubStep3[ ]
A3([A:1])
B3([B:3])
C3[C:0]
end
end
SubStep1 --> SubMutation1 --> SubStep2
SubStep2 --> SubMutation2 --> SubStep3
B2 .-> WhenNotB
A3 .-> WhenTimeB3
B3 .-> WhenTimeB3
subgraph Subs[ ]
WhenNotB>"WhenNot B"]
WhenTimeB3>"WhenTime A:1 B:3"]
end
aRPC
aRPC Client Server
flowchart TB
subgraph s [Server Host]
direction TB
Server[aRPC Server]
Worker[Worker Mach]
end
subgraph c [Client Host]
direction TB
Consumer[Consumer]
Client[aRPC Client]
RemoteWorker[Remote Worker Mach]
end
Client -- WorkerPayload state --> Consumer
Client --> RemoteWorker
Worker --> Server
Client -- Mutations --> Server
Server -. Clock Updates .-> Client
aRPC Architecture
flowchart TB
subgraph s [Server Host]
direction TB
Server[aRPC Server]
Worker[Worker Mach]
end
subgraph c [Client Host]
direction TB
Consumer[Consumer]
Client[aRPC Client]
RemoteWorker[Remote Worker Mach]
end
Client -- WorkerPayload state --> Consumer
Client --> RemoteWorker
Worker --> Server
Client -- Mutations --> Server
Server -. Clock Updates .-> Client
Worker Pool Architecture
flowchart LR
c1-RemoteWorker -- aRPC --> w1-rpcPub
c1-RemoteSupervisor -- aRPC --> s1-rpcPub
subgraph Client 1
c1-Client[Client]
c1-RemoteWorker[RemoteWorker]
c1-RemoteSupervisor[RemoteSupervisor]
c1-Client --> c1-RemoteWorker
c1-Client --> c1-RemoteSupervisor
end
subgraph Client 2
c2-Client[Client]
c2-RemoteWorker[RemoteWorker]
c2-RemoteSupervisor[RemoteSupervisor]
c2-Client --> c2-RemoteWorker
c2-Client --> c2-RemoteSupervisor
end
subgraph Node Host
subgraph Worker Pool
w1-rpcPub --> Worker1
w1-rpcPub([Public aRPC])
w1-rpcPriv --> Worker1
w1-rpcPriv([Private aRPC])
w2-rpcPub --> Worker2
w2-rpcPub([Public aRPC])
w2-rpcPriv --> Worker2
w2-rpcPriv([Private aRPC])
w3-rpcPub --> Worker3
w3-rpcPub([Public aRPC])
w3-rpcPriv --> Worker3
w3-rpcPriv([Private aRPC])
end
s1-rpcPub([Public aRPC])
s1-rpcPub --> Supervisor1
Supervisor1 --> RemoteWorker1
Supervisor1[Supervisor]
RemoteWorker1 -- aRPC --> w1-rpcPriv
Supervisor1 -- fork --> Worker1
Supervisor1 --> RemoteWorker2
RemoteWorker2 -- aRPC --> w2-rpcPriv
Supervisor1 -- fork --> Worker2
Supervisor1 --> RemoteWorker3
RemoteWorker3 -- aRPC --> w3-rpcPriv
Supervisor1 -- fork --> Worker3
end
c2-RemoteWorker -- aRPC --> w2-rpcPub
c2-RemoteSupervisor -- aRPC --> s1-rpcPub
Flows
Legend
flowchart
leg-State([State])
leg-HandlerOrMethod["HandlerOrMethod()"]
subscription[["subscription to A"]]
subgraph LegendAdd [State A adds state B]
leg-A1([A]) -- Add --> leg-B1([B])
end
subgraph LegendCall [Method call]
leg-HandlerOrMethod21["HandlerOrMethod1()"] -. call .-> leg-MethodName22["HandlerOrMethod2()"]
end
subgraph LegendHandle [State handler]
leg-A3([A]) == handle ==> leg-HandlerOrMethod3["AState()"]
end
RPC Getter Flow
Consumer requests payload from a remote worker.
flowchart TB
subgraph ClientHost [Client Host]
subgraph Consumer
con-MethodOrHandler["MethodOrHandler()"]
con-WorkerPayload(["WorkerPayload"])
end
subgraph RemoteWorkerMach [Remote Worker Mach]
%% Provide Worker is requested to provide some (named) data.
rw-Provide([ProvideABC])
end
subgraph RPCClientMach [RPC Client Mach]
c-WorkerPayload([WorkerPayload])
c-RemoteSendPayload["RemoteSendPayload()"]
c-WorkerPayloadState["WorkerPayloadState()"]
end
end
subgraph ServerHost [Server Host]
subgraph RPCServer [RPC Server]
srv-SendPayloadState["SendPayloadState()"]
end
subgraph SourceWorkerMach [Source Worker Mach]
%% Provide Worker is requested to provide some (named) data.
sw-Provide([ProvideABC])
sw-ProvideState["ProvideABCState()"]
sw-SendPayload(["SendPayload"])
end
end
%% steps
con-MethodOrHandler -- Add --> rw-Provide
rw-Provide -- Add --> sw-Provide
sw-Provide == handle ==> sw-ProvideState
sw-ProvideState -- Add --> sw-SendPayload
sw-SendPayload == handle ==> srv-SendPayloadState
srv-SendPayloadState -. call .-> c-RemoteSendPayload
c-RemoteSendPayload -- Add --> c-WorkerPayload
c-WorkerPayload == handle ==> c-WorkerPayloadState
c-WorkerPayloadState -- Add --> con-WorkerPayload
Worker Bootstrap
Node Supervisor forks a new worker process for the pool.
flowchart TB
subgraph SupervisorMach [Supervisor State Mach]
ForkWorker([ForkWorker])
ForkingWorker([ForkingWorker])
AwaitingWorker([AwaitingWorker])
WorkerForked([WorkerForked])
exec["exec.Command()"]
newBootstrap["newBootstrap()"]
whenWorkerAddr[["when:WorkerAddr"]]
ForkWorker == handle ==> ForkWorkerState["ForkWorkerState()"] -. call .-> newBootstrap
ForkWorker -- Add --> ForkingWorker
ForkingWorker == handle ==> ForkingWorkerState["ForkingWorkerState()"] -. call .-> exec
ForkingWorker -- Add --> AwaitingWorker
AwaitingWorker -- wait --> whenWorkerAddr
whenWorkerAddr --> WorkerForked
end
exec .-> Worker
newBootstrap .-> BootstrapMach
subgraph BootstrapMach [Bootstrap State Mach]
WorkerAddr([WorkerAddr])
WorkerAddr -- tick --> whenWorkerAddr
end
subgraph Worker [Worker State Mach]
RpcReadyState["RpcReadyState()"]
RpcReady([RpcReady]) == handle ==> RpcReadyState
end
RpcReadyState -- aRPC Add --> WorkerAddr
Transition Lifecycle
direction: right
classes: {
node: {
style: {
stroke: white
border-radius: 999
fill: "#45475A"
font-size: 20
}
}
group: {
style: {
stroke: "#5F5C5C"
fill: "#262424"
font-size: 30
}
}
}
Mutation -> Transition.Consensus.Relations -> Transition.Consensus.Negotiation -> Transition.Execution
Transition: {
class: group
Consensus: {
class: group
Relations
Negotiation
Relations: {
label: 2. Relations
class: node
}
Negotiation: {
label: 3. Negotiation
class: node
}
}
Execution
Execution: {
label: 4. Execution
class: node
}
}
Transition.Execution -> Mutation: queue {
style: {
font-size: 20
bold: true
}
}
Transition.Execution -> Auto: state changed {
style: {
font-size: 20
bold: true
}
}
Auto -> Mutation: queue {
style: {
font-size: 20
bold: true
}
}
Mutation: {
label: 1. Mutation
class: node
}
Auto: {
label: 5. Auto States
class: node
}