datastore: go.mercari.io/datastore/boom Index | Examples | Files

package boom

import "go.mercari.io/datastore/boom"

Package boom handles the troublesome processing of datastore.Key automatically. It calculates the Kind, ID, and Name from the name of struct and tags.

Key handling

boom beautifully maps keys and objects, making it easier to write code. It is easier to collect information on one object than to treat Key and Entity separately. Handling is very easy if Key has only ID or Name. It just adds boom:"id" to the tag, as in the following code:

type Post struct {
	ID		int64 `datastore:"-" boom:"id"`
	Content	string
}

When Put the value of ID field is uses as the ID of Key, and when Get ID value of Key is set in ID field. This allows you to break code to think or write about Key in your program.

Kind of Key is also calculated automatically. By default, the name of the passed struct is the Kind name. In the example of the previous code, 'Post' becomes Kind. If you want to explicitly specify, boom:"kind" is given to the tag.

In the case of the following code, the Kind name will be 'pay' if there is no value in the Kind field. If you have some value in the Kind field, that value will be the Kind name.

type Payment struct {
	Kind	string	`datastore:"-" boom:"kind,pay"`
	ID		int64	`datastore:"-" boom:"id"`
	Amount	int
}

As for ParentKey, there is also a means to ease it. boom:"parent" is given to the tag, field value is used as ParentKey.

For goon user

boom has a considerable API compatibility with goom.

There is a difference in behavior when Put under transaction. Cloud Datastore does not assign the ID immediately before the Commit. go.mercari.io/datastore following the Cloud Datastore specification will behave similarly even if the back end is AppEngine Datastore. Therefore, if you need to use ID before Commit after Putting, you need to call AllocateID yourself beforehand.

Also, boom does not have any mechanism about the cache. Because, it should be done with middleware on go.mercari.io/datastore. Simple and nice, do not you?

Index

Examples

Package Files

batch.go boom.go doc.go doc_ja.go interfaces.go query.go transaction.go tx_aecompat.go tx_batch.go

func DatastoreTransaction Uses

func DatastoreTransaction(tx *Transaction) datastore.Transaction

DatastoreTransaction returns datastore.Transaction that contains in boom's Transaction. This function should not be used unless you have a special reason.

type AECompatibleOperations Uses

type AECompatibleOperations interface {
    Kind(src interface{}) string
    Key(src interface{}) datastore.Key
    KeyError(src interface{}) (datastore.Key, error)
    Get(dst interface{}) error
    GetMulti(dst interface{}) error
    Put(src interface{}) (datastore.Key, error)
    PutMulti(src interface{}) ([]datastore.Key, error)
    Delete(src interface{}) error
    DeleteMulti(src interface{}) error
}

AECompatibleOperations represents Transaction, if not, both common operations. In AppEngine Datastore transactions immediately return Key. In order to realize this, this wrapper internally performs AllocateID when it is required.

This is for migrating existing code and should not be used if possible.

type AECompatibleTransaction Uses

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

AECompatibleTransaction implements AECompatibleOperations. It is useful for migration when using AppEngine Datastore, when using transactions or not using it with using the same code.

func ToAECompatibleTransaction Uses

func ToAECompatibleTransaction(tx *Transaction) *AECompatibleTransaction

ToAECompatibleTransaction converts a transaction to AECompatibleTransaction. AECompatibleTransaction implements AECompatibleOperations.

func (*AECompatibleTransaction) Boom Uses

func (tx *AECompatibleTransaction) Boom() *Boom

Boom object that is the source of the Batch object is returned.

func (*AECompatibleTransaction) Commit Uses

func (tx *AECompatibleTransaction) Commit() (datastore.Commit, error)

Commit applies the enqueued operations atomically.

func (*AECompatibleTransaction) Delete Uses

func (tx *AECompatibleTransaction) Delete(src interface{}) error

Delete deletes the entity. key will be extract from src struct.

func (*AECompatibleTransaction) DeleteMulti Uses

func (tx *AECompatibleTransaction) DeleteMulti(src interface{}) error

DeleteMulti is a batch version of Delete.

func (*AECompatibleTransaction) Get Uses

func (tx *AECompatibleTransaction) Get(dst interface{}) error

Get loads the entity stored for key into dst, which must be a struct pointer or implement PropertyLoadSaver. key will be extracted from dst.

If there is no such entity for the key, Get returns ErrNoSuchEntity. The values of dst's unmatched struct fields are not modified, and matching slice-typed fields are not reset before appending to them. In particular, it is recommended to pass a pointer to a zero valued struct on each Get call.

func (*AECompatibleTransaction) GetMulti Uses

func (tx *AECompatibleTransaction) GetMulti(dst interface{}) error

GetMulti is a batch version of Get. key will be extracted from each struct of dst.

dst must be a []S, []*S, []I or []P, for some struct type S, some interface type I, or some non-interface non-pointer type P such that P or *P implements PropertyLoadSaver. If an []I, each element must be a valid dst for Get: it must be a struct pointer or implement PropertyLoadSaver.

func (*AECompatibleTransaction) Key Uses

func (tx *AECompatibleTransaction) Key(src interface{}) datastore.Key

Key retrieves datastore key from struct without error occurred.

func (*AECompatibleTransaction) KeyError Uses

func (tx *AECompatibleTransaction) KeyError(src interface{}) (datastore.Key, error)

KeyError retrieves datastore key from struct with error occurred.

func (*AECompatibleTransaction) Kind Uses

func (tx *AECompatibleTransaction) Kind(src interface{}) string

Kind retrieves kind name from struct.

func (*AECompatibleTransaction) Put Uses

func (tx *AECompatibleTransaction) Put(src interface{}) (datastore.Key, error)

Put saves the entity src into the datastore. key will be extract from src struct. src must be a struct pointer or implement PropertyLoadSaver; if a struct pointer then any unexported fields of that struct will be skipped. If k is an incomplete key, the returned key will be a unique key generated by the datastore, and inject key to src struct.

func (*AECompatibleTransaction) PutMulti Uses

func (tx *AECompatibleTransaction) PutMulti(src interface{}) ([]datastore.Key, error)

PutMulti is a batch version of Put.

src must satisfy the same conditions as the dst argument to GetMulti.

func (*AECompatibleTransaction) Rollback Uses

func (tx *AECompatibleTransaction) Rollback() error

Rollback abandons a pending transaction.

type Batch Uses

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

Batch can queue operations on Datastore and process them in batch. Batch does nothing until you call Exec(). This helps to reduce the number of RPCs.

func (*Batch) Boom Uses

func (b *Batch) Boom() *Boom

Boom object that is the source of the Batch object is returned.

func (*Batch) Delete Uses

func (b *Batch) Delete(dst interface{}, h datastore.BatchErrHandler)

Delete Entity operation into the queue.

func (*Batch) Exec Uses

func (b *Batch) Exec() error

Exec will perform all the processing that was queued. This process is done recursively until the queue is empty. The return value may be MultiError, but the order of contents is not guaranteed.

func (*Batch) Get Uses

func (b *Batch) Get(dst interface{}, h datastore.BatchErrHandler)

Get Entity operation into the queue.

func (*Batch) Put Uses

func (b *Batch) Put(src interface{}, h datastore.BatchPutHandler)

Put Entity operation into the queue. This operation doesn't Put to Datastore immediately. If a h is provided, it passes the processing result to the handler, and treats the return value as the value of the result of Putting.

type Boom Uses

type Boom struct {
    Context context.Context
    Client  datastore.Client
}

Boom is a datastore client wrapper to make it easy to understand the handling of Key.

Code:

ctx := context.Background()
// of-course, you can use aedatastore instead of clouddatastore!
client, err := clouddatastore.FromContext(
    ctx,
    datastore.WithProjectID(ProjectID),
)
if err != nil {
    panic(err)
}
defer client.Close()
defer testutils.CleanUpAllEntities(ctx, client)

bm := boom.FromClient(ctx, client)

type Data struct {
    ID   int64 `datastore:"-" boom:"id"`
    Name string
}

key, err := bm.Put(&Data{Name: "mercari"})
if err != nil {
    panic(err)
}
if key.ID() == 0 {
    panic("unexpected state")
}

obj := &Data{ID: key.ID()}
err = bm.Get(obj)
if err != nil {
    panic(err)
}

fmt.Println(obj.Name)

Output:

mercari

Code:

ctx := context.Background()
client, err := clouddatastore.FromContext(ctx)
if err != nil {
    panic(err)
}
defer client.Close()
defer testutils.CleanUpAllEntities(ctx, client)

bm := boom.FromClient(ctx, client)

type Payment struct {
    Kind   string `datastore:"-" boom:"kind,pay"`
    ID     int64  `datastore:"-" boom:"id"`
    Amount int
}

key, err := bm.Put(&Payment{
    Amount: 100,
})
if err != nil {
    panic(err)
}
fmt.Println(key.Kind())

key, err = bm.Put(&Payment{
    Kind:   "支払い",
    Amount: 100,
})
if err != nil {
    panic(err)
}
fmt.Println(key.Kind())

Output:

pay
支払い

Code:

ctx := context.Background()
client, err := clouddatastore.FromContext(ctx)
if err != nil {
    panic(err)
}
defer client.Close()
defer testutils.CleanUpAllEntities(ctx, client)

bm := boom.FromClient(ctx, client)

type Post struct {
    ID      string `datastore:"-" boom:"id"`
    Content string
}

type Comment struct {
    ParentKey datastore.Key `datastore:"-" boom:"parent"`
    ID        int64         `datastore:"-" boom:"id"`
    Message   string
}

key, err := bm.Put(&Post{
    ID:      "foobar",
    Content: "post!",
})
if err != nil {
    panic(err)
}

key, err = bm.Put(&Comment{
    ParentKey: key,
    ID:        1,
    Message:   "comment!",
})
if err != nil {
    panic(err)
}
fmt.Println(key.String())

Output:

/Post,foobar/Comment,1

Code:

ctx, cancelFn := appengineContext()
go cancelFn()

client, err := aedatastore.FromContext(ctx)
if err != nil {
    panic(err)
}
defer client.Close()

// add cache layer likes goon!
client.AppendMiddleware(localcache.New(
    localcache.WithLogger(func(ctx context.Context, format string, args ...interface{}) {
        fmt.Println(fmt.Sprintf(format, args...))
    }),
))
client.AppendMiddleware(aememcache.New(
    aememcache.WithLogger(func(ctx context.Context, format string, args ...interface{}) {
        fmt.Println(fmt.Sprintf(format, args...))
    }),
))

bm := boom.FromClient(ctx, client)

type Data struct {
    ID  string `datastore:"-" boom:"id"`
    Str string
}

_, err = bm.Put(&Data{
    ID:  "test",
    Str: "foobar",
})
if err != nil {
    panic(err)
}

err = bm.Get(&Data{ID: "test"})
if err != nil {
    panic(err)
}

Output:

dsmiddleware/aememcache.SetMulti: incoming len=1
dsmiddleware/aememcache.SetMulti: len=1
dsmiddleware/localcache.SetMulti: len=1
dsmiddleware/localcache.SetMulti: idx=0 key=/Data,test len(ps)=1
dsmiddleware/localcache.GetMulti: len=1
dsmiddleware/localcache.GetMulti: idx=0 key=/Data,test
dsmiddleware/localcache.GetMulti: idx=0, hit key=/Data,test len(ps)=1

func FromClient Uses

func FromClient(ctx context.Context, client datastore.Client) *Boom

FromClient make new Boom object from specified datastore.Client.

func FromContext Uses

func FromContext(ctx context.Context) (*Boom, error)

FromContext make new Boom object with specified context.

Deprecated: use FromClient instead.

func (*Boom) AllocateID Uses

func (bm *Boom) AllocateID(src interface{}) (datastore.Key, error)

AllocateID takes a struct whose key has not yet been set as an argument, allocates the Key of the relevant Kind, and sets it to a struct.

func (*Boom) AllocateIDs Uses

func (bm *Boom) AllocateIDs(src interface{}) ([]datastore.Key, error)

AllocateIDs takes a slice of a struct whose key has not yet been set as an argument, secures the Key of the relevant Kind, and sets it to each struct.

func (*Boom) Batch Uses

func (bm *Boom) Batch() *Batch

Batch creates batch mode objects.

func (*Boom) Count Uses

func (bm *Boom) Count(q datastore.Query) (int, error)

Count returns the number of results for the given query.

The running time and number of API calls made by Count scale linearly with with the sum of the query's offset and limit. Unless the result count is expected to be small, it is best to specify a limit; otherwise Count will continue until it finishes counting or the provided context expires.

func (*Boom) DecodeCursor Uses

func (bm *Boom) DecodeCursor(s string) (datastore.Cursor, error)

DecodeCursor from its base-64 string representation.

func (*Boom) Delete Uses

func (bm *Boom) Delete(src interface{}) error

Delete deletes the entity. key will be extract from src struct.

func (*Boom) DeleteMulti Uses

func (bm *Boom) DeleteMulti(src interface{}) error

DeleteMulti is a batch version of Delete.

func (*Boom) Get Uses

func (bm *Boom) Get(dst interface{}) error

Get loads the entity stored for key into dst, which must be a struct pointer or implement PropertyLoadSaver. key will be extracted from dst.

If there is no such entity for the key, Get returns ErrNoSuchEntity. The values of dst's unmatched struct fields are not modified, and matching slice-typed fields are not reset before appending to them. In particular, it is recommended to pass a pointer to a zero valued struct on each Get call.

func (*Boom) GetAll Uses

func (bm *Boom) GetAll(q datastore.Query, dst interface{}) ([]datastore.Key, error)

GetAll runs the provided query that it returns all entities that match that query, as well as appending the values to dst.

dst must have type *[]S or *[]*S or *[]P, for some struct type S or some non-interface, non-pointer type P such that P or *P implements PropertyLoadSaver.

As a special case, *PropertyList is an invalid type for dst, even though a PropertyList is a slice of structs. It is treated as invalid to avoid being mistakenly passed when *[]PropertyList was intended.

The keys are injected to each dst struct.

If q is a “keys-only” query, GetAll ignores dst and only returns the keys.

The running time and number of API calls made by GetAll scale linearly with with the sum of the query's offset and limit. Unless the result count is expected to be small, it is best to specify a limit; otherwise GetAll will continue until it finishes collecting results or the provided context expires.

func (*Boom) GetMulti Uses

func (bm *Boom) GetMulti(dst interface{}) error

GetMulti is a batch version of Get. key will be extracted from each struct of dst.

dst must be a []S, []*S, []I or []P, for some struct type S, some interface type I, or some non-interface non-pointer type P such that P or *P implements PropertyLoadSaver. If an []I, each element must be a valid dst for Get: it must be a struct pointer or implement PropertyLoadSaver.

func (*Boom) Key Uses

func (bm *Boom) Key(src interface{}) datastore.Key

Key retrieves datastore key from struct without error occurred.

func (*Boom) KeyError Uses

func (bm *Boom) KeyError(src interface{}) (datastore.Key, error)

KeyError retrieves datastore key from struct with error occurred.

func (*Boom) Kind Uses

func (bm *Boom) Kind(src interface{}) string

Kind retrieves kind name from struct.

func (*Boom) NewQuery Uses

func (bm *Boom) NewQuery(k string) datastore.Query

NewQuery creates a new Query for a specific entity kind.

An empty kind means to return all entities, including entities created and managed by other App Engine features, and is called a kindless query. Kindless queries cannot include filters or sort orders on property values.

func (*Boom) NewTransaction Uses

func (bm *Boom) NewTransaction() (*Transaction, error)

NewTransaction starts a new transaction.

func (*Boom) Put Uses

func (bm *Boom) Put(src interface{}) (datastore.Key, error)

Put saves the entity src into the datastore. key will be extract from src struct. src must be a struct pointer or implement PropertyLoadSaver; if a struct pointer then any unexported fields of that struct will be skipped. If k is an incomplete key, the returned key will be a unique key generated by the datastore, and inject key to src struct.

func (*Boom) PutMulti Uses

func (bm *Boom) PutMulti(src interface{}) ([]datastore.Key, error)

PutMulti is a batch version of Put.

src must satisfy the same conditions as the dst argument to GetMulti.

func (*Boom) Run Uses

func (bm *Boom) Run(q datastore.Query) *Iterator

Run runs the given query.

func (*Boom) RunInTransaction Uses

func (bm *Boom) RunInTransaction(f func(tx *Transaction) error) (datastore.Commit, error)

RunInTransaction runs f in a transaction. f is invoked with a Transaction that f should use for all the transaction's datastore operations.

f must not call Commit or Rollback on the provided Transaction.

If f returns nil, RunInTransaction commits the transaction, returning the Commit and a nil error if it succeeds. If the commit fails due to a conflicting transaction, RunInTransaction gives up and returns ErrConcurrentTransaction immediately. If you want to retry operation, You have to retry by yourself.

If f returns non-nil, then the transaction will be rolled back and RunInTransaction will return the same error.

Note that when f returns, the transaction is not committed. Calling code must not assume that any of f's changes have been committed until RunInTransaction returns nil.

type Iterator Uses

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

Iterator is the result of running a query.

func (*Iterator) Cursor Uses

func (it *Iterator) Cursor() (datastore.Cursor, error)

Cursor returns a cursor for the iterator's current location.

func (*Iterator) Next Uses

func (it *Iterator) Next(dst interface{}) (datastore.Key, error)

Next returns the key of the next result. When there are no more results, iterator.Done is returned as the error.

If the query is not keys only and dst is non-nil, it also loads the entity stored for that key into the struct pointer or PropertyLoadSaver dst, with the same semantics and possible errors as for the Get function.

type Transaction Uses

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

Transaction represents a set of datastore operations to be committed atomically.

Operations are enqueued by calling the Put and Delete methods on Transaction (or their Multi-equivalents). These operations are only committed when the Commit method is invoked. To ensure consistency, reads must be performed by using Transaction's Get method or by using the Transaction method when building a query.

A Transaction must be committed or rolled back exactly once.

func (*Transaction) Batch Uses

func (tx *Transaction) Batch() *TransactionBatch

Batch creates batch mode objects.

func (*Transaction) Boom Uses

func (tx *Transaction) Boom() *Boom

Boom object that is the source of the Batch object is returned.

func (*Transaction) Commit Uses

func (tx *Transaction) Commit() (datastore.Commit, error)

Commit applies the enqueued operations atomically.

func (*Transaction) Delete Uses

func (tx *Transaction) Delete(src interface{}) error

Delete deletes the entity. key will be extract from src struct.

func (*Transaction) DeleteMulti Uses

func (tx *Transaction) DeleteMulti(src interface{}) error

DeleteMulti is a batch version of Delete.

func (*Transaction) Get Uses

func (tx *Transaction) Get(dst interface{}) error

Get loads the entity stored for key into dst, which must be a struct pointer or implement PropertyLoadSaver. key will be extracted from dst.

If there is no such entity for the key, Get returns ErrNoSuchEntity. The values of dst's unmatched struct fields are not modified, and matching slice-typed fields are not reset before appending to them. In particular, it is recommended to pass a pointer to a zero valued struct on each Get call.

func (*Transaction) GetMulti Uses

func (tx *Transaction) GetMulti(dst interface{}) error

GetMulti is a batch version of Get. key will be extracted from each struct of dst.

dst must be a []S, []*S, []I or []P, for some struct type S, some interface type I, or some non-interface non-pointer type P such that P or *P implements PropertyLoadSaver. If an []I, each element must be a valid dst for Get: it must be a struct pointer or implement PropertyLoadSaver.

func (*Transaction) Key Uses

func (tx *Transaction) Key(src interface{}) datastore.Key

Key retrieves datastore key from struct without error occurred.

func (*Transaction) KeyError Uses

func (tx *Transaction) KeyError(src interface{}) (datastore.Key, error)

KeyError retrieves datastore key from struct with error occurred.

func (*Transaction) Kind Uses

func (tx *Transaction) Kind(src interface{}) string

Kind retrieves kind name from struct.

func (*Transaction) Put Uses

func (tx *Transaction) Put(src interface{}) (datastore.PendingKey, error)

Put saves the entity src into the datastore. key will be extract from src struct. src must be a struct pointer or implement PropertyLoadSaver; if a struct pointer then any unexported fields of that struct will be skipped. If k is an incomplete key, the returned key will be a unique key generated by the datastore, and inject key to src struct.

func (*Transaction) PutMulti Uses

func (tx *Transaction) PutMulti(src interface{}) ([]datastore.PendingKey, error)

PutMulti is a batch version of Put.

src must satisfy the same conditions as the dst argument to GetMulti.

func (*Transaction) Rollback Uses

func (tx *Transaction) Rollback() error

Rollback abandons a pending transaction.

type TransactionBatch Uses

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

TransactionBatch can queue operations on Datastore and process them in batch. Batch does nothing until you call Exec(). This helps to reduce the number of RPCs.

func (*TransactionBatch) Boom Uses

func (b *TransactionBatch) Boom() *Boom

Boom object that is the source of the TransactionBatch object is returned.

func (*TransactionBatch) Delete Uses

func (b *TransactionBatch) Delete(dst interface{}, h datastore.BatchErrHandler)

Delete Entity operation into the queue.

func (*TransactionBatch) Exec Uses

func (b *TransactionBatch) Exec() error

Exec will perform all the processing that was queued. This process is done recursively until the queue is empty. The return value may be MultiError, but the order of contents is not guaranteed.

func (*TransactionBatch) Get Uses

func (b *TransactionBatch) Get(dst interface{}, h datastore.BatchErrHandler)

Get Entity operation into the queue.

func (*TransactionBatch) Put Uses

func (b *TransactionBatch) Put(src interface{}, h datastore.TxBatchPutHandler)

Put Entity operation into the queue. This operation doesn't Put to Datastore immediately. If a h is provided, it passes the processing result to the handler, and treats the return value as the value of the result of Putting.

func (*TransactionBatch) Transaction Uses

func (b *TransactionBatch) Transaction() *Transaction

Transaction object that is the source of the TransactionBatch object is returned.

Package boom imports 6 packages (graph) and is imported by 2 packages. Updated 2018-09-15. Refresh now. Tools for package owners.