Events
Events are non-extensible, script-only accessible un-managed objects that can trigger events and notifications delayed or on a recurring schedule.
When fired, events move into the
processing
state, and then into the completed
or failed
state once handled.count
{ Number readOnly } If recurring, this property will hold the number of times the event was triggered, whether manually or through scheduling.err
{ Any readOnly } A fault that is recorded if the event handler failed for any reason, threw an error, etc.expiresAt
{ Date indexed, removable } If set, the event will not trigger once expired and will eventually be garbage collected and deleted by cortex.if
{ Expression removable } An optional expression that triggers the event if it evaluates to a truey value (!!if()
).key
{ String indexed, unique, removable } An optional unique key up to 512 characters to uniquely identify the event.parent
{ ObjectID readOnly } Set to the_id
of a triggering recurring event.parentKey
{ String readOnly, indexed } Set to thekey
of a triggering recurring event.principal
{ ObjectID } An account or service account used as the calling principal. Can be set using keys and email addresses.retention
{ Number = never } The retention policy bits. Only affect non-recurring events and children of recurring events.- never = 0 - delete the event after it triggers.
- failed = 1 - retain events that fail.
- completed = 2 - retain events that complete.
- skipped = 4 - retain events that were skipped via conditional.
schedule
{ String } A cron format recurrence schedule. Once set, thestate
is set toscheduled
and thestart
property is set to the next time in the schedule. Recurring events cannot be changed to non-recurring events and vice versa.start
{ Date = new Date() } The date to trigger the event.started
{ Date readOnly } The date the event processing was started (or last started int he case of a recurring event).state
{ Number indexed, readOnly } The current state- scheduled = 0 - event is recurring.
- pending = 1 - event is scheduled to run.
- processing = 2 - event is currently processing.
- completed = 3 - event triggered successfully.
- failed = 4 - an error occurred during processing and was stored in
err
. - skipped = 5 - skipped because a condition was not met.
A
script
event trigger an @on
runtime event based on the event
and param
properties, mirroring the script.fire()
functionality. The param
value becomes the script.arguments
and is also passed as the first argument to the event handler.event
{ String } The event name that matches a registered runtime event (@on
).param
{ Any } An object passed to the event handler as the first argument.
const { on } = require('decorators')
class Events {
@on('ns__test')
static nsTest(param, runtime) {
// runtime.source === 'event' when fried from an event instance
}
}
A
notification
event sends a notification based on the name
, variables
and options
properties, mirroring the require('notifications').send(...)
script functionality.Because notifications can have multiple endpoints, if more than one error is produced, any additional endpoint errors are added as child faults to the first error.
name
{ String } Notification name. Can be null or missing for custom notifications.variables
{ Any } Template variables.options
{ Any } Notification options.
A
driver
event runs a db operation based on the options
and privileged
properties, mirroring the require('db.util').createOperation(options, [options]).execute()
script functionality.Supported operations are:
deleteMany
, deleteOne
, insertMany
, insertOne
, patchMany
, patchOne
, updateMany
, updateOne
.options
{ Object } Operation options fromoperation.getOptions()
.privileged
{ Boolean = false } If true, privileged options (those only available in-script)will be included (skipAcl, roles, grant, bypassCreateAcl).
For testing purposes, a
console
event outputs param
as if console.log(param)
were called from a script. Console logging is not available in production environments.param
{ Any } Max 8KB message to be output.
return consts.events
/*
{
"retention": {
"never": 0,
"failed": 1,
"completed": 2,
"skipped": 4
},
"states": {
"scheduled": 0,
"pending": 1,
"processing": 2,
"completed": 3,
"failed": 4,
"skipped": 5
}
}
*/
To schedule a user event, simply insert an event instance.
When a recurring event - one with a
schedule
cron - is triggered, it will insert a new event with a pending
state with a start
date set to the current time, and tick up the count
property of the parent.A
err.events.failed
trigger is called when an event fails. The trigger context
is the event instance, with an additional params
(script.arguments) object containing the err
object.const { trigger } = require('decorators')
class ErrorHandling {
@trigger('err.events.failed')
handleError({ context, params: { err }}) {
}
}
configuration.events.softLimit
( Number = 80,000, readOnly ) The number of pending events that can be inserted before theerr.events.softLimitExceeded
trigger is fired. When fired,configuration.events.triggerSoftLimit
is set tofalse
and will not trigger again until reset.configuration.events.hardLimit
( Number = 100,000, readOnly ) The number of pending events that can be inserted before theerr.events.hardLimitExceeded
trigger is fired. When fired,configuration.events.triggerHardLimit
is set tofalse
and will not trigger again until reset. When this threshold is reached, acortex.invalidArgument.maxAllowed
Fault is thrown.configuration.events.triggerSoftLimit
( Boolean = true ) Initially true, this is set to false if the soft limit is triggered and a script trigger exists in the environment runtime. The trigger will not fire again until the property is reset totrue
. The trigger is always fired inline.configuration.events.triggerHardLimit
( Boolean = true ) Initially true, this is set to false if the hard limit is triggered and a script trigger exists in the environment runtime. The trigger will not fire again until the property is reset totrue
. The trigger is always fired inline.
// listen for limit triggers
const { trigger } = require('decorators')
class Limits {
@trigger('err.events.softLimitExceeded')
onSoftLimit() {
// time to take a look.
}
@trigger('err.events.hardLimitExceeded')
onHardLimit() {
// this is an error. events won't insert or recur.
}
}
const { Event } = org.objects,
{ events: { retention: { failed, skipped } } } = consts
// insert a script event to trigger as soon as possible. and retain only if failed or skipped.
Event.insertOne(
{
type: 'script',
key: 'unique.key',
event: 'c_room_room_event',
param: {
anything: 'up to 16kb'
},
if: {
$eq: ['principal._id', script.principal._id]
},
retention: failed | skipped
}
).grant('update').bypassCreateAcl().execute()
// insert a script event to trigger in 24 hours
Event.insertOne(
{
type: 'script',
key: 'unique.key',
event: 'c_room_room_event',
param: {
anything: 'up to 16kb'
},
start: new Date(Date.now() + 86400000)
}
).grant('update').bypassCreateAcl().execute()
// insert a custom notification to be sent once a day at 5am UTC, running as the current principal.
Event.insertOne(
{
type: 'notification',
key: 'scheduled.notif.123',
principal: script.principal,
schedule: '0 5 * * *',
options: {
endpoints: {
email: {
recipients: [
],
subject: 'Medable',
message: 'Medable rocks!', // message (plain text) is currently required.
html: '<html><p>Medable rocks!<p></html>'
}
}
}
}
).grant('update').bypassCreateAcl().execute()
// insert a console logger that will run every minute and expire in 5 minutes.
// then, force it to run immediately after scheduling (any recurring event can be
// set to run manually, but this resets the next time it will run).
Event.insertOne(
{
type: 'console',
param: 'foo',
key: 'scheduled will expire in 5 minutes',
schedule: '* * * * *',
expiresAt: new Date(Date.now() + (1000 * 60 * 5))
}
).grant('update').bypassCreateAcl().execute()
Event.updateOne(
{
key: 'scheduled will expire in 5 minutes'
},
{
$set: {
start: new Date()
}
}
).skipAcl().grant('update').execute()
Last modified 1yr ago