diff --git a/apps/guildhall_chronicle/lib/guildhall/chronicle/application.ex b/apps/guildhall_chronicle/lib/guildhall/chronicle/application.ex index ef36e75..6c28b91 100644 --- a/apps/guildhall_chronicle/lib/guildhall/chronicle/application.ex +++ b/apps/guildhall_chronicle/lib/guildhall/chronicle/application.ex @@ -1,19 +1,13 @@ defmodule Guildhall.Chronicle.Application do - # See https://hexdocs.pm/elixir/Application.html - # for more information on OTP Applications @moduledoc false - use Application @impl true def start(_type, _args) do children = [ - # Starts a worker by calling: Guildhall.Chronicle.Worker.start_link(arg) - # {Guildhall.Chronicle.Worker, arg} + Guildhall.Chronicle.Consumer ] - # See https://hexdocs.pm/elixir/Supervisor.html - # for other strategies and supported options opts = [strategy: :one_for_one, name: Guildhall.Chronicle.Supervisor] Supervisor.start_link(children, opts) end diff --git a/apps/guildhall_chronicle/lib/guildhall/chronicle/consumer.ex b/apps/guildhall_chronicle/lib/guildhall/chronicle/consumer.ex new file mode 100644 index 0000000..53d533c --- /dev/null +++ b/apps/guildhall_chronicle/lib/guildhall/chronicle/consumer.ex @@ -0,0 +1,26 @@ +defmodule Guildhall.Chronicle.Consumer do + @moduledoc """ + Consumes Chronicle events and projects them into the Ops DB. + + See DESIGN-OPS-DB-CHAIN-OF-CUSTODY-0001 §2.5 for the projector + design — idempotent insert, checkpoint recovery, catch-up on + restart, backpressure handling. + + Stub — the transport (gRPC vs NATS vs Kafka) and the Chronicle + event schema are not yet finalized. This module will subscribe + to the chosen transport and call into the Ops DB repo for each + event, updating `projector_checkpoint` after a successful batch. + """ + use GenServer + require Logger + + def start_link(opts \\ []) do + GenServer.start_link(__MODULE__, opts, name: __MODULE__) + end + + @impl true + def init(_opts) do + Logger.info("Chronicle.Consumer started (stub — no transport configured)") + {:ok, %{last_entry_id: nil}} + end +end diff --git a/apps/guildhall_orchestrator/lib/guildhall/orchestrator/application.ex b/apps/guildhall_orchestrator/lib/guildhall/orchestrator/application.ex index 51f7f10..49946ba 100644 --- a/apps/guildhall_orchestrator/lib/guildhall/orchestrator/application.ex +++ b/apps/guildhall_orchestrator/lib/guildhall/orchestrator/application.ex @@ -1,19 +1,13 @@ defmodule Guildhall.Orchestrator.Application do - # See https://hexdocs.pm/elixir/Application.html - # for more information on OTP Applications @moduledoc false - use Application @impl true def start(_type, _args) do children = [ - # Starts a worker by calling: Guildhall.Orchestrator.Worker.start_link(arg) - # {Guildhall.Orchestrator.Worker, arg} + Guildhall.Orchestrator.CeremonyOrchestrator ] - # See https://hexdocs.pm/elixir/Supervisor.html - # for other strategies and supported options opts = [strategy: :one_for_one, name: Guildhall.Orchestrator.Supervisor] Supervisor.start_link(children, opts) end diff --git a/apps/guildhall_orchestrator/lib/guildhall/orchestrator/ceremony_orchestrator.ex b/apps/guildhall_orchestrator/lib/guildhall/orchestrator/ceremony_orchestrator.ex new file mode 100644 index 0000000..cf23dea --- /dev/null +++ b/apps/guildhall_orchestrator/lib/guildhall/orchestrator/ceremony_orchestrator.ex @@ -0,0 +1,49 @@ +defmodule Guildhall.Orchestrator.CeremonyOrchestrator do + @moduledoc """ + Coordinates ceremony workflows by (eventually) watching substrate + CeremonyRequest CRDs and notifying witnesses via PubSub. + + Currently a stub — the K8s CRD watcher will be wired in once the + `:k8s` package is added and a kubeconfig is available. + + ### Orchestrator vs engine + + This module ORCHESTRATES (notifies humans, collects signatures, + broadcasts status). The substrate `CeremonyEngine` DECIDES + (evaluates Accord conditions, advances the state machine). + + See DESIGN-ORG-OPS-FRAMEWORK-0001 §3.2 for the separation. + """ + use GenServer + require Logger + + def start_link(opts \\ []) do + GenServer.start_link(__MODULE__, opts, name: __MODULE__) + end + + @doc """ + Broadcast a ceremony status change to all LiveView subscribers. + + Called by the K8s watcher (future) or manually in tests. Fans + out on both the per-ceremony topic and the wildcard topic. + """ + def broadcast_ceremony_status(ceremony_id, status) do + Phoenix.PubSub.broadcast( + Guildhall.PubSub, + "ceremony:#{ceremony_id}", + {:ceremony_status, ceremony_id, status} + ) + + Phoenix.PubSub.broadcast( + Guildhall.PubSub, + "ceremony:*", + {:ceremony_status, ceremony_id, status} + ) + end + + @impl true + def init(_opts) do + Logger.info("CeremonyOrchestrator started (stub — no K8s watcher yet)") + {:ok, %{watcher: nil}} + end +end