grpcds

package module
v0.0.0-...-1ddc73e Latest Latest
Warning

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

Go to latest
Published: Apr 6, 2023 License: MIT Imports: 16 Imported by: 0

README

This is a gRPC shim for go-datastore.

The server wraps a datastore in a gRPC server, so that datastores can run out-of-process. If you have a special datastore implementation, simply wrap your datastore in this server and run it, and your datastore can then be called via gRPC from another process via TCP or Unix domain sockets.

The client implements the datastore interface, and calls out to a remote gRPC server.

Why not HTTP?

This could also be implemented with HTTP, but streaming results with chunked encoding and good error messaging is complicated with HTTP, and each client language would need to implement that non-trivial logic. This is much easier with gRPC, which has streaming support and client codegen built-in. The downside is that gRPC is not available for as many programming languages as HTTP. Another downside is that you can't reuse ubiquitous HTTP caching infrastructure and load balancing. The primary use case for this is to run as a sidecar, and gRPC fits that bill well. If there's a significant need for remote datastores, an HTTP version of this might be more appropriate.

Queries

Queries support a number of challenging features for RPC:

  • Results are streamed
  • Filters and orders are code, not data, so we have to do extra work to use them as data
  • Structured errors are embedded in results

Filters and Orders

Filters and orders require special treatment, since they do not have codecs by default.

To support this, each filter and order must be named, and the name mapped to a codec implementation. Both client and server must do this for the desired filters and orders.

This library includes support for the default datastore filters and orders, except OrderByFunction.

Errors

Each result can also contain a structured Go error. Some of these are meaningful (for example, when a result is not found in must return datastore.ErrNotFound). When sending an error in a result, we encode the error as a standard gRPC status protobuf in the same way we do API calls, and apply the same translation logic on the client side, so that datastore-specific errors remain consistent.

Datastore Features

When the client-side datastore is constructed, it negotiates the features supported by the server-side datastore, and then returns an underlying implementation that only implements those features.

"Features" are the extra interfaces that Datastores may implement, such as datastore.Batching, datastore.CheckedDatastore, etc.

This means that client-side interface assertions will behave exactly the same as if you were using the remote datastore directly.

Transactions

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DSToGRPCError

func DSToGRPCError(err error) *status.Status

DSToGRPCError converts a datastore error into a well-formed gRPC error.

func GRPCToDSError

func GRPCToDSError(err error) error

GRPCToDSError converts a well-formed gRPC error into a Datastore error.

func New

func New(ctx context.Context, client pb.DatastoreClient, optFns ...func(o *Options)) (ds.Datastore, error)

New constructs a new shim client that implements the Datastore interface. This negotiates the datastore features that the remote datastore supports, and constructs an underlying representation that only implements those features, so that type assertions on feature interfaces work as expected.

func WithQueryFilterCodec

func WithQueryFilterCodec(codec QueryFilterCodec) func(o *Options)

WithQueryFilterEncoders sets the given query filter encoders. These map from a concrete type that implements

func WithQueryOrderCodec

func WithQueryOrderCodec(codec QueryOrderCodec) func(o *Options)

Types

type Datastore

type Datastore struct {
	QueryFilterCodecs map[reflect.Type]QueryFilterCodec
	QueryOrderCodecs  map[reflect.Type]QueryOrderCodec
	Client            pb.DatastoreClient
}

Datastore forwards all requests to a gRPC server.

func (*Datastore) Batch

func (d *Datastore) Batch(ctx context.Context) (ds.Batch, error)

func (*Datastore) Check

func (d *Datastore) Check(ctx context.Context) error

func (*Datastore) Close

func (d *Datastore) Close() error

func (*Datastore) CollectGarbage

func (d *Datastore) CollectGarbage(ctx context.Context) error

func (*Datastore) Delete

func (d *Datastore) Delete(ctx context.Context, key ds.Key) error

func (*Datastore) DiskUsage

func (d *Datastore) DiskUsage(ctx context.Context) (uint64, error)

func (*Datastore) Get

func (d *Datastore) Get(ctx context.Context, key ds.Key) (value []byte, err error)

func (*Datastore) GetExpiration

func (d *Datastore) GetExpiration(ctx context.Context, key ds.Key) (time.Time, error)

func (*Datastore) GetSize

func (d *Datastore) GetSize(ctx context.Context, key ds.Key) (size int, err error)

func (*Datastore) Has

func (d *Datastore) Has(ctx context.Context, key ds.Key) (exists bool, err error)

func (*Datastore) NewTransaction

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

func (*Datastore) Put

func (d *Datastore) Put(ctx context.Context, key ds.Key, value []byte) error

func (*Datastore) PutWithTTL

func (d *Datastore) PutWithTTL(ctx context.Context, key ds.Key, value []byte, ttl time.Duration) error

func (*Datastore) Query

func (d *Datastore) Query(ctx context.Context, q query.Query) (query.Results, error)

func (*Datastore) Scrub

func (d *Datastore) Scrub(ctx context.Context) error

func (*Datastore) SetTTL

func (d *Datastore) SetTTL(ctx context.Context, key ds.Key, ttl time.Duration) error

func (*Datastore) Sync

func (d *Datastore) Sync(ctx context.Context, prefix ds.Key) error

type FilterKeyCompareCodec

type FilterKeyCompareCodec struct{}

func (*FilterKeyCompareCodec) Decode

func (f *FilterKeyCompareCodec) Decode(b []byte) (query.Filter, error)

func (*FilterKeyCompareCodec) Encode

func (f *FilterKeyCompareCodec) Encode(filter query.Filter) ([]byte, error)

func (*FilterKeyCompareCodec) Name

func (f *FilterKeyCompareCodec) Name() string

func (*FilterKeyCompareCodec) Type

type FilterKeyPrefixCodec

type FilterKeyPrefixCodec struct{}

func (*FilterKeyPrefixCodec) Decode

func (f *FilterKeyPrefixCodec) Decode(b []byte) (query.Filter, error)

func (*FilterKeyPrefixCodec) Encode

func (f *FilterKeyPrefixCodec) Encode(filter query.Filter) ([]byte, error)

func (*FilterKeyPrefixCodec) Name

func (f *FilterKeyPrefixCodec) Name() string

func (*FilterKeyPrefixCodec) Type

func (f *FilterKeyPrefixCodec) Type() reflect.Type

type FilterValueCompareCodec

type FilterValueCompareCodec struct{}

func (*FilterValueCompareCodec) Decode

func (f *FilterValueCompareCodec) Decode(b []byte) (query.Filter, error)

func (*FilterValueCompareCodec) Encode

func (f *FilterValueCompareCodec) Encode(filter query.Filter) ([]byte, error)

func (*FilterValueCompareCodec) Name

func (f *FilterValueCompareCodec) Name() string

func (*FilterValueCompareCodec) Type

type Options

type Options struct {
	QueryFilterCodecs map[reflect.Type]QueryFilterCodec
	QueryOrderCodecs  map[reflect.Type]QueryOrderCodec
}

type OrderByKeyCodec

type OrderByKeyCodec struct{}

func (*OrderByKeyCodec) Decode

func (o *OrderByKeyCodec) Decode(b []byte) (query.Order, error)

func (*OrderByKeyCodec) Encode

func (o *OrderByKeyCodec) Encode(query.Order) ([]byte, error)

func (*OrderByKeyCodec) Name

func (o *OrderByKeyCodec) Name() string

func (*OrderByKeyCodec) Type

func (o *OrderByKeyCodec) Type() reflect.Type

type OrderByKeyDescCodec

type OrderByKeyDescCodec struct{}

func (*OrderByKeyDescCodec) Decode

func (o *OrderByKeyDescCodec) Decode(b []byte) (query.Order, error)

func (*OrderByKeyDescCodec) Encode

func (o *OrderByKeyDescCodec) Encode(query.Order) ([]byte, error)

func (*OrderByKeyDescCodec) Name

func (o *OrderByKeyDescCodec) Name() string

func (*OrderByKeyDescCodec) Type

func (o *OrderByKeyDescCodec) Type() reflect.Type

type OrderByValueCodec

type OrderByValueCodec struct{}

func (*OrderByValueCodec) Decode

func (o *OrderByValueCodec) Decode(b []byte) (query.Order, error)

func (*OrderByValueCodec) Encode

func (o *OrderByValueCodec) Encode(query.Order) ([]byte, error)

func (*OrderByValueCodec) Name

func (o *OrderByValueCodec) Name() string

func (*OrderByValueCodec) Type

func (o *OrderByValueCodec) Type() reflect.Type

type OrderByValueDescCodec

type OrderByValueDescCodec struct{}

func (*OrderByValueDescCodec) Decode

func (o *OrderByValueDescCodec) Decode(b []byte) (query.Order, error)

func (*OrderByValueDescCodec) Encode

func (o *OrderByValueDescCodec) Encode(query.Order) ([]byte, error)

func (*OrderByValueDescCodec) Name

func (o *OrderByValueDescCodec) Name() string

func (*OrderByValueDescCodec) Type

type QueryFilterCodec

type QueryFilterCodec interface {
	Name() string
	Type() reflect.Type
	Encode(query.Filter) ([]byte, error)
	Decode([]byte) (query.Filter, error)
}

QueryFilterCodec provides a codec definition for RPC transfers of a query filter.

type QueryOrderCodec

type QueryOrderCodec interface {
	Name() string
	Type() reflect.Type
	Encode(query.Order) ([]byte, error)
	Decode([]byte) (query.Order, error)
}

QueryOrderCodec provides a codec definition for RPC transfers of a query order.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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