vitess.io/vitess@v0.16.2/go/vt/topo/workflow.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package topo 18 19 import ( 20 "path" 21 22 "context" 23 24 "google.golang.org/protobuf/proto" 25 26 workflowpb "vitess.io/vitess/go/vt/proto/workflow" 27 ) 28 29 // This file provides the utility methods to save / retrieve workflows 30 // in the topology global cell. 31 32 const ( 33 workflowsPath = "workflows" 34 workflowFilename = "Workflow" 35 ) 36 37 func pathForWorkflow(uuid string) string { 38 return path.Join(workflowsPath, uuid, workflowFilename) 39 } 40 41 // WorkflowInfo is a meta struct that contains the version of a Workflow. 42 type WorkflowInfo struct { 43 version Version 44 *workflowpb.Workflow 45 } 46 47 // GetWorkflowNames returns the names of the existing 48 // workflows. They are sorted by uuid. 49 func (ts *Server) GetWorkflowNames(ctx context.Context) ([]string, error) { 50 entries, err := ts.globalCell.ListDir(ctx, workflowsPath, false /*full*/) 51 switch { 52 case IsErrType(err, NoNode): 53 return nil, nil 54 case err == nil: 55 return DirEntriesToStringArray(entries), nil 56 default: 57 return nil, err 58 } 59 } 60 61 // CreateWorkflow creates the given workflow, and returns the initial 62 // WorkflowInfo. 63 func (ts *Server) CreateWorkflow(ctx context.Context, w *workflowpb.Workflow) (*WorkflowInfo, error) { 64 // Pack the content. 65 contents, err := proto.Marshal(w) 66 if err != nil { 67 return nil, err 68 } 69 70 // Save it. 71 filePath := pathForWorkflow(w.Uuid) 72 version, err := ts.globalCell.Create(ctx, filePath, contents) 73 if err != nil { 74 return nil, err 75 } 76 return &WorkflowInfo{ 77 version: version, 78 Workflow: w, 79 }, nil 80 } 81 82 // GetWorkflow reads a workflow from the global cell. 83 func (ts *Server) GetWorkflow(ctx context.Context, uuid string) (*WorkflowInfo, error) { 84 // Read the file. 85 filePath := pathForWorkflow(uuid) 86 contents, version, err := ts.globalCell.Get(ctx, filePath) 87 if err != nil { 88 return nil, err 89 } 90 91 // Unpack the contents. 92 w := &workflowpb.Workflow{} 93 if err := proto.Unmarshal(contents, w); err != nil { 94 return nil, err 95 } 96 97 return &WorkflowInfo{ 98 version: version, 99 Workflow: w, 100 }, nil 101 } 102 103 // SaveWorkflow saves the WorkflowInfo object. If the version is not 104 // good any more, ErrBadVersion is returned. 105 func (ts *Server) SaveWorkflow(ctx context.Context, wi *WorkflowInfo) error { 106 // Pack the content. 107 contents, err := proto.Marshal(wi.Workflow) 108 if err != nil { 109 return err 110 } 111 112 // Save it. 113 filePath := pathForWorkflow(wi.Uuid) 114 version, err := ts.globalCell.Update(ctx, filePath, contents, wi.version) 115 if err != nil { 116 return err 117 } 118 119 // Remember the new version. 120 wi.version = version 121 return nil 122 } 123 124 // DeleteWorkflow deletes the specified workflow. After this, the 125 // WorkflowInfo object should not be used any more. 126 func (ts *Server) DeleteWorkflow(ctx context.Context, wi *WorkflowInfo) error { 127 filePath := pathForWorkflow(wi.Uuid) 128 return ts.globalCell.Delete(ctx, filePath, wi.version) 129 }