Skip to content

Commit

Permalink
avoid deadlock on instances table when running multiple instances
Browse files Browse the repository at this point in the history
  • Loading branch information
cenkalti committed Sep 14, 2020
1 parent f12e3aa commit 08c5431
Showing 1 changed file with 3 additions and 10 deletions.
13 changes: 3 additions & 10 deletions internal/table/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,23 +397,16 @@ func (t *Table) Instances(ctx context.Context) (int64, error) {
// and clears out any inactive instances from the list, such as
// instances that were unable to call DeleteInstance during shutdown.
func (t *Table) UpdateInstance(ctx context.Context, id uint32) error {
// The MySQL driver doesn't support multiple statements in a single Exec if they contain placeholders.
// That's why we use a transaction.
tx, err := t.db.BeginTx(ctx, nil)
if err != nil {
return err
}
defer tx.Rollback() // nolint: errcheck
now := t.Clk.NowUTC()
s1 := "INSERT INTO " + t.name + "_instances(id, updated_at) VALUES (" + strconv.FormatUint(uint64(id), 10) + ",IFNULL(CAST(? as DATETIME), UTC_TIMESTAMP())) ON DUPLICATE KEY UPDATE updated_at=IFNULL(?, UTC_TIMESTAMP())"
if _, err = tx.ExecContext(ctx, s1, now, now); err != nil {
if _, err := t.db.ExecContext(ctx, s1, now, now); err != nil {
return err
}
s2 := "DELETE FROM " + t.name + "_instances WHERE updated_at < IFNULL(CAST(? as DATETIME), UTC_TIMESTAMP) - INTERVAL 1 MINUTE"
if _, err = tx.ExecContext(ctx, s2, now); err != nil {
if _, err := t.db.ExecContext(ctx, s2, now); err != nil {
return err
}
return tx.Commit()
return nil
}

// DeleteInstance removes an entry from the list of active instances.
Expand Down

0 comments on commit 08c5431

Please sign in to comment.