mirror of
https://github.com/coder/coder.git
synced 2025-07-21 01:28:49 +00:00
feat: add queries to clean lost connections in PGCoordinator (#10938)
Adds cleanup queries to clean out "lost" peer and tunnel state after 24 hours. We leave this state in the database so that anything trying to connect to the peer can see that it was lost, but clean it up after 24 hours to ensure our table doesn't grow without bounds.
This commit is contained in:
@ -695,6 +695,20 @@ func (q *querier) CleanTailnetCoordinators(ctx context.Context) error {
|
|||||||
return q.db.CleanTailnetCoordinators(ctx)
|
return q.db.CleanTailnetCoordinators(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q *querier) CleanTailnetLostPeers(ctx context.Context) error {
|
||||||
|
if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return q.db.CleanTailnetLostPeers(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *querier) CleanTailnetTunnels(ctx context.Context) error {
|
||||||
|
if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return q.db.CleanTailnetTunnels(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (q *querier) DeleteAPIKeyByID(ctx context.Context, id string) error {
|
func (q *querier) DeleteAPIKeyByID(ctx context.Context, id string) error {
|
||||||
return deleteQ(q.log, q.auth, q.db.GetAPIKeyByID, q.db.DeleteAPIKeyByID)(ctx, id)
|
return deleteQ(q.log, q.auth, q.db.GetAPIKeyByID, q.db.DeleteAPIKeyByID)(ctx, id)
|
||||||
}
|
}
|
||||||
|
@ -956,6 +956,14 @@ func (*FakeQuerier) CleanTailnetCoordinators(_ context.Context) error {
|
|||||||
return ErrUnimplemented
|
return ErrUnimplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (*FakeQuerier) CleanTailnetLostPeers(context.Context) error {
|
||||||
|
return ErrUnimplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*FakeQuerier) CleanTailnetTunnels(context.Context) error {
|
||||||
|
return ErrUnimplemented
|
||||||
|
}
|
||||||
|
|
||||||
func (q *FakeQuerier) DeleteAPIKeyByID(_ context.Context, id string) error {
|
func (q *FakeQuerier) DeleteAPIKeyByID(_ context.Context, id string) error {
|
||||||
q.mutex.Lock()
|
q.mutex.Lock()
|
||||||
defer q.mutex.Unlock()
|
defer q.mutex.Unlock()
|
||||||
|
@ -121,6 +121,20 @@ func (m metricsStore) CleanTailnetCoordinators(ctx context.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m metricsStore) CleanTailnetLostPeers(ctx context.Context) error {
|
||||||
|
start := time.Now()
|
||||||
|
r0 := m.s.CleanTailnetLostPeers(ctx)
|
||||||
|
m.queryLatencies.WithLabelValues("CleanTailnetLostPeers").Observe(time.Since(start).Seconds())
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m metricsStore) CleanTailnetTunnels(ctx context.Context) error {
|
||||||
|
start := time.Now()
|
||||||
|
r0 := m.s.CleanTailnetTunnels(ctx)
|
||||||
|
m.queryLatencies.WithLabelValues("CleanTailnetTunnels").Observe(time.Since(start).Seconds())
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
func (m metricsStore) DeleteAPIKeyByID(ctx context.Context, id string) error {
|
func (m metricsStore) DeleteAPIKeyByID(ctx context.Context, id string) error {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
err := m.s.DeleteAPIKeyByID(ctx, id)
|
err := m.s.DeleteAPIKeyByID(ctx, id)
|
||||||
|
@ -126,6 +126,34 @@ func (mr *MockStoreMockRecorder) CleanTailnetCoordinators(arg0 interface{}) *gom
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CleanTailnetCoordinators", reflect.TypeOf((*MockStore)(nil).CleanTailnetCoordinators), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CleanTailnetCoordinators", reflect.TypeOf((*MockStore)(nil).CleanTailnetCoordinators), arg0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CleanTailnetLostPeers mocks base method.
|
||||||
|
func (m *MockStore) CleanTailnetLostPeers(arg0 context.Context) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "CleanTailnetLostPeers", arg0)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// CleanTailnetLostPeers indicates an expected call of CleanTailnetLostPeers.
|
||||||
|
func (mr *MockStoreMockRecorder) CleanTailnetLostPeers(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CleanTailnetLostPeers", reflect.TypeOf((*MockStore)(nil).CleanTailnetLostPeers), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CleanTailnetTunnels mocks base method.
|
||||||
|
func (m *MockStore) CleanTailnetTunnels(arg0 context.Context) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "CleanTailnetTunnels", arg0)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// CleanTailnetTunnels indicates an expected call of CleanTailnetTunnels.
|
||||||
|
func (mr *MockStoreMockRecorder) CleanTailnetTunnels(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CleanTailnetTunnels", reflect.TypeOf((*MockStore)(nil).CleanTailnetTunnels), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteAPIKeyByID mocks base method.
|
// DeleteAPIKeyByID mocks base method.
|
||||||
func (m *MockStore) DeleteAPIKeyByID(arg0 context.Context, arg1 string) error {
|
func (m *MockStore) DeleteAPIKeyByID(arg0 context.Context, arg1 string) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
@ -43,6 +43,8 @@ type sqlcQuerier interface {
|
|||||||
// referenced by the latest build of a workspace.
|
// referenced by the latest build of a workspace.
|
||||||
ArchiveUnusedTemplateVersions(ctx context.Context, arg ArchiveUnusedTemplateVersionsParams) ([]uuid.UUID, error)
|
ArchiveUnusedTemplateVersions(ctx context.Context, arg ArchiveUnusedTemplateVersionsParams) ([]uuid.UUID, error)
|
||||||
CleanTailnetCoordinators(ctx context.Context) error
|
CleanTailnetCoordinators(ctx context.Context) error
|
||||||
|
CleanTailnetLostPeers(ctx context.Context) error
|
||||||
|
CleanTailnetTunnels(ctx context.Context) error
|
||||||
DeleteAPIKeyByID(ctx context.Context, id string) error
|
DeleteAPIKeyByID(ctx context.Context, id string) error
|
||||||
DeleteAPIKeysByUserID(ctx context.Context, userID uuid.UUID) error
|
DeleteAPIKeysByUserID(ctx context.Context, userID uuid.UUID) error
|
||||||
DeleteAllTailnetClientSubscriptions(ctx context.Context, arg DeleteAllTailnetClientSubscriptionsParams) error
|
DeleteAllTailnetClientSubscriptions(ctx context.Context, arg DeleteAllTailnetClientSubscriptionsParams) error
|
||||||
|
@ -4522,6 +4522,31 @@ func (q *sqlQuerier) CleanTailnetCoordinators(ctx context.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cleanTailnetLostPeers = `-- name: CleanTailnetLostPeers :exec
|
||||||
|
DELETE
|
||||||
|
FROM tailnet_peers
|
||||||
|
WHERE updated_at < now() - INTERVAL '24 HOURS' AND status = 'lost'::tailnet_status
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *sqlQuerier) CleanTailnetLostPeers(ctx context.Context) error {
|
||||||
|
_, err := q.db.ExecContext(ctx, cleanTailnetLostPeers)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const cleanTailnetTunnels = `-- name: CleanTailnetTunnels :exec
|
||||||
|
DELETE FROM tailnet_tunnels
|
||||||
|
WHERE updated_at < now() - INTERVAL '24 HOURS' AND
|
||||||
|
NOT EXISTS (
|
||||||
|
SELECT 1 FROM tailnet_peers
|
||||||
|
WHERE id = tailnet_tunnels.src_id AND coordinator_id = tailnet_tunnels.coordinator_id
|
||||||
|
)
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *sqlQuerier) CleanTailnetTunnels(ctx context.Context) error {
|
||||||
|
_, err := q.db.ExecContext(ctx, cleanTailnetTunnels)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
const deleteAllTailnetClientSubscriptions = `-- name: DeleteAllTailnetClientSubscriptions :exec
|
const deleteAllTailnetClientSubscriptions = `-- name: DeleteAllTailnetClientSubscriptions :exec
|
||||||
DELETE
|
DELETE
|
||||||
FROM tailnet_client_subscriptions
|
FROM tailnet_client_subscriptions
|
||||||
|
@ -122,6 +122,19 @@ DELETE
|
|||||||
FROM tailnet_coordinators
|
FROM tailnet_coordinators
|
||||||
WHERE heartbeat_at < now() - INTERVAL '24 HOURS';
|
WHERE heartbeat_at < now() - INTERVAL '24 HOURS';
|
||||||
|
|
||||||
|
-- name: CleanTailnetLostPeers :exec
|
||||||
|
DELETE
|
||||||
|
FROM tailnet_peers
|
||||||
|
WHERE updated_at < now() - INTERVAL '24 HOURS' AND status = 'lost'::tailnet_status;
|
||||||
|
|
||||||
|
-- name: CleanTailnetTunnels :exec
|
||||||
|
DELETE FROM tailnet_tunnels
|
||||||
|
WHERE updated_at < now() - INTERVAL '24 HOURS' AND
|
||||||
|
NOT EXISTS (
|
||||||
|
SELECT 1 FROM tailnet_peers
|
||||||
|
WHERE id = tailnet_tunnels.src_id AND coordinator_id = tailnet_tunnels.coordinator_id
|
||||||
|
);
|
||||||
|
|
||||||
-- name: UpsertTailnetPeer :one
|
-- name: UpsertTailnetPeer :one
|
||||||
INSERT INTO
|
INSERT INTO
|
||||||
tailnet_peers (
|
tailnet_peers (
|
||||||
|
Reference in New Issue
Block a user