-
Notifications
You must be signed in to change notification settings - Fork 0
/
options.go
215 lines (182 loc) · 4.84 KB
/
options.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
package gooseplus
import (
"context"
"io/fs"
"os"
"time"
"github.com/pressly/goose/v3"
"go.uber.org/zap"
)
type (
// Option for the Migrator.
//
// Default settings are:
//
// dialect: "postgres",
// base: "sql",
// envs: []string{"base"},
// timeout: 5 * time.Minute,
// migrationTimeout: 1 * time.Minute,
// logger: zap.NewExample(),
// fsys: os.DirFS("."),
Option func(*options)
options struct {
dialect string
base string
fsys fs.FS
versionTable string
logger *zap.Logger
envs []string
timeout time.Duration
migrationTimeout time.Duration
withGlobalLock bool
// gooseOptions []goose.OptionsFunc
}
)
var baseOptions = options{
dialect: "postgres",
base: "sql",
envs: []string{"base"},
timeout: 5 * time.Minute,
migrationTimeout: 1 * time.Minute,
logger: zap.NewExample(),
fsys: os.DirFS("."),
}
func applyOptionsWithDefaults(opts []Option) options {
if len(opts) == 0 {
return baseOptions
}
o := baseOptions
for _, apply := range opts {
apply(&o)
}
if len(o.envs) == 0 {
o.envs = []string{""}
}
return o
}
func (o options) withOptionalTimeout(ctx context.Context) (context.Context, func()) {
if o.timeout == 0 {
return ctx, func() {}
}
if _, ok := ctx.Deadline(); ok {
// parent context is already set with a deadline
return ctx, func() {}
}
return context.WithTimeout(ctx, o.timeout)
}
func (o options) withMigrationTimeout(ctx context.Context) (context.Context, func()) {
if o.migrationTimeout == 0 {
return ctx, func() {}
}
return context.WithTimeout(ctx, o.migrationTimeout)
}
// setGooseGlobals sets global variables in goose: guard against race
// (but cannot be used concurrently with different settings)
func (o options) setGooseGlobals(lg *zap.Logger) error {
gooseMx.Lock()
defer gooseMx.Unlock()
goose.SetBaseFS(o.fsys)
o.setVersionTable()
goose.SetLogger(zap.NewStdLog(lg))
err := goose.SetDialect(o.dialect)
return err
}
func (o options) setVersionTable() {
if o.versionTable == "" {
return
}
// sets goose's global var
goose.SetTableName(o.versionTable)
}
// WithTimeout specifies a timeout to apply to the whole migration process.
//
// NOTE: if Migrate(ctx) is called with a context that already contains a deadline,
// that deadline will override this option.
//
// The zero value disables the timeout.
//
// Default is 5m.
func WithTimeout(timeout time.Duration) Option {
return func(o *options) {
o.timeout = timeout
}
}
// WithMigrationTimeout specifies a timeout to apply for each individual migration.
//
// The zero value disables the timeout.
//
// Default is 1m.
func WithMigrationTimeout(timeout time.Duration) Option {
return func(o *options) {
o.migrationTimeout = timeout
}
}
// WithDialect indicates the database SQL dialect.
//
// For details see https://pkg.go.dev/github.com/pressly/goose/v3#Dialect
func WithDialect(dialect string) Option {
return func(o *options) {
o.dialect = dialect
}
}
// WithEnvironments appends environment-specific folders to merge with the migrations.
//
// The default setting is a single folder "base".
func WithEnvironments(envs ...string) Option {
return func(o *options) {
o.envs = append(o.envs, envs...)
}
}
// SetEnvironments overrides environment-specific folders to merge with the migrations.
//
// Setting to nil or to an empty slice will disable folders: migrations will be searched for in the base path only.
func SetEnvironments(envs []string) Option {
return func(o *options) {
o.envs = envs
}
}
// WithFS provides the file system where migrations are located.
//
// The base is os.Dir(".").
func WithFS(fsys fs.FS) Option {
return func(o *options) {
o.fsys = fsys
}
}
// WithBasePath provides the root directory where migrations are located on the FS.
func WithBasePath(base string) Option {
return func(o *options) {
o.base = base
}
}
// WithLogger provides a structured zap logger to the migrator.
func WithLogger(zlg *zap.Logger) Option {
return func(o *options) {
o.logger = zlg
}
}
// WithVersionTable tells goose to use an non-default version table.
//
// The default is "". Setting an empty table equates to using the default.
func WithVersionTable(table string) Option {
return func(o *options) {
o.versionTable = table
}
}
// WithGlobalLock prevent several migrations to run in parallel by applying a global lock.
//
// The default is false, meaning that deploying several instances in parallel won't work well.
func WithGlobalLock(enabled bool) Option {
return func(o *options) {
o.withGlobalLock = enabled
}
}
/* not workable for now.
// WithGooseOptions allows to inject other options available to `goose` users.
func WithGooseOptions(gooseOptions ...goose.OptionsFunc) Option {
return func(o *options) {
o.gooseOptions = gooseOptions
}
}
*/