Skip to content

Sync records to a webhook

Send every create, update and delete in a collection to an external service, and let the record be indexed as normal.

Trigger: record.index:<nsid>. Needs: happyview-http. Script variables: WEBHOOK_URL.

The receiving service should treat each request as “set the state of this URI”, keyed by uri. The same record can reach this script more than once, so a service that appends a row per request will see duplicates. See Create scripts may run more than once.

local json = require("internal.json")
local http = require("happyview.http")
function handle(input, ctx)
local res = http.post(ctx.env.WEBHOOK_URL, {
headers = { ["Content-Type"] = "application/json" },
body = json.encode({
action = input.action,
uri = input.uri,
did = input.did,
record = input.record,
}),
})
if res.status >= 400 then
error("webhook answered " .. res.status)
end
-- On delete `record` is null, which still lets the delete proceed.
return input.record or true
end
  1. record.index catches creates, updates and deletes for the collection, unless a more specific record.create, record.update or record.delete script exists for an action.
  2. The script posts the event to the URL in the WEBHOOK_URL script variable.
  3. http.post returns a 4xx or 5xx answer as an ordinary result, so the script checks status and raises for it.
  4. It returns the record so indexing goes ahead unchanged. A script that returns nothing would stop the record from being indexed.

If the request fails or the webhook answers with an error status, the script fails. A record script is retried up to 4 times in total and then dead-lettered, and the record is indexed anyway. Wrap the call in pcall (Lua) or try/catch (JavaScript and TypeScript) if you would rather log the failure and carry on.

Record scripts run before indexing, so a slow webhook slows down indexing for everything behind it. Keep the endpoint fast, or have the script create a background job and do the call from there.