Documentation ¶
Overview ¶
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 ¶
- type AECompatibleOperations
- type AECompatibleTransaction
- func (tx *AECompatibleTransaction) Boom() *Boom
- func (tx *AECompatibleTransaction) Commit() (datastore.Commit, error)
- func (tx *AECompatibleTransaction) Delete(src interface{}) error
- func (tx *AECompatibleTransaction) DeleteMulti(src interface{}) error
- func (tx *AECompatibleTransaction) Get(dst interface{}) error
- func (tx *AECompatibleTransaction) GetMulti(dst interface{}) error
- func (tx *AECompatibleTransaction) Key(src interface{}) datastore.Key
- func (tx *AECompatibleTransaction) KeyError(src interface{}) (datastore.Key, error)
- func (tx *AECompatibleTransaction) Kind(src interface{}) string
- func (tx *AECompatibleTransaction) Put(src interface{}) (datastore.Key, error)
- func (tx *AECompatibleTransaction) PutMulti(src interface{}) ([]datastore.Key, error)
- func (tx *AECompatibleTransaction) Rollback() error
- type Batch
- type Boom
- func (bm *Boom) AllocateID(src interface{}) (datastore.Key, error)
- func (bm *Boom) AllocateIDs(src interface{}) ([]datastore.Key, error)
- func (bm *Boom) Batch() *Batch
- func (bm *Boom) Count(q datastore.Query) (int, error)
- func (bm *Boom) DecodeCursor(s string) (datastore.Cursor, error)
- func (bm *Boom) Delete(src interface{}) error
- func (bm *Boom) DeleteMulti(src interface{}) error
- func (bm *Boom) Get(dst interface{}) error
- func (bm *Boom) GetAll(q datastore.Query, dst interface{}) ([]datastore.Key, error)
- func (bm *Boom) GetMulti(dst interface{}) error
- func (bm *Boom) Key(src interface{}) datastore.Key
- func (bm *Boom) KeyError(src interface{}) (datastore.Key, error)
- func (bm *Boom) Kind(src interface{}) string
- func (bm *Boom) NewQuery(k string) datastore.Query
- func (bm *Boom) NewTransaction() (*Transaction, error)
- func (bm *Boom) Put(src interface{}) (datastore.Key, error)
- func (bm *Boom) PutMulti(src interface{}) ([]datastore.Key, error)
- func (bm *Boom) Run(q datastore.Query) *Iterator
- func (bm *Boom) RunInTransaction(f func(tx *Transaction) error) (datastore.Commit, error)
- type Iterator
- type Transaction
- func (tx *Transaction) Batch() *TransactionBatch
- func (tx *Transaction) Boom() *Boom
- func (tx *Transaction) Commit() (datastore.Commit, error)
- func (tx *Transaction) Delete(src interface{}) error
- func (tx *Transaction) DeleteMulti(src interface{}) error
- func (tx *Transaction) Get(dst interface{}) error
- func (tx *Transaction) GetMulti(dst interface{}) error
- func (tx *Transaction) Key(src interface{}) datastore.Key
- func (tx *Transaction) KeyError(src interface{}) (datastore.Key, error)
- func (tx *Transaction) Kind(src interface{}) string
- func (tx *Transaction) Put(src interface{}) (datastore.PendingKey, error)
- func (tx *Transaction) PutMulti(src interface{}) ([]datastore.PendingKey, error)
- func (tx *Transaction) Rollback() error
- type TransactionBatch
- func (b *TransactionBatch) Boom() *Boom
- func (b *TransactionBatch) Delete(dst interface{}, h datastore.BatchErrHandler)
- func (b *TransactionBatch) Exec() error
- func (b *TransactionBatch) Get(dst interface{}, h datastore.BatchErrHandler)
- func (b *TransactionBatch) Put(src interface{}, h datastore.TxBatchPutHandler)
- func (b *TransactionBatch) Transaction() *Transaction
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AECompatibleOperations ¶ added in v0.5.0
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 ¶ added in v0.5.0
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 ¶ added in v0.5.0
func ToAECompatibleTransaction(tx *Transaction) *AECompatibleTransaction
ToAECompatibleTransaction converts a transaction to AECompatibleTransaction. AECompatibleTransaction implements AECompatibleOperations.
func (*AECompatibleTransaction) Boom ¶ added in v0.5.0
func (tx *AECompatibleTransaction) Boom() *Boom
Boom object that is the source of the Batch object is returned.
func (*AECompatibleTransaction) Commit ¶ added in v0.5.0
func (tx *AECompatibleTransaction) Commit() (datastore.Commit, error)
Commit applies the enqueued operations atomically.
func (*AECompatibleTransaction) Delete ¶ added in v0.5.0
func (tx *AECompatibleTransaction) Delete(src interface{}) error
Delete deletes the entity. key will be extract from src struct.
func (*AECompatibleTransaction) DeleteMulti ¶ added in v0.5.0
func (tx *AECompatibleTransaction) DeleteMulti(src interface{}) error
DeleteMulti is a batch version of Delete.
func (*AECompatibleTransaction) Get ¶ added in v0.5.0
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 ¶ added in v0.5.0
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 ¶ added in v0.5.0
func (tx *AECompatibleTransaction) Key(src interface{}) datastore.Key
Key retrieves datastore key from struct without error occurred.
func (*AECompatibleTransaction) KeyError ¶ added in v0.5.0
func (tx *AECompatibleTransaction) KeyError(src interface{}) (datastore.Key, error)
KeyError retrieves datastore key from struct with error occurred.
func (*AECompatibleTransaction) Kind ¶ added in v0.5.0
func (tx *AECompatibleTransaction) Kind(src interface{}) string
Kind retrieves kind name from struct.
func (*AECompatibleTransaction) Put ¶ added in v0.5.0
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 ¶ added in v0.5.0
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 ¶ added in v0.5.0
func (tx *AECompatibleTransaction) Rollback() error
Rollback abandons a pending transaction.
type Batch ¶
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 ¶ added in v0.14.0
Boom object that is the source of the Batch object is returned.
func (*Batch) Delete ¶
func (b *Batch) Delete(dst interface{}, h datastore.BatchErrHandler)
Delete Entity operation into the queue.
func (*Batch) Exec ¶
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 ¶
func (b *Batch) Get(dst interface{}, h datastore.BatchErrHandler)
Get Entity operation into the queue.
func (*Batch) Put ¶
func (b *Batch) Put(src interface{}, h datastore.BatchPutHandler)
Put Entity operation into the queue. This operation doesn't Put to Datastore immediatly. 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 ¶
Boom is a datastore client wrapper to make it easy to understand the handling of Key.
Example ¶
package main import ( "context" "fmt" "go.mercari.io/datastore" "go.mercari.io/datastore/boom" "go.mercari.io/datastore/clouddatastore" "go.mercari.io/datastore/internal/testutils" ) const ProjectID = "datastore-wrapper" func main() { 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
Example (Kind) ¶
package main import ( "context" "fmt" "go.mercari.io/datastore/boom" "go.mercari.io/datastore/clouddatastore" "go.mercari.io/datastore/internal/testutils" ) func main() { 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 支払い
Example (Parent) ¶
package main import ( "context" "fmt" "go.mercari.io/datastore" "go.mercari.io/datastore/boom" "go.mercari.io/datastore/clouddatastore" "go.mercari.io/datastore/internal/testutils" ) func main() { 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
Example (WithCache) ¶
package main import ( "context" "fmt" "go.mercari.io/datastore/aedatastore" "go.mercari.io/datastore/boom" "go.mercari.io/datastore/dsmiddleware/aememcache" "go.mercari.io/datastore/dsmiddleware/localcache" "google.golang.org/appengine" "google.golang.org/appengine/aetest" ) func appengineContext() (ctx context.Context, cancelFn func() error) { inst, err := aetest.NewInstance(&aetest.Options{StronglyConsistentDatastore: true, SuppressDevAppServerLog: true}) if err != nil { panic(err) } cancelFn = inst.Close r, err := inst.NewRequest("GET", "/", nil) if err != nil { panic(err) } ctx = appengine.NewContext(r) return } func main() { 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 ¶
FromClient make new Boom object from specified datastore.Client.
func FromContext
deprecated
func (*Boom) AllocateID ¶ added in v0.4.0
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 ¶ added in v0.4.0
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) Count ¶
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 ¶ added in v0.3.0
DecodeCursor from its base-64 string representation.
func (*Boom) DeleteMulti ¶
DeleteMulti is a batch version of Delete.
func (*Boom) Get ¶
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 ¶
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 ¶
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) NewQuery ¶ added in v0.6.0
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 ¶
func (bm *Boom) NewTransaction() (*Transaction, error)
NewTransaction starts a new transaction.
func (*Boom) Put ¶
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 ¶
PutMulti is a batch version of Put.
src must satisfy the same conditions as the dst argument to GetMulti.
func (*Boom) RunInTransaction ¶
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 ¶
type Iterator struct {
// contains filtered or unexported fields
}
Iterator is the result of running a query.
func (*Iterator) Next ¶
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 ¶
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 ¶
func (tx *Transaction) Batch() *TransactionBatch
Batch creates batch mode objects.
func (*Transaction) Boom ¶ added in v0.14.0
func (tx *Transaction) Boom() *Boom
Boom object that is the source of the Batch object is returned.
func (*Transaction) Commit ¶
func (tx *Transaction) Commit() (datastore.Commit, error)
Commit applies the enqueued operations atomically.
func (*Transaction) Delete ¶
func (tx *Transaction) Delete(src interface{}) error
Delete deletes the entity. key will be extract from src struct.
func (*Transaction) DeleteMulti ¶
func (tx *Transaction) DeleteMulti(src interface{}) error
DeleteMulti is a batch version of Delete.
func (*Transaction) Get ¶
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 ¶
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 ¶ added in v0.5.0
func (tx *Transaction) Key(src interface{}) datastore.Key
Key retrieves datastore key from struct without error occurred.
func (*Transaction) KeyError ¶ added in v0.5.0
func (tx *Transaction) KeyError(src interface{}) (datastore.Key, error)
KeyError retrieves datastore key from struct with error occurred.
func (*Transaction) Kind ¶ added in v0.5.0
func (tx *Transaction) Kind(src interface{}) string
Kind retrieves kind name from struct.
func (*Transaction) Put ¶
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 ¶
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 ¶
func (tx *Transaction) Rollback() error
Rollback abandons a pending transaction.
type TransactionBatch ¶
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 ¶ added in v0.14.0
func (b *TransactionBatch) Boom() *Boom
Boom object that is the source of the TransactionBatch object is returned.
func (*TransactionBatch) Delete ¶
func (b *TransactionBatch) Delete(dst interface{}, h datastore.BatchErrHandler)
Delete Entity operation into the queue.
func (*TransactionBatch) Exec ¶
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 ¶
func (b *TransactionBatch) Get(dst interface{}, h datastore.BatchErrHandler)
Get Entity operation into the queue.
func (*TransactionBatch) Put ¶
func (b *TransactionBatch) Put(src interface{}, h datastore.TxBatchPutHandler)
Put Entity operation into the queue. This operation doesn't Put to Datastore immediatly. 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 ¶ added in v0.14.0
func (b *TransactionBatch) Transaction() *Transaction
Transaction object that is the source of the TransactionBatch object is returned.