Skip to content

Commit 57effdc

Browse files
authored
Merge pull request #8753 from dolthub/db/async
make autoincrement tracker load async
2 parents 30258b9 + cabcb31 commit 57effdc

File tree

4 files changed

+80
-9
lines changed

4 files changed

+80
-9
lines changed

Diff for: go/libraries/doltcore/sqle/dsess/autoincrement_tracker.go

+70-5
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ package dsess
1616

1717
import (
1818
"context"
19+
"errors"
1920
"io"
2021
"math"
2122
"strings"
2223
"sync"
24+
"time"
2325

2426
"github.com/dolthub/go-mysql-server/sql"
2527
gmstypes "github.com/dolthub/go-mysql-server/sql/types"
@@ -48,6 +50,8 @@ type AutoIncrementTracker struct {
4850
sequences *sync.Map // map[string]uint64
4951
mm *mutexmap.MutexMap
5052
lockMode LockMode
53+
init chan struct{}
54+
initErr error
5155
}
5256

5357
var _ globalstate.AutoIncrementTracker = &AutoIncrementTracker{}
@@ -61,8 +65,9 @@ func NewAutoIncrementTracker(ctx context.Context, dbName string, roots ...doltdb
6165
dbName: dbName,
6266
sequences: &sync.Map{},
6367
mm: mutexmap.NewMutexMap(),
68+
init: make(chan struct{}),
6469
}
65-
ait.InitWithRoots(ctx, roots...)
70+
ait.runInitWithRootsAsync(ctx, roots...)
6671
return &ait, nil
6772
}
6873

@@ -76,13 +81,22 @@ func loadAutoIncValue(sequences *sync.Map, tableName string) uint64 {
7681
}
7782

7883
// Current returns the next value to be generated in the auto increment sequence for the table named
79-
func (a *AutoIncrementTracker) Current(tableName string) uint64 {
80-
return loadAutoIncValue(a.sequences, tableName)
84+
func (a *AutoIncrementTracker) Current(tableName string) (uint64, error) {
85+
err := a.waitForInit()
86+
if err != nil {
87+
return 0, err
88+
}
89+
return loadAutoIncValue(a.sequences, tableName), nil
8190
}
8291

8392
// Next returns the next auto increment value for the table named using the provided value from an insert (which may
8493
// be null or 0, in which case it will be generated from the sequence).
8594
func (a *AutoIncrementTracker) Next(tbl string, insertVal interface{}) (uint64, error) {
95+
err := a.waitForInit()
96+
if err != nil {
97+
return 0, err
98+
}
99+
86100
tbl = strings.ToLower(tbl)
87101

88102
given, err := CoerceAutoIncrementValue(insertVal)
@@ -113,6 +127,10 @@ func (a *AutoIncrementTracker) Next(tbl string, insertVal interface{}) (uint64,
113127
}
114128

115129
func (a *AutoIncrementTracker) CoerceAutoIncrementValue(val interface{}) (uint64, error) {
130+
err := a.waitForInit()
131+
if err != nil {
132+
return 0, err
133+
}
116134
return CoerceAutoIncrementValue(val)
117135
}
118136

@@ -140,6 +158,11 @@ func CoerceAutoIncrementValue(val interface{}) (uint64, error) {
140158
// table. Otherwise, the update is silently disregarded. So far this matches the MySQL behavior, but Dolt uses the
141159
// maximum value for this table across all branches.
142160
func (a *AutoIncrementTracker) Set(ctx *sql.Context, tableName string, table *doltdb.Table, ws ref.WorkingSetRef, newAutoIncVal uint64) (*doltdb.Table, error) {
161+
err := a.waitForInit()
162+
if err != nil {
163+
return nil, err
164+
}
165+
143166
tableName = strings.ToLower(tableName)
144167

145168
release := a.mm.Lock(tableName)
@@ -338,16 +361,27 @@ func getMaxIndexValue(ctx context.Context, indexData durable.Index) (uint64, err
338361
}
339362

340363
// AddNewTable initializes a new table with an auto increment column to the tracker, as necessary
341-
func (a *AutoIncrementTracker) AddNewTable(tableName string) {
364+
func (a *AutoIncrementTracker) AddNewTable(tableName string) error {
365+
err := a.waitForInit()
366+
if err != nil {
367+
return err
368+
}
369+
342370
tableName = strings.ToLower(tableName)
343371
// only initialize the sequence for this table if no other branch has such a table
344372
a.sequences.LoadOrStore(tableName, uint64(1))
373+
return nil
345374
}
346375

347376
// DropTable drops the table with the name given.
348377
// To establish the new auto increment value, callers must also pass all other working sets in scope that may include
349378
// a table with the same name, omitting the working set that just deleted the table named.
350379
func (a *AutoIncrementTracker) DropTable(ctx *sql.Context, tableName string, wses ...*doltdb.WorkingSet) error {
380+
err := a.waitForInit()
381+
if err != nil {
382+
return err
383+
}
384+
351385
tableName = strings.ToLower(tableName)
352386

353387
release := a.mm.Lock(tableName)
@@ -389,6 +423,11 @@ func (a *AutoIncrementTracker) DropTable(ctx *sql.Context, tableName string, wse
389423
}
390424

391425
func (a *AutoIncrementTracker) AcquireTableLock(ctx *sql.Context, tableName string) (func(), error) {
426+
err := a.waitForInit()
427+
if err != nil {
428+
return nil, err
429+
}
430+
392431
_, i, _ := sql.SystemVariables.GetGlobal("innodb_autoinc_lock_mode")
393432
lockMode := LockMode(i.(int64))
394433
if lockMode == LockMode_Interleaved {
@@ -398,7 +437,23 @@ func (a *AutoIncrementTracker) AcquireTableLock(ctx *sql.Context, tableName stri
398437
return a.mm.Lock(tableName), nil
399438
}
400439

401-
func (a *AutoIncrementTracker) InitWithRoots(ctx context.Context, roots ...doltdb.Rootish) error {
440+
func (a *AutoIncrementTracker) waitForInit() error {
441+
select {
442+
case <-a.init:
443+
return a.initErr
444+
case <-time.After(5 * time.Minute):
445+
return errors.New("failed to initialize autoincrement tracker")
446+
}
447+
}
448+
449+
func (a *AutoIncrementTracker) runInitWithRootsAsync(ctx context.Context, roots ...doltdb.Rootish) {
450+
go func() {
451+
defer close(a.init)
452+
a.initErr = a.initWithRoots(ctx, roots...)
453+
}()
454+
}
455+
456+
func (a *AutoIncrementTracker) initWithRoots(ctx context.Context, roots ...doltdb.Rootish) error {
402457
eg, egCtx := errgroup.WithContext(ctx)
403458
eg.SetLimit(128)
404459

@@ -435,3 +490,13 @@ func (a *AutoIncrementTracker) InitWithRoots(ctx context.Context, roots ...doltd
435490

436491
return eg.Wait()
437492
}
493+
494+
func (a *AutoIncrementTracker) InitWithRoots(ctx context.Context, roots ...doltdb.Rootish) error {
495+
err := a.waitForInit()
496+
if err != nil {
497+
return err
498+
}
499+
a.init = make(chan struct{})
500+
a.runInitWithRootsAsync(ctx, roots...)
501+
return a.waitForInit()
502+
}

Diff for: go/libraries/doltcore/sqle/globalstate/auto_increment_tracker.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ import (
2727
// interface here because implementations need to reach into session state, requiring a dependency on this package.
2828
type AutoIncrementTracker interface {
2929
// Current returns the current auto increment value for the given table.
30-
Current(tableName string) uint64
30+
Current(tableName string) (uint64, error)
3131
// Next returns the next auto increment value for the given table, and increments the current value.
3232
Next(tbl string, insertVal interface{}) (uint64, error)
3333
// AddNewTable adds a new table to the tracker, initializing the auto increment value to 1.
34-
AddNewTable(tableName string)
34+
AddNewTable(tableName string) error
3535
// DropTable removes a table from the tracker.
3636
DropTable(ctx *sql.Context, tableName string, wses ...*doltdb.WorkingSet) error
3737
// CoerceAutoIncrementValue coerces the given value to a uint64, returning an error if it can't be done.

Diff for: go/libraries/doltcore/sqle/writer/noms_write_session.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,10 @@ func (s *nomsWriteSession) flush(ctx *sql.Context) (*doltdb.WorkingSet, error) {
179179
// Update the auto increment value for the table if a tracker was provided
180180
// TODO: the table probably needs an autoincrement tracker no matter what
181181
if schema.HasAutoIncrement(ed.Schema()) {
182-
v := s.aiTracker.Current(name)
182+
v, err := s.aiTracker.Current(name)
183+
if err != nil {
184+
return err
185+
}
183186
tbl, err = tbl.SetAutoIncrementValue(ctx, v)
184187
if err != nil {
185188
return err

Diff for: go/libraries/doltcore/sqle/writer/prolly_write_session.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,10 @@ func (s *prollyWriteSession) flush(ctx *sql.Context, autoIncSet bool, manualAuto
165165
// override was specified (e.g. if the next value was set explicitly)
166166
if schema.HasAutoIncrement(wr.sch) {
167167
// TODO: need schema name for auto increment
168-
autoIncVal := s.aiTracker.Current(name.Name)
168+
autoIncVal, err := s.aiTracker.Current(name.Name)
169+
if err != nil {
170+
return err
171+
}
169172
override, hasManuallySetAi := manualAutoIncrementsSettings[name.Name]
170173
if hasManuallySetAi {
171174
autoIncVal = override

0 commit comments

Comments
 (0)