boom

package
v1.8.2 Latest Latest
Warning

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

Go to latest
Published: Jul 12, 2022 License: MIT Imports: 6 Imported by: 24

README

boom

BOOM HEADSHOT!

goon likes interface for go.mercari.io/datastore. see https://godoc.org/go.mercari.io/datastore/boom

TODO

  • namespace

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

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func DatastoreTransaction added in v1.2.0

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.

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

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

func (b *Batch) Boom() *Boom

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

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

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 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

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.

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

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

FromClient make new Boom object from specified datastore.Client.

func FromContext deprecated

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

FromContext make new Boom object with specified context.

Deprecated: use FromClient instead.

func (*Boom) AllocateID added in v0.4.0

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 added in v0.4.0

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

func (bm *Boom) Batch() *Batch

Batch creates batch mode objects.

func (*Boom) Count

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 added in v0.3.0

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

DecodeCursor from its base-64 string representation.

func (*Boom) Delete

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

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

func (*Boom) DeleteMulti

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

DeleteMulti is a batch version of Delete.

func (*Boom) Get

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

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

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

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

Key retrieves datastore key from struct without error occurred.

func (*Boom) KeyError

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

KeyError retrieves datastore key from struct with error occurred.

func (*Boom) Kind

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

Kind retrieves kind name from struct.

func (*Boom) NewQuery added in v0.6.0

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

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

NewTransaction starts a new transaction.

func (*Boom) Put

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

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

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

Run runs the given query.

func (*Boom) RunInTransaction

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

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

Iterator is the result of running a query.

func (*Iterator) Cursor

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

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

func (*Iterator) Next

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

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 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 added in v0.14.0

func (b *TransactionBatch) Transaction() *Transaction

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

Jump to

Keyboard shortcuts

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