Update spec and readme
This commit is contained in:
+39
-20
@@ -1,40 +1,59 @@
|
||||
# `pub struct Infra`
|
||||
|
||||
Infra is a service which listens for activity and synchronizes relay updates to a remote zooid instance via `api_url`.
|
||||
Infra is a background worker that listens for activity and synchronizes relay configuration to a remote zooid instance.
|
||||
|
||||
Members:
|
||||
|
||||
- `api_url: String` - the URL of the zooid instance to be managed, from `ZOOID_API_URL`
|
||||
- `blossom_s3: Option<BlossomS3Sync>` - shared Blossom S3 settings from `BLOSSOM_S3_*` when region, bucket, access key, and secret are all non-empty after trim
|
||||
- `env: Env` - configuration; supplies `zooid_api_url`, `relay_domain`, the `BLOSSOM_S3_*` and `LIVEKIT_*` settings, and the robot key used to sign requests
|
||||
- `query: Query`
|
||||
- `command: Command`
|
||||
|
||||
## `pub fn new(query: Query, command: Command) -> Self`
|
||||
## `pub fn new(query: Query, command: Command, env: &Env) -> Self`
|
||||
|
||||
- Reads environment and populates members
|
||||
- Stores `query`, `command`, and a clone of `env`
|
||||
|
||||
## `pub async fn start(self)`
|
||||
|
||||
- Subscribes to `command.notify`
|
||||
- On startup, schedules delayed sync retries for relays whose `sync_error` is non-empty.
|
||||
- Loops on `rx.recv()`, calling `handle_activity` for each received `Activity`.
|
||||
- Runs `reconcile_relay_state("startup")` before entering the loop
|
||||
- Loops on `rx.recv()`, calling `handle_activity` for each `Activity`
|
||||
- On `Lagged`, runs `reconcile_relay_state("lagged")`; on `Closed`, exits
|
||||
|
||||
## `async fn handle_activity(&self, activity: &Activity)`
|
||||
|
||||
- For `create_relay`, `update_relay`, `activate_relay`, or `deactivate_relay` activity, calls `sync_and_report` immediately.
|
||||
- For `fail_relay_sync`, schedules a delayed retry using exponential backoff based on consecutive failures for the relay.
|
||||
- Retry scheduling stops after the configured max attempts to avoid infinite retry loops.
|
||||
- Other activity types are ignored (e.g. `complete_relay_sync`).
|
||||
- Ignores anything that isn't a `relay` resource with activity type `create_relay`, `update_relay`, `activate_relay`, `deactivate_relay`, or `fail_relay_sync`
|
||||
- For `fail_relay_sync`, schedules a delayed retry via `schedule_relay_sync_retry`
|
||||
- Otherwise resolves the relay (skip if gone) and calls `sync_relay`
|
||||
|
||||
## `async fn sync_and_report(&self, relay: &Relay, is_new: bool)`
|
||||
## `async fn reconcile_relay_state(&self, source: &str)`
|
||||
|
||||
- Calls `sync_relay` and on success calls `command.complete_relay_sync`.
|
||||
- On failure calls `command.fail_relay_sync`.
|
||||
- Lists relays still pending sync (`query.list_relays_pending_sync`)
|
||||
- For each: `sync_relay` immediately if its `sync_error` is empty, otherwise `schedule_relay_sync_retry`
|
||||
|
||||
## `async fn sync_relay(&self, relay: &Relay, is_new: bool)`
|
||||
## `async fn schedule_relay_sync_retry(&self, relay_id: &str, source: &str)`
|
||||
|
||||
- If `is_new`, sends `POST /relay/:id` to create the relay in zooid.
|
||||
- Otherwise, sends `PATCH /relay/:id` to update it.
|
||||
- Includes `secret` only for relay creation (`POST`) so updates do not rotate relay identity.
|
||||
- Passes relay configuration in the body including host, schema, inactive flag, info, policy, groups, management, blossom, livekit, push, and roles.
|
||||
- When `blossom_s3` is configured and the relay has blossom enabled, the blossom section includes `adapter: "s3"`, S3 fields from the environment, and `s3.key_prefix` set to the relay's `schema`. Otherwise blossom omits S3 (zooid defaults to local storage) or sends `{ "enabled": false }` when blossom is disabled.
|
||||
- Counts the relay's consecutive trailing `fail_relay_sync` activities to derive the attempt number
|
||||
- Computes an exponential backoff (base 30s, doubling, capped at 15 minutes); gives up after `RELAY_SYNC_RETRY_MAX_ATTEMPTS` (6) to avoid infinite retry loops
|
||||
- Spawns a task that sleeps for the delay, then re-reads the relay and `sync_relay`s it (no-op if the relay is gone)
|
||||
|
||||
## `async fn sync_relay(&self, relay: &Relay)`
|
||||
|
||||
- Calls `try_sync_relay`; on success `command.complete_relay_sync`, on failure `command.fail_relay_sync` with the error
|
||||
|
||||
## `async fn try_sync_relay(&self, relay: &Relay)`
|
||||
|
||||
- A relay is "new" only if it has never completed a sync (`synced != 1` and no `complete_relay_sync` activity exists). New relays are created with `POST /relay/:id`; existing relays are updated with `PATCH /relay/:id`.
|
||||
- A freshly generated `secret` is included only for creation (`POST`), so updates don't rotate relay identity and we never store the secret.
|
||||
- The body carries relay configuration: `host` (= `subdomain.relay_domain`), `schema`, `inactive` (true when status is `inactive` or `delinquent`), `info` (name/icon/description/pubkey), `policy`, `groups`, `management`, `blossom`, `livekit`, `push`, and hard-coded `roles`.
|
||||
- When `blossom_enabled`, the blossom section uses `adapter: "s3"` with the `BLOSSOM_S3_*` settings and `s3.key_prefix` set to the relay's `schema`; otherwise it sends `{ "enabled": false }`.
|
||||
- When `livekit_enabled`, the livekit section carries the `LIVEKIT_*` settings; otherwise `{ "enabled": false }`.
|
||||
|
||||
## `pub async fn list_relay_members(&self, relay_id: &str) -> Result<Vec<String>>`
|
||||
|
||||
- `GET /relay/:id/members` from zooid; returns the `members` array
|
||||
|
||||
## `async fn request(&self, method, path, body)`
|
||||
|
||||
- Sends an authenticated request to the zooid API at `path` (relative to `env.zooid_api_url`), with a 5s timeout
|
||||
- Authenticates each request with a NIP-98 header via `env.make_auth`
|
||||
- Returns the response on 2xx; bails with the status and body text otherwise
|
||||
|
||||
Reference in New Issue
Block a user