mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: modify replicasync to handle NATS explicitly (#26666)
relates to GRU-69 Modifies replicasync to handle discovering NATS enabled primary replicas explicitly, and passing that info to the NATS Pubsub. This PR adds a new deployment value to explicitly represent the host or IP that the replica can be reached on. It isn't wired up to the CLI, but piggybacks on the DERP config for now. We learn the NATS port directly from NATS at runtime, and propagate it thru replicasync to learn all peers for clustering.
This commit is contained in:
@@ -678,7 +678,8 @@ func New(ctx context.Context, options *Options) (_ *API, err error) {
|
||||
}
|
||||
|
||||
// We always want to run the replica manager even if we don't have DERP
|
||||
// enabled, since it's used to detect other coder servers for licensing.
|
||||
// enabled, since it's used to detect other coder servers for licensing,
|
||||
// and NATS clustering for HA pubsub.
|
||||
api.replicaManager, err = replicasync.New(ctx, options.Logger, options.Database, options.ReplicaSyncPubsub, &replicasync.Options{
|
||||
ID: api.AGPL.ID,
|
||||
RelayAddress: options.DERPServerRelayAddress,
|
||||
@@ -686,6 +687,7 @@ func New(ctx context.Context, options *Options) (_ *API, err error) {
|
||||
RegionID: int32(options.DERPServerRegionID),
|
||||
TLSConfig: meshTLSConfig,
|
||||
UpdateInterval: options.ReplicaSyncUpdateInterval,
|
||||
ClusterHost: options.ClusterHost,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("initialize replica: %w", err)
|
||||
@@ -788,6 +790,7 @@ type Options struct {
|
||||
// Used for high availability.
|
||||
ReplicaSyncUpdateInterval time.Duration
|
||||
ReplicaErrorGracePeriod time.Duration
|
||||
ClusterHost string // IP or hostname to reach this specific replica
|
||||
DERPServerRelayAddress string
|
||||
DERPServerRegionID int
|
||||
|
||||
|
||||
@@ -631,7 +631,7 @@ func TestMultiReplica_NATSPubsubPeers(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitLong)
|
||||
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true})
|
||||
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}).Leveled(slog.LevelDebug)
|
||||
db, pgPubsub := dbtestutil.NewDB(t)
|
||||
clusterToken := "shared-token"
|
||||
|
||||
@@ -671,13 +671,19 @@ func TestMultiReplica_NATSPubsubPeers(t *testing.T) {
|
||||
t.Cleanup(func() { _ = natsB.Close() })
|
||||
|
||||
mgr, err := replicasync.New(ctx, logger.Named("replica-b"), db, pgPubsub, &replicasync.Options{
|
||||
ID: uuid.New(),
|
||||
RelayAddress: fmt.Sprintf("nats://127.0.0.1:%d", natsB.Server.ClusterAddr().Port),
|
||||
ID: uuid.New(),
|
||||
// port doesn't matter because we don't have an API up, but replicasync will refuse peers that don't set
|
||||
// RelayAddress at all.
|
||||
RelayAddress: "https://127.0.0.1",
|
||||
ClusterHost: "127.0.0.1",
|
||||
RegionID: 12345,
|
||||
UpdateInterval: testutil.IntervalFast,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { _ = mgr.Close() })
|
||||
require.NotNil(t, natsB.Server.ClusterAddr())
|
||||
// nolint: gosec // nats listens on TCP ports
|
||||
mgr.SetSelfNATSPort(int32(natsB.Server.ClusterAddr().Port))
|
||||
|
||||
subject := "nats.replica"
|
||||
messages := make(chan []byte, 1)
|
||||
|
||||
@@ -667,8 +667,8 @@ func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request)
|
||||
Error: req.ReplicaError,
|
||||
DatabaseLatency: 0,
|
||||
Primary: false,
|
||||
ClusterHost: "", // TODO
|
||||
NATSPort: 0, // TODO
|
||||
ClusterHost: "",
|
||||
NATSPort: 0, // proxies do not run NATS
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("update replica: %w", err)
|
||||
@@ -686,8 +686,8 @@ func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request)
|
||||
Version: req.Version,
|
||||
DatabaseLatency: 0,
|
||||
Primary: false,
|
||||
ClusterHost: "", // TODO
|
||||
NATSPort: 0, // TODO
|
||||
ClusterHost: "",
|
||||
NATSPort: 0, // proxies do not run NATS
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert replica: %w", err)
|
||||
@@ -830,8 +830,8 @@ func (api *API) workspaceProxyDeregister(rw http.ResponseWriter, r *http.Request
|
||||
Error: replica.Error,
|
||||
DatabaseLatency: replica.DatabaseLatency,
|
||||
Primary: replica.Primary,
|
||||
ClusterHost: "", // TODO
|
||||
NATSPort: 0, // TODO
|
||||
ClusterHost: "",
|
||||
NATSPort: 0, // proxies do not run NATS
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("update replica: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user