phpbotscout serve¶
Runs phpbotscout as a long-lived process. It reads the public channels of every
configured server, answers the questions addressed to it, keeps the knowledge
index current on a timer, and purges stored questions and answers as they
expire. It posts an answer only in a server whose post_answers is set, and
records it everywhere; see run the bot.
Usage¶
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 |
Holds the one gateway connection and reads every configured server's public channels, minus any excluded. | Backs off, by the discord.restart keys: 10 restarts, 2s initial, 5m maximum by default |
messaging |
The in-process bus that carries each message and reaction from the gateway to the answering path. | None |
health |
The /healthz, /livez and /readyz listener. |
None |
index-refresher |
Re-reads the corpus on a timer. | None |
question-purge |
Deletes questions after 180 days and answer text after 120, once a day. | None |
The connection 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, and as a count on /healthz: the index-staleness
check is DEGRADED with stale sources: N while any source is stale, which
leaves the endpoint healthy.
A refresh that the forge rate-limits stops early and logs
index refresh stopped early. The sources it did not reach keep their index
and are tried again next tick. See
index refresh.
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, --accessible) are
inherited from the root command.