Examples
Introduction
The Lua scripting engine is a powerful tool for extending the features of the OCS to perform custom actions within the OCS engine. It is, however, sometimes opaque how to use the Lua API.
The following examples ideally give some idea of how the OCS Lua API can be used to achieve new functionality in the OCS.
Immediately Transition to a New Lifecycle State
A lifecycle action might, for testing or temporary purposes, need to transition immediately to a new state once entered. This might be useful if a lifecycle state is simply used as a marker for EDR purposes.
To achieve an immediate transition, create a lifecycle action which immediately
succeeds with the transition event name. Given two states, A
and B
, with a
transition from A
to B
done by an event named a_to_b
, the following lua
action (created on A
) will achieve this:
local ocs = require "n2.n2ocs"
local f = function (context)
ocs.succeeded("a_to_b")
end
return ocs.create_lifecycle_action_handler(f)
Trigger the Removal of the Lifecycle Owner
To remove a subscription from an wallet, or to remove an wallet from the OCS, the associated subscription or wallet lifecycle normally itself would determine it should be delete (resource API methods exist on the OCS to remove wallets and subscriptions from wallets, but these methods are designed for provisioning and data administration and not BAU).
To remove the owner of a lifecycle then, a lifecycle action must trigger the
removal. To do this, the action uses the delete()
method of the lifecycle
instance.
The delete()
method is available on lifecycles other than the current
lifecycle too, so it is possible to trigger this deletion on lifecycles other
than the active one.
local ocs = require "n2.n2ocs"
local f = function (context)
context.active_lifecycle_instance().delete()
end
return ocs.create_lifecycle_action_handler(f)
This is often the action of a lifecycle’s DELETE
or REMOVE
state.
Set a Lifecycle State’s Transition Date/Time
A lifecycle state might require it’s transition time to be dynamically set for
some reason. To achieve this, use the set_transition_out_time()
method,
passing in the expiry as either a fixed date/time (based on seconds since
Jan 01 1970), or as a table describing how to calculate the expiry.
For example, to set the expiry to be 100 days from the moment the action runs for a lifecycle:
local ocs = require "n2.n2ocs"
local f = function (context)
local expiry = { days = 100 }
context.active_lifecycle_instance().set_transition_out_time(expiry)
end
return ocs.create_lifecycle_action_handler(f)
Trigger Notification Before Bucket Expiry
If a bucket is created with a lifecycle using the supplementary-lifecycle
annotation, then the bucket lifecycle will process. A lifecycle
can define a fake transition that does not actually transition, but
rather triggers a pre-expiry notification.
The lifecycle transition can be configured using the following JSON:
{
"id": "pre_expiry_notification_3d",
"event": "pre_expiry_notification_3d",
"timer": {
"days": 3
},
"timer_reference": "transition_out_time",
"action": "-- see below",
"action_language": "lua"
}
In this transition the timer
defines a transition of 3 days and because
it is special (it is against the transition_out_time
it occurs
3 days before the transition out time.
Lua code to run as the action can then send the notification:
local jslee = require "n2.jslee.JSLEE"
local ocs = require "n2.n2ocs"
function trigger(context)
local bucket = context.active_lifecycle_target()
if (bucket.is_bucket() and bucket.as_bucket().expiry() ~= nil) then
local notification = {
wallet_id = context.active_wallet().id(),
bucket = bucket.as_table()
}
ocs.notify("pre_expiry_notification", "3d", notification)
end
end
return ocs.create_lifecycle_action_handler(trigger)
Note that the handler does not use ocs.succeeded()
to trigger
an actual transition. Instead, this action runs once, (at 3 days
prior to expiry, or as soon as the wallet is accessed after this
instant), and on execution will send a notification with both
the wallet ID and the bucket information that triggered the
notification.
Credit a Subscriber Wallet
One of the features of the N-Squared OCS is that subscription processing is controlled by state machines that are (a) defined dynamically through configuration and (b) control the execution of actions such as debiting and crediting wallets using scripts executed during the processing of these state machines.
To perform a credit as part of a lifecycle (one that is likely attached to a subscription/service), script code uses the engine’s .credit() method.
local ocs = require "n2.n2ocs"
local engine = require "n2.n2ocs.engine"
local action = function(context)
local sub = context.active_subscription()
local svc = subscription.service ()
local request = {
credit_requested = context.ancillary_information ().buckets
credit_context = {
derived_from = "service," .. svc.id .. "," .. svc.name
}
}
local ok, error = engine.credit (request)
if not ok then
-- transition to the grace state.
-- An error EDR would already have been generated by the system
ocs.succeeded('grace')
else
-- transition to the granted state
-- this will then automatically transition out in N days.
ocs.succeeded('granted')
end
end
return ocs.create_lifecycle_action_handler(action)