---
title: "The event cycle in fiery"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{The event cycle in fiery}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

fiery is using an event-based model to allow you to program the logic. During
the life cycle of an app a range of different events will be triggered and it
is possible to add event handlers to these using the `on()` method. An event
handler is simply a function that will get called every time an event is
fired. Apart from the predefined life cycle events it is also possible to
trigger custom events using the `trigger()` method. Manual triggering of life
cycle events is not allowed.

## Life cycle Events
Following is a list of all life cycle events. These cannot be triggered
manually, but is fired as part of the normal lifetime of a fiery server:

- `start`: Will trigger once when the app is started but before it is
  running. The handlers will receive the app itself as the `server` argument
  as well as any argument passed on from the `ignite()` method. Any return
  value is discarded.
- `resume`: Will trigger once after the start event if the app has been
  started using the `reignite()` method. The handlers will receive the app
  itself as the `server` argument as well as any argument passed on from the
  `reignite()` method. Any return value is discarded.
- `end`: Will trigger once after the app is stopped. The handlers will
  receive the app itself as the `server` argument. Any return value is
  discarded.
- `cycle-start`: Will trigger in the beginning of each loop, before the
  request queue is flushed. The handlers will receive the app itself as the
  `server` argument. Any return value is discarded.
- `cycle-end`: Will trigger in the end of each loop, after the request
  queue is flushed and all delayed, timed, and asynchronous calls have been
  executed. The handlers will receive the app itself as the `server` argument.
  Any return value is discarded.
- `header`: Will trigger every time the header of a request is received.
  The return value of the last called handler is used to determine if further
  processing of the request will be done. If the return value is `TRUE` the
  request will continue on to normal processing. If the return value is
  `FALSE` the response will be send back and the connection will be closed
  without retrieving the payload. The handlers will receive the app itself as
  the `server` argument, the client id as the `id` argument and the request
  object as the `request` argument.
- `before-request`: Will trigger prior to handling of a request (that is,
  every time a request is received unless it is short-circuited by the
  `header` handlers). The return values of the handlers will be passed on to
  the request handlers and can thus be used to inject data into the request
  handlers (e.g. session specific data). The handlers will receive the app
  itself as the `server` argument, the client id as the `id` argument and the
  request object as the `request` argument.
- `request`: Will trigger after the `before-request` event. This is where
  the main request handling is done. The return value of the last handler is
  send back to the client as response. If no handler is registered a `404`
  error is returned automatically. If the return value is not a valid
  response, a `500` server error is returned instead. The handlers will
  receive the app itself as the `server` argument, the client id as the `id`
  argument, the request object as the `request` argument, and the list of
  values created by the before-event handlers as the `arg_list` argument.
- `after-request`: Will trigger after the `request` event. This can be
  used to inspect the response (but not modify it) before it is send to the
  client. The handlers will receive the app itself as the `server` argument,
  the client id as the `id` argument, the request object as the `request`
  argument, and the response as the `response` argument. Any return value is
  discarded.
- `before-message`: This event is triggered when a websocket message is
  received. As with the `before-request` event the return values of the
  handlers are passed on to the `message` handlers. Specifically if a
  `'binary'` and `'message'` value is returned they will override the original
  values in the `message` and `after-message` handler arguments. This can e.g.
  be used to decode the message once before passing it through the `message`
  handlers. The `before-message` handlers will receive the app itself as the
  `server` argument, the client id as the `id` argument, a flag indicating
  whether the message is binary as the `binary` argument, the message itself
  as the `message` argument, and the request object used to establish the
  connection with the client as the `request` argument.
- `message`: This event is triggered after the `before-message` event and
  is used for the primary websocket message handling. As with the `request`
  event, the handlers for the `message` event receives the return values from
  the `before-message` handlers which can be used to e.g. inject session
  specific data. The message handlers will receive the app itself as the
  `server` argument, the client id as the `id` argument, a flag indicating
  whether the message is binary as the `binary` argument, the message itself
  as the `message` argument, the request object used to establish the
  connection with the client as the `request` argument, and the values
  returned by the before-message handlers as the `arg_list` argument. Contrary
  to the `request` event the return values of the handlers are ignored as
  websocket communication is bidirectional.
- `after-message`: This event is triggered after the `message` event. It
  is provided more as an equivalent to the `after-request` event than out of
  necessity as there is no final response to inspect and handler can thus just
  as well be attached to the `message` event. For clear division of server
  logic, message specific handlers should be attached to the `message` event,
  whereas general handlers should, if possible, be attached to the
  `after-message` event. The `after-message` handlers will receive the app
  itself as the `server` argument, the client id as the `id` argument, a flag
  indicating whether the message is binary as the `binary` argument, the
  message itself as the `message` argument, and the request object used to
  establish the connection with the client as the `request` argument.
- `send`: This event is triggered after a websocket message is send to a
  client. The handlers will receive the app itself as the `server` argument,
  the client id as the `id` argument and the send message as the `message`
  argument. Any return value is discarded.
- `websocket-opened`: This event is triggered when a client tries to establish a
  WebSocket connection to the server. The handler will receive the app itself as
  the `server` argument, the client id as the `id` argument, and the WebSocket
  class provided by httpuv as the `connection` argument. Any return value is
  discarded. Since this event exposes logic from the httpuv package through the
  `connection` argument it is liable to changes in the httpuv API.
- `websocket-closed`: This event will be triggered every time a websocket
  connection is closed. The handlers will receive the app itself as the
  `server` argument, the client id as the `id` argument and request used to
  establish the closed connection as the `request` argument. Any return value
  is discarded.

## Custom Events
Apart from the predefined events, it is also possible to trigger and listen
to custom events. The syntax is as follows:

```{r, eval=FALSE}
# Add a handler to the 'new-event' event
id <- app$on('new-event', function() {
  message('Event fired')
})

# Trigger the event
app$trigger('new-event')

# Remove the handler
app$off(id)
```

Additional parameters passed on to the `trigger()` method will be passed on
to the handler. There is no limit to the number of handlers that can be
attached to custom events. When an event is triggered they will simply be
called in the order they have been added. Triggering a non-existing event is
not an error, so plugins are free to fire off events without worrying about
whether handlers have been added.

## Triggering Events Externally:
If a fiery server is running in blocking mode it is not possible to
communicate with it using the `trigger()` method (though these can be fired by
other callbacks in the server logic). Instead it is possible to assign a
directory to look in for event trigger instructions. The trigger directory is
set using the `trigger_dir` field, e.g.:

```{r, eval=FALSE}
app$trigger_dir <- '/some/path/to/dir/'
```

Events are triggered by placing an `rds` file named after the event in the
trigger directory. The file must contain a list, and the elements of the list
will be passed on as arguments to the event handlers. After the event has
been triggered the file will be deleted. The following command will trigger
the `external-event` on a server looking in `'/some/path/to/dir/'`:

```{r, eval=FALSE}
saveRDS(list(arg1 = 'test'), '/some/path/to/dir/external-event.rds')
```
