mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: acquire lock for individual workspace transition (#15859)
When Coder is ran in High Availability mode, each Coder instance has a lifecycle executor. These lifecycle executors are all trying to do the same work, and whilst transactions saves us from this causing an issue, we are still doing extra work that could be prevented. This PR adds a `TryAcquireLock` call for each attempted workspace transition, meaning two Coder instances shouldn't duplicate effort.
This commit is contained in:
@@ -3,6 +3,7 @@ package autobuild
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -177,6 +178,15 @@ func (e *Executor) runOnce(t time.Time) Stats {
|
||||
err := e.db.InTx(func(tx database.Store) error {
|
||||
var err error
|
||||
|
||||
ok, err := tx.TryAcquireLock(e.ctx, database.GenLockID(fmt.Sprintf("lifecycle-executor:%s", wsID)))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("try acquire lifecycle executor lock: %w", err)
|
||||
}
|
||||
if !ok {
|
||||
log.Debug(e.ctx, "unable to acquire lock for workspace, skipping")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Re-check eligibility since the first check was outside the
|
||||
// transaction and the workspace settings may have changed.
|
||||
ws, err = tx.GetWorkspaceByID(e.ctx, wsID)
|
||||
@@ -389,7 +399,7 @@ func (e *Executor) runOnce(t time.Time) Stats {
|
||||
}
|
||||
return nil
|
||||
}()
|
||||
if err != nil {
|
||||
if err != nil && !xerrors.Is(err, context.Canceled) {
|
||||
log.Error(e.ctx, "failed to transition workspace", slog.Error(err))
|
||||
statsMu.Lock()
|
||||
stats.Errors[wsID] = err
|
||||
|
||||
Reference in New Issue
Block a user