Directives
When processing an order, the Katalys Platform might issue what we call directives. These instruct an integration to perform certain tasks, usually related to orders and products (checking product availability, calculating order tax, …).
Integrators might be familiar with the concept of webhooks—this is the model that directives are largely based on, with the main difference being that we only expect the integration to offer a single HTTP endpoint that will receive JSON payloads from the Katalys Platform.
A payload might include multiple directives and each directive might reference a different entity in the system. This is why each directive in the payload includes its own arguments, even though they might repeat:
{
"directives": [
{
"id": "d3cca723-6317-4fdf-8ccd-9a0ca10aff77",
"directive": "update_availability",
"args": {
"order_id": "44f13c01-3f72-4096-9abc-d9bae86e2ef2"
}
},
{
"id": "24ab1e15-5681-4a05-9987-2a413ef4dd6b",
"directive": "update_available_shipping_rates",
"args": {
"order_id": "44f13c01-3f72-4096-9abc-d9bae86e2ef2"
}
},
{
"id": "a2b9c1df-5caf-4785-a37b-6d6f38a177e8",
"directive": "update_tax_amounts",
"args": {
"order_id": "44f13c01-3f72-4096-9abc-d9bae86e2ef2"
}
}
]
}
Directives should be processed in order. There is no need to attempt to optimize the process by attempting to satisfy multiple directives at once or share data between them.
Robust processing and error handling
The most important part (aside from satisfying the directives themselves) is to service the request in a robust manner, such that a failure in processing one of the directives is correctly signaled in the response and does not cause request processing to fail with a 500 server error.
Notice how we handle errors, collect the error message and error’s backtrack.
results = []
directives.each do |payload|
result = {
source_id: payload.id,
source_directive: payload.directive
}
begin
result.merge!({
status: "ok",
data: process_directive(payload)
})
rescue e
result.merge!({
status: "error",
data: { message: e.message, trace: e.backtrace }
})
end
results.push(result)
end
JSON.dump({ results: results })
Following the above ruby snippet, the resulting response could look like this:
Notice how a failed directive is sent back with error details. Please implement the same structure.
You’re free to add additional fields to the details object and help yourself address crashes.
{
"results": [
{
"source_directive": "update_availability",
"source_id": "ee4d346f-de86-4285-934c-a9f1b9c5c0ed",
"status": "ok"
},
{
"source_directive": "update_available_shipping_rates",
"source_id": "45a42385-8ebd-45bb-9ac8-c7365aa157ac",
"status": "ok"
},
{
"source_directive": "update_tax_amounts",
"details": {
"message": "[TEST] simulate_error_reporting_health_check",
"trace": [
"lib/shopify_app_web/controllers/oneo_to_merchant_controller.rb:61",
"lib/shopify_app_web/controllers/oneo_to_merchant_controller.rb:33",
"lib/phoenix/router.ex:354"
]
},
"source_id": "6e1efe64-2f37-40c4-8198-c8b7827dba5d",
"status": "error"
}
]
}