Skip to content

Commit 89fd916

Browse files
committedJun 25, 2022
Support transactions
1 parent ddfb158 commit 89fd916

File tree

3 files changed

+199
-79
lines changed

3 files changed

+199
-79
lines changed
 

‎dbump.go

+52-18
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ type Config struct {
2424
// Set mode explicitly to show how migration should be done.
2525
Mode MigratorMode
2626

27+
// DisableTx will run every migration not in a transaction.
28+
// This completely depends on a specific Migrator implementation
29+
// because not every database supports transaction, so this option can be no-op all the time.
30+
DisableTx bool
31+
2732
// UseForce to get a lock on a database. MUST be used with the caution.
2833
// Should be used when previous migration run didn't unlock the database,
2934
// and this blocks subsequent runs.
@@ -44,6 +49,10 @@ type Migrator interface {
4449
Version(ctx context.Context) (version int, err error)
4550
SetVersion(ctx context.Context, version int) error
4651

52+
Begin(ctx context.Context) error
53+
Commit(ctx context.Context) error
54+
Rollback(ctx context.Context) error
55+
4756
Exec(ctx context.Context, query string, args ...interface{}) error
4857
}
4958

@@ -176,18 +185,46 @@ func (m *mig) runMigrationLocked(ctx context.Context, ms []*Migration) error {
176185
}
177186

178187
for _, step := range m.prepareSteps(curr, target, ms) {
179-
if step.IsQuery {
180-
err = m.Exec(ctx, step.Query)
181-
} else {
182-
err = step.QueryFn(ctx, m)
183-
}
184-
if err != nil {
188+
if err := m.execStep(ctx, step); err != nil {
185189
return fmt.Errorf("exec: %w", err)
186190
}
191+
}
192+
return nil
193+
}
187194

188-
if err := m.SetVersion(ctx, step.Version); err != nil {
189-
return fmt.Errorf("set version: %w", err)
195+
func (m *mig) execStep(ctx context.Context, step step) error {
196+
if m.Config.DisableTx {
197+
return m.execSimpleStep(ctx, step)
198+
}
199+
return m.execStepSafely(ctx, step)
200+
}
201+
202+
func (m *mig) execStepSafely(ctx context.Context, step step) (err error) {
203+
if err := m.Migrator.Begin(ctx); err != nil {
204+
return fmt.Errorf("begin tx: %w", err)
205+
}
206+
207+
defer func() {
208+
if err != nil {
209+
if errRollback := m.Migrator.Rollback(ctx); errRollback != nil {
210+
err = fmt.Errorf("rollback tx: %w", errRollback)
211+
}
190212
}
213+
}()
214+
215+
err = m.execSimpleStep(ctx, step)
216+
if err == nil {
217+
err = m.Commit(ctx)
218+
}
219+
return err
220+
}
221+
222+
func (m *mig) execSimpleStep(ctx context.Context, step step) error {
223+
if err := m.Exec(ctx, step.Query); err != nil {
224+
return fmt.Errorf("exec: %w", err)
225+
}
226+
if err := m.SetVersion(ctx, step.Version); err != nil {
227+
return fmt.Errorf("set version: %w", err)
191228
}
192229
return nil
193230
}
@@ -261,7 +298,6 @@ type step struct {
261298
Version int
262299
IsQuery bool
263300
Query string
264-
QueryFn MigrationFn
265301
}
266302

267303
func (m *Migration) toStep(up bool) step {
@@ -283,15 +319,9 @@ type locklessMigrator struct {
283319
m Migrator
284320
}
285321

286-
func (llm *locklessMigrator) Init(ctx context.Context) error {
287-
return llm.m.Init(ctx)
288-
}
289-
func (llm *locklessMigrator) LockDB(ctx context.Context) error {
290-
return nil
291-
}
292-
func (llm *locklessMigrator) UnlockDB(ctx context.Context) error {
293-
return nil
294-
}
322+
func (llm *locklessMigrator) Init(ctx context.Context) error { return llm.m.Init(ctx) }
323+
func (llm *locklessMigrator) LockDB(ctx context.Context) error { return nil }
324+
func (llm *locklessMigrator) UnlockDB(ctx context.Context) error { return nil }
295325

296326
func (llm *locklessMigrator) Version(ctx context.Context) (version int, err error) {
297327
return llm.m.Version(ctx)
@@ -300,6 +330,10 @@ func (llm *locklessMigrator) SetVersion(ctx context.Context, version int) error
300330
return llm.m.SetVersion(ctx, version)
301331
}
302332

333+
func (llm *locklessMigrator) Begin(ctx context.Context) error { return llm.Begin(ctx) }
334+
func (llm *locklessMigrator) Commit(ctx context.Context) error { return llm.Commit(ctx) }
335+
func (llm *locklessMigrator) Rollback(ctx context.Context) error { return llm.Rollback(ctx) }
336+
303337
func (llm *locklessMigrator) Exec(ctx context.Context, query string, args ...interface{}) error {
304338
return llm.m.Exec(ctx, query, args...)
305339
}

0 commit comments

Comments
 (0)
Please sign in to comment.