182 lines
6.5 KiB
Markdown
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.
|