# `Mnemosyne.Notifier`
[🔗](https://github.com/edlontech/mnemosyne/blob/main/lib/mnemosyne/notifier.ex#L1)

Behaviour for pluggable event notification.

Implementations receive real-time events about graph changes,
session transitions, and maintenance operations.

# `event`

```elixir
@type event() ::
  {:changeset_applied, Mnemosyne.Graph.Changeset.t(), metadata()}
  | {:nodes_deleted, [String.t()], metadata()}
  | {:decay_completed,
     %{
       checked: non_neg_integer(),
       deleted: non_neg_integer(),
       deleted_ids: [String.t()]
     }, metadata()}
  | {:consolidation_completed,
     %{
       checked: non_neg_integer(),
       deleted: non_neg_integer(),
       deleted_ids: [String.t()]
     }, metadata()}
  | {:validation_completed,
     %{
       checked: non_neg_integer(),
       penalized: non_neg_integer(),
       orphaned: non_neg_integer()
     }, metadata()}
  | {:repair_completed,
     %{
       checked: non_neg_integer(),
       repaired_nodes: non_neg_integer(),
       dangling_refs: non_neg_integer(),
       orphans_deleted: non_neg_integer(),
       orphan_ids: [String.t()]
     }, metadata()}
  | {:session_transition, session_id :: String.t(), old_state :: atom(),
     new_state :: atom(), metadata()}
  | {:recall_executed, query :: String.t(), results :: term(), metadata()}
  | {:recall_failed, query :: String.t(), reason :: term(), metadata()}
  | {:step_appended, session_id :: String.t(),
     %{
       step_index: non_neg_integer(),
       trajectory_id: String.t(),
       boundary_detected: boolean()
     }, metadata()}
  | {:trajectory_committed, session_id :: String.t(),
     trajectory_id :: String.t(),
     %{node_count: non_neg_integer(), node_ids: [String.t()]}, metadata()}
  | {:trajectory_flushed, session_id :: String.t(), trajectory_id :: String.t(),
     %{node_count: non_neg_integer(), node_ids: [String.t()]}, metadata()}
  | {:session_expired, session_id :: String.t(), metadata()}
  | {:trajectory_extraction_failed, session_id :: String.t(),
     trajectory_id :: String.t(), reason :: term(), metadata()}
  | {:append_failed, session_id :: String.t(), %{error: term()}}
  | {:write_failed, operation :: atom(), reason :: term(), metadata()}
  | {:write_crashed, operation :: atom(), reason :: term(), metadata()}
```

# `metadata`

```elixir
@type metadata() :: %{
  optional(:session_id) =&gt; String.t() | nil,
  optional(:trace) =&gt; struct() | nil,
  optional(:node_ids) =&gt; [String.t()]
}
```

# `notify`

```elixir
@callback notify(repo_id :: String.t(), event()) :: :ok
```

# `safe_notify`

```elixir
@spec safe_notify(module(), String.t(), event()) :: :ok
```

Invokes `notifier.notify/2`, rescuing any exception and logging a warning.

Always returns `:ok`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
