Production Pulse · 7 / 8
Share one signal-sending library
Consolidate scheduled, event-driven and manual signals behind one supplied Lua library.
YOUR TASK
Make this happen
Connect
integration_actor_library.monitortolibrariesin actor.cococo.Keep each supplied entry-point script: heartbeat, job.updated and manual.
Update the Action output to a required boolean
acceptedfield.
This lesson starts with the previous working solution. Build and connect the next capability. Your earlier drafts are kept separately.
Read the starter files
main.cococo
integration_document "monitor" {
integrationId = "com.academy.monitor"
sdkVersion = "2.0"
version = "1.0.0"
description = "A small heartbeat integration"
resources = [integration_resource_requirement.monitor_service]
policy = integration_policy.monitor
apiClients = [integration_api_client.monitor]
actor = integration_actor.monitor
}
actor.cococo
integration_actor "monitor" {
subscriptions = [integration_actor_subscription.job_updates]
actions = [integration_actor_action.status]
timers = [integration_actor_timer.heartbeat, integration_actor_timer.daily_review]
}
timer.cococo
integration_actor_timer "heartbeat" {
name = "heartbeat"
schedule = { every = "5m" }
jitter = "15s"
source = "return { alive = true }"
}
events.cococo
integration_actor_subscription "job_updates" {
topic = "job.updated"
source = file("scripts/job-updated.lua")
}
actions.cococo
integration_actor_action "status" {
name = "status"
label = "Check production pulse"
inputSchema = { type = "object", properties = {} }
outputSchema = {
type = "object"
properties = { alive = { type = "boolean" } }
required = ["alive"]
}
source = file("scripts/status.lua")
}
resources.cococo
integration_resource_requirement "monitor_service" {
id = "monitor_service"
type = "protocol/http"
optional = false
description = "HTTP device for the monitoring service"
}
policy.cococo
integration_policy_statement "devices" {
effect = "ALLOW"
actions = ["device:*"]
resources = [integration_resource_requirement.monitor_service.id]
}
integration_policy "monitor" {
statements = [integration_policy_statement.devices]
}
client.cococo
integration_api_client "monitor" {
name = "monitor"
schema = file("contracts/monitor.openapi.json")
definition = file("contracts/monitor.api.xml")
}
daily.cococo
integration_actor_timer "daily_review" {
name = "daily_review"
schedule = { cron = "0 6 * * *" }
source = "return { review = true }"
}
library.cococo
integration_actor_library "monitor" {
name = "monitor"
# TODO: add source — see the task above.
}
Supplied scripts and pinned contracts (read-only)
These fixtures explain the runtime behaviour being composed. They are included in validation but are not executed. The generated API definition is supplied, not an XML authoring task.
scripts/heartbeat.lua
local monitor = ctx.script.load("monitor")
return monitor.send("heartbeat")
scripts/job-updated.lua
local event, config = ...
local monitor = ctx.script.load("monitor")
return monitor.send("job.updated")
scripts/status.lua
local input, actionConfig = ...
local monitor = ctx.script.load("monitor")
return monitor.send("manual")
contracts/monitor.openapi.json
{
"openapi": "3.0.3",
"info": {
"title": "Production Pulse",
"version": "1.0.0"
},
"paths": {
"/signals": {
"post": {
"operationId": "sendSignal",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"reason"
],
"properties": {
"reason": {
"type": "string"
}
}
}
}
}
},
"responses": {
"200": {
"description": "Signal accepted",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"accepted"
],
"properties": {
"accepted": {
"type": "boolean"
}
}
}
}
}
}
}
}
}
}
}
contracts/monitor.api.xml
<api-client name="monitor" schema-sha256="ff335ef17f27b04682e45ed20fc932d10c89dc2b37572defa7addf51129fa220"><operation id="sendSignal"/></api-client>
scripts/monitor.lua
local monitor = {}
monitor.send = function(reason: string)
local client = ctx.api.get("monitor"):init(ctx.device.get("monitor_service"))
local ok, response = client:sendSignal({ body = { reason = reason } })
if not ok then
error(response)
end
return { accepted = response.body.accepted }
end
return monitor