go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/gae/service/datastore/raw_interface.go (about) 1 // Copyright 2015 The LUCI 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 // http://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 datastore 16 17 import ( 18 "context" 19 "fmt" 20 ) 21 22 // Cursor wraps datastore.Cursor. 23 type Cursor interface { 24 fmt.Stringer 25 } 26 27 // CursorCB is used to obtain a Cursor while Run'ing a query on either 28 // Interface or RawInterface. 29 // 30 // it can be invoked to obtain the current cursor. 31 type CursorCB func() (Cursor, error) 32 33 // RawRunCB is the callback signature provided to RawInterface.Run 34 // 35 // - key is the Key of the entity 36 // - val is the data of the entity (or nil, if the query was keys-only) 37 // 38 // Return nil to continue iterating through the query results, or an error to 39 // stop. If you return the error `Stop`, then Run will stop the query and 40 // return nil. 41 type RawRunCB func(key *Key, val PropertyMap, getCursor CursorCB) error 42 43 // GetMultiCB is the callback signature provided to RawInterface.GetMulti 44 // 45 // - idx is the index of the entity, ranging from 0 through len-1. 46 // - val is the data of the entity 47 // - It may be nil if some of the keys to the GetMulti were bad, since all 48 // keys are validated before the RPC occurs! 49 // - err is an error associated with this entity (e.g. ErrNoSuchEntity). 50 // 51 // The callback is called once per element. It may be called concurrently, and 52 // may be called out of order. The "idx" variable describes which element is 53 // being processed. If any callbacks are invoked, exactly one callback will be 54 // invoked for each supplied element. 55 type GetMultiCB func(idx int, val PropertyMap, err error) 56 57 // NewKeyCB is the callback signature provided to RawInterface.PutMulti and 58 // RawInterface.AllocateIDs. It is invoked once for each positional key that 59 // was generated as the result of a call. 60 // 61 // - idx is the index of the entity, ranging from 0 through len-1. 62 // - key is the new key for the entity (if the original was incomplete) 63 // - It may be nil if some of the keys/vals to the PutMulti were bad, since 64 // all keys are validated before the RPC occurs! 65 // - err is an error associated with putting this entity. 66 // 67 // The callback is called once per element. It may be called concurrently, and 68 // may be called out of order. The "idx" variable describes which element is 69 // being processed. If any callbacks are invoked, exactly one callback will be 70 // invoked for each supplied element. 71 type NewKeyCB func(idx int, key *Key, err error) 72 73 // DeleteMultiCB is the callback signature provided to RawInterface.DeleteMulti 74 // 75 // - idx is the index of the entity, ranging from 0 through len-1. 76 // - err is an error associated with deleting this entity. 77 // 78 // The callback is called once per element. It may be called concurrently, and 79 // may be called out of order. The "idx" variable describes which element is 80 // being processed. If any callbacks are invoked, exactly one callback will be 81 // invoked for each supplied element. 82 type DeleteMultiCB func(idx int, err error) 83 84 // Constraints represent implementation constraints. 85 // 86 // A zero-value Constraints is valid, and indicates that no constraints are 87 // present. 88 type Constraints struct { 89 // MaxGetSize is the maximum number of entities that can be referenced in a 90 // single GetMulti call. If <= 0, no constraint is applied. 91 MaxGetSize int 92 // MaxPutSize is the maximum number of entities that can be referenced in a 93 // single PutMulti call. If <= 0, no constraint is applied. 94 MaxPutSize int 95 // MaxDeleteSize is the maximum number of entities that can be referenced in a 96 // single DeleteMulti call. If <= 0, no constraint is applied. 97 MaxDeleteSize int 98 } 99 100 type nullMetaGetterType struct{} 101 102 func (nullMetaGetterType) GetMeta(string) (any, bool) { return nil, false } 103 104 var nullMetaGetter MetaGetter = nullMetaGetterType{} 105 106 // MultiMetaGetter is a carrier for metadata, used with RawInterface.GetMulti 107 // 108 // It's OK to default-construct this. GetMeta will just return 109 // (nil, ErrMetaFieldUnset) for every index. 110 type MultiMetaGetter []MetaGetter 111 112 // NewMultiMetaGetter returns a new MultiMetaGetter object. data may be nil. 113 func NewMultiMetaGetter(data []PropertyMap) MultiMetaGetter { 114 if len(data) == 0 { 115 return nil 116 } 117 inner := make(MultiMetaGetter, len(data)) 118 for i, pm := range data { 119 inner[i] = pm 120 } 121 return inner 122 } 123 124 // GetMeta is like PropertyLoadSaver.GetMeta, but it also takes an index 125 // indicating which slot you want metadata for. If idx isn't there, this 126 // returns (nil, ErrMetaFieldUnset). 127 func (m MultiMetaGetter) GetMeta(idx int, key string) (any, bool) { 128 return m.GetSingle(idx).GetMeta(key) 129 } 130 131 // GetSingle gets a single MetaGetter at the specified index. 132 func (m MultiMetaGetter) GetSingle(idx int) MetaGetter { 133 if idx >= len(m) || m[idx] == nil { 134 return nullMetaGetter 135 } 136 return m[idx] 137 } 138 139 // RawInterface implements the datastore functionality without any of the fancy 140 // reflection stuff. This is so that Filters can avoid doing lots of redundant 141 // reflection work. See datastore.Interface for a more user-friendly interface. 142 type RawInterface interface { 143 // AllocateIDs allows you to allocate IDs from the datastore without putting 144 // any data. The supplied keys must be PartialValid and share the same entity 145 // type. 146 // 147 // If there's no error, the keys in the slice will be replaced with keys 148 // containing integer IDs assigned to them. 149 AllocateIDs(keys []*Key, cb NewKeyCB) error 150 151 // RunInTransaction runs f in a transaction. 152 // 153 // opts may be nil. 154 // 155 // NOTE: Implementations and filters are guaranteed that: 156 // - f is not nil 157 RunInTransaction(f func(c context.Context) error, opts *TransactionOptions) error 158 159 // DecodeCursor converts a string returned by a Cursor into a Cursor instance. 160 // It will return an error if the supplied string is not valid, or could not 161 // be decoded by the implementation. 162 DecodeCursor(s string) (Cursor, error) 163 164 // Run executes the given query, and calls `cb` for each successfully item. 165 // 166 // NOTE: Implementations and filters are guaranteed that: 167 // - query is not nil 168 // - cb is not nil 169 Run(q *FinalizedQuery, cb RawRunCB) error 170 171 // Count executes the given query and returns the number of entries which 172 // match it. 173 Count(q *FinalizedQuery) (int64, error) 174 175 // GetMulti retrieves items from the datastore. 176 // 177 // If there was a server error, it will be returned directly. Otherwise, 178 // callback will execute once per key/value pair, returning either the 179 // operation result or individual error for each position. If the callback 180 // receives an error, it will immediately forward that error and stop 181 // subsequent callbacks. 182 // 183 // meta is used to propagate metadata from higher levels. 184 // 185 // NOTE: Implementations and filters are guaranteed that: 186 // - len(keys) > 0 187 // - all keys are Valid, !Incomplete, and in the current namespace 188 // - cb is not nil 189 GetMulti(keys []*Key, meta MultiMetaGetter, cb GetMultiCB) error 190 191 // PutMulti writes items to the datastore. 192 // 193 // If there was a server error, it will be returned directly. Otherwise, 194 // callback will execute once per key/value pair, returning either the 195 // operation result or individual error for each position. If the callback 196 // receives an error, it will immediately forward that error and stop 197 // subsequent callbacks. 198 // 199 // NOTE: Implementations and filters are guaranteed that: 200 // - len(keys) > 0 201 // - len(keys) == len(vals) 202 // - all keys are Valid and in the current namespace 203 // - cb is not nil 204 PutMulti(keys []*Key, vals []PropertyMap, cb NewKeyCB) error 205 206 // DeleteMulti removes items from the datastore. 207 // 208 // If there was a server error, it will be returned directly. Otherwise, 209 // callback will execute once per key/value pair, returning either the 210 // operation result or individual error for each position. If the callback 211 // receives an error, it will immediately forward that error and stop 212 // subsequent callbacks. 213 // 214 // NOTE: Implementations and filters are guaranteed that 215 // - len(keys) > 0 216 // - all keys are Valid, !Incomplete, and in the current namespace 217 // - none keys of the keys are 'special' (use a kind prefixed with '__') 218 // - cb is not nil 219 DeleteMulti(keys []*Key, cb DeleteMultiCB) error 220 221 // WithoutTransaction returns a derived Context without a transaction applied. 222 // This may be called even when outside of a transaction, in which case the 223 // input Context is a valid return value. 224 WithoutTransaction() context.Context 225 226 // CurrentTransaction returns a reference to the current Transaction, or nil 227 // if the Context does not have a current Transaction. 228 CurrentTransaction() Transaction 229 230 // Constraints returns this implementation's constraints. 231 Constraints() Constraints 232 233 // GetTestable returns the Testable interface for the implementation, or nil 234 // if there is none. 235 GetTestable() Testable 236 }