github.com/cornelk/go-cloud@v0.17.1/docstore/driver/driver.go (about) 1 // Copyright 2019 The Go Cloud Development Kit Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package driver defines interfaces to be implemented by docstore drivers, which 16 // will be used by the docstore package to interact with the underlying services. 17 // Application code should use package docstore. 18 package driver // import "github.com/cornelk/go-cloud/docstore/driver" 19 20 import ( 21 "context" 22 23 "github.com/cornelk/go-cloud/internal/gcerr" 24 ) 25 26 // A Collection is a set of documents. 27 type Collection interface { 28 // Key returns the document key, or nil if the document doesn't have one, which 29 // means it is absent or zero value, such as 0, a nil interface value, and any 30 // empty array or string. 31 // 32 // If the collection is able to generate a key for a Create action, then 33 // it should not return an error if the key is missing. If the collection 34 // can't generate a missing key, it should return an error. 35 // 36 // The returned key must be comparable. 37 // 38 // The returned key should not be encoded with the driver's codec; it should 39 // be the user-supplied Go value. 40 Key(Document) (interface{}, error) 41 42 // RevisionField returns the name of the field used to hold revisions. 43 // If the empty string is returned, docstore.DefaultRevisionField will be used. 44 RevisionField() string 45 46 // RunActions executes a slice of actions. 47 // 48 // If unordered is false, it must appear as if the actions were executed in the 49 // order they appear in the slice, from the client's point of view. The actions 50 // need not happen atomically, nor does eventual consistency in the service 51 // need to be taken into account. For example, after a write returns 52 // successfully, the driver can immediately perform a read on the same document, 53 // even though the service's semantics does not guarantee that the read will see 54 // the write. RunActions should return immediately after the first action that fails. 55 // The returned slice should have a single element. 56 // 57 // opts controls the behavior of RunActions and is guaranteed to be non-nil. 58 RunActions(ctx context.Context, actions []*Action, opts *RunActionsOptions) ActionListError 59 60 // RunGetQuery executes a Query. 61 // 62 // Implementations can choose to execute the Query as one single request or 63 // multiple ones, depending on their service offerings. The portable type 64 // exposes OpenCensus metrics for the call to RunGetQuery (but not for 65 // subsequent calls to DocumentIterator.Next), so drivers should prefer to 66 // make at least one RPC during RunGetQuery itself instead of lazily waiting 67 // for the first call to Next. 68 RunGetQuery(context.Context, *Query) (DocumentIterator, error) 69 70 // QueryPlan returns the plan for the query. 71 QueryPlan(*Query) (string, error) 72 73 // RevisionToBytes converts a revision to a byte slice. 74 RevisionToBytes(interface{}) ([]byte, error) 75 76 // BytesToRevision converts a []byte to a revision. 77 BytesToRevision([]byte) (interface{}, error) 78 79 // As converts i to driver-specific types. 80 // See https://github.com/cornelk/go-cloud/concepts/as/ for background information. 81 As(i interface{}) bool 82 83 // ErrorAs allows drivers to expose driver-specific types for returned 84 // errors. 85 // 86 // See https://github.com/cornelk/go-cloud/concepts/as/ for background information. 87 ErrorAs(err error, i interface{}) bool 88 89 // ErrorCode should return a code that describes the error, which was returned by 90 // one of the other methods in this interface. 91 ErrorCode(error) gcerr.ErrorCode 92 93 // Close cleans up any resources used by the Collection. Once Close is called, 94 // there will be no method calls to the Collection other than As, ErrorAs, and 95 // ErrorCode. 96 Close() error 97 } 98 99 // DeleteQueryer should be implemented by Collections that can handle Query.Delete 100 // efficiently. If a Collection does not implement this interface, then Query.Delete 101 // will be implemented by calling RunGetQuery and deleting the returned documents. 102 type DeleteQueryer interface { 103 RunDeleteQuery(context.Context, *Query) error 104 } 105 106 // UpdateQueryer should be implemented by Collections that can handle Query.Update 107 // efficiently. If a Collection does not implement this interface, then Query.Update 108 // will be implemented by calling RunGetQuery and updating the returned documents. 109 type UpdateQueryer interface { 110 RunUpdateQuery(context.Context, *Query, []Mod) error 111 } 112 113 // ActionKind describes the type of an action. 114 type ActionKind int 115 116 // Values for ActionKind. 117 const ( 118 Create ActionKind = iota 119 Replace 120 Put 121 Get 122 Delete 123 Update 124 ) 125 126 //go:generate stringer -type=ActionKind 127 128 // An Action describes a single operation on a single document. 129 type Action struct { 130 Kind ActionKind // the kind of action 131 Doc Document // the document on which to perform the action 132 Key interface{} // the document key returned by Collection.Key, to avoid recomputing it 133 FieldPaths [][]string // field paths to retrieve, for Get only 134 Mods []Mod // modifications to make, for Update only 135 Index int // the index of the action in the original action list 136 } 137 138 // A Mod is a modification to a field path in a document. 139 // At present, the only modifications supported are: 140 // - set the value at the field path, or create the field path if it doesn't exist 141 // - delete the field path (when Value is nil) 142 type Mod struct { 143 FieldPath []string 144 Value interface{} 145 } 146 147 // IncOp is a value representing an increment modification. 148 type IncOp struct { 149 Amount interface{} 150 } 151 152 // An ActionListError contains all the errors encountered from a call to RunActions, 153 // and the positions of the corresponding actions. 154 type ActionListError []struct { 155 Index int 156 Err error 157 } 158 159 // NewActionListError creates an ActionListError from a slice of errors. 160 // If the ith element err of the slice is non-nil, the resulting ActionListError 161 // will have an item {i, err}. 162 func NewActionListError(errs []error) ActionListError { 163 var alerr ActionListError 164 for i, err := range errs { 165 if err != nil { 166 alerr = append(alerr, struct { 167 Index int 168 Err error 169 }{i, err}) 170 } 171 } 172 return alerr 173 } 174 175 // RunActionsOptions controls the behavior of RunActions. 176 type RunActionsOptions struct { 177 // BeforeDo is a callback that must be called once, sequentially, before each one 178 // or group of the underlying service's actions is executed. asFunc allows 179 // drivers to expose driver-specific types. 180 BeforeDo func(asFunc func(interface{}) bool) error 181 } 182 183 // A Query defines a query operation to find documents within a collection based 184 // on a set of requirements. 185 type Query struct { 186 // FieldPaths contain a list of field paths the user selects to return in the 187 // query results. The returned documents should only have these fields 188 // populated. 189 FieldPaths [][]string 190 191 // Filters contain a list of filters for the query. If there are more than one 192 // filter, they should be combined with AND. 193 Filters []Filter 194 195 // Limit sets the maximum number of results returned by running the query. When 196 // Limit <= 0, the driver implementation should return all possible results. 197 Limit int 198 199 // OrderByField is the field to use for sorting the results. 200 OrderByField string 201 202 // OrderAscending specifies the sort direction. 203 OrderAscending bool 204 205 // BeforeQuery is a callback that must be called exactly once before the 206 // underlying service's query is executed. asFunc allows drivers to expose 207 // driver-specific types. 208 BeforeQuery func(asFunc func(interface{}) bool) error 209 } 210 211 // A Filter defines a filter expression used to filter the query result. 212 // If the value is a number type, the filter uses numeric comparison. 213 // If the value is a string type, the filter uses UTF-8 string comparison. 214 // TODO(#1762): support comparison of other types. 215 type Filter struct { 216 FieldPath []string // the field path to filter 217 Op string // the operation, supports =, >, >=, <, <= 218 Value interface{} // the value to compare using the operation 219 } 220 221 // A DocumentIterator iterates through the results (for Get action). 222 type DocumentIterator interface { 223 224 // Next tries to get the next item in the query result and decodes into Document 225 // with the driver's codec. 226 // When there are no more results, it should return io.EOF. 227 // Once Next returns a non-nil error, it will never be called again. 228 Next(context.Context, Document) error 229 230 // Stop terminates the iterator before Next return io.EOF, allowing any cleanup 231 // needed. 232 Stop() 233 234 // As converts i to driver-specific types. 235 // See https://github.com/cornelk/go-cloud/concepts/as/ for background information. 236 As(i interface{}) bool 237 } 238 239 // EqualOp is the name of the equality operator. 240 // It is defined here to avoid confusion between "=" and "==". 241 const EqualOp = "="