heartbeat: notify Michael by email when each queued task completes
Adds notify_task_complete/3 called after every queue task resolves (done, blocked, or failed). Posts to Telepathy's POST /email endpoint. Also adds :inets and :ssl to extra_applications so :httpc is available. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6271e973a6
commit
11a9026597
@ -120,12 +120,15 @@ defmodule Symbiont.Heartbeat do
|
|||||||
"Heartbeat: task #{task["id"]} returned but self-reported blocked — marking blocked"
|
"Heartbeat: task #{task["id"]} returned but self-reported blocked — marking blocked"
|
||||||
)
|
)
|
||||||
Symbiont.Queue.block(task["id"], text)
|
Symbiont.Queue.block(task["id"], text)
|
||||||
|
notify_task_complete(task, :blocked, text)
|
||||||
else
|
else
|
||||||
Symbiont.Queue.complete(task["id"], text)
|
Symbiont.Queue.complete(task["id"], text)
|
||||||
|
notify_task_complete(task, :done, text)
|
||||||
end
|
end
|
||||||
|
|
||||||
{:error, reason} ->
|
{:error, reason} ->
|
||||||
Symbiont.Queue.fail(task["id"], inspect(reason))
|
Symbiont.Queue.fail(task["id"], inspect(reason))
|
||||||
|
notify_task_complete(task, :failed, inspect(reason))
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
@ -186,4 +189,56 @@ defmodule Symbiont.Heartbeat do
|
|||||||
defp schedule_next(interval) do
|
defp schedule_next(interval) do
|
||||||
Process.send_after(self(), :tick, interval)
|
Process.send_after(self(), :tick, interval)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp notify_task_complete(task, status, result) do
|
||||||
|
task_id = task["id"] || "unknown"
|
||||||
|
task_desc = task["task"] || ""
|
||||||
|
priority = task["priority"] || "normal"
|
||||||
|
|
||||||
|
subject =
|
||||||
|
case status do
|
||||||
|
:done -> "Task done [#{priority}]: #{String.slice(task_desc, 0, 60)}"
|
||||||
|
:blocked -> "Task blocked [#{priority}]: #{String.slice(task_desc, 0, 60)}"
|
||||||
|
:failed -> "Task failed [#{priority}]: #{String.slice(task_desc, 0, 60)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
snippet = String.slice(result || "", 0, 800)
|
||||||
|
|
||||||
|
body = """
|
||||||
|
Task #{task_id} completed with status: #{status}
|
||||||
|
|
||||||
|
Description:
|
||||||
|
#{task_desc}
|
||||||
|
|
||||||
|
Result:
|
||||||
|
#{snippet}
|
||||||
|
|
||||||
|
Muse
|
||||||
|
"""
|
||||||
|
|
||||||
|
payload =
|
||||||
|
Jason.encode!(%{
|
||||||
|
to: "mdwyer@michaelmdwyer.com",
|
||||||
|
subject: subject,
|
||||||
|
body: body,
|
||||||
|
from_name: "Muse"
|
||||||
|
})
|
||||||
|
|
||||||
|
url = ~c"http://localhost:8114/email"
|
||||||
|
|
||||||
|
try do
|
||||||
|
:httpc.request(
|
||||||
|
:post,
|
||||||
|
{url, [], ~c"application/json", payload},
|
||||||
|
[{:timeout, 10_000}],
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
|
Logger.info("Task notification sent: #{task_id} → #{status}")
|
||||||
|
rescue
|
||||||
|
e -> Logger.warning("Task notification failed for #{task_id}: #{Exception.message(e)}")
|
||||||
|
catch
|
||||||
|
_, reason -> Logger.warning("Task notification failed for #{task_id}: #{inspect(reason)}")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user