# For Package Authors

### 1. Developer Interfaces

mirai offers the following functions primarily for package authors using mirai:

1. `require_daemons()` will error and prompt the user to set daemons (with a clickable function link if the cli package is available) if daemons are not already set.
2. `daemons_set()`, to detect if daemons have already been set and prompt the user to set daemons if not.
3. `on_daemon()`, to detect if code is already running on a daemon, i.e. within a `mirai()` call.
4. `register_serial()` to register custom serialization functions, which are automatically available by default for all subsequent `daemons()` calls.
5. `nextget()`, for querying values for a compute profile, such as ‘url’, described in the function’s documentation. Note: only the specifically-documented values are supported interfaces.

### 2. Guidance

mirai as a framework is designed to support completely transparent and inter-operable use within packages. A core design precept of not relying on global options or environment variables minimises the likelihood of conflict between use by different packages.

There are hence only a few important points to note:

1. `daemons()` settings should wherever possible be left to end-users. This means that as a package author, you should just consider that mirai are run on whatever resources are available to the user at the time the code is run. You do not need to anticipate whether an end-user will run the code on their own machine, distributed over the network, or a mixture of both.

- Consider pointing to the documentation for `mirai::daemons()`, or re-exporting `daemons()` in your package as a convenience.
- Never include a call to `daemons()` when using `mirai_map()`. This is important to ensure that there is no accidental recursive creation of daemons on the same machine, for example if your function is used within another package’s function that also uses mirai.
- Exceptionally, a `daemons(n = 1, dispatcher = FALSE, .compute = ...)` call may be used to set up a single dedicated daemon, but only if used with a unique value for `.compute`. A representative example of this usage pattern is `logger::appender_async()`, where the logger package’s ‘namespace’ concept maps directly to mirai’s ‘compute profile’.

2. The shape and contents of a `status()` call must not be used programatically, as this user interface is subject to change at any time. Use `nextget()` where possible instead.

- An exception is that `status()$connections` may be used to return the total number of daemon connections at any time.

3. The functions `unresolved()`, `is_error_value()`, `is_mirai_error()`, and `is_mirai_interrupt()` should be used to test for the relevant state of a mirai or its value.

- The characteristics of their current implementation, e.g. as a logical NA for an ‘unresolvedValue’, should not be relied upon, as these are subject to change at any time.

4. For CRAN packages, all examples and tests should respect the following rules when running on CRAN:

- Use only one daemon (with `dispatcher = FALSE`) to ensure that only one additional process is used, to remain within the 2-core limit.
- Always reset daemons at the end of each example or test file. Allow at least a one-second sleep to ensure that all background processes have properly exited and that no ‘detritus’ from the processes remains.
- Never modify the default value of `asyncdial` or `autoexit` for `daemon()`, in that function or any functions that pass arguments through to it such as `daemons()`. This is to ensure that processes exit as soon as the host process does.