Files
threshold/internal/session/repository_jobs.go
T
Michael Gaffney 9529491fa6 feat(session): Delete terminated sessions in batches
This changes the periodic job that deletes terminated sessions to delete
the those sessions in batches. Prior to this, a single SQL DELETE
command was used to delete all qualifying terminated sessions. In
systems under heavy load, the statement could timeout leading to a
situation where no qualifying terminated sessions were ever being
deleted.
2024-10-25 10:25:52 -04:00

73 lines
2.0 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package session
import (
"context"
"database/sql"
"time"
"github.com/hashicorp/boundary/internal/db/timestamp"
"github.com/hashicorp/boundary/internal/errors"
)
type deleteJobParams struct {
TotalToDelete int
BatchSize int
WindowStartTime *timestamp.Timestamp
}
func (r *Repository) getDeleteJobParams(ctx context.Context, threshold time.Duration) (deleteJobParams, error) {
const op = "session.(Repository).getDeleteJobParams"
args := []any{
sql.Named("threshold_seconds", threshold.Seconds()),
}
rows, err := r.reader.Query(ctx, getDeleteJobParams, args)
if err != nil {
return deleteJobParams{}, errors.Wrap(ctx, err, op, errors.WithMsg("error getting parameters for delete terminated sessions job"))
}
defer rows.Close()
var jobParams deleteJobParams
for rows.Next() {
if err := r.reader.ScanRows(ctx, rows, &jobParams); err != nil {
return deleteJobParams{}, errors.Wrap(ctx, err, op, errors.WithMsg("scan row failed"))
}
}
if err := rows.Err(); err != nil {
return deleteJobParams{}, errors.Wrap(ctx, err, op, errors.WithMsg("next row failed"))
}
return jobParams, nil
}
func (r *Repository) setDeleteJobBatchSize(ctx context.Context, batchSize int) error {
const op = "session.(Repository).setDeleteJobBatchSize"
args := []any{
sql.Named("batch_size", batchSize),
}
_, err := r.writer.Exec(ctx, setDeleteJobBatchSize, args)
if err != nil {
return errors.Wrap(ctx, err, op, errors.WithMsg("error setting delete job batch size"))
}
return nil
}
func (r *Repository) deleteTerminatedSessionsBatch(ctx context.Context, terminatedBefore *timestamp.Timestamp, batchSize int) (int, error) {
const op = "session.(Repository).deleteTerminatedSessionsBatch"
args := []any{
sql.Named("terminated_before", terminatedBefore),
sql.Named("batch_size", batchSize),
}
c, err := r.writer.Exec(ctx, deleteTerminatedInBatch, args)
if err != nil {
return 0, errors.Wrap(ctx, err, op, errors.WithMsg("error deleting terminated sessions"))
}
return c, nil
}