Signals in Moya are a way for your project code to respond to various events that may occur during the processing of a request, or at other points during the lifetime of the server. For example, you may want to run some code when server starts up, or when an object is written to the database.
Signals are identified by a string in dotted notation. For example, sys.startup
, is a signal for the server starting up. You may write code that handles a signal with the <handle> tag. Here's an example of handling the sys.startup
signal:
<handle signal="sys.startup"><echo>Moya is starting up. To infinity, and beyond!</echo></handle>
If you add the above code to your project (it can go anywhere), Moya will display text in the console when you run the server. Naturally, in a real project a signal handler would so something more useful.
The signal
attribute of <handle> may also accept wildcards – an asterisk is used to indicate that it will match anything with the same prefix. For example, if you were to set signal
to sys.*
, the handler would be invoked for any signal in the sys
namespace.
Some signals have an associated sender
, which is the library name of an element from which the signal is sent. For example, database related signals set the sender to the model name. You can whose to handle signals from a given sender with the sender
attribute of <handle>. For example, the following handler will be invoked for every database signal sent from the User model:
<handle signal="db.*" sender="moya.auth#User"><echo>DB signal handled</echo></handle>
When a handler is invoked, Moya passes in a signal
object with information regarding the signal. It contains three keys; name
is the name of the signal, sender
is the sender, and data
is a dictionary containing extra information regarding the signal.
The contents of a signal's data
dictionary vary according to the signal. For example, database related signals contain a value called object
, which is the database object associated with the signal. Here's an example of a signal handler used in the Auth library:
<handle signal="db.before-update" from="moya.auth#User"><!-- Hash password automatically --><let user="signal.data.object" /><call macro="#hashpassword" if="'$' not in user.password"dst="user.password" let:password="user.password"/></handle>
This handler is invoked just prior to writing a User object to the database. The handler hashes the password, so as not to store it in plain text. If we didn't use a handler here, we would have to cut and paste a line of code to every point where the User model is saves – which would be prone to errors.
Some signals are sent by Moya itself, but you may also write code that sends, or fires custom signals. This allows you to respond to events without cluttering up your code. The <fire> tag is used to fire a custom signal. You can set the name of the signal to fire with the signal
attribute, and the sender with the sender
attribute. Additional data (which will be stored in signal.data
) is set via the moya-codelet map. Here's an firing a signal:
<fire signal="moyaproject.sushifinder.out-of-stock" let:item="Tuna Roll" />
The following would catch the above signal:
<handle signal="moyaproject.sushifinder.out-of-stock"><echo>We need to order more ${signal.data.item}s!</echo></handle>
Signal names with a single dot, such as db.before-update
, sys.startup
, are reserved by Moya. Custom signals should be named with the prefix of the library they are being sent from, e.g. moyaproject.sushifinder.out-of-stock
.
If signals fall in to broad catagories, it is a good idea to name your signals to reflect that. For example, you could have moyaproject.sushifinder.stock.out-of-stock
and moyaproject.sushifinder.stock.low-stock
etc. A single handler may be written to respond to all stock related signals (with a signal
attribute of moyaproject.sushihandler.stock.*
).
Moya intentionally ignores all exceptions that occur within signal handlers. Otherwise, you could never be sure that code you write won't break due to a bug in a signal handler (possibly written by a third party).
If a traceback does happen within a signal handler, Moya will write a message to the logs. Moya will also display a trace in the console if debug mode is enabled. You can also step through code in signal handlers and insert <breakpoint> tags as normal.
If you enable log_signals
in Project Settings, Moya will write a message to the log every time it sends a signal. You could also replicate this with a catch all signal handler, such as the following:
<handler signal="*"><echo>Signal ${signal.name} detected</echo><echo>Sent by ${signal.sender or 'nobody'}</echo><echo>Signal data:</echo><echo obj="signal.data"/></handler>
The following signals are built-in to Moya.
System signals are sent at various points in the life-time of the server. System signals begin with the prefix sys
.
A number of signals are sent at several points during the request process. Request signals begin with the request
prefix.
result
.
response
.
response
object.Note, that since the response has been sent when the request.end
signal is fired, modifying the response will have no effect.