coder/enterprise/tailnet/handshaker.go

74 lines
1.4 KiB
Go

package tailnet
import (
"context"
"fmt"
"sync"
"github.com/google/uuid"
"cdr.dev/slog"
"github.com/coder/coder/v2/coderd/database/pubsub"
)
type readyForHandshake struct {
src uuid.UUID
dst uuid.UUID
}
type handshaker struct {
ctx context.Context
logger slog.Logger
coordinatorID uuid.UUID
pubsub pubsub.Pubsub
updates <-chan readyForHandshake
workerWG sync.WaitGroup
}
func newHandshaker(ctx context.Context,
logger slog.Logger,
id uuid.UUID,
ps pubsub.Pubsub,
updates <-chan readyForHandshake,
startWorkers <-chan struct{},
) *handshaker {
s := &handshaker{
ctx: ctx,
logger: logger,
coordinatorID: id,
pubsub: ps,
updates: updates,
}
// add to the waitgroup immediately to avoid any races waiting for it before
// the workers start.
s.workerWG.Add(numHandshakerWorkers)
go func() {
<-startWorkers
for i := 0; i < numHandshakerWorkers; i++ {
go s.worker()
}
}()
return s
}
func (t *handshaker) worker() {
defer t.workerWG.Done()
for {
select {
case <-t.ctx.Done():
t.logger.Debug(t.ctx, "handshaker worker exiting", slog.Error(t.ctx.Err()))
return
case rfh := <-t.updates:
err := t.pubsub.Publish(eventReadyForHandshake, []byte(fmt.Sprintf(
"%s,%s", rfh.dst.String(), rfh.src.String(),
)))
if err != nil {
t.logger.Error(t.ctx, "publish ready for handshake", slog.Error(err))
}
}
}
}