01f8988cc3
Add a --bind flag (default 127.0.0.1) to membershipd that controls which network interface both the control-plane HTTP API and the embedded NATS data plane listen on. Use 0.0.0.0 to expose the stack to the LAN so remote peers (phones, other PCs) can connect; keep the default for a loopback-only dev stack. embeddednats gains StartHost(storeDir, host, port) for explicit interface control; Start stays a backward-compatible wrapper (host "" = nats default 0.0.0.0) so the playground and tests are untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
63 lines
2.2 KiB
Go
63 lines
2.2 KiB
Go
// Package embeddednats starts an in-process NATS server with JetStream enabled.
|
|
//
|
|
// This lets the whole unibus stack run with `go run` without installing or
|
|
// managing a separate NATS deployment. In production, point clients at an
|
|
// external NATS via the --nats-url flag instead of using this.
|
|
package embeddednats
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
server "github.com/nats-io/nats-server/v2/server"
|
|
)
|
|
|
|
// Start launches an embedded nats-server with JetStream enabled, listening on
|
|
// the given port and persisting JetStream state under storeDir. The listen host
|
|
// is left at the nats-server default ("0.0.0.0", all interfaces). It blocks
|
|
// until the server is ready to accept connections (up to 5s) and returns the
|
|
// running server. The caller is responsible for calling Shutdown on it.
|
|
//
|
|
// Start is a thin backward-compatible wrapper over StartHost; callers that need
|
|
// to control the bind interface (loopback vs LAN) should use StartHost directly.
|
|
func Start(storeDir string, port int) (*server.Server, error) {
|
|
return StartHost(storeDir, "", port)
|
|
}
|
|
|
|
// StartHost is Start with explicit control over the bind interface. host selects
|
|
// which network interface the data plane listens on: pass "127.0.0.1" to keep
|
|
// NATS loopback-only (the safe default for a single-host dev stack) or "0.0.0.0"
|
|
// to expose it to the LAN so remote peers (phones, other PCs) can connect. An
|
|
// empty host falls back to the nats-server default ("0.0.0.0", all interfaces).
|
|
func StartHost(storeDir, host string, port int) (*server.Server, error) {
|
|
opts := &server.Options{
|
|
JetStream: true,
|
|
StoreDir: storeDir,
|
|
Host: host,
|
|
Port: port,
|
|
DontListen: false,
|
|
// Keep the embedded server quiet by default; the host app logs the URLs.
|
|
NoLog: true,
|
|
NoSigs: true,
|
|
}
|
|
|
|
ns, err := server.NewServer(opts)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("embeddednats: new server: %w", err)
|
|
}
|
|
|
|
go ns.Start()
|
|
|
|
if !ns.ReadyForConnections(5 * time.Second) {
|
|
ns.Shutdown()
|
|
return nil, fmt.Errorf("embeddednats: server not ready for connections within 5s")
|
|
}
|
|
|
|
return ns, nil
|
|
}
|
|
|
|
// ClientURL returns a NATS connection URL for the running embedded server.
|
|
func ClientURL(ns *server.Server) string {
|
|
return ns.ClientURL()
|
|
}
|