The CoCore architecture consists of:
- A User (e.g. you sitting in front of your computer wanting to know the result of 4 + 9).
- A Control Server owned by CoCore.
- One or more Worker servers that may have shared tenancy (e.g. Contoso Inc. isn't using all of the resources on their file server and leases the spare compute time to CoCore).
A successful request flows through the CoCore architecture roughly as follows:
sequenceDiagram
User->>Control Server: Run Function A113 with arguments XYZ
Control Server->>Worker: Run the Docker container for A113, arguments XYZ
Worker->>Control Server: Started Execution B999
Worker-->>Control Server: Stream Output Chunk 1
Worker-->>Control Server: Stream Output Chunk 2
Worker-->>Control Server: ...
Worker->>Control Server: Execution B999 is Complete
Control Server->>User: Execution B999 of A113 is Complete, output is [...]
This diagram introduces two new terms of art:
- A Function is some code provided by the user, e.g.
print 'Hello, world'
- An Execution is a single run of that function, potentially with different arguments. A function will likely be executed many times.
When a user requests that a function is run, the control server creates an execution record to track the invocation and assigns it to a worker. The worker then communicates with the control server via web sockets to provide (a) a heartbeat indicating that the function is still running and (b) in-progress updates to stdout and stderr.
Once an execution is created, it can move between its states (as represented by the state
column in the database) in the following ways:
flowchart LR
open[Open] -->|Worker gets task| running
running[Running] -->|Execution Success| success[Success]
running -->|Execution Failure| failure[Failure]
running -->|Execution Timeout| timeout[Timeout]
running -->|User Cancels| cancelled[Cancelled]
All of the transitions are driven by the worker notifying the command server of the change, except for user cancellations for which the command server has to tell the worker to cancel the task.