(bnd binding)
| 598 | } |
| 599 | |
| 600 | func (b *binder) writeOne(bnd binding) error { |
| 601 | var err error |
| 602 | if bnd.kind == proto.CoordinateResponse_PeerUpdate_DISCONNECTED { |
| 603 | _, err = b.store.DeleteTailnetPeer(b.ctx, database.DeleteTailnetPeerParams{ |
| 604 | ID: uuid.UUID(bnd.bKey), |
| 605 | CoordinatorID: b.coordinatorID, |
| 606 | }) |
| 607 | // writeOne is idempotent |
| 608 | if xerrors.Is(err, sql.ErrNoRows) { |
| 609 | err = nil |
| 610 | } |
| 611 | } else { |
| 612 | var nodeRaw []byte |
| 613 | nodeRaw, err = gProto.Marshal(bnd.node) |
| 614 | if err != nil { |
| 615 | // this is very bad news, but it should never happen because the node was Unmarshalled or converted by this |
| 616 | // process earlier. |
| 617 | b.logger.Critical(b.ctx, "failed to marshal node", slog.Error(err)) |
| 618 | return err |
| 619 | } |
| 620 | status := database.TailnetStatusOk |
| 621 | if bnd.kind == proto.CoordinateResponse_PeerUpdate_LOST { |
| 622 | status = database.TailnetStatusLost |
| 623 | } |
| 624 | _, err = b.store.UpsertTailnetPeer(b.ctx, database.UpsertTailnetPeerParams{ |
| 625 | ID: uuid.UUID(bnd.bKey), |
| 626 | CoordinatorID: b.coordinatorID, |
| 627 | Node: nodeRaw, |
| 628 | Status: status, |
| 629 | }) |
| 630 | } |
| 631 | |
| 632 | if err != nil && !database.IsQueryCanceledError(err) { |
| 633 | b.logger.Error(b.ctx, "failed to write binding to database", |
| 634 | slog.F("binding_id", bnd.bKey), |
| 635 | slog.F("node", bnd.node), |
| 636 | slog.Error(err)) |
| 637 | } |
| 638 | if err == nil { |
| 639 | publishPeerUpdate(b.ctx, b.pubsub, b.logger, uuid.UUID(bnd.bKey)) |
| 640 | } |
| 641 | return err |
| 642 | } |
| 643 | |
| 644 | // storeBinding stores the latest binding, where we interpret kind == DISCONNECTED as removing the binding. This keeps the map |
| 645 | // from growing without bound. |
no test coverage detected