diff --git a/lib/symbiont/heartbeat.ex b/lib/symbiont/heartbeat.ex index ed2eb66..045e417 100644 --- a/lib/symbiont/heartbeat.ex +++ b/lib/symbiont/heartbeat.ex @@ -120,12 +120,15 @@ defmodule Symbiont.Heartbeat do "Heartbeat: task #{task["id"]} returned but self-reported blocked — marking blocked" ) Symbiont.Queue.block(task["id"], text) + notify_task_complete(task, :blocked, text) else Symbiont.Queue.complete(task["id"], text) + notify_task_complete(task, :done, text) end {:error, reason} -> Symbiont.Queue.fail(task["id"], inspect(reason)) + notify_task_complete(task, :failed, inspect(reason)) end end) end) @@ -186,4 +189,56 @@ defmodule Symbiont.Heartbeat do defp schedule_next(interval) do Process.send_after(self(), :tick, interval) 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 diff --git a/mix.exs b/mix.exs index f53fe11..8968fb3 100644 --- a/mix.exs +++ b/mix.exs @@ -15,7 +15,7 @@ defmodule Symbiont.MixProject do def application do [ - extra_applications: [:logger, :crypto], + extra_applications: [:logger, :crypto, :inets, :ssl], mod: {Symbiont.Application, []} ] end