Files
LocalAI/core/services/messaging/interfaces.go
T
Ettore Di Giacinto eb7ed9b910 refactor(distributed): delete MessagingClient and shrink the NATS client to fan-out
Nothing in the tree publishes, subscribes, queue-subscribes or requests through
the MessagingClient interface any more, so it is deleted rather than shrunk to
Broadcaster: two exported names for one method set in one package is an
invitation for the next author to pick whichever the surrounding file already
imported.

    $ grep -rn 'messaging\.MessagingClient' --include='*.go' .
    core/services/syncstate/syncstate.go:54:  // It is messaging.Broadcaster rather than messaging.MessagingClient because

(one hit, a comment; no live referent. The naive grep in the plan also matches
prose and the local test type names fakeMessagingClient and
countingMessagingClient, so it can never be empty.)

*messaging.Client is shrunk to exactly Broadcaster plus its own lifecycle.
QueueSubscribe, QueueSubscribeReply, SubscribeReply, Request, Conn and the
package helpers QueueSubscribeJSON and RequestJSON go with it; none had a
production caller. Deleting the methods rather than only the call sites is what
makes putting a family back on this carrier a build error instead of a line that
compiles, publishes successfully, and is delivered onto a carrier the deployment
is being taken off. Conn is in that list because while it existed every other
name was one c.Conn().X() away; the flush-and-verdict that its real consumers
needed is now ConfirmRoundTrip, which keeps the NATS JWT permission specs armed.

The client, its options and its TLS plumbing are NOT deleted, and both processes
stay on the bus. agent.<name>.cancel is the one fan-out family that could not
move: its only subscriber is the agent worker, which has no database and cannot
join the PostgreSQL carrier at all, so a cancel published there would reach no
worker and be reported as sent. The frontend passes the client to
newFanoutBridges as its cancelCarrier and the worker subscribes on it, so
--nats-url stays required on agent-worker. Both go with the tunnel cancel verb.

The struct field is renamed Nats -> CancelCarrier to say what it is for, and
agentpool loses the messaging.Publisher it held only to be non-nil: it never
published on it, and it was gating whether a frontend runs agents distributed or
in an in-process pool. Retiring the bus would have flipped every replica back to
the in-process pool silently. The gate now reads the agent store, which is the
dependency the mode actually requires.

Also deletes four subject builders with no production publisher
(SubjectFineTuneProgress, SubjectFineTuneCancel, SubjectCacheInvalidateSkills,
SubjectCacheInvalidateCollection), the queue and request/reply halves of the
shared test double, and the e2e specs that were their only callers. Every
surviving subject is now pinned to its exact literal, because a subject is a
cross-version wire format and a rename that looks internal stops half a fleet
hearing the other half.

Docs: distributed-mode.md and cli-reference.md no longer claim NATS carries the
agent-worker job subjects, the frontend's cross-replica events, or an agent
worker's real work.

Assisted-by: Claude Opus 5 [claude-code]
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
2026-09-27 03:05:13 +00:00

48 lines
2.0 KiB
Go

package messaging
// Publisher publishes JSON-encoded messages to broadcast subjects.
type Publisher interface {
Publish(subject string, data any) error
}
// Subscription represents a subscription that can be unsubscribed.
type Subscription interface {
Unsubscribe() error
}
// Broadcaster is the whole messaging surface: a publish reaches every
// subscriber on every replica.
//
// There is no second interface. Request/reply became a control RPC on the
// worker's tunnel, queue groups became a claim queue on the job store, and what
// is left is fan-out, which is one method more than Publisher. The wider
// MessagingClient that used to sit here is deleted rather than shrunk: two
// exported names for one method set in one package is an invitation for the
// next author to pick whichever the surrounding file already imported.
//
// IsConnected and Close are deliberately NOT here, and their absence is stated
// rather than left to be inferred.
//
// IsConnected has no production consumer. It is asserted by specs and read by
// logging, and a carrier's consumers must not branch on it. "The carrier is
// down" is not one of the four conditions a node's state can be in, and no code
// may turn it into evidence that a worker is absent.
//
// Close DOES have real callers, and they hold a CONCRETE type rather than this
// interface, which is why the interface can omit it.
type Broadcaster interface {
Publisher
Subscribe(subject string, handler func([]byte)) (Subscription, error)
}
// One of the two carriers a deployment dials, asserted in the package that owns
// the interface rather than at whichever call site is migrated next.
//
// *pgbus.Bus is the other and cannot be named here, because it imports this
// package; it is asserted from interfaces_test.go, which also pins that
// *Client's method set is this interface plus its own lifecycle and nothing
// else. That pin is the guard, not this line: a conformance assertion stays
// true however many methods grow back, so it cannot say that the retired halves
// are gone.
var _ Broadcaster = (*Client)(nil)