updatetask.go ×34

Frontier kind: Code frontier

unlabeled · c_4e6638a13bb3

11 tests · 2549 LOC · 112 files · introduces 0 tests · 135 LOC · 3 files

Introduces — evidence that enters the hierarchy at this concept

Code
43 ranges135 lines · 3 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
463 ranges2549 lines · 112 files · Browse complete extent
All tests (intent)
11 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

3 files ranked by introduced lines: 135 introduced LOC across 43 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

go.temporal.io/server/tools/common/schema/updatetask.go 105 introduced LOC · 34 ranges

Open complete file

66
67 // NewUpdateSchemaTask returns a new instance of UpdateTask
68 > func NewUpdateSchemaTask(db DB, config *UpdateConfig, logger log.Logger) *UpdateTask { updatetask.go
69 > return &UpdateTask{
70 > db: db,
71 > config: config,
72 > logger: logger,
73 > }
74 > }
75
76 // Run executes the task
77 > func (task *UpdateTask) Run() error { updatetask.go
78 > config := task.config
79 >
80 > task.logger.Info("UpdateSchemaTask started", tag.Any("config", config))
81 >
82 > if config.IsDryRun {
83 if err := task.setupDryRunDatabase(); err != nil {
84 return fmt.Errorf("error creating dryrun database:%v", err.Error())
86 }
87
88 > currVer, err := task.db.ReadSchemaVersion() updatetask.go
89 > if err != nil {
90 return fmt.Errorf("error reading current schema version:%v", err.Error())
91 }
92
93 > updates, err := task.buildChangeSet(currVer) updatetask.go
94 > if err != nil {
95 return err
96 }
97
98 > err = task.executeUpdates(currVer, updates) updatetask.go
99 > if err != nil {
100 return err
101 }
102
103 > task.logger.Info("UpdateSchemaTask done") updatetask.go
104 >
105 > return nil
106 }
107
108 > func (task *UpdateTask) executeUpdates(currVer string, updates []changeSet) error { updatetask.go
109 > if len(updates) == 0 {
110 task.logger.Debug(fmt.Sprintf("found zero updates from current version %v", currVer))
111 return nil
112 }
113
114 > task.logger.Debug(fmt.Sprintf("running %v updates for current version %v", len(updates), currVer)) updatetask.go
115 > for _, cs := range updates {
116 > err := task.execStmts(cs.version, cs.cqlStmts)
117 > if err != nil {
118 return err
119 }
120 > err = task.updateSchemaVersion(currVer, &cs) updatetask.go
121 > if err != nil {
122 return err
123 }
124
125 > task.logger.Debug(fmt.Sprintf("Schema updated from %v to %v", currVer, cs.version)) updatetask.go
126 > currVer = cs.version
127 }
128
129 > return nil updatetask.go
130 }
131
132 > func (task *UpdateTask) execStmts(ver string, stmts []string) error { updatetask.go
133 > task.logger.Debug(fmt.Sprintf("---- Executing updates for version %v ----", ver))
134 > for _, stmt := range stmts {
135 > task.logger.Debug(rmspaceRegex.ReplaceAllString(stmt, " "))
136 > err := task.db.Exec(stmt)
137 > if err != nil {
138 // To make schema update idempotent, we need to handle error when retry on previous partially succeeded update attempt.
139 // There are 2 major cases that will be handled:
150 }
151 }
152 > task.logger.Debug("---- Done ----") updatetask.go
153 > return nil
154 }
155
156 > func (task *UpdateTask) updateSchemaVersion(oldVer string, cs *changeSet) error { updatetask.go
157 > err := task.db.UpdateSchemaVersion(cs.version, cs.manifest.MinCompatibleVersion)
158 > if err != nil {
159 return fmt.Errorf("failed to update schema_version table, err=%v", err.Error())
160 }
161 > err = task.db.WriteSchemaUpdateLog(oldVer, cs.manifest.CurrVersion, cs.manifest.md5, cs.manifest.Description) updatetask.go
162 > if err != nil {
163 return fmt.Errorf("failed to add entry to schema_update_history, err=%v", err.Error())
164 }
165
166 > return nil updatetask.go
167 }
168
169 > func (task *UpdateTask) buildChangeSet(currVer string) ([]changeSet, error) { updatetask.go
170 >
171 > config := task.config
172 >
173 > var fsys fs.FS
174 > var dir string
175 > if len(config.SchemaName) > 0 {
176 fsys = dbschemas.Assets()
177 dir = path.Join(config.SchemaName, "versioned")
178 > } else { updatetask.go
179 > fsys = os.DirFS(config.SchemaDir)
180 > dir = "."
181 > }
182
183 > verDirs, err := readSchemaDir(fsys, dir, currVer, config.TargetVersion, task.logger) updatetask.go
184 > if err != nil {
185 return nil, fmt.Errorf("error listing schema dir:%v", err.Error())
186 }
187
188 > task.logger.Debug(fmt.Sprintf("Schema Dirs: %s", verDirs)) updatetask.go
189 >
190 > var result []changeSet
191 >
192 > for _, vd := range verDirs {
193 > dirPath := path.Join(dir, vd)
194 >
195 > m, e := readManifest(fsys, dirPath)
196 > if e != nil {
197 return nil, fmt.Errorf("error processing manifest for version %v:%v", vd, e.Error())
198 }
199
200 > if m.CurrVersion != dirToVersion(vd) { updatetask.go
201 return nil, fmt.Errorf(
202 "manifest version doesn't match with dirname, dir=%v,manifest.version=%v",
205 }
206
207 > stmts, e := task.parseSQLStmts(fsys, dirPath, m) updatetask.go
208 > if e != nil {
209 return nil, e
210 }
211
212 > e = validateCQLStmts(stmts) updatetask.go
213 > if e != nil {
214 return nil, fmt.Errorf("error processing version %v:%v", vd, e.Error())
215 }
216
217 > cs := changeSet{} updatetask.go
218 > cs.manifest = m
219 > cs.cqlStmts = stmts
220 > cs.version = m.CurrVersion
221 > result = append(result, cs)
222 }
223
224 > return result, nil updatetask.go
225 }
226
227 > func (task *UpdateTask) parseSQLStmts(fsys fs.FS, dir string, manifest *manifest) ([]string, error) { updatetask.go
228 > result := make([]string, 0, 4)
229 >
230 > for _, file := range manifest.SchemaUpdateCqlFiles {
231 > schemaPath := path.Join(dir, file)
232 > task.logger.Info("Processing schema file: " + schemaPath)
233 > schemaBuf, err := fs.ReadFile(fsys, schemaPath)
234 > if err != nil {
235 return nil, fmt.Errorf("error reading file %s: %w", schemaPath, err)
236 }
237 > stmts, err := persistence.LoadAndSplitQueryFromReaders([]io.Reader{bytes.NewBuffer(schemaBuf)}) updatetask.go
238 > if err != nil {
239 return nil, fmt.Errorf("error parsing file %v, err=%v", schemaPath, err)
240 }
241 > result = append(result, stmts...) updatetask.go
242 }
243
244 > if len(result) == 0 && !manifest.AllowNoCqlFiles { updatetask.go
245 return nil, fmt.Errorf("found 0 updates in dir %v", dir)
246 }
247
248 > return result, nil updatetask.go
249 }
250
251 > func validateCQLStmts(stmts []string) error { updatetask.go
252 > for _, stmt := range stmts {
253 > valid := false
254 > for _, prefix := range whitelistedCQLPrefixes {
255 > if strings.HasPrefix(stmt, prefix) {
256 > valid = true
257 > break
258 }
259 }
260 > if !valid { updatetask.go
261 return fmt.Errorf("CQL prefix not in whitelist, stmt=%v", stmt)
262 }
263 }
264 > return nil updatetask.go
265 }
266
427 }
428
429 > func dirToVersion(dir string) string { updatetask.go
430 > return dir[1:]
431 > }
go.temporal.io/server/tools/common/schema/test/updatetest.go 18 introduced LOC · 5 ranges

Open complete file

29
30 // SetupSuiteBase sets up the test suite
31 > func (tb *UpdateSchemaTestBase) SetupSuiteBase(db DB, pluginName string, conn ConnectParams) { updatetest.go
32 > tb.conn = conn
33 > tb.Assertions = require.New(tb.T()) // Have to define our overridden assertions in the test setup. If we did it earlier, tb.T() will return nil
34 > tb.Logger = log.NewTestLogger()
35 > tb.rand = rand.New(rand.NewSource(time.Now().UnixNano()))
36 > tb.DBName = fmt.Sprintf("update_test_%v", tb.rand.Int63())
37 > err := db.CreateDatabase(tb.DBName)
38 > if err != nil {
39 tb.Logger.Fatal("error creating database, ", tag.Error(err))
40 }
41 > tb.db = db updatetest.go
42 > tb.pluginName = pluginName
43 }
44
45 // TearDownSuiteBase tears down the test suite
46 > func (tb *UpdateSchemaTestBase) TearDownSuiteBase() { updatetest.go
47 > tb.NoError(tb.db.DropDatabase(tb.DBName))
48 > tb.db.Close()
49 > }
50
51 // RunDryrunTest tests a dryrun schema setup & update
153 }
154
155 > func (tb *UpdateSchemaTestBase) getCommandBase() []string { updatetest.go
156 > command := []string{"./tool"}
157 > if tb.pluginName != "" {
158 command = append(command, "-pl", tb.pluginName)
159 }
160 > return append(command, tb.conn.CLIFlags()...) updatetest.go
161 }
go.temporal.io/server/tools/common/schema/handler.go 12 introduced LOC · 4 ranges

Open complete file

21
22 // Update updates the schema for the specified database
23 > func Update(cli *cli.Context, db DB, logger log.Logger) error { handler.go
24 > cfg, err := newUpdateConfig(cli, db)
25 > if err != nil {
26 return err
27 }
28 > return NewUpdateSchemaTask(db, cfg, logger).Run() handler.go
29 }
30
31 > func newUpdateConfig(cli *cli.Context, db DB) (*UpdateConfig, error) { handler.go
32 > config := new(UpdateConfig)
33 > config.SchemaDir = cli.String(CLIOptSchemaDir)
34 > config.SchemaName = cli.String(CLIOptSchemaName)
35 > config.TargetVersion = cli.String(CLIOptTargetVersion)
36 >
37 > if err := validateUpdateConfig(config, db); err != nil {
38 return nil, err
39 }
40 > return config, nil handler.go
41 }
42