// Package mq exposes the broker-agnostic messaging seam used by services. package mq import ( "context" "encoding/json" "errors" "time" ) var ErrUnavailable = errors.New("message broker unavailable") const ( AtMostOnce byte = 0 AtLeastOnce byte = 1 ExactlyOnce byte = 2 ) type Message struct { Topic string Payload []byte QoS byte Retain bool } func (m Message) DecodeJSON(target any) error { return json.Unmarshal(m.Payload, target) } type Handler func(context.Context, Message) type Client interface { Publish(context.Context, string, []byte, byte, bool) error Subscribe(context.Context, string, byte, Handler) error Unsubscribe(context.Context, ...string) error Connected() bool Close() error } // Registry exposes named broker clients while preserving Client as the // default EMQX/MQTT boundary for existing modules. type Registry interface { Client(provider string) Client PublishTo(context.Context, string, string, []byte, byte, bool) error SubscribeTo(context.Context, string, string, byte, Handler) error UnsubscribeFrom(context.Context, string, ...string) error ConnectedTo(provider string) bool } type Config struct { Enabled bool Broker string ClientID string Username string Password string KeepAlive time.Duration CleanSession bool ConnectTimeout time.Duration } func PublishJSON(ctx context.Context, client Client, topic string, value any, qos byte, retain bool) error { if client == nil { return ErrUnavailable } payload, err := json.Marshal(value) if err != nil { return err } return client.Publish(ctx, topic, payload, qos, retain) }