Skip to content

phpbotscout serve

Runs phpbotscout as a long-lived process. It supervises two things: the Discord gateway that watches the allowlisted channels, and the scheduled refresh that keeps the knowledge index current.

Usage

$ phpbotscout serve

Managed services

Services register with controls rather than being hand-rolled goroutines, so startup ordering, health and shutdown are the supervisor's job and not each service's.

Service What it does Restart policy
discord-gateway/<guild> Connects the gateway and reads the allowlisted channels. One per configured guild. Backs off: 10 restarts, 2s initial, 5m maximum
index-refresher Re-reads the corpus on a timer. None

The gateway backs off because a gateway that cannot connect will not connect harder for being asked more often, and Discord rate-limits identify. The refresher has no policy because its Start cannot fail, and the failure it does have — a forge that will not answer — is not fixed by restarting anything.

The scheduled refresh

The refresher calls the same Refresh that index refresh calls. One code path, so the scheduled and manual routes cannot drift into disagreeing about what is indexed.

It refreshes once at startup and then on every tick of index.refresh_interval. Refreshing at startup rather than waiting a full interval means a daemon restarted after downtime notices the world moved on promptly. Startup does not wait for that first refresh — indexing the corpus takes minutes, and a supervisor waiting on it would report the daemon as failing to come up while it was working correctly.

Two refreshes never overlap. If one is still running when the next tick arrives, that tick is skipped rather than queued: two concurrent runs would write the same documents in parallel.

Failure is degradation, not an outage

A refresh that fails is counted and logged, and the daemon keeps running.

  • Liveness always passes. A restart would not reach an unreachable forge.
  • Readiness does not fail on a stale index. Answering from what is already indexed — with a caveat — beats not answering, and taking the bot out of service would fix nothing. This is the same judgement the gateway makes about a reconnect that lost events.

Staleness is reported through index status, which is where an operator can act on it.

A source that fails while the rest of the run succeeds is logged by name with its reason. The run itself reports success, so that log line is the only signal that part of the corpus went unindexed.

Shutdown

Stop waits for a refresh already in flight. Returning immediately would let the process exit between writing a document and recording the commit it came from, leaving the index claiming to hold content it does not. The wait is bounded by the shutdown deadline; past it the refresh is cancelled and its transaction rolls back.

Startup refuses a bad configuration

Building the forge provider makes no network call, so it can only fail on a configuration an operator can fix in seconds — a malformed API URL, an index path that cannot be opened, a provider that cannot enumerate a namespace. Those fail startup, in keeping with how the gateway's own configuration is treated.

A forge that is merely unreachable is a different thing entirely. That is not known at startup, surfaces later as a failed refresh, and degrades rather than stopping the daemon.

Health endpoints

serve mounts /healthz, /livez and /readyz on the health listener, which binds 127.0.0.1:8081 by default. Wildcard binds are refused.

Flags

serve defines no flags of its own.

Name Description Default
-h, --help Help for serve. false

Global flags (--config, --debug, --output, --ci) are inherited from the root command.

Example

$ phpbotscout --config ./config.yaml serve