synit-manual/src/operation/builtin/daemon.md

182 lines
6.5 KiB
Markdown

# Process supervision and management
- Relevant schema: [[syndicate-rs]/syndicate-server/protocols/schemas/externalServices.prs](https://git.syndicate-lang.org/syndicate-lang/syndicate-rs/src/branch/main/syndicate-server/protocols/schemas/externalServices.prs)
Assertions [requiring](../service.md#require-service) a service with name matching
`DaemonService` cause the server to start a subprocess-based service:
```preserves-schema
DaemonService = <daemon @id any> .
```
Each `daemon` service can have zero or more subprocesses associated with it. Subprocesses can
be long-lived services or short-lived, system-state-changing programs or scripts.
## Adding process specifications to a service
Each subprocess associated with a `DaemonService` is defined with a `DaemonProcess` assertion:
```preserves-schema
DaemonProcess = <daemon @id any @config DaemonProcessSpec>.
DaemonProcessSpec =
/ @simple CommandLine
/ @oneShot <one-shot @setup CommandLine>
/ @full FullDaemonProcess .
```
The simplest kind of subprocess specification is a `CommandLine`, either a string (sent to `sh
-c`) or an array of program name (looked up in the `$PATH`) and arguments:
```preserves-schema
CommandLine = @shell string / @full FullCommandLine .
FullCommandLine = [@program string, @args string ...] .
```
The `simple` and `oneShot` variants of `DaemonProcessSpec` expand into `FullDaemonProcess`
values as follows:
- a `simple` command-line *c* becomes `{ argv: `*c*` }`; and
- a record `<one-shot `*c*`>` becomes `{ argv: `*c*`, readyOnStart: false, restart: on-error }`.
## Subprocess specification
The `FullDaemonProcess` type matches a Preserves dictionary having, at minimum, an `argv` key,
and optionally including many other parameters controlling various aspects of the subprocess to
be created.[^full-process-split-out]
```preserves-schema
FullDaemonProcess =
& @process FullProcess
& @readyOnStart ReadyOnStart
& @restart RestartField
& @protocol ProtocolField .
FullProcess =
& { argv: CommandLine }
& @env ProcessEnv
& @dir ProcessDir
& @clearEnv ClearEnv .
```
The `CommandLine` associated with `argv` specifies the program name to invoke and its
command-line arguments. The other options are described in the remainder of this section.
### Ready-signalling
If the key `readyOnStart` is present in a `FullDaemonProcess` dictionary, then if its
associated value is `#t` (the default), the service will be considered
[`ready`](../service.md#service-states) immediately after it has been spawned; if its value is
`#f`, some other arrangement is expected to be made to announce a `ready` `ServiceState`
against the service's name.
```preserves-schema
ReadyOnStart =
/ @present { readyOnStart: bool }
/ @invalid { readyOnStart: any }
/ @absent {} .
```
### Whether and when to restart
The default restart policy is `always`. It can be overridden by providing the key `restart` a
`FullDaemonProcess` dictionary, mapping to a valid `RestartPolicy` value.
```preserves-schema
RestartField =
/ @present { restart: RestartPolicy }
/ @invalid { restart: any }
/ @absent {} .
RestartPolicy = =always / =on-error / =all / =never .
```
The valid restart policies are:
- `always`: Whether the process terminates normally or abnormally, restart it without affecting
any peer processes within the service.
- `on-error`: If the process terminates normally, leave everything alone; if it terminates
abnormally, restart it without affecting peers.
- `all`: If the process terminates normally, leave everything alone; if it terminates
abnormally, restart the whole daemon (all processes within the `Daemonservice`).
- `never`: Treat both normal and abnormal termination as normal termination; that is, never
restart, and enter state [`complete`](../service.md#service-states) even if the process
fails.
### Speaking Syndicate Network Protocol via stdin/stdout
By default, the `syndicate-server` program assumes nothing about the information to be read and
written via a subprocess's standard input and standard output. This can be overridden with a
`protocol` entry in a `FullDaemonProcess` specification. (Standard error is always considered
to produce information to be put in the system logs, however.)
```preserves-schema
ProtocolField =
/ @present { protocol: Protocol }
/ @invalid { protocol: any }
/ @absent {} .
Protocol = =none / =application/syndicate / =text/syndicate .
```
The available options for `protocol` are:
- `none`: the standard input of the subprocess is connected to `/dev/null`, and the standard
output and standard error are logged.
- `application/syndicate`: the subprocess standard input and output are used as a *binary*
syntax [Syndicate network protocol](../../protocol.md) relay. Standard error is logged. The
subprocess is expected to make some [entity](../../glossary.md#entity) available to the
server via [initial oid](../../glossary.md#initial-oid) 0. The server reflects this
expectation by automatically placing a [service object](../service.md#service-object) record
into the dataspace alongside the `daemon` record defining the subprocess.
- `text/syndicate`: as for `application/syndicate`, but Preserves' *text* syntax is used
instead of binary syntax.
### Specifying subprocess environment variables
By default, the Unix process environment passed on to subprocesses is not changed. Supplying
`clearEnv` and/or `env` keys alters this behaviour.
```preserves-schema
ClearEnv =
/ @present { clearEnv: bool }
/ @invalid { clearEnv: any }
/ @absent {} .
ProcessEnv =
/ @present { env: { EnvVariable: EnvValue ...:... } }
/ @invalid { env: any }
/ @absent {} .
EnvVariable = @string string / @symbol symbol / @invalid any .
EnvValue = @set string / @remove #f / @invalid any .
```
Setting `clearEnv` to `#t` causes the environment to be emptied before `env` is processed and
before the subprocess is started. The `env` key is expected to contain a dictionary whose keys
are strings or symbols and whose values are either a string, to set the variable to a new
value, or `#f`, to remove it from the environment.
### Setting the Current Working Directory for a subprocess
By default, each subprocess inherits the current working directory of the `syndicate-server`
program. Setting a `dir` key to a string value in a `FullDaemonProcess` overrides this.
```preserves-schema
ProcessDir =
/ @present { dir: string }
/ @invalid { dir: any }
/ @absent {} .
```
----
#### Notes
[^full-process-split-out]: The `FullProcess` type is split out in order for it to be able to be
reused outside the specific context of a *daemon* process.