blob: ff0dd7ca61916267db1277ced2d212dc5d846b59 [file] [log] [blame]
// Copyright 2015 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package datastore
import (
"context"
"fmt"
)
// Cursor wraps datastore.Cursor.
type Cursor interface {
fmt.Stringer
}
// CursorCB is used to obtain a Cursor while Run'ing a query on either
// Interface or RawInterface.
//
// it can be invoked to obtain the current cursor.
type CursorCB func() (Cursor, error)
// RawRunCB is the callback signature provided to RawInterface.Run
//
// - key is the Key of the entity
// - val is the data of the entity (or nil, if the query was keys-only)
//
// Return nil to continue iterating through the query results, or an error to
// stop. If you return the error `Stop`, then Run will stop the query and
// return nil.
type RawRunCB func(key *Key, val PropertyMap, getCursor CursorCB) error
// GetMultiCB is the callback signature provided to RawInterface.GetMulti
//
// - idx is the index of the entity, ranging from 0 through len-1.
// - val is the data of the entity
// * It may be nil if some of the keys to the GetMulti were bad, since all
// keys are validated before the RPC occurs!
// - err is an error associated with this entity (e.g. ErrNoSuchEntity).
//
// The callback is called once per element. It may be called concurrently, and
// may be called out of order. The "idx" variable describes which element is
// being processed. If any callbacks are invoked, exactly one callback will be
// invoked for each supplied element.
type GetMultiCB func(idx int, val PropertyMap, err error)
// NewKeyCB is the callback signature provided to RawInterface.PutMulti and
// RawInterface.AllocateIDs. It is invoked once for each positional key that
// was generated as the result of a call.
//
// - idx is the index of the entity, ranging from 0 through len-1.
// - key is the new key for the entity (if the original was incomplete)
// * It may be nil if some of the keys/vals to the PutMulti were bad, since
// all keys are validated before the RPC occurs!
// - err is an error associated with putting this entity.
//
// The callback is called once per element. It may be called concurrently, and
// may be called out of order. The "idx" variable describes which element is
// being processed. If any callbacks are invoked, exactly one callback will be
// invoked for each supplied element.
type NewKeyCB func(idx int, key *Key, err error)
// DeleteMultiCB is the callback signature provided to RawInterface.DeleteMulti
//
// - idx is the index of the entity, ranging from 0 through len-1.
// - err is an error associated with deleting this entity.
//
// The callback is called once per element. It may be called concurrently, and
// may be called out of order. The "idx" variable describes which element is
// being processed. If any callbacks are invoked, exactly one callback will be
// invoked for each supplied element.
type DeleteMultiCB func(idx int, err error)
// Constraints represent implementation constraints.
//
// A zero-value Constraints is valid, and indicates that no constraints are
// present.
type Constraints struct {
// MaxGetSize is the maximum number of entities that can be referenced in a
// single GetMulti call. If <= 0, no constraint is applied.
MaxGetSize int
// MaxPutSize is the maximum number of entities that can be referenced in a
// single PutMulti call. If <= 0, no constraint is applied.
MaxPutSize int
// MaxDeleteSize is the maximum number of entities that can be referenced in a
// single DeleteMulti call. If <= 0, no constraint is applied.
MaxDeleteSize int
}
type nullMetaGetterType struct{}
func (nullMetaGetterType) GetMeta(string) (interface{}, bool) { return nil, false }
var nullMetaGetter MetaGetter = nullMetaGetterType{}
// MultiMetaGetter is a carrier for metadata, used with RawInterface.GetMulti
//
// It's OK to default-construct this. GetMeta will just return
// (nil, ErrMetaFieldUnset) for every index.
type MultiMetaGetter []MetaGetter
// NewMultiMetaGetter returns a new MultiMetaGetter object. data may be nil.
func NewMultiMetaGetter(data []PropertyMap) MultiMetaGetter {
if len(data) == 0 {
return nil
}
inner := make(MultiMetaGetter, len(data))
for i, pm := range data {
inner[i] = pm
}
return inner
}
// GetMeta is like PropertyLoadSaver.GetMeta, but it also takes an index
// indicating which slot you want metadata for. If idx isn't there, this
// returns (nil, ErrMetaFieldUnset).
func (m MultiMetaGetter) GetMeta(idx int, key string) (interface{}, bool) {
return m.GetSingle(idx).GetMeta(key)
}
// GetSingle gets a single MetaGetter at the specified index.
func (m MultiMetaGetter) GetSingle(idx int) MetaGetter {
if idx >= len(m) || m[idx] == nil {
return nullMetaGetter
}
return m[idx]
}
// RawInterface implements the datastore functionality without any of the fancy
// reflection stuff. This is so that Filters can avoid doing lots of redundant
// reflection work. See datastore.Interface for a more user-friendly interface.
type RawInterface interface {
// AllocateIDs allows you to allocate IDs from the datastore without putting
// any data. The supplied keys must be PartialValid and share the same entity
// type.
//
// If there's no error, the keys in the slice will be replaced with keys
// containing integer IDs assigned to them.
AllocateIDs(keys []*Key, cb NewKeyCB) error
// RunInTransaction runs f in a transaction.
//
// opts may be nil.
//
// NOTE: Implementations and filters are guaranteed that:
// - f is not nil
RunInTransaction(f func(c context.Context) error, opts *TransactionOptions) error
// DecodeCursor converts a string returned by a Cursor into a Cursor instance.
// It will return an error if the supplied string is not valid, or could not
// be decoded by the implementation.
DecodeCursor(s string) (Cursor, error)
// Run executes the given query, and calls `cb` for each successfully item.
//
// NOTE: Implementations and filters are guaranteed that:
// - query is not nil
// - cb is not nil
Run(q *FinalizedQuery, cb RawRunCB) error
// Count executes the given query and returns the number of entries which
// match it.
Count(q *FinalizedQuery) (int64, error)
// GetMulti retrieves items from the datastore.
//
// If there was a server error, it will be returned directly. Otherwise,
// callback will execute once per key/value pair, returning either the
// operation result or individual error for each position. If the callback
// receives an error, it will immediately forward that error and stop
// subsequent callbacks.
//
// meta is used to propagate metadata from higher levels.
//
// NOTE: Implementations and filters are guaranteed that:
// - len(keys) > 0
// - all keys are Valid, !Incomplete, and in the current namespace
// - cb is not nil
GetMulti(keys []*Key, meta MultiMetaGetter, cb GetMultiCB) error
// PutMulti writes items to the datastore.
//
// If there was a server error, it will be returned directly. Otherwise,
// callback will execute once per key/value pair, returning either the
// operation result or individual error for each position. If the callback
// receives an error, it will immediately forward that error and stop
// subsequent callbacks.
//
// NOTE: Implementations and filters are guaranteed that:
// - len(keys) > 0
// - len(keys) == len(vals)
// - all keys are Valid and in the current namespace
// - cb is not nil
PutMulti(keys []*Key, vals []PropertyMap, cb NewKeyCB) error
// DeleteMulti removes items from the datastore.
//
// If there was a server error, it will be returned directly. Otherwise,
// callback will execute once per key/value pair, returning either the
// operation result or individual error for each position. If the callback
// receives an error, it will immediately forward that error and stop
// subsequent callbacks.
//
// NOTE: Implementations and filters are guaranteed that
// - len(keys) > 0
// - all keys are Valid, !Incomplete, and in the current namespace
// - none keys of the keys are 'special' (use a kind prefixed with '__')
// - cb is not nil
DeleteMulti(keys []*Key, cb DeleteMultiCB) error
// WithoutTransaction returns a derived Context without a transaction applied.
// This may be called even when outside of a transaction, in which case the
// input Context is a valid return value.
WithoutTransaction() context.Context
// CurrentTransaction returns a reference to the current Transaction, or nil
// if the Context does not have a current Transaction.
CurrentTransaction() Transaction
// Constraints returns this implementation's constraints.
Constraints() Constraints
// GetTestable returns the Testable interface for the implementation, or nil
// if there is none.
GetTestable() Testable
}