store

package
v0.1.10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 21, 2020 License: MIT Imports: 51 Imported by: 0

README

Store

Store is a json-document database backed by Threads V2.

This document describes its public API, and its internal design/architecture. Internal understanding isn't necessary to use Store, but will help understand how things are wired. Creating a Store under the default configuration will automatically build everything required to work.

Currently, a Store is backed by a single Thread. In the future, this can change making the Store map different Models to different Threads, or any other combination.

Usage

ToDo: Describe public API here.

Internal Design

In this section, there is a high-level overview of internal Store design.

Diagram

The following diagram try to express all components and their relationships and communications:

Design

The above diagram depicts the different components inside a Store. Also, it travels through their relationships caused by a transaction commit. The inverse path, caused by a new event detected in other peer log in the thread, is somewhat similar but in the other direction.

Arrows aren't always synchronous calls, but also channel notifications and other mediums in order to inverse dependency between components. Arrows are conceptual communications.

Models

Models are part of Store public-api. Main responsibility: store instances of a user-defined schema.

Models are json-schemas that describe instance types of the Store. They provide the public API for creating, deleting, updating, and querying instances within this model. They also provide read/write transactions which have serializable isolation within the Store scope.

Indexes

Models support indexes for faster queries on schema-defined fields. When registering a new schema (and defining a Model), a caller may supply a list of field paths to index on. This creates an Index, which can be used to speed up queries at the expense of additional storage and compute on entity creation and updates. For stores with a small number of entities, it may not be worth the added overhead, so as always avoid optimizing your queries until you need it!

Insertion with indexes costs approximately twice as much as without (depending on the complexity and frequency of a given index), whereas updates are only slightly more costly (almost identical in most cases). Depending on the underlying data distribution, queries can be greater than an order of magnitude faster. This depends on many factors, including the size of the store (i.e., number of entities), the uniqueness of the indexed field, and the complexity of the query. For example, in our benchmark tests using a relatively simple Model and a relatively small store size (i.e., ~5000 entities), the query speedup for a simple OR-based equality test is ~10x. See store/bench_test.go for details or to run the benchmarks yourself.

EventCodec

This is an internal component not available in the public API. Main responsibility: Transform and apply and encode/decode transaction actions.

EventCodec is an abstraction used to:

  • Transform actions made in a txn, to an array of store.Event that will be dispatcher to be reduced.
  • Encode actions made in a txn to a format.Node which will serve as the next building block for the appended Record in the local peer log.
  • The reverse of last point, when receiving external actions to allow to be dispatched.

For example, if within a model WriteTxn(), a new instance is created and other was updated, these two action will be sent to the EventCodec to transform them in Events. These Event have a byte payload with the encoded transformation. Currently, the only implementation of EventCodec is a jsonpatcher, which transforms these actions in json-merge/patches, and store them as payloads in events.

These events are also aggregated in a returned format.Node, which is the compatible/analogous information to be used by Threadservice to add in the peer own log in the thread associated with the Store. Likewise, EventCodec also do the inverse transformation. Given a format.Node, it transforms its byte payload into actions that will be reduced in the store.

The EventCodec abstraction allows an extensibility point. If instead of a json-patcher we want to encode model changes as full instance snapshots (i.e: instead of generating the json-patch, let generate the full instance data), we could provide another implementation of the EventCodec to use in the Store.

Similarly, more advanced encodings of JSON-Document changes can be implemented as EventCodec such as JSON-Documents-Delta-CRDTs, or a hybrid json-patch with logical clocks.

Dispatcher

This is an internal component not available in the public API. Main responsibility: Source of truth regarding known store.Events for the Store. Will notify registered parties to let them know about new ones..

Every Event generated in the Store is sent to a Dispatcher when write transactions are committed. The dispatcher is responsible for broadcasting these events to all registered Reducers. A reducer is a party which is interested in knowing about Store events. Currently, the only reducer is the Store itself.

For example, if a particular instance is updated in a Model, these corresponding actions will be encoded as Event by the EventCodec as mentioned in the last section. These Events will be dispatched to the Dispatcher, which will:

  • Store the new event in durable storage. If the txn made multiple changes, this is done transactionally.
  • Broadcast them to all registered Reducers (which currently is only Store). Reducers will apply those changes for their own interests.

The implications of this design imply that real Store state changes can only happen when the Dispatcher broadcast new store.Events. A Reducer can't distinguish between Events generated locally or externally. External events are the results of Threadservice sending new events to the Dispatcher, which means that new Events where detected in other peer logs of the same Thread.

Datastore

This is an internal component not available in the public API. Main responsibility: Delivering durable persistence for data.

Datastore is the underlying persistence of Model instances and Dispatcher raw Event information. In both cases, their interface is a datastore.TxnDatastore to have txn guarantees.

Local Event Bus

This is an internal component not available in the public API. Main responsibility: Deliver format.Node encoded information of changes done in local commited transactions. Currently, only to SingleThreadAdapter is listening to this bus.

Store Listener

This is part of the public-api. Main responsibility: Notify external actors that the Store changed its state, with details about the change: in which model, what action (Create, Save, Delete), and wich EntityID.

Listeners are useful for clients that want to be notified about changes in the Store. Recall that Store state can change by external events, such as receiving external changes from other peers sharing the Store.

The client can configure which kind of events wants to be notified. Can add any number of criterias; if more than one criteria is used they will be interpreted as OR conditions. A criteria contains the following information:

  • Which model to listen changes
  • What action is done (Create, Save, Delete)
  • Which EntitiID

Any of the above three attributes can be set empty. For example, we can listen to all changes of all entities in a model if only the first attribute is set and the other two are left empty/default.

StoreThreadAdapter (SingleThreadAdapter, unique implementation)

This is an internal component not available in the public API. Main responsibility: Responsible to be the two-way communication between Store and Threads.

Every time a new local format.Node is generated in the Store due to a write transaction commit, the StoreThreadAdapter will notify Threadservice that a new Record should be added to the local peer log.

Similarly, when Threadservice detects new Records in other peer logs, it will dispatch them to SingleThreadAdapter. Then, it will transform it into a Store Events that will be dispatched to Dispatcher and ultimately will be reduced to impact Store state.

As said initially, currently, the Store is only mapped to a single Thread. But is possible to decide a different map, where a Store might be backed by more than one thread or any other schema. This is the component that should be taking this decisions.

Threadservice

This component is part of the public-api so that it can be accessed. Main responsibility: Is the Store interface with Threads layer.

Threadservice is the bidirectional communication interface to the underlying Thread backing the Store. It only interacts with StoreThreadAdapter

Documentation

Overview

Package eventstore provides a Store which manage models

Index

Constants

View Source
const (
	// Eq is "equals"
	Eq = JSONOperation(eq)
	// Ne is "not equal to"
	Ne = JSONOperation(ne)
	// Gt is "greater than"
	Gt = JSONOperation(gt)
	// Lt is "less than"
	Lt = JSONOperation(lt)
	// Ge is "greater than or equal to"
	Ge = JSONOperation(ge)
	// Le is "less than or equal to"
	Le = JSONOperation(le)
)

Variables

View Source
var (
	ErrUniqueExists = errors.New("unique constraint violation")
	ErrNotIndexable = errors.New("value not indexable")
	ErrNoIndexFound = errors.New("no index found")
)

ErrUniqueExists is the error thrown when data is being inserted for a unique constraint value that already exists

View Source
var (
	// ErrNotFound indicates that the specified instance doesn't
	// exist in the model.
	ErrNotFound = errors.New("instance not found")
	// ErrReadonlyTx indicates that no write operations can be done since
	// the current transaction is readonly.
	ErrReadonlyTx = errors.New("read only transaction")
	// ErrInvalidSchemaInstance indicates the current operation is from an
	// instance that doesn't satisfy the model schema.
	ErrInvalidSchemaInstance = errors.New("instance doesn't correspond to schema")
)
View Source
var (
	// ErrInvalidSortingField is returned when a query sorts a result by a
	// non-existent field in the model schema.
	ErrInvalidSortingField = errors.New("sorting field doesn't correspond to instance type")
	// ErrInvalidSliceType is returned when a query receives a result by a
	// slice type which doesn't correspond to the model being queried.
	ErrInvalidSliceType = errors.New("slice type doesn't correspond to model type")
)
View Source
var (
	// ErrInvalidModel indicates that the registered model isn't valid,
	// most probably doesn't have an EntityID.ID field.
	ErrInvalidModel = errors.New("the model is invalid")
	// ErrInvalidModelType indicates the provided default type isn't compatible
	// with a Model type.
	ErrInvalidModelType = errors.New("the model type should be a non-nil pointer to a struct")
)

Functions

func DefaultDecode added in v0.1.6

func DefaultDecode(data []byte, value interface{}) error

DefaultDecode is the default decoding func from badgerhold (Gob)

func DefaultEncode added in v0.1.6

func DefaultEncode(value interface{}) ([]byte, error)

DefaultEncode is the default encoding func from badgerhold (Gob)

func NewSimpleTx

func NewSimpleTx(ds datastore.Datastore) datastore.Txn

Types

type Action

type Action struct {
	Model string
	Type  ActionType
	ID    core.EntityID
}

type ActionType

type ActionType int
const (
	ActionCreate ActionType = iota + 1
	ActionSave
	ActionDelete
)

type Comparer

type Comparer interface {
	Compare(other interface{}) (int, error)
}

Comparer compares a type against the encoded value in the store. The result should be 0 if current==other, -1 if current < other, and +1 if current > other. If a field in a struct doesn't specify a comparer, then the default comparison is used (convert to string and compare) this interface is already handled for standard Go Types as well as more complex ones such as those in time and big an error is returned if the type cannot be compared The concrete type will always be passedin, not a pointer

type Config

type Config struct {
	RepoPath   string
	Datastore  ds.TxnDatastore
	EventCodec core.EventCodec
	JsonMode   bool
	Debug      bool
	LowMem     bool
}

Config has configuration parameters for a store

type Criterion

type Criterion struct {
	// contains filtered or unexported fields
}

Criterion is a partial condition that can specify comparison operator for a field.

func Where

func Where(field string) *Criterion

Where starts to create a query condition for a field

func (*Criterion) Eq

func (c *Criterion) Eq(value interface{}) *Query

Eq is an equality operator against a field

func (*Criterion) Fn

func (c *Criterion) Fn(mf MatchFunc) *Query

Fn is a custom evaluation function against a field

func (*Criterion) Ge

func (c *Criterion) Ge(value interface{}) *Query

Ge is a greater or equal operator against a field

func (*Criterion) Gt

func (c *Criterion) Gt(value interface{}) *Query

Gt is a greater operator against a field

func (*Criterion) Le

func (c *Criterion) Le(value interface{}) *Query

Le is a less or equal operator against a field

func (*Criterion) Lt

func (c *Criterion) Lt(value interface{}) *Query

Lt is a less operation against a field

func (*Criterion) Ne

func (c *Criterion) Ne(value interface{}) *Query

Ne is a not equal operator against a field

type Datastore

type Datastore struct {
	kt.KeyTransform
	ds.Datastore
	// contains filtered or unexported fields
}

Datastore keeps a KeyTransform function

func (*Datastore) NewTransaction

func (d *Datastore) NewTransaction(readOnly bool) (ds.Txn, error)

type DecodeFunc added in v0.1.6

type DecodeFunc func(data []byte, value interface{}) error

DecodeFunc is a function for decoding a value from bytes

type EncodeFunc added in v0.1.6

type EncodeFunc func(value interface{}) ([]byte, error)

EncodeFunc is a function for encoding a value into bytes

type Index added in v0.1.6

type Index struct {
	IndexFunc func(name string, value []byte) (ds.Key, error)
	Unique    bool
}

Index is a function that returns the indexable, encoded bytes of the passed in bytes

type IndexConfig added in v0.1.6

type IndexConfig struct {
	Path   string `json:"path"`
	Unique bool   `json:"unique,omitempty"`
}

IndexConfig stores the configuration for a given Index.

type Indexer added in v0.1.6

type Indexer interface {
	BaseKey() ds.Key
	Indexes() map[string]Index //[indexname]indexFunc
}

Indexer is the interface to implement to support Model property indexes

type JSONCriterion

type JSONCriterion struct {
	FieldPath string
	Operation JSONOperation
	Value     JSONValue
	// contains filtered or unexported fields
}

JSONCriterion represents a restriction on a field

func JSONWhere

func JSONWhere(field string) *JSONCriterion

JSONWhere starts to create a query condition for a field

func (*JSONCriterion) Eq

func (c *JSONCriterion) Eq(value interface{}) *JSONQuery

Eq is an equality operator against a field

func (*JSONCriterion) Ge

func (c *JSONCriterion) Ge(value interface{}) *JSONQuery

Ge is a greater or equal operator against a field

func (*JSONCriterion) Gt

func (c *JSONCriterion) Gt(value interface{}) *JSONQuery

Gt is a greater operator against a field

func (*JSONCriterion) Le

func (c *JSONCriterion) Le(value interface{}) *JSONQuery

Le is a less or equal operator against a field

func (*JSONCriterion) Lt

func (c *JSONCriterion) Lt(value interface{}) *JSONQuery

Lt is a less operation against a field

func (*JSONCriterion) Ne

func (c *JSONCriterion) Ne(value interface{}) *JSONQuery

Ne is a not equal operator against a field

type JSONOperation

type JSONOperation int

JSONOperation models comparison operators

type JSONQuery

type JSONQuery struct {
	Ands  []*JSONCriterion
	Ors   []*JSONQuery
	Sort  JSONSort
	Index string
}

JSONQuery is a json-seriable query representation

func JSONOrderBy

func JSONOrderBy(field string) *JSONQuery

JSONOrderBy specify ascending order for the query results.

func JSONOrderByDesc

func JSONOrderByDesc(field string) *JSONQuery

JSONOrderByDesc specify descending order for the query results.

func (*JSONQuery) JSONAnd

func (q *JSONQuery) JSONAnd(field string) *JSONCriterion

JSONAnd concatenates a new condition in an existing field.

func (*JSONQuery) JSONOr

func (q *JSONQuery) JSONOr(orQuery *JSONQuery) *JSONQuery

JSONOr concatenates a new condition that is sufficient for an instance to satisfy, independant of the current Query. Has left-associativity as: (a And b) Or c

func (*JSONQuery) JSONOrderBy

func (q *JSONQuery) JSONOrderBy(field string) *JSONQuery

JSONOrderBy specify ascending order for the query results. On multiple calls, only the last one is considered.

func (*JSONQuery) JSONOrderByDesc

func (q *JSONQuery) JSONOrderByDesc(field string) *JSONQuery

JSONOrderByDesc specify descending order for the query results. On multiple calls, only the last one is considered.

func (*JSONQuery) UseIndex added in v0.1.6

func (q *JSONQuery) UseIndex(path string) *JSONQuery

UseIndex specifies the index to use when running this query

type JSONSort

type JSONSort struct {
	FieldPath string
	Desc      bool
}

JSONSort represents a sort order on a field

type JSONValue

type JSONValue struct {
	String *string
	Bool   *bool
	Float  *float64
}

JSONValue models a single value in JSON

type ListenActionType

type ListenActionType int
const (
	ListenAll ListenActionType = iota
	ListenCreate
	ListenSave
	ListenDelete
)

type ListenOption

type ListenOption struct {
	Type  ListenActionType
	Model string
	ID    core.EntityID
}

type Listener

type Listener interface {
	Channel() <-chan Action
	Close()
}

type LocalEventListener

type LocalEventListener struct {
	// contains filtered or unexported fields
}

LocalEventListener notifies about new locally generated ipld.Nodes results of transactions

func (*LocalEventListener) Channel

func (l *LocalEventListener) Channel() <-chan format.Node

Channel returns an unbuffered channel to receive local events

func (*LocalEventListener) Discard

func (l *LocalEventListener) Discard()

Discard indicates that no further events will be received and ready for being garbage collected

type Manager

type Manager struct {
	io.Closer
	// contains filtered or unexported fields
}

func NewManager

func NewManager(ts service.Service, opts ...Option) (*Manager, error)

NewManager hydrates stores from prefixes and starts them.

func (*Manager) Close

func (m *Manager) Close() error

Close all the in-mem stores.

func (*Manager) GetStore

func (m *Manager) GetStore(id uuid.UUID) *Store

GetStore returns a store by id from the in-mem map.

func (*Manager) NewStore

func (m *Manager) NewStore() (id uuid.UUID, store *Store, err error)

NewStore creates a new store and prefix its datastore with base key.

type MarshaledResult added in v0.1.6

type MarshaledResult struct {
	query.Result
	MarshaledValue map[string]interface{}
}

type MatchFunc

type MatchFunc func(value interface{}) (bool, error)

MatchFunc is a function used to test an arbitrary matching value in a query

type Model

type Model struct {
	// contains filtered or unexported fields
}

Model contains instances of a schema, and provides operations for creating, updating, deleting, and quering them.

func (*Model) AddIndex added in v0.1.6

func (m *Model) AddIndex(path string, unique bool) error

AddIndex creates a new index based on the given path string. Set unique to true if you want a unique constraint on the given path. See https://github.com/tidwall/gjson for documentation on the supported path structure. Adding an index will override any overlapping index values if they already exist. @note: This does NOT currently build the index. If items have been added prior to adding a new index, they will NOT be indexed a posteriori.

func (*Model) BaseKey added in v0.1.6

func (m *Model) BaseKey() ds.Key

func (*Model) Create

func (m *Model) Create(vs ...interface{}) error

Create creates instances in the model.

func (*Model) Delete

func (m *Model) Delete(ids ...core.EntityID) error

Delete deletes instances by its IDs. It doesn't fail if the ID doesn't exist.

func (*Model) Find

func (m *Model) Find(result interface{}, q *Query) error

Find executes a Query into result.

func (*Model) FindByID

func (m *Model) FindByID(id core.EntityID, v interface{}) error

FindByID finds an instance by its ID and saves it in v. If doesn't exists returns ErrNotFound.

func (*Model) FindJSON

func (m *Model) FindJSON(q *JSONQuery) (ret []string, err error)

FindJSON executes a Query in in JSONMode and returns the result.

func (*Model) Has

func (m *Model) Has(ids ...core.EntityID) (exists bool, err error)

Has returns true if all IDs exist in the model, false otherwise.

func (*Model) Indexes added in v0.1.6

func (m *Model) Indexes() map[string]Index

Indexes is a map of model properties to Indexes

func (*Model) ReadTxn

func (m *Model) ReadTxn(f func(txn *Txn) error) error

ReadTxn creates an explicit readonly transaction. Any operation that tries to mutate an instance of the model will ErrReadonlyTx. Provides serializable isolation gurantees.

func (*Model) Save

func (m *Model) Save(vs ...interface{}) error

Save saves changes of instances in the model.

func (*Model) WriteTxn

func (m *Model) WriteTxn(f func(txn *Txn) error) error

WriteTxn creates an explicit write transaction. Provides serializable isolation gurantees.

type Option

type Option func(*Config) error

Option takes a Config and modifies it

func WithDebug

func WithDebug(enable bool) Option

WithDebug indicate to output debug information

func WithEventCodec

func WithEventCodec(ec core.EventCodec) Option

WithEventCodec configure to use ec as the EventCodec manager for transforming actions in events, and viceversa

func WithJsonMode

func WithJsonMode(enabled bool) Option

func WithLowMem added in v0.1.10

func WithLowMem(low bool) Option

func WithRepoPath

func WithRepoPath(path string) Option

type Query

type Query struct {
	// contains filtered or unexported fields
}

Query allows to build queries to fetch data from a model.

func OrderBy

func OrderBy(field string) *Query

OrderBy specify ascending order for the query results.

func OrderByDesc

func OrderByDesc(field string) *Query

OrderByDesc specify descending order for the query results.

func (*Query) And

func (q *Query) And(field string) *Criterion

And concatenates a new condition in an existing field.

func (*Query) Or

func (q *Query) Or(orQuery *Query) *Query

Or concatenates a new condition that is sufficient for an instance to satisfy, independent of the current Query. Has left-associativity as: (a And b) Or c

func (*Query) OrderBy

func (q *Query) OrderBy(field string) *Query

OrderBy specify ascending order for the query results. On multiple calls, only the last one is considered.

func (*Query) OrderByDesc

func (q *Query) OrderByDesc(field string) *Query

OrderByDesc specify descending order for the query results. On multiple calls, only the last one is considered.

type Reducer

type Reducer interface {
	Reduce(events []core.Event) error
}

Reducer applies an event to an existing state.

type ServiceBoostrapper

type ServiceBoostrapper interface {
	coreservice.Service
	GetIpfsLite() *ipfslite.Peer
	Bootstrap(addrs []peer.AddrInfo)
}

DefaultService is a boostrapable default Service with sane defaults.

func DefaultService

func DefaultService(repoPath string, opts ...ServiceOption) (ServiceBoostrapper, error)

type ServiceConfig

type ServiceConfig struct {
	HostAddr    ma.Multiaddr
	Debug       bool
	GRPCOptions []grpc.ServerOption
}

type ServiceOption

type ServiceOption func(c *ServiceConfig) error

func WithServiceDebug

func WithServiceDebug(enabled bool) ServiceOption

func WithServiceGRPCOptions added in v0.1.6

func WithServiceGRPCOptions(opts ...grpc.ServerOption) ServiceOption

func WithServiceHostAddr

func WithServiceHostAddr(addr ma.Multiaddr) ServiceOption

type SimpleTx

type SimpleTx struct {
	// contains filtered or unexported fields
}

SimpleTx implements the transaction interface for datastores who do not have any sort of underlying transactional support

func (*SimpleTx) Commit

func (bt *SimpleTx) Commit() error

func (*SimpleTx) Delete

func (bt *SimpleTx) Delete(key datastore.Key) error

func (*SimpleTx) Discard

func (bt *SimpleTx) Discard()

func (*SimpleTx) Get

func (bt *SimpleTx) Get(k datastore.Key) ([]byte, error)

func (*SimpleTx) GetSize

func (bt *SimpleTx) GetSize(k datastore.Key) (int, error)

func (*SimpleTx) Has

func (bt *SimpleTx) Has(k datastore.Key) (bool, error)

func (*SimpleTx) Put

func (bt *SimpleTx) Put(key datastore.Key, val []byte) error

func (*SimpleTx) Query

func (bt *SimpleTx) Query(q query.Query) (query.Results, error)

type Store

type Store struct {
	io.Closer
	// contains filtered or unexported fields
}

Store is the aggregate-root of events and state. External/remote events are dispatched to the Store, and are internally processed to impact model states. Likewise, local changes in models registered produce events dispatched externally.

func NewStore

func NewStore(ts service.Service, opts ...Option) (*Store, error)

NewStore creates a new Store, which will *own* ds and dispatcher for internal use. Saying it differently, ds and dispatcher shouldn't be used externally.

func (*Store) Close

func (s *Store) Close() error

Close closes the store

func (*Store) GetModel

func (s *Store) GetModel(name string) *Model

GetModel returns a model by name.

func (*Store) Listen

func (s *Store) Listen(los ...ListenOption) (Listener, error)

Listen returns a Listener which notifies about actions applying the defined filters. The Store *won't* wait for slow receivers, so if the channel is full, the action will be dropped.

func (*Store) Reduce

func (s *Store) Reduce(events []core.Event) error

Reduce processes txn events into the models.

func (*Store) Register

func (s *Store) Register(name string, defaultInstance interface{}) (*Model, error)

Register a new model in the store by infering using a defaultInstance

func (*Store) RegisterSchema

func (s *Store) RegisterSchema(name string, schema string, indexes ...*IndexConfig) (*Model, error)

RegisterSchema a new model in the store with a JSON schema.

func (*Store) Service

func (s *Store) Service() service.Service

Service returns the Service used by the store

func (*Store) Start

func (s *Store) Start() error

Start should be called immediatelly after registering all schemas and before any operation on them. If the store already boostraped on a thread, it will continue using that thread. In the opposite case, it will create a new thread.

func (*Store) StartFromAddr

func (s *Store) StartFromAddr(addr ma.Multiaddr, followKey, readKey *symmetric.Key) error

StartFromAddr should be called immediatelly after registering all schemas and before any operation on them. It pulls the current Store thread from thread addr

func (*Store) ThreadID

func (s *Store) ThreadID() (thread.ID, bool, error)

ThreadID returns the store's theadID if it exists.

type TxMapDatastore

type TxMapDatastore struct {
	*datastore.MapDatastore
	// contains filtered or unexported fields
}

func NewTxMapDatastore

func NewTxMapDatastore() *TxMapDatastore

func (*TxMapDatastore) NewTransaction

func (d *TxMapDatastore) NewTransaction(readOnly bool) (datastore.Txn, error)

type Txn

type Txn struct {
	// contains filtered or unexported fields
}

Txn represents a read/write transaction in the Store. It allows for serializable isolation level within the store.

func (*Txn) Commit

func (t *Txn) Commit() error

Commit applies all changes done in the current transaction to the model. This is a syncrhonous call so changes can be assumed to be applied on function return.

func (*Txn) Create

func (t *Txn) Create(new ...interface{}) error

Create creates new instances in the model If the ID value on the instance is nil or otherwise a null value (e.g., "" in jsonMode), the ID is updated in-place to reflect the automatically-genereted UUID.

func (*Txn) Delete

func (t *Txn) Delete(ids ...core.EntityID) error

Delete deletes instances by ID when the current transaction commits.

func (*Txn) Discard

func (t *Txn) Discard()

Discard discards all changes done in the current transaction.

func (*Txn) Find

func (t *Txn) Find(res interface{}, q *Query) error

Find executes a query and store the result in res which should be a slice of pointers with the correct model type. If the slice isn't empty, will be emptied.

func (*Txn) FindByID

func (t *Txn) FindByID(id core.EntityID, v interface{}) error

FindByID gets an instance by ID in the current txn scope.

func (*Txn) FindJSON

func (t *Txn) FindJSON(q *JSONQuery) ([]string, error)

FindJSON queries for entities by JSONQuery

func (*Txn) Has

func (t *Txn) Has(ids ...core.EntityID) (bool, error)

Has returns true if all IDs exists in the model, false otherwise.

func (*Txn) Save

func (t *Txn) Save(updated ...interface{}) error

Save saves an instance changes to be commited when the current transaction commits.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL