Configuring Backup Approvers
Sym gives you the ability to define an arbitrary number of backup destinations for a request, and configure timeouts between each.
Overview
When making access requests, it is possible for you to specify that you would like the initial request destination to have one or more backups. This is useful in the case of:
- Message delivery failure (e.g. a destination channel has been deleted)
- Failure to respond to a request (e.g. your first intended responder is on PTO)
Terminology
Term | Description |
---|---|
message delivery failure | A message cannot be sent to a request destination for whatever reason (e.g a Slack channel does not exist). |
timeout | A request is not approved or denied within the configured timeout (in seconds) window. |
request forward | A timeout or message delivery failure has occurred. |
request expire | We have exhausted all request forward destinations and the last one has either failed or timed out; the request terminates without a response. |
Implementation
In order to use the backup approvers feature, your get_approvers()
reducer must return a RequestDestinationFallback
object. The values passed in to parameters continue_on_delivery_failure
and continue_on_timeout
will determine whether the system will try the next approver based on the failure type.
Failure type | Behavior when true | Behavior when false or None |
---|---|---|
continue_on_delivery_failure | The next destination will be tried immediately after a failed delivery to the current destination. | If false , after a delivery failure, the next approver will not be tried. |
continue_on_timeout | The next RequestDestination will be tried after the timeout (in seconds) specified on the current `RequestDestination. | If None , the next approver will not be tried in the case of a timeout. |
Example
In this example, we will return a RequestDestinationFallback
object from get_approvers()
to walk through what the SDK will do in various scenarios.
from sym.sdk.annotations import reducer
from sym.sdk.integrations import slack
@reducer
def get_approvers(evt):
return slack.fallback(
slack.channel("#sym-requests", allow_self=True, timeout=600),
slack.channel("#sym-backup", allow_self=True, timeout=1200),
slack.user("[email protected]", timeout=None),
continue_on_timeout=True)
In this example, assuming no delivery failures:
- The request will be sent to the
#sym-requests
Slack channel via arequest
event. - If there is no response within 600 seconds (10 mins), the request will be sent to the
#sym-backup
Slack channel via arequest_forward
event. - If there is no response within 1200 seconds (20 mins), the request will be sent via DM to the Slack user with the email
[email protected]
via arequest_forward
event . Since there is notimeout
specified on thatRequestDestination
, it will hang there indefinitely until[email protected]
responds.
Adding in a timeout
However, if we modify the example slightly to add a timeout
on the slack.user
object, like so:
from sym.sdk.annotations import reducer
from sym.sdk.integrations import slack
@reducer
def get_approvers(evt):
return slack.fallback(
slack.channel("#sym-requests", allow_self=True, timeout=600),
slack.channel("#sym-backup", allow_self=True, timeout=1200),
slack.user("[email protected]", timeout=1800),
continue_on_timeout=True)
In this modified example, if there is no response from [email protected]
within 1800 seconds (30 mins), the SDK will fire a request_expire
event, and the message in Slack will be updated to show that the request has timed out.
Advanced: Events
As with all transitions in the Sym SDK, Backup Approvers exposes hooks to the SDK.
It is important to note that the Events that occur in the SDK will be slightly different depending on the behavior specified by the RequestDestinationFallback
returned by get_approvers()
.
In general:
- When a
continue_on_timeout
occurs, Sym will fire arequest_forward
Event. - When a
continue_on_delivery
failure occurs, no new event will be fired. The logic will simply try the next destination without firing any events. - When we have reached the end of our list of destinations and the last one times out, Sym will fire a
request_expire
Event.
Just like other Events, you can write a hook in your impl.py
with custom Python logic that will run on
or after
request_forward
and request_expire
.
Note:request_forward
hooks take an additional param request_forward_context (RequestForwardContext)
, which contains information about the full forwarding context of a Request, including both the full list of potential destinations, and its current index in moving through that list.
For example, you might want to DM a requestor each time their request went to a new, valid destination:
from sym.sdk.annotations import hook
from sym.sdk.integrations import slack
@hook
def on_request_forward(evt, request_forward_context):
index = request_forward_context.current_destination_index
current_destination = request_forward_context.all_request_destinations[index]
if current_destination:
slack.send_message(
evt.get_actor("request"),
f"Your request was forwarded to {current_destination}"
)
Further reading
For more information about
RequestForwardContext
, see our SDK docs here.
Updated 17 days ago