---
# System prepended metadata

title: Synpse Agent

---

# Synpse Agent

## Logic

`application` - package responsible for reading API and updating internal `store` to represent expected state
agent should be reconciling towards. It will either delete/update/create records in the `store` to set state.

`queue` - acts as a queue for workers to do one or other actions with application. It can be either Create/Delete.

`supervisor` - is supervisor for applications. It has few important reconciling functions:
    `monitor`:
        - Iterated via API state `store` and check what is application state in the runtime. and update ephemeral TTL `stateStore` and emits customer events.
        Monitor will set states `Running`, `Failed`, `Exited`, `Unknown` - these are states on which `reconcile` will act. 
        As these are being refresh on every monitoring loop, it should update if state already exists. So consider scenario:
        - Application is in `Failed` state.
        - Monitor observed it and sets `Failed` state.
        - Reconcile picks the `Failed` state and updates it to `Deleting` state to clean
        - Worker picks the `Deleting` state and deletes it.
        - Monitor will try to monitor again and will not find anything so will not set state store. 
        - TTL expires and reconcile will ack as new application is being created
    `reconcile` - Will act on `store` state and `stateStore` ephemeral store. And based on it will emit either `create`, `delete` events.
        - On `no stateStore` and present in `store` create
        - On `Failed`, `Exited` and `Unknown` states - delete
        - On `Pending` - ignore, worker is working on this
        - On `Created` - ingore, worker is working on this
        - On `Deleting` - ingore, worker is working on this
        - On `Running when present in API` - ignore, all is ok
        - On `Running when NOT in API` - delete

Very important edge case: 
- As we dont have resource locking we should never allow 2 version running at the same time. So before we do start
we should check with runtime to see if it is already running (any same application container). If it is - we should not start. Maybe retry giving GC more time?

Possible scenario - Create:
    - New application created - Not in API - `Pending` is set
    - Worker pick it up and starts Creating. Worker keeps TTL on `Pending` so no new application will be picked up.
    - It created and TTL is released. 
    - Monitor will pick it from Runtime and Mark as `Running`
    
Possible scenario - Update:
    - application is in `Running` state
    - `reconcile` noticed it is NOT in `store` but it is in `stateStore` (New version replaces it in store). Emits `delete` event for current one. 
    - `worker` deleted the application
    - `reconcile` will pick new version and emit `create` event in parallel
    - worker create flow has checks `IfLatest` and should prevent any creates if newer state already exits. It might create container but not start.  (Need to think this one. We need check `ifLatest` and if previous version is running. Might short loop to keep iterating. If we are still latest and still have old running - wait)
    - `monitor` will GC those with created but not started with `Unknown` state and so Delete event will happen.

