# `CMDC.Provider.Registry.Broadcaster`
[🔗](https://github.com/tupleyun/cmdc/blob/v0.5.3/lib/cmdc/provider/registry/broadcaster.ex#L1)

Provider Profile 变更跨节点广播 behaviour。

cmdc 主库默认提供两个实现：

| 实现 | 适用场景 |
|---|---|
| `CMDC.Provider.Registry.Broadcaster.Noop` | 单机部署 / 测试 |
| `CMDC.Provider.Registry.Broadcaster.PG`（默认）| BEAM 集群 best-effort |

生产多节点强一致场景请自实现接 Phoenix.PubSub / Redis Streams。

## 实现要求

- `broadcast/1` **必须**返回 `:ok`；抛异常会被 Registry 捕获并降级（telemetry 会标记 `broadcaster_called?: false`）
- 实现内部如有 GenServer / 长连接，自行管理生命周期；可选实现 `setup/1` 在 Registry init 时被调用一次

## 远端消息约定

当 broadcaster 收到来自其它节点的事件时，需要给本节点 `CMDC.Provider.Registry` 进程
发送如下消息（Registry handle_info 已实现写入本地 ETS）：

    send(GenServer.whereis(CMDC.Provider.Registry),
         {:cmdc_registry_remote, {:register, name, [provider:, opts:]}})

    send(GenServer.whereis(CMDC.Provider.Registry),
         {:cmdc_registry_remote, {:unregister, name}})

## 配置示例

    # config/config.exs
    config :cmdc, CMDC.Provider.Registry,
      broadcaster: MyApp.PhoenixPubSubBroadcaster

## 自定义实现样板

    defmodule MyApp.PhoenixPubSubBroadcaster do
      @behaviour CMDC.Provider.Registry.Broadcaster

      @topic "cmdc:provider_registry"

      # 可选：Registry init 时调用，订阅 PubSub topic
      def setup(_opts) do
        Phoenix.PubSub.subscribe(MyApp.PubSub, @topic)
        :ok
      end

      @impl true
      def broadcast(event) do
        Phoenix.PubSub.broadcast(MyApp.PubSub, @topic, {:cmdc_registry_remote, event})
      end
    end

# `event`

```elixir
@type event() ::
  {:register, name :: String.t(), profile_opts :: keyword()}
  | {:unregister, name :: String.t()}
```

广播事件 — register 含完整 profile_opts，unregister 只含 name。

# `broadcast`

```elixir
@callback broadcast(event()) :: :ok
```

广播 profile 变更事件。必须返回 `:ok`，异常会被 Registry 捕获降级。

# `setup`
*optional* 

```elixir
@callback setup(opts :: keyword()) :: :ok
```

可选回调 — Registry GenServer `init/1` 时调用一次，
适用于需要订阅 PubSub topic / join PG group 等初始化场景。

返回 `:ok` 表示成功；其它返回值会被忽略但记录 warning。

---

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