databroker: implement leases (#2172)

* databroker: implement leases

* return error

* handle gRPC errors
This commit is contained in:
Caleb Doxsey 2021-05-10 13:30:25 -06:00 committed by GitHub
parent a54d43b937
commit 94aa0b1a48
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 2135 additions and 149 deletions

View file

@ -5,6 +5,8 @@ import (
"context"
"sync/atomic"
"google.golang.org/protobuf/types/known/emptypb"
"github.com/pomerium/pomerium/config"
"github.com/pomerium/pomerium/internal/databroker"
databrokerpb "github.com/pomerium/pomerium/pkg/grpc/databroker"
@ -54,6 +56,13 @@ func (srv *dataBrokerServer) setKey(cfg *config.Config) {
// Databroker functions
func (srv *dataBrokerServer) AcquireLease(ctx context.Context, req *databrokerpb.AcquireLeaseRequest) (*databrokerpb.AcquireLeaseResponse, error) {
if err := grpcutil.RequireSignedJWT(ctx, srv.sharedKey.Load().([]byte)); err != nil {
return nil, err
}
return srv.server.AcquireLease(ctx, req)
}
func (srv *dataBrokerServer) Get(ctx context.Context, req *databrokerpb.GetRequest) (*databrokerpb.GetResponse, error) {
if err := grpcutil.RequireSignedJWT(ctx, srv.sharedKey.Load().([]byte)); err != nil {
return nil, err
@ -75,6 +84,20 @@ func (srv *dataBrokerServer) Put(ctx context.Context, req *databrokerpb.PutReque
return srv.server.Put(ctx, req)
}
func (srv *dataBrokerServer) ReleaseLease(ctx context.Context, req *databrokerpb.ReleaseLeaseRequest) (*emptypb.Empty, error) {
if err := grpcutil.RequireSignedJWT(ctx, srv.sharedKey.Load().([]byte)); err != nil {
return nil, err
}
return srv.server.ReleaseLease(ctx, req)
}
func (srv *dataBrokerServer) RenewLease(ctx context.Context, req *databrokerpb.RenewLeaseRequest) (*emptypb.Empty, error) {
if err := grpcutil.RequireSignedJWT(ctx, srv.sharedKey.Load().([]byte)); err != nil {
return nil, err
}
return srv.server.RenewLease(ctx, req)
}
func (srv *dataBrokerServer) SetOptions(ctx context.Context, req *databrokerpb.SetOptionsRequest) (*databrokerpb.SetOptionsResponse, error) {
if err := grpcutil.RequireSignedJWT(ctx, srv.sharedKey.Load().([]byte)); err != nil {
return nil, err

View file

@ -10,8 +10,10 @@ import (
"sync"
"github.com/google/go-cmp/cmp"
"github.com/google/uuid"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
"github.com/pomerium/pomerium/config"
"github.com/pomerium/pomerium/internal/log"
@ -72,6 +74,34 @@ func (srv *Server) UpdateConfig(options ...ServerOption) {
}
}
// AcquireLease acquires a lease.
func (srv *Server) AcquireLease(ctx context.Context, req *databroker.AcquireLeaseRequest) (*databroker.AcquireLeaseResponse, error) {
_, span := trace.StartSpan(ctx, "databroker.grpc.AcquireLease")
defer span.End()
log.Info(ctx).
Str("peer", grpcutil.GetPeerAddr(ctx)).
Str("name", req.GetName()).
Dur("duration", req.GetDuration().AsDuration()).
Msg("acquire lease")
db, err := srv.getBackend()
if err != nil {
return nil, err
}
leaseID := uuid.NewString()
acquired, err := db.Lease(ctx, req.GetName(), leaseID, req.GetDuration().AsDuration())
if err != nil {
return nil, err
} else if !acquired {
return nil, status.Error(codes.AlreadyExists, "lease is already taken")
}
return &databroker.AcquireLeaseResponse{
Id: leaseID,
}, nil
}
// Get gets a record from the in-memory list.
func (srv *Server) Get(ctx context.Context, req *databroker.GetRequest) (*databroker.GetResponse, error) {
_, span := trace.StartSpan(ctx, "databroker.grpc.Get")
@ -169,6 +199,55 @@ func (srv *Server) Put(ctx context.Context, req *databroker.PutRequest) (*databr
}, nil
}
// ReleaseLease releases a lease.
func (srv *Server) ReleaseLease(ctx context.Context, req *databroker.ReleaseLeaseRequest) (*emptypb.Empty, error) {
_, span := trace.StartSpan(ctx, "databroker.grpc.ReleaseLease")
defer span.End()
log.Info(ctx).
Str("peer", grpcutil.GetPeerAddr(ctx)).
Str("name", req.GetName()).
Str("id", req.GetId()).
Msg("release lease")
db, err := srv.getBackend()
if err != nil {
return nil, err
}
_, err = db.Lease(ctx, req.GetName(), req.GetId(), -1)
if err != nil {
return nil, err
}
return new(emptypb.Empty), nil
}
// RenewLease releases a lease.
func (srv *Server) RenewLease(ctx context.Context, req *databroker.RenewLeaseRequest) (*emptypb.Empty, error) {
_, span := trace.StartSpan(ctx, "databroker.grpc.RenewLease")
defer span.End()
log.Info(ctx).
Str("peer", grpcutil.GetPeerAddr(ctx)).
Str("name", req.GetName()).
Str("id", req.GetId()).
Dur("duration", req.GetDuration().AsDuration()).
Msg("renew lease")
db, err := srv.getBackend()
if err != nil {
return nil, err
}
acquired, err := db.Lease(ctx, req.GetName(), req.GetId(), req.GetDuration().AsDuration())
if err != nil {
return nil, err
} else if !acquired {
return nil, status.Error(codes.AlreadyExists, "lease no longer held")
}
return new(emptypb.Empty), nil
}
// SetOptions sets options for a type in the databroker.
func (srv *Server) SetOptions(ctx context.Context, req *databroker.SetOptionsRequest) (*databroker.SetOptionsResponse, error) {
_, span := trace.StartSpan(ctx, "databroker.grpc.SetOptions")

View file

@ -90,6 +90,12 @@ func (mgr *Manager) UpdateConfig(options ...Option) {
// Run runs the manager. This method blocks until an error occurs or the given context is canceled.
func (mgr *Manager) Run(ctx context.Context) error {
leaser := databroker.NewLeaser("identity_manager", time.Second*30, mgr)
return leaser.Run(ctx)
}
// RunLeased runs the identity manager when a lease is acquired.
func (mgr *Manager) RunLeased(ctx context.Context) error {
ctx = withLog(ctx)
update := make(chan updateRecordsMessage, 1)
clear := make(chan struct{}, 1)
@ -107,6 +113,11 @@ func (mgr *Manager) Run(ctx context.Context) error {
return eg.Wait()
}
// GetDataBrokerServiceClient gets the databroker client.
func (mgr *Manager) GetDataBrokerServiceClient() databroker.DataBrokerServiceClient {
return mgr.cfg.Load().dataBrokerClient
}
func (mgr *Manager) refreshLoop(ctx context.Context, update <-chan updateRecordsMessage, clear <-chan struct{}) error {
// wait for initial sync
select {

View file

@ -7,6 +7,9 @@ import (
"io"
)
//go:generate go run github.com/golang/mock/mockgen -source=databroker.pb.go -destination ./mock_databroker/databroker.pb.go DataBrokerServiceClient
//go:generate go run github.com/golang/mock/mockgen -source=leaser.go -destination ./mock_databroker/leaser.go LeaserHandler
// ApplyOffsetAndLimit applies the offset and limit to the list of records.
func ApplyOffsetAndLimit(all []*Record, offset, limit int) (records []*Record, totalCount int) {
records = all

View file

@ -14,6 +14,8 @@ import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
anypb "google.golang.org/protobuf/types/known/anypb"
durationpb "google.golang.org/protobuf/types/known/durationpb"
emptypb "google.golang.org/protobuf/types/known/emptypb"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
@ -880,129 +882,392 @@ func (*SyncLatestResponse_Record) isSyncLatestResponse_Response() {}
func (*SyncLatestResponse_Versions) isSyncLatestResponse_Response() {}
type AcquireLeaseRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Name is the name of the lease. Only a single client can hold the lease on
// the specified name at any one time.
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
// Duration is the duration of the lease. After the duration is reached the
// lease can be acquired by other clients.
Duration *durationpb.Duration `protobuf:"bytes,2,opt,name=duration,proto3" json:"duration,omitempty"`
}
func (x *AcquireLeaseRequest) Reset() {
*x = AcquireLeaseRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_databroker_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *AcquireLeaseRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AcquireLeaseRequest) ProtoMessage() {}
func (x *AcquireLeaseRequest) ProtoReflect() protoreflect.Message {
mi := &file_databroker_proto_msgTypes[15]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AcquireLeaseRequest.ProtoReflect.Descriptor instead.
func (*AcquireLeaseRequest) Descriptor() ([]byte, []int) {
return file_databroker_proto_rawDescGZIP(), []int{15}
}
func (x *AcquireLeaseRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *AcquireLeaseRequest) GetDuration() *durationpb.Duration {
if x != nil {
return x.Duration
}
return nil
}
type AcquireLeaseResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Id is the id of the acquired lease. Subsequent calls to release or renew
// will need both the lease name and the lease id.
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
}
func (x *AcquireLeaseResponse) Reset() {
*x = AcquireLeaseResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_databroker_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *AcquireLeaseResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AcquireLeaseResponse) ProtoMessage() {}
func (x *AcquireLeaseResponse) ProtoReflect() protoreflect.Message {
mi := &file_databroker_proto_msgTypes[16]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AcquireLeaseResponse.ProtoReflect.Descriptor instead.
func (*AcquireLeaseResponse) Descriptor() ([]byte, []int) {
return file_databroker_proto_rawDescGZIP(), []int{16}
}
func (x *AcquireLeaseResponse) GetId() string {
if x != nil {
return x.Id
}
return ""
}
type ReleaseLeaseRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
}
func (x *ReleaseLeaseRequest) Reset() {
*x = ReleaseLeaseRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_databroker_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ReleaseLeaseRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ReleaseLeaseRequest) ProtoMessage() {}
func (x *ReleaseLeaseRequest) ProtoReflect() protoreflect.Message {
mi := &file_databroker_proto_msgTypes[17]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ReleaseLeaseRequest.ProtoReflect.Descriptor instead.
func (*ReleaseLeaseRequest) Descriptor() ([]byte, []int) {
return file_databroker_proto_rawDescGZIP(), []int{17}
}
func (x *ReleaseLeaseRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *ReleaseLeaseRequest) GetId() string {
if x != nil {
return x.Id
}
return ""
}
type RenewLeaseRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
Duration *durationpb.Duration `protobuf:"bytes,3,opt,name=duration,proto3" json:"duration,omitempty"`
}
func (x *RenewLeaseRequest) Reset() {
*x = RenewLeaseRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_databroker_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RenewLeaseRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RenewLeaseRequest) ProtoMessage() {}
func (x *RenewLeaseRequest) ProtoReflect() protoreflect.Message {
mi := &file_databroker_proto_msgTypes[18]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RenewLeaseRequest.ProtoReflect.Descriptor instead.
func (*RenewLeaseRequest) Descriptor() ([]byte, []int) {
return file_databroker_proto_rawDescGZIP(), []int{18}
}
func (x *RenewLeaseRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *RenewLeaseRequest) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *RenewLeaseRequest) GetDuration() *durationpb.Duration {
if x != nil {
return x.Duration
}
return nil
}
var File_databroker_proto protoreflect.FileDescriptor
var file_databroker_proto_rawDesc = []byte{
0x0a, 0x10, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x12, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x1a, 0x19,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f,
0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73,
0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe8, 0x01, 0x0a, 0x06, 0x52,
0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12,
0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74,
0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
0x02, 0x69, 0x64, 0x12, 0x28, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x3b, 0x0a,
0x0b, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a,
0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x64, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe8, 0x01, 0x0a, 0x06, 0x52, 0x65, 0x63, 0x6f,
0x72, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20,
0x01, 0x28, 0x04, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04,
0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
0x12, 0x28, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x65,
0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x65, 0x0a, 0x08, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x73, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65,
0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x74, 0x65,
0x73, 0x74, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x52,
0x65, 0x63, 0x6f, 0x72, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x37, 0x0a, 0x07,
0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63,
0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x08, 0x63, 0x61, 0x70,
0x61, 0x63, 0x69, 0x74, 0x79, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x63, 0x61, 0x70,
0x61, 0x63, 0x69, 0x74, 0x79, 0x22, 0x30, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x39, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f,
0x6b, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x06, 0x72, 0x65, 0x63, 0x6f,
0x72, 0x64, 0x22, 0x66, 0x0a, 0x0c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x16, 0x0a, 0x06,
0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6f, 0x66,
0x66, 0x73, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x04, 0x20,
0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x5e, 0x0a, 0x0d, 0x51, 0x75,
0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x07, 0x72,
0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64,
0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64,
0x52, 0x07, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74,
0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a,
0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x38, 0x0a, 0x0a, 0x50, 0x75,
0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x63, 0x6f,
0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62,
0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x06, 0x72, 0x65,
0x63, 0x6f, 0x72, 0x64, 0x22, 0x60, 0x0a, 0x0b, 0x50, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x76, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x73, 0x65, 0x72,
0x76, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65,
0x63, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x61, 0x74,
0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x06,
0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x22, 0x56, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74,
0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12,
0x2d, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x13, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x4f, 0x70,
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x43,
0x0a, 0x12, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b,
0x65, 0x72, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x73, 0x22, 0x5b, 0x0a, 0x0b, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x76, 0x65, 0x72,
0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x63,
0x6f, 0x72, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
0x04, 0x52, 0x0d, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x22, 0x3a, 0x0a, 0x0c, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x12, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x52, 0x65,
0x63, 0x6f, 0x72, 0x64, 0x52, 0x06, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x22, 0x27, 0x0a, 0x11,
0x53, 0x79, 0x6e, 0x63, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x82, 0x01, 0x0a, 0x12, 0x53, 0x79, 0x6e, 0x63, 0x4c, 0x61,
0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x06,
0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64,
0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64,
0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x32, 0x0a, 0x08, 0x76, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x64,
0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x73, 0x48, 0x00, 0x52, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x0a,
0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x9a, 0x03, 0x0a, 0x11, 0x44,
0x61, 0x74, 0x61, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x12, 0x36, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x16, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72,
0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x17, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x03, 0x50, 0x75, 0x74, 0x12,
0x16, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x74,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72,
0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x3c, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x18, 0x2e, 0x64, 0x61, 0x74, 0x61,
0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72,
0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b,
0x0a, 0x0a, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x64,
0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x64, 0x61,
0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x53,
0x79, 0x6e, 0x63, 0x12, 0x17, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72,
0x2e, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x64,
0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x0a, 0x53, 0x79, 0x6e, 0x63,
0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f,
0x6b, 0x65, 0x72, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b,
0x65, 0x72, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x70,
0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63,
0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
0x2e, 0x41, 0x6e, 0x79, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x3b, 0x0a, 0x0b, 0x6d, 0x6f,
0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x6d, 0x6f, 0x64,
0x69, 0x66, 0x69, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x64, 0x65, 0x6c, 0x65, 0x74,
0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69,
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64,
0x41, 0x74, 0x22, 0x65, 0x0a, 0x08, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25,
0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f,
0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02,
0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x63, 0x6f,
0x72, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x37, 0x0a, 0x07, 0x4f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79,
0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69,
0x74, 0x79, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69,
0x74, 0x79, 0x22, 0x30, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x74, 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x02, 0x69, 0x64, 0x22, 0x39, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72,
0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x06, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x22,
0x66, 0x0a, 0x0c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74,
0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66,
0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65,
0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x5e, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x07, 0x72, 0x65, 0x63, 0x6f,
0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x61, 0x74, 0x61,
0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x72,
0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74,
0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x38, 0x0a, 0x0a, 0x50, 0x75, 0x74, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b,
0x65, 0x72, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x06, 0x72, 0x65, 0x63, 0x6f, 0x72,
0x64, 0x22, 0x60, 0x0a, 0x0b, 0x50, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69,
0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x06, 0x72, 0x65, 0x63, 0x6f, 0x72,
0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72,
0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x06, 0x72, 0x65, 0x63,
0x6f, 0x72, 0x64, 0x22, 0x56, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2d, 0x0a, 0x07,
0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e,
0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f,
0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x43, 0x0a, 0x12, 0x53,
0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x2d, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x13, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e,
0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x22, 0x5b, 0x0a, 0x0b, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x25, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64,
0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d,
0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a,
0x0c, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a,
0x06, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e,
0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72,
0x64, 0x52, 0x06, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x22, 0x27, 0x0a, 0x11, 0x53, 0x79, 0x6e,
0x63, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12,
0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79,
0x70, 0x65, 0x22, 0x82, 0x01, 0x0a, 0x12, 0x53, 0x79, 0x6e, 0x63, 0x4c, 0x61, 0x74, 0x65, 0x73,
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x72, 0x65, 0x63,
0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x61, 0x74, 0x61,
0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x48, 0x00, 0x52,
0x06, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x32, 0x0a, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69,
0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x64, 0x61, 0x74, 0x61,
0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x48,
0x00, 0x52, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x0a, 0x0a, 0x08, 0x72,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x60, 0x0a, 0x13, 0x41, 0x63, 0x71, 0x75, 0x69,
0x72, 0x65, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12,
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x26, 0x0a, 0x14, 0x41, 0x63, 0x71,
0x75, 0x69, 0x72, 0x65, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
0x64, 0x22, 0x39, 0x0a, 0x13, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4c, 0x65, 0x61, 0x73,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02,
0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x6e, 0x0a, 0x11,
0x52, 0x65, 0x6e, 0x65, 0x77, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x35, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xfb, 0x04, 0x0a,
0x11, 0x44, 0x61, 0x74, 0x61, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x12, 0x51, 0x0a, 0x0c, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4c, 0x65, 0x61,
0x73, 0x65, 0x12, 0x1f, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e,
0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72,
0x2e, 0x41, 0x63, 0x71, 0x75, 0x69, 0x72, 0x65, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x16, 0x2e, 0x64,
0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65,
0x72, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a,
0x03, 0x50, 0x75, 0x74, 0x12, 0x16, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65,
0x72, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x64,
0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x18,
0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x51, 0x75, 0x65, 0x72,
0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62,
0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4c, 0x65,
0x61, 0x73, 0x65, 0x12, 0x1f, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72,
0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x0a,
0x52, 0x65, 0x6e, 0x65, 0x77, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x1d, 0x2e, 0x64, 0x61, 0x74,
0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x6e, 0x65, 0x77, 0x4c, 0x65, 0x61,
0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
0x79, 0x12, 0x4b, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12,
0x1d, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x74,
0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e,
0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x74, 0x4f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b,
0x0a, 0x04, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x17, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f,
0x6b, 0x65, 0x72, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x18, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x53, 0x79, 0x6e,
0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x0a, 0x53,
0x79, 0x6e, 0x63, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x2e, 0x64, 0x61, 0x74, 0x61,
0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x4c, 0x61, 0x74, 0x65, 0x73,
0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62,
0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69,
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75,
0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67,
0x72, 0x70, 0x63, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -1017,7 +1282,7 @@ func file_databroker_proto_rawDescGZIP() []byte {
return file_databroker_proto_rawDescData
}
var file_databroker_proto_msgTypes = make([]protoimpl.MessageInfo, 15)
var file_databroker_proto_msgTypes = make([]protoimpl.MessageInfo, 19)
var file_databroker_proto_goTypes = []interface{}{
(*Record)(nil), // 0: databroker.Record
(*Versions)(nil), // 1: databroker.Versions
@ -1034,13 +1299,19 @@ var file_databroker_proto_goTypes = []interface{}{
(*SyncResponse)(nil), // 12: databroker.SyncResponse
(*SyncLatestRequest)(nil), // 13: databroker.SyncLatestRequest
(*SyncLatestResponse)(nil), // 14: databroker.SyncLatestResponse
(*anypb.Any)(nil), // 15: google.protobuf.Any
(*timestamppb.Timestamp)(nil), // 16: google.protobuf.Timestamp
(*AcquireLeaseRequest)(nil), // 15: databroker.AcquireLeaseRequest
(*AcquireLeaseResponse)(nil), // 16: databroker.AcquireLeaseResponse
(*ReleaseLeaseRequest)(nil), // 17: databroker.ReleaseLeaseRequest
(*RenewLeaseRequest)(nil), // 18: databroker.RenewLeaseRequest
(*anypb.Any)(nil), // 19: google.protobuf.Any
(*timestamppb.Timestamp)(nil), // 20: google.protobuf.Timestamp
(*durationpb.Duration)(nil), // 21: google.protobuf.Duration
(*emptypb.Empty)(nil), // 22: google.protobuf.Empty
}
var file_databroker_proto_depIdxs = []int32{
15, // 0: databroker.Record.data:type_name -> google.protobuf.Any
16, // 1: databroker.Record.modified_at:type_name -> google.protobuf.Timestamp
16, // 2: databroker.Record.deleted_at:type_name -> google.protobuf.Timestamp
19, // 0: databroker.Record.data:type_name -> google.protobuf.Any
20, // 1: databroker.Record.modified_at:type_name -> google.protobuf.Timestamp
20, // 2: databroker.Record.deleted_at:type_name -> google.protobuf.Timestamp
0, // 3: databroker.GetResponse.record:type_name -> databroker.Record
0, // 4: databroker.QueryResponse.records:type_name -> databroker.Record
0, // 5: databroker.PutRequest.record:type_name -> databroker.Record
@ -1050,23 +1321,31 @@ var file_databroker_proto_depIdxs = []int32{
0, // 9: databroker.SyncResponse.record:type_name -> databroker.Record
0, // 10: databroker.SyncLatestResponse.record:type_name -> databroker.Record
1, // 11: databroker.SyncLatestResponse.versions:type_name -> databroker.Versions
3, // 12: databroker.DataBrokerService.Get:input_type -> databroker.GetRequest
7, // 13: databroker.DataBrokerService.Put:input_type -> databroker.PutRequest
5, // 14: databroker.DataBrokerService.Query:input_type -> databroker.QueryRequest
9, // 15: databroker.DataBrokerService.SetOptions:input_type -> databroker.SetOptionsRequest
11, // 16: databroker.DataBrokerService.Sync:input_type -> databroker.SyncRequest
13, // 17: databroker.DataBrokerService.SyncLatest:input_type -> databroker.SyncLatestRequest
4, // 18: databroker.DataBrokerService.Get:output_type -> databroker.GetResponse
8, // 19: databroker.DataBrokerService.Put:output_type -> databroker.PutResponse
6, // 20: databroker.DataBrokerService.Query:output_type -> databroker.QueryResponse
10, // 21: databroker.DataBrokerService.SetOptions:output_type -> databroker.SetOptionsResponse
12, // 22: databroker.DataBrokerService.Sync:output_type -> databroker.SyncResponse
14, // 23: databroker.DataBrokerService.SyncLatest:output_type -> databroker.SyncLatestResponse
18, // [18:24] is the sub-list for method output_type
12, // [12:18] is the sub-list for method input_type
12, // [12:12] is the sub-list for extension type_name
12, // [12:12] is the sub-list for extension extendee
0, // [0:12] is the sub-list for field type_name
21, // 12: databroker.AcquireLeaseRequest.duration:type_name -> google.protobuf.Duration
21, // 13: databroker.RenewLeaseRequest.duration:type_name -> google.protobuf.Duration
15, // 14: databroker.DataBrokerService.AcquireLease:input_type -> databroker.AcquireLeaseRequest
3, // 15: databroker.DataBrokerService.Get:input_type -> databroker.GetRequest
7, // 16: databroker.DataBrokerService.Put:input_type -> databroker.PutRequest
5, // 17: databroker.DataBrokerService.Query:input_type -> databroker.QueryRequest
17, // 18: databroker.DataBrokerService.ReleaseLease:input_type -> databroker.ReleaseLeaseRequest
18, // 19: databroker.DataBrokerService.RenewLease:input_type -> databroker.RenewLeaseRequest
9, // 20: databroker.DataBrokerService.SetOptions:input_type -> databroker.SetOptionsRequest
11, // 21: databroker.DataBrokerService.Sync:input_type -> databroker.SyncRequest
13, // 22: databroker.DataBrokerService.SyncLatest:input_type -> databroker.SyncLatestRequest
16, // 23: databroker.DataBrokerService.AcquireLease:output_type -> databroker.AcquireLeaseResponse
4, // 24: databroker.DataBrokerService.Get:output_type -> databroker.GetResponse
8, // 25: databroker.DataBrokerService.Put:output_type -> databroker.PutResponse
6, // 26: databroker.DataBrokerService.Query:output_type -> databroker.QueryResponse
22, // 27: databroker.DataBrokerService.ReleaseLease:output_type -> google.protobuf.Empty
22, // 28: databroker.DataBrokerService.RenewLease:output_type -> google.protobuf.Empty
10, // 29: databroker.DataBrokerService.SetOptions:output_type -> databroker.SetOptionsResponse
12, // 30: databroker.DataBrokerService.Sync:output_type -> databroker.SyncResponse
14, // 31: databroker.DataBrokerService.SyncLatest:output_type -> databroker.SyncLatestResponse
23, // [23:32] is the sub-list for method output_type
14, // [14:23] is the sub-list for method input_type
14, // [14:14] is the sub-list for extension type_name
14, // [14:14] is the sub-list for extension extendee
0, // [0:14] is the sub-list for field type_name
}
func init() { file_databroker_proto_init() }
@ -1255,6 +1534,54 @@ func file_databroker_proto_init() {
return nil
}
}
file_databroker_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AcquireLeaseRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_databroker_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AcquireLeaseResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_databroker_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReleaseLeaseRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_databroker_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RenewLeaseRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_databroker_proto_msgTypes[2].OneofWrappers = []interface{}{}
file_databroker_proto_msgTypes[14].OneofWrappers = []interface{}{
@ -1267,7 +1594,7 @@ func file_databroker_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_databroker_proto_rawDesc,
NumEnums: 0,
NumMessages: 15,
NumMessages: 19,
NumExtensions: 0,
NumServices: 1,
},
@ -1293,12 +1620,18 @@ const _ = grpc.SupportPackageIsVersion6
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type DataBrokerServiceClient interface {
// AcquireLease acquires a distributed mutex lease.
AcquireLease(ctx context.Context, in *AcquireLeaseRequest, opts ...grpc.CallOption) (*AcquireLeaseResponse, error)
// Get gets a record.
Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error)
// Put saves a record.
Put(ctx context.Context, in *PutRequest, opts ...grpc.CallOption) (*PutResponse, error)
// Query queries for records.
Query(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error)
// ReleaseLease releases a distributed mutex lease.
ReleaseLease(ctx context.Context, in *ReleaseLeaseRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
// RenewLease renews a distributed mutex lease.
RenewLease(ctx context.Context, in *RenewLeaseRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
// SetOptions sets the options for a type in the databroker.
SetOptions(ctx context.Context, in *SetOptionsRequest, opts ...grpc.CallOption) (*SetOptionsResponse, error)
// Sync streams changes to records after the specified version.
@ -1315,6 +1648,15 @@ func NewDataBrokerServiceClient(cc grpc.ClientConnInterface) DataBrokerServiceCl
return &dataBrokerServiceClient{cc}
}
func (c *dataBrokerServiceClient) AcquireLease(ctx context.Context, in *AcquireLeaseRequest, opts ...grpc.CallOption) (*AcquireLeaseResponse, error) {
out := new(AcquireLeaseResponse)
err := c.cc.Invoke(ctx, "/databroker.DataBrokerService/AcquireLease", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *dataBrokerServiceClient) Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) {
out := new(GetResponse)
err := c.cc.Invoke(ctx, "/databroker.DataBrokerService/Get", in, out, opts...)
@ -1342,6 +1684,24 @@ func (c *dataBrokerServiceClient) Query(ctx context.Context, in *QueryRequest, o
return out, nil
}
func (c *dataBrokerServiceClient) ReleaseLease(ctx context.Context, in *ReleaseLeaseRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, "/databroker.DataBrokerService/ReleaseLease", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *dataBrokerServiceClient) RenewLease(ctx context.Context, in *RenewLeaseRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, "/databroker.DataBrokerService/RenewLease", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *dataBrokerServiceClient) SetOptions(ctx context.Context, in *SetOptionsRequest, opts ...grpc.CallOption) (*SetOptionsResponse, error) {
out := new(SetOptionsResponse)
err := c.cc.Invoke(ctx, "/databroker.DataBrokerService/SetOptions", in, out, opts...)
@ -1417,12 +1777,18 @@ func (x *dataBrokerServiceSyncLatestClient) Recv() (*SyncLatestResponse, error)
// DataBrokerServiceServer is the server API for DataBrokerService service.
type DataBrokerServiceServer interface {
// AcquireLease acquires a distributed mutex lease.
AcquireLease(context.Context, *AcquireLeaseRequest) (*AcquireLeaseResponse, error)
// Get gets a record.
Get(context.Context, *GetRequest) (*GetResponse, error)
// Put saves a record.
Put(context.Context, *PutRequest) (*PutResponse, error)
// Query queries for records.
Query(context.Context, *QueryRequest) (*QueryResponse, error)
// ReleaseLease releases a distributed mutex lease.
ReleaseLease(context.Context, *ReleaseLeaseRequest) (*emptypb.Empty, error)
// RenewLease renews a distributed mutex lease.
RenewLease(context.Context, *RenewLeaseRequest) (*emptypb.Empty, error)
// SetOptions sets the options for a type in the databroker.
SetOptions(context.Context, *SetOptionsRequest) (*SetOptionsResponse, error)
// Sync streams changes to records after the specified version.
@ -1435,6 +1801,9 @@ type DataBrokerServiceServer interface {
type UnimplementedDataBrokerServiceServer struct {
}
func (*UnimplementedDataBrokerServiceServer) AcquireLease(context.Context, *AcquireLeaseRequest) (*AcquireLeaseResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method AcquireLease not implemented")
}
func (*UnimplementedDataBrokerServiceServer) Get(context.Context, *GetRequest) (*GetResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Get not implemented")
}
@ -1444,6 +1813,12 @@ func (*UnimplementedDataBrokerServiceServer) Put(context.Context, *PutRequest) (
func (*UnimplementedDataBrokerServiceServer) Query(context.Context, *QueryRequest) (*QueryResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Query not implemented")
}
func (*UnimplementedDataBrokerServiceServer) ReleaseLease(context.Context, *ReleaseLeaseRequest) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method ReleaseLease not implemented")
}
func (*UnimplementedDataBrokerServiceServer) RenewLease(context.Context, *RenewLeaseRequest) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method RenewLease not implemented")
}
func (*UnimplementedDataBrokerServiceServer) SetOptions(context.Context, *SetOptionsRequest) (*SetOptionsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SetOptions not implemented")
}
@ -1458,6 +1833,24 @@ func RegisterDataBrokerServiceServer(s *grpc.Server, srv DataBrokerServiceServer
s.RegisterService(&_DataBrokerService_serviceDesc, srv)
}
func _DataBrokerService_AcquireLease_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AcquireLeaseRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DataBrokerServiceServer).AcquireLease(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/databroker.DataBrokerService/AcquireLease",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DataBrokerServiceServer).AcquireLease(ctx, req.(*AcquireLeaseRequest))
}
return interceptor(ctx, in, info, handler)
}
func _DataBrokerService_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetRequest)
if err := dec(in); err != nil {
@ -1512,6 +1905,42 @@ func _DataBrokerService_Query_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
func _DataBrokerService_ReleaseLease_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ReleaseLeaseRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DataBrokerServiceServer).ReleaseLease(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/databroker.DataBrokerService/ReleaseLease",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DataBrokerServiceServer).ReleaseLease(ctx, req.(*ReleaseLeaseRequest))
}
return interceptor(ctx, in, info, handler)
}
func _DataBrokerService_RenewLease_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RenewLeaseRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DataBrokerServiceServer).RenewLease(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/databroker.DataBrokerService/RenewLease",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DataBrokerServiceServer).RenewLease(ctx, req.(*RenewLeaseRequest))
}
return interceptor(ctx, in, info, handler)
}
func _DataBrokerService_SetOptions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SetOptionsRequest)
if err := dec(in); err != nil {
@ -1576,6 +2005,10 @@ var _DataBrokerService_serviceDesc = grpc.ServiceDesc{
ServiceName: "databroker.DataBrokerService",
HandlerType: (*DataBrokerServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "AcquireLease",
Handler: _DataBrokerService_AcquireLease_Handler,
},
{
MethodName: "Get",
Handler: _DataBrokerService_Get_Handler,
@ -1588,6 +2021,14 @@ var _DataBrokerService_serviceDesc = grpc.ServiceDesc{
MethodName: "Query",
Handler: _DataBrokerService_Query_Handler,
},
{
MethodName: "ReleaseLease",
Handler: _DataBrokerService_ReleaseLease_Handler,
},
{
MethodName: "RenewLease",
Handler: _DataBrokerService_RenewLease_Handler,
},
{
MethodName: "SetOptions",
Handler: _DataBrokerService_SetOptions_Handler,

View file

@ -4,6 +4,8 @@ package databroker;
option go_package = "github.com/pomerium/pomerium/pkg/grpc/databroker";
import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
message Record {
@ -31,9 +33,7 @@ message GetRequest {
string type = 1;
string id = 2;
}
message GetResponse {
Record record = 1;
}
message GetResponse { Record record = 1; }
message QueryRequest {
string type = 1;
@ -56,17 +56,13 @@ message SetOptionsRequest {
string type = 1;
Options options = 2;
}
message SetOptionsResponse {
Options options = 1;
}
message SetOptionsResponse { Options options = 1; }
message SyncRequest {
uint64 server_version = 1;
uint64 record_version = 2;
}
message SyncResponse {
Record record = 1;
}
message SyncResponse { Record record = 1; }
message SyncLatestRequest { string type = 1; }
message SyncLatestResponse {
@ -76,14 +72,43 @@ message SyncLatestResponse {
}
}
message AcquireLeaseRequest {
// Name is the name of the lease. Only a single client can hold the lease on
// the specified name at any one time.
string name = 1;
// Duration is the duration of the lease. After the duration is reached the
// lease can be acquired by other clients.
google.protobuf.Duration duration = 2;
}
message AcquireLeaseResponse {
// Id is the id of the acquired lease. Subsequent calls to release or renew
// will need both the lease name and the lease id.
string id = 1;
}
message ReleaseLeaseRequest {
string name = 1;
string id = 2;
}
message RenewLeaseRequest {
string name = 1;
string id = 2;
google.protobuf.Duration duration = 3;
}
// The DataBrokerService stores key-value data.
service DataBrokerService {
// AcquireLease acquires a distributed mutex lease.
rpc AcquireLease(AcquireLeaseRequest) returns (AcquireLeaseResponse);
// Get gets a record.
rpc Get(GetRequest) returns (GetResponse);
// Put saves a record.
rpc Put(PutRequest) returns (PutResponse);
// Query queries for records.
rpc Query(QueryRequest) returns (QueryResponse);
// ReleaseLease releases a distributed mutex lease.
rpc ReleaseLease(ReleaseLeaseRequest) returns (google.protobuf.Empty);
// RenewLease renews a distributed mutex lease.
rpc RenewLease(RenewLeaseRequest) returns (google.protobuf.Empty);
// SetOptions sets the options for a type in the databroker.
rpc SetOptions(SetOptionsRequest) returns (SetOptionsResponse);
// Sync streams changes to records after the specified version.

View file

@ -0,0 +1,159 @@
package databroker
import (
"context"
"errors"
"time"
"github.com/cenkalti/backoff/v4"
"golang.org/x/sync/errgroup"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/durationpb"
"github.com/pomerium/pomerium/internal/log"
)
// a retryableError is one we'll retry later
type retryableError struct {
error
}
func (err retryableError) Is(target error) bool {
if _, ok := target.(retryableError); ok {
return true
}
return false
}
// A LeaserHandler is a handler for the locker.
type LeaserHandler interface {
GetDataBrokerServiceClient() DataBrokerServiceClient
RunLeased(ctx context.Context) error
}
// A Leaser attempts to acquire a lease and if successful runs the handler. If the lease
// is released the context used for the handler will be canceled and a new lease
// acquisition will be attempted.
type Leaser struct {
handler LeaserHandler
leaseName string
ttl time.Duration
}
// NewLeaser creates a new Leaser.
func NewLeaser(leaseName string, ttl time.Duration, handler LeaserHandler) *Leaser {
return &Leaser{
leaseName: leaseName,
ttl: ttl,
handler: handler,
}
}
// Run acquires the lease and runs the handler. This continues until either:
//
// 1. ctx is canceled
// 2. a non-cancel error is returned from handler
//
func (locker *Leaser) Run(ctx context.Context) error {
retryTicker := time.NewTicker(locker.ttl / 2)
defer retryTicker.Stop()
bo := backoff.NewExponentialBackOff()
bo.MaxElapsedTime = 0
for {
err := locker.runOnce(ctx, bo.Reset)
switch {
case err == nil:
select {
case <-ctx.Done():
return ctx.Err()
case <-retryTicker.C:
}
case errors.Is(err, retryableError{}):
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(bo.NextBackOff()):
}
default:
return err
}
}
}
func (locker *Leaser) runOnce(ctx context.Context, resetBackoff func()) error {
res, err := locker.handler.GetDataBrokerServiceClient().AcquireLease(ctx, &AcquireLeaseRequest{
Name: locker.leaseName,
Duration: durationpb.New(locker.ttl),
})
// if the lease already exists, retry later
if status.Code(err) == codes.AlreadyExists {
return nil
} else if err != nil {
log.Warn(ctx).Err(err).Msg("leaser: error acquiring lease")
return retryableError{err}
}
resetBackoff()
leaseID := res.Id
log.Info(ctx).
Str("lease_name", locker.leaseName).
Str("lease_id", leaseID).
Msg("leaser: lease acquired")
return locker.withLease(ctx, leaseID)
}
func (locker *Leaser) withLease(ctx context.Context, leaseID string) error {
// always release the lock in case the parent context is canceled
defer func() {
_, _ = locker.handler.GetDataBrokerServiceClient().ReleaseLease(context.Background(), &ReleaseLeaseRequest{
Name: locker.leaseName,
Id: leaseID,
})
}()
renewTicker := time.NewTicker(locker.ttl / 2)
defer renewTicker.Stop()
// if renewal fails, cancel the handler
runCtx, runCancel := context.WithCancel(ctx)
eg, egCtx := errgroup.WithContext(runCtx)
eg.Go(func() error {
defer runCancel()
for {
select {
case <-egCtx.Done():
return egCtx.Err()
case <-renewTicker.C:
}
_, err := locker.handler.GetDataBrokerServiceClient().RenewLease(ctx, &RenewLeaseRequest{
Name: locker.leaseName,
Id: leaseID,
Duration: durationpb.New(locker.ttl),
})
if status.Code(err) == codes.AlreadyExists {
log.Info(ctx).
Str("lease_name", locker.leaseName).
Str("lease_id", leaseID).
Msg("leaser: lease lost")
// failed to renew lease
return nil
} else if err != nil {
log.Warn(ctx).Err(err).Msg("leaser: error renewing lease")
return retryableError{err}
}
}
})
eg.Go(func() error {
return locker.handler.RunLeased(egCtx)
})
err := eg.Wait()
if errors.Is(err, context.Canceled) {
err = nil
}
return err
}

View file

@ -0,0 +1,138 @@
package databroker_test
import (
"context"
"errors"
"testing"
"time"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/durationpb"
"github.com/pomerium/pomerium/pkg/grpc/databroker"
"github.com/pomerium/pomerium/pkg/grpc/databroker/mock_databroker"
)
func TestLeaser(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
exitErr := errors.New("EXIT")
t.Run("acquires lease", func(t *testing.T) {
client := mock_databroker.NewMockDataBrokerServiceClient(ctrl)
client.EXPECT().
AcquireLease(gomock.Any(), &databroker.AcquireLeaseRequest{
Name: "TEST",
Duration: durationpb.New(time.Second * 30),
}).
Return(&databroker.AcquireLeaseResponse{
Id: "lease1",
}, nil).
Times(1)
client.EXPECT().
ReleaseLease(gomock.Any(), &databroker.ReleaseLeaseRequest{
Name: "TEST",
Id: "lease1",
}).
Times(1)
handler := mock_databroker.NewMockLeaserHandler(ctrl)
handler.EXPECT().
GetDataBrokerServiceClient().
Return(client).
AnyTimes()
handler.EXPECT().
RunLeased(gomock.Any()).
Return(exitErr).
Times(1)
leaser := databroker.NewLeaser("TEST", time.Second*30, handler)
err := leaser.Run(context.Background())
assert.Equal(t, exitErr, err)
})
t.Run("retries acquire", func(t *testing.T) {
client := mock_databroker.NewMockDataBrokerServiceClient(ctrl)
client.EXPECT().
AcquireLease(gomock.Any(), &databroker.AcquireLeaseRequest{
Name: "TEST",
Duration: durationpb.New(time.Second * 30),
}).
Return(nil, status.Error(codes.Unavailable, "UNAVAILABLE")).
Times(2)
client.EXPECT().
AcquireLease(gomock.Any(), &databroker.AcquireLeaseRequest{
Name: "TEST",
Duration: durationpb.New(time.Second * 30),
}).
Return(&databroker.AcquireLeaseResponse{
Id: "lease1",
}, nil).
Times(1)
client.EXPECT().
ReleaseLease(gomock.Any(), &databroker.ReleaseLeaseRequest{
Name: "TEST",
Id: "lease1",
}).
Times(1)
handler := mock_databroker.NewMockLeaserHandler(ctrl)
handler.EXPECT().
GetDataBrokerServiceClient().
Return(client).
AnyTimes()
handler.EXPECT().
RunLeased(gomock.Any()).
Return(exitErr).
Times(1)
leaser := databroker.NewLeaser("TEST", time.Second*30, handler)
err := leaser.Run(context.Background())
assert.Equal(t, exitErr, err)
})
t.Run("renews", func(t *testing.T) {
client := mock_databroker.NewMockDataBrokerServiceClient(ctrl)
client.EXPECT().
AcquireLease(gomock.Any(), &databroker.AcquireLeaseRequest{
Name: "TEST",
Duration: durationpb.New(time.Millisecond),
}).
Return(&databroker.AcquireLeaseResponse{
Id: "lease1",
}, nil).
Times(1)
client.EXPECT().
RenewLease(gomock.Any(), &databroker.RenewLeaseRequest{
Name: "TEST",
Id: "lease1",
Duration: durationpb.New(time.Millisecond),
}).
MinTimes(1)
client.EXPECT().
ReleaseLease(gomock.Any(), &databroker.ReleaseLeaseRequest{
Name: "TEST",
Id: "lease1",
}).
Times(1)
handler := mock_databroker.NewMockLeaserHandler(ctrl)
handler.EXPECT().
GetDataBrokerServiceClient().
Return(client).
AnyTimes()
handler.EXPECT().
RunLeased(gomock.Any()).
DoAndReturn(func(ctx context.Context) error {
time.Sleep(time.Millisecond * 20)
return exitErr
}).
Times(1)
leaser := databroker.NewLeaser("TEST", time.Millisecond, handler)
err := leaser.Run(context.Background())
assert.Equal(t, exitErr, err)
})
}

View file

@ -0,0 +1,894 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: databroker.pb.go
// Package mock_databroker is a generated GoMock package.
package mock_databroker
import (
context "context"
reflect "reflect"
gomock "github.com/golang/mock/gomock"
databroker "github.com/pomerium/pomerium/pkg/grpc/databroker"
grpc "google.golang.org/grpc"
metadata "google.golang.org/grpc/metadata"
emptypb "google.golang.org/protobuf/types/known/emptypb"
)
// MockisSyncLatestResponse_Response is a mock of isSyncLatestResponse_Response interface.
type MockisSyncLatestResponse_Response struct {
ctrl *gomock.Controller
recorder *MockisSyncLatestResponse_ResponseMockRecorder
}
// MockisSyncLatestResponse_ResponseMockRecorder is the mock recorder for MockisSyncLatestResponse_Response.
type MockisSyncLatestResponse_ResponseMockRecorder struct {
mock *MockisSyncLatestResponse_Response
}
// NewMockisSyncLatestResponse_Response creates a new mock instance.
func NewMockisSyncLatestResponse_Response(ctrl *gomock.Controller) *MockisSyncLatestResponse_Response {
mock := &MockisSyncLatestResponse_Response{ctrl: ctrl}
mock.recorder = &MockisSyncLatestResponse_ResponseMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockisSyncLatestResponse_Response) EXPECT() *MockisSyncLatestResponse_ResponseMockRecorder {
return m.recorder
}
// isSyncLatestResponse_Response mocks base method.
func (m *MockisSyncLatestResponse_Response) isSyncLatestResponse_Response() {
m.ctrl.T.Helper()
m.ctrl.Call(m, "isSyncLatestResponse_Response")
}
// isSyncLatestResponse_Response indicates an expected call of isSyncLatestResponse_Response.
func (mr *MockisSyncLatestResponse_ResponseMockRecorder) isSyncLatestResponse_Response() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "isSyncLatestResponse_Response", reflect.TypeOf((*MockisSyncLatestResponse_Response)(nil).isSyncLatestResponse_Response))
}
// MockDataBrokerServiceClient is a mock of DataBrokerServiceClient interface.
type MockDataBrokerServiceClient struct {
ctrl *gomock.Controller
recorder *MockDataBrokerServiceClientMockRecorder
}
// MockDataBrokerServiceClientMockRecorder is the mock recorder for MockDataBrokerServiceClient.
type MockDataBrokerServiceClientMockRecorder struct {
mock *MockDataBrokerServiceClient
}
// NewMockDataBrokerServiceClient creates a new mock instance.
func NewMockDataBrokerServiceClient(ctrl *gomock.Controller) *MockDataBrokerServiceClient {
mock := &MockDataBrokerServiceClient{ctrl: ctrl}
mock.recorder = &MockDataBrokerServiceClientMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockDataBrokerServiceClient) EXPECT() *MockDataBrokerServiceClientMockRecorder {
return m.recorder
}
// AcquireLease mocks base method.
func (m *MockDataBrokerServiceClient) AcquireLease(ctx context.Context, in *databroker.AcquireLeaseRequest, opts ...grpc.CallOption) (*databroker.AcquireLeaseResponse, error) {
m.ctrl.T.Helper()
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "AcquireLease", varargs...)
ret0, _ := ret[0].(*databroker.AcquireLeaseResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AcquireLease indicates an expected call of AcquireLease.
func (mr *MockDataBrokerServiceClientMockRecorder) AcquireLease(ctx, in interface{}, opts ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AcquireLease", reflect.TypeOf((*MockDataBrokerServiceClient)(nil).AcquireLease), varargs...)
}
// Get mocks base method.
func (m *MockDataBrokerServiceClient) Get(ctx context.Context, in *databroker.GetRequest, opts ...grpc.CallOption) (*databroker.GetResponse, error) {
m.ctrl.T.Helper()
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Get", varargs...)
ret0, _ := ret[0].(*databroker.GetResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Get indicates an expected call of Get.
func (mr *MockDataBrokerServiceClientMockRecorder) Get(ctx, in interface{}, opts ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockDataBrokerServiceClient)(nil).Get), varargs...)
}
// Put mocks base method.
func (m *MockDataBrokerServiceClient) Put(ctx context.Context, in *databroker.PutRequest, opts ...grpc.CallOption) (*databroker.PutResponse, error) {
m.ctrl.T.Helper()
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Put", varargs...)
ret0, _ := ret[0].(*databroker.PutResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Put indicates an expected call of Put.
func (mr *MockDataBrokerServiceClientMockRecorder) Put(ctx, in interface{}, opts ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockDataBrokerServiceClient)(nil).Put), varargs...)
}
// Query mocks base method.
func (m *MockDataBrokerServiceClient) Query(ctx context.Context, in *databroker.QueryRequest, opts ...grpc.CallOption) (*databroker.QueryResponse, error) {
m.ctrl.T.Helper()
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Query", varargs...)
ret0, _ := ret[0].(*databroker.QueryResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Query indicates an expected call of Query.
func (mr *MockDataBrokerServiceClientMockRecorder) Query(ctx, in interface{}, opts ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Query", reflect.TypeOf((*MockDataBrokerServiceClient)(nil).Query), varargs...)
}
// ReleaseLease mocks base method.
func (m *MockDataBrokerServiceClient) ReleaseLease(ctx context.Context, in *databroker.ReleaseLeaseRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
m.ctrl.T.Helper()
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "ReleaseLease", varargs...)
ret0, _ := ret[0].(*emptypb.Empty)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ReleaseLease indicates an expected call of ReleaseLease.
func (mr *MockDataBrokerServiceClientMockRecorder) ReleaseLease(ctx, in interface{}, opts ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReleaseLease", reflect.TypeOf((*MockDataBrokerServiceClient)(nil).ReleaseLease), varargs...)
}
// RenewLease mocks base method.
func (m *MockDataBrokerServiceClient) RenewLease(ctx context.Context, in *databroker.RenewLeaseRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
m.ctrl.T.Helper()
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "RenewLease", varargs...)
ret0, _ := ret[0].(*emptypb.Empty)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// RenewLease indicates an expected call of RenewLease.
func (mr *MockDataBrokerServiceClientMockRecorder) RenewLease(ctx, in interface{}, opts ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RenewLease", reflect.TypeOf((*MockDataBrokerServiceClient)(nil).RenewLease), varargs...)
}
// SetOptions mocks base method.
func (m *MockDataBrokerServiceClient) SetOptions(ctx context.Context, in *databroker.SetOptionsRequest, opts ...grpc.CallOption) (*databroker.SetOptionsResponse, error) {
m.ctrl.T.Helper()
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "SetOptions", varargs...)
ret0, _ := ret[0].(*databroker.SetOptionsResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SetOptions indicates an expected call of SetOptions.
func (mr *MockDataBrokerServiceClientMockRecorder) SetOptions(ctx, in interface{}, opts ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetOptions", reflect.TypeOf((*MockDataBrokerServiceClient)(nil).SetOptions), varargs...)
}
// Sync mocks base method.
func (m *MockDataBrokerServiceClient) Sync(ctx context.Context, in *databroker.SyncRequest, opts ...grpc.CallOption) (databroker.DataBrokerService_SyncClient, error) {
m.ctrl.T.Helper()
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Sync", varargs...)
ret0, _ := ret[0].(databroker.DataBrokerService_SyncClient)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Sync indicates an expected call of Sync.
func (mr *MockDataBrokerServiceClientMockRecorder) Sync(ctx, in interface{}, opts ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sync", reflect.TypeOf((*MockDataBrokerServiceClient)(nil).Sync), varargs...)
}
// SyncLatest mocks base method.
func (m *MockDataBrokerServiceClient) SyncLatest(ctx context.Context, in *databroker.SyncLatestRequest, opts ...grpc.CallOption) (databroker.DataBrokerService_SyncLatestClient, error) {
m.ctrl.T.Helper()
varargs := []interface{}{ctx, in}
for _, a := range opts {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "SyncLatest", varargs...)
ret0, _ := ret[0].(databroker.DataBrokerService_SyncLatestClient)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SyncLatest indicates an expected call of SyncLatest.
func (mr *MockDataBrokerServiceClientMockRecorder) SyncLatest(ctx, in interface{}, opts ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{ctx, in}, opts...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncLatest", reflect.TypeOf((*MockDataBrokerServiceClient)(nil).SyncLatest), varargs...)
}
// MockDataBrokerService_SyncClient is a mock of DataBrokerService_SyncClient interface.
type MockDataBrokerService_SyncClient struct {
ctrl *gomock.Controller
recorder *MockDataBrokerService_SyncClientMockRecorder
}
// MockDataBrokerService_SyncClientMockRecorder is the mock recorder for MockDataBrokerService_SyncClient.
type MockDataBrokerService_SyncClientMockRecorder struct {
mock *MockDataBrokerService_SyncClient
}
// NewMockDataBrokerService_SyncClient creates a new mock instance.
func NewMockDataBrokerService_SyncClient(ctrl *gomock.Controller) *MockDataBrokerService_SyncClient {
mock := &MockDataBrokerService_SyncClient{ctrl: ctrl}
mock.recorder = &MockDataBrokerService_SyncClientMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockDataBrokerService_SyncClient) EXPECT() *MockDataBrokerService_SyncClientMockRecorder {
return m.recorder
}
// CloseSend mocks base method.
func (m *MockDataBrokerService_SyncClient) CloseSend() error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "CloseSend")
ret0, _ := ret[0].(error)
return ret0
}
// CloseSend indicates an expected call of CloseSend.
func (mr *MockDataBrokerService_SyncClientMockRecorder) CloseSend() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloseSend", reflect.TypeOf((*MockDataBrokerService_SyncClient)(nil).CloseSend))
}
// Context mocks base method.
func (m *MockDataBrokerService_SyncClient) Context() context.Context {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Context")
ret0, _ := ret[0].(context.Context)
return ret0
}
// Context indicates an expected call of Context.
func (mr *MockDataBrokerService_SyncClientMockRecorder) Context() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Context", reflect.TypeOf((*MockDataBrokerService_SyncClient)(nil).Context))
}
// Header mocks base method.
func (m *MockDataBrokerService_SyncClient) Header() (metadata.MD, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Header")
ret0, _ := ret[0].(metadata.MD)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Header indicates an expected call of Header.
func (mr *MockDataBrokerService_SyncClientMockRecorder) Header() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Header", reflect.TypeOf((*MockDataBrokerService_SyncClient)(nil).Header))
}
// Recv mocks base method.
func (m *MockDataBrokerService_SyncClient) Recv() (*databroker.SyncResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Recv")
ret0, _ := ret[0].(*databroker.SyncResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Recv indicates an expected call of Recv.
func (mr *MockDataBrokerService_SyncClientMockRecorder) Recv() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Recv", reflect.TypeOf((*MockDataBrokerService_SyncClient)(nil).Recv))
}
// RecvMsg mocks base method.
func (m_2 *MockDataBrokerService_SyncClient) RecvMsg(m interface{}) error {
m_2.ctrl.T.Helper()
ret := m_2.ctrl.Call(m_2, "RecvMsg", m)
ret0, _ := ret[0].(error)
return ret0
}
// RecvMsg indicates an expected call of RecvMsg.
func (mr *MockDataBrokerService_SyncClientMockRecorder) RecvMsg(m interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecvMsg", reflect.TypeOf((*MockDataBrokerService_SyncClient)(nil).RecvMsg), m)
}
// SendMsg mocks base method.
func (m_2 *MockDataBrokerService_SyncClient) SendMsg(m interface{}) error {
m_2.ctrl.T.Helper()
ret := m_2.ctrl.Call(m_2, "SendMsg", m)
ret0, _ := ret[0].(error)
return ret0
}
// SendMsg indicates an expected call of SendMsg.
func (mr *MockDataBrokerService_SyncClientMockRecorder) SendMsg(m interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMsg", reflect.TypeOf((*MockDataBrokerService_SyncClient)(nil).SendMsg), m)
}
// Trailer mocks base method.
func (m *MockDataBrokerService_SyncClient) Trailer() metadata.MD {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Trailer")
ret0, _ := ret[0].(metadata.MD)
return ret0
}
// Trailer indicates an expected call of Trailer.
func (mr *MockDataBrokerService_SyncClientMockRecorder) Trailer() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Trailer", reflect.TypeOf((*MockDataBrokerService_SyncClient)(nil).Trailer))
}
// MockDataBrokerService_SyncLatestClient is a mock of DataBrokerService_SyncLatestClient interface.
type MockDataBrokerService_SyncLatestClient struct {
ctrl *gomock.Controller
recorder *MockDataBrokerService_SyncLatestClientMockRecorder
}
// MockDataBrokerService_SyncLatestClientMockRecorder is the mock recorder for MockDataBrokerService_SyncLatestClient.
type MockDataBrokerService_SyncLatestClientMockRecorder struct {
mock *MockDataBrokerService_SyncLatestClient
}
// NewMockDataBrokerService_SyncLatestClient creates a new mock instance.
func NewMockDataBrokerService_SyncLatestClient(ctrl *gomock.Controller) *MockDataBrokerService_SyncLatestClient {
mock := &MockDataBrokerService_SyncLatestClient{ctrl: ctrl}
mock.recorder = &MockDataBrokerService_SyncLatestClientMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockDataBrokerService_SyncLatestClient) EXPECT() *MockDataBrokerService_SyncLatestClientMockRecorder {
return m.recorder
}
// CloseSend mocks base method.
func (m *MockDataBrokerService_SyncLatestClient) CloseSend() error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "CloseSend")
ret0, _ := ret[0].(error)
return ret0
}
// CloseSend indicates an expected call of CloseSend.
func (mr *MockDataBrokerService_SyncLatestClientMockRecorder) CloseSend() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloseSend", reflect.TypeOf((*MockDataBrokerService_SyncLatestClient)(nil).CloseSend))
}
// Context mocks base method.
func (m *MockDataBrokerService_SyncLatestClient) Context() context.Context {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Context")
ret0, _ := ret[0].(context.Context)
return ret0
}
// Context indicates an expected call of Context.
func (mr *MockDataBrokerService_SyncLatestClientMockRecorder) Context() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Context", reflect.TypeOf((*MockDataBrokerService_SyncLatestClient)(nil).Context))
}
// Header mocks base method.
func (m *MockDataBrokerService_SyncLatestClient) Header() (metadata.MD, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Header")
ret0, _ := ret[0].(metadata.MD)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Header indicates an expected call of Header.
func (mr *MockDataBrokerService_SyncLatestClientMockRecorder) Header() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Header", reflect.TypeOf((*MockDataBrokerService_SyncLatestClient)(nil).Header))
}
// Recv mocks base method.
func (m *MockDataBrokerService_SyncLatestClient) Recv() (*databroker.SyncLatestResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Recv")
ret0, _ := ret[0].(*databroker.SyncLatestResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Recv indicates an expected call of Recv.
func (mr *MockDataBrokerService_SyncLatestClientMockRecorder) Recv() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Recv", reflect.TypeOf((*MockDataBrokerService_SyncLatestClient)(nil).Recv))
}
// RecvMsg mocks base method.
func (m_2 *MockDataBrokerService_SyncLatestClient) RecvMsg(m interface{}) error {
m_2.ctrl.T.Helper()
ret := m_2.ctrl.Call(m_2, "RecvMsg", m)
ret0, _ := ret[0].(error)
return ret0
}
// RecvMsg indicates an expected call of RecvMsg.
func (mr *MockDataBrokerService_SyncLatestClientMockRecorder) RecvMsg(m interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecvMsg", reflect.TypeOf((*MockDataBrokerService_SyncLatestClient)(nil).RecvMsg), m)
}
// SendMsg mocks base method.
func (m_2 *MockDataBrokerService_SyncLatestClient) SendMsg(m interface{}) error {
m_2.ctrl.T.Helper()
ret := m_2.ctrl.Call(m_2, "SendMsg", m)
ret0, _ := ret[0].(error)
return ret0
}
// SendMsg indicates an expected call of SendMsg.
func (mr *MockDataBrokerService_SyncLatestClientMockRecorder) SendMsg(m interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMsg", reflect.TypeOf((*MockDataBrokerService_SyncLatestClient)(nil).SendMsg), m)
}
// Trailer mocks base method.
func (m *MockDataBrokerService_SyncLatestClient) Trailer() metadata.MD {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Trailer")
ret0, _ := ret[0].(metadata.MD)
return ret0
}
// Trailer indicates an expected call of Trailer.
func (mr *MockDataBrokerService_SyncLatestClientMockRecorder) Trailer() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Trailer", reflect.TypeOf((*MockDataBrokerService_SyncLatestClient)(nil).Trailer))
}
// MockDataBrokerServiceServer is a mock of DataBrokerServiceServer interface.
type MockDataBrokerServiceServer struct {
ctrl *gomock.Controller
recorder *MockDataBrokerServiceServerMockRecorder
}
// MockDataBrokerServiceServerMockRecorder is the mock recorder for MockDataBrokerServiceServer.
type MockDataBrokerServiceServerMockRecorder struct {
mock *MockDataBrokerServiceServer
}
// NewMockDataBrokerServiceServer creates a new mock instance.
func NewMockDataBrokerServiceServer(ctrl *gomock.Controller) *MockDataBrokerServiceServer {
mock := &MockDataBrokerServiceServer{ctrl: ctrl}
mock.recorder = &MockDataBrokerServiceServerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockDataBrokerServiceServer) EXPECT() *MockDataBrokerServiceServerMockRecorder {
return m.recorder
}
// AcquireLease mocks base method.
func (m *MockDataBrokerServiceServer) AcquireLease(arg0 context.Context, arg1 *databroker.AcquireLeaseRequest) (*databroker.AcquireLeaseResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AcquireLease", arg0, arg1)
ret0, _ := ret[0].(*databroker.AcquireLeaseResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AcquireLease indicates an expected call of AcquireLease.
func (mr *MockDataBrokerServiceServerMockRecorder) AcquireLease(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AcquireLease", reflect.TypeOf((*MockDataBrokerServiceServer)(nil).AcquireLease), arg0, arg1)
}
// Get mocks base method.
func (m *MockDataBrokerServiceServer) Get(arg0 context.Context, arg1 *databroker.GetRequest) (*databroker.GetResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Get", arg0, arg1)
ret0, _ := ret[0].(*databroker.GetResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Get indicates an expected call of Get.
func (mr *MockDataBrokerServiceServerMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockDataBrokerServiceServer)(nil).Get), arg0, arg1)
}
// Put mocks base method.
func (m *MockDataBrokerServiceServer) Put(arg0 context.Context, arg1 *databroker.PutRequest) (*databroker.PutResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Put", arg0, arg1)
ret0, _ := ret[0].(*databroker.PutResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Put indicates an expected call of Put.
func (mr *MockDataBrokerServiceServerMockRecorder) Put(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockDataBrokerServiceServer)(nil).Put), arg0, arg1)
}
// Query mocks base method.
func (m *MockDataBrokerServiceServer) Query(arg0 context.Context, arg1 *databroker.QueryRequest) (*databroker.QueryResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Query", arg0, arg1)
ret0, _ := ret[0].(*databroker.QueryResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Query indicates an expected call of Query.
func (mr *MockDataBrokerServiceServerMockRecorder) Query(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Query", reflect.TypeOf((*MockDataBrokerServiceServer)(nil).Query), arg0, arg1)
}
// ReleaseLease mocks base method.
func (m *MockDataBrokerServiceServer) ReleaseLease(arg0 context.Context, arg1 *databroker.ReleaseLeaseRequest) (*emptypb.Empty, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ReleaseLease", arg0, arg1)
ret0, _ := ret[0].(*emptypb.Empty)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ReleaseLease indicates an expected call of ReleaseLease.
func (mr *MockDataBrokerServiceServerMockRecorder) ReleaseLease(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReleaseLease", reflect.TypeOf((*MockDataBrokerServiceServer)(nil).ReleaseLease), arg0, arg1)
}
// RenewLease mocks base method.
func (m *MockDataBrokerServiceServer) RenewLease(arg0 context.Context, arg1 *databroker.RenewLeaseRequest) (*emptypb.Empty, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "RenewLease", arg0, arg1)
ret0, _ := ret[0].(*emptypb.Empty)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// RenewLease indicates an expected call of RenewLease.
func (mr *MockDataBrokerServiceServerMockRecorder) RenewLease(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RenewLease", reflect.TypeOf((*MockDataBrokerServiceServer)(nil).RenewLease), arg0, arg1)
}
// SetOptions mocks base method.
func (m *MockDataBrokerServiceServer) SetOptions(arg0 context.Context, arg1 *databroker.SetOptionsRequest) (*databroker.SetOptionsResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SetOptions", arg0, arg1)
ret0, _ := ret[0].(*databroker.SetOptionsResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SetOptions indicates an expected call of SetOptions.
func (mr *MockDataBrokerServiceServerMockRecorder) SetOptions(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetOptions", reflect.TypeOf((*MockDataBrokerServiceServer)(nil).SetOptions), arg0, arg1)
}
// Sync mocks base method.
func (m *MockDataBrokerServiceServer) Sync(arg0 *databroker.SyncRequest, arg1 databroker.DataBrokerService_SyncServer) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Sync", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// Sync indicates an expected call of Sync.
func (mr *MockDataBrokerServiceServerMockRecorder) Sync(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sync", reflect.TypeOf((*MockDataBrokerServiceServer)(nil).Sync), arg0, arg1)
}
// SyncLatest mocks base method.
func (m *MockDataBrokerServiceServer) SyncLatest(arg0 *databroker.SyncLatestRequest, arg1 databroker.DataBrokerService_SyncLatestServer) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SyncLatest", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// SyncLatest indicates an expected call of SyncLatest.
func (mr *MockDataBrokerServiceServerMockRecorder) SyncLatest(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncLatest", reflect.TypeOf((*MockDataBrokerServiceServer)(nil).SyncLatest), arg0, arg1)
}
// MockDataBrokerService_SyncServer is a mock of DataBrokerService_SyncServer interface.
type MockDataBrokerService_SyncServer struct {
ctrl *gomock.Controller
recorder *MockDataBrokerService_SyncServerMockRecorder
}
// MockDataBrokerService_SyncServerMockRecorder is the mock recorder for MockDataBrokerService_SyncServer.
type MockDataBrokerService_SyncServerMockRecorder struct {
mock *MockDataBrokerService_SyncServer
}
// NewMockDataBrokerService_SyncServer creates a new mock instance.
func NewMockDataBrokerService_SyncServer(ctrl *gomock.Controller) *MockDataBrokerService_SyncServer {
mock := &MockDataBrokerService_SyncServer{ctrl: ctrl}
mock.recorder = &MockDataBrokerService_SyncServerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockDataBrokerService_SyncServer) EXPECT() *MockDataBrokerService_SyncServerMockRecorder {
return m.recorder
}
// Context mocks base method.
func (m *MockDataBrokerService_SyncServer) Context() context.Context {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Context")
ret0, _ := ret[0].(context.Context)
return ret0
}
// Context indicates an expected call of Context.
func (mr *MockDataBrokerService_SyncServerMockRecorder) Context() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Context", reflect.TypeOf((*MockDataBrokerService_SyncServer)(nil).Context))
}
// RecvMsg mocks base method.
func (m_2 *MockDataBrokerService_SyncServer) RecvMsg(m interface{}) error {
m_2.ctrl.T.Helper()
ret := m_2.ctrl.Call(m_2, "RecvMsg", m)
ret0, _ := ret[0].(error)
return ret0
}
// RecvMsg indicates an expected call of RecvMsg.
func (mr *MockDataBrokerService_SyncServerMockRecorder) RecvMsg(m interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecvMsg", reflect.TypeOf((*MockDataBrokerService_SyncServer)(nil).RecvMsg), m)
}
// Send mocks base method.
func (m *MockDataBrokerService_SyncServer) Send(arg0 *databroker.SyncResponse) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Send", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Send indicates an expected call of Send.
func (mr *MockDataBrokerService_SyncServerMockRecorder) Send(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Send", reflect.TypeOf((*MockDataBrokerService_SyncServer)(nil).Send), arg0)
}
// SendHeader mocks base method.
func (m *MockDataBrokerService_SyncServer) SendHeader(arg0 metadata.MD) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SendHeader", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SendHeader indicates an expected call of SendHeader.
func (mr *MockDataBrokerService_SyncServerMockRecorder) SendHeader(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendHeader", reflect.TypeOf((*MockDataBrokerService_SyncServer)(nil).SendHeader), arg0)
}
// SendMsg mocks base method.
func (m_2 *MockDataBrokerService_SyncServer) SendMsg(m interface{}) error {
m_2.ctrl.T.Helper()
ret := m_2.ctrl.Call(m_2, "SendMsg", m)
ret0, _ := ret[0].(error)
return ret0
}
// SendMsg indicates an expected call of SendMsg.
func (mr *MockDataBrokerService_SyncServerMockRecorder) SendMsg(m interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMsg", reflect.TypeOf((*MockDataBrokerService_SyncServer)(nil).SendMsg), m)
}
// SetHeader mocks base method.
func (m *MockDataBrokerService_SyncServer) SetHeader(arg0 metadata.MD) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SetHeader", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SetHeader indicates an expected call of SetHeader.
func (mr *MockDataBrokerService_SyncServerMockRecorder) SetHeader(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetHeader", reflect.TypeOf((*MockDataBrokerService_SyncServer)(nil).SetHeader), arg0)
}
// SetTrailer mocks base method.
func (m *MockDataBrokerService_SyncServer) SetTrailer(arg0 metadata.MD) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetTrailer", arg0)
}
// SetTrailer indicates an expected call of SetTrailer.
func (mr *MockDataBrokerService_SyncServerMockRecorder) SetTrailer(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTrailer", reflect.TypeOf((*MockDataBrokerService_SyncServer)(nil).SetTrailer), arg0)
}
// MockDataBrokerService_SyncLatestServer is a mock of DataBrokerService_SyncLatestServer interface.
type MockDataBrokerService_SyncLatestServer struct {
ctrl *gomock.Controller
recorder *MockDataBrokerService_SyncLatestServerMockRecorder
}
// MockDataBrokerService_SyncLatestServerMockRecorder is the mock recorder for MockDataBrokerService_SyncLatestServer.
type MockDataBrokerService_SyncLatestServerMockRecorder struct {
mock *MockDataBrokerService_SyncLatestServer
}
// NewMockDataBrokerService_SyncLatestServer creates a new mock instance.
func NewMockDataBrokerService_SyncLatestServer(ctrl *gomock.Controller) *MockDataBrokerService_SyncLatestServer {
mock := &MockDataBrokerService_SyncLatestServer{ctrl: ctrl}
mock.recorder = &MockDataBrokerService_SyncLatestServerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockDataBrokerService_SyncLatestServer) EXPECT() *MockDataBrokerService_SyncLatestServerMockRecorder {
return m.recorder
}
// Context mocks base method.
func (m *MockDataBrokerService_SyncLatestServer) Context() context.Context {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Context")
ret0, _ := ret[0].(context.Context)
return ret0
}
// Context indicates an expected call of Context.
func (mr *MockDataBrokerService_SyncLatestServerMockRecorder) Context() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Context", reflect.TypeOf((*MockDataBrokerService_SyncLatestServer)(nil).Context))
}
// RecvMsg mocks base method.
func (m_2 *MockDataBrokerService_SyncLatestServer) RecvMsg(m interface{}) error {
m_2.ctrl.T.Helper()
ret := m_2.ctrl.Call(m_2, "RecvMsg", m)
ret0, _ := ret[0].(error)
return ret0
}
// RecvMsg indicates an expected call of RecvMsg.
func (mr *MockDataBrokerService_SyncLatestServerMockRecorder) RecvMsg(m interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecvMsg", reflect.TypeOf((*MockDataBrokerService_SyncLatestServer)(nil).RecvMsg), m)
}
// Send mocks base method.
func (m *MockDataBrokerService_SyncLatestServer) Send(arg0 *databroker.SyncLatestResponse) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Send", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Send indicates an expected call of Send.
func (mr *MockDataBrokerService_SyncLatestServerMockRecorder) Send(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Send", reflect.TypeOf((*MockDataBrokerService_SyncLatestServer)(nil).Send), arg0)
}
// SendHeader mocks base method.
func (m *MockDataBrokerService_SyncLatestServer) SendHeader(arg0 metadata.MD) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SendHeader", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SendHeader indicates an expected call of SendHeader.
func (mr *MockDataBrokerService_SyncLatestServerMockRecorder) SendHeader(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendHeader", reflect.TypeOf((*MockDataBrokerService_SyncLatestServer)(nil).SendHeader), arg0)
}
// SendMsg mocks base method.
func (m_2 *MockDataBrokerService_SyncLatestServer) SendMsg(m interface{}) error {
m_2.ctrl.T.Helper()
ret := m_2.ctrl.Call(m_2, "SendMsg", m)
ret0, _ := ret[0].(error)
return ret0
}
// SendMsg indicates an expected call of SendMsg.
func (mr *MockDataBrokerService_SyncLatestServerMockRecorder) SendMsg(m interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMsg", reflect.TypeOf((*MockDataBrokerService_SyncLatestServer)(nil).SendMsg), m)
}
// SetHeader mocks base method.
func (m *MockDataBrokerService_SyncLatestServer) SetHeader(arg0 metadata.MD) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SetHeader", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SetHeader indicates an expected call of SetHeader.
func (mr *MockDataBrokerService_SyncLatestServerMockRecorder) SetHeader(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetHeader", reflect.TypeOf((*MockDataBrokerService_SyncLatestServer)(nil).SetHeader), arg0)
}
// SetTrailer mocks base method.
func (m *MockDataBrokerService_SyncLatestServer) SetTrailer(arg0 metadata.MD) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetTrailer", arg0)
}
// SetTrailer indicates an expected call of SetTrailer.
func (mr *MockDataBrokerService_SyncLatestServerMockRecorder) SetTrailer(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTrailer", reflect.TypeOf((*MockDataBrokerService_SyncLatestServer)(nil).SetTrailer), arg0)
}

View file

@ -0,0 +1,64 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: leaser.go
// Package mock_databroker is a generated GoMock package.
package mock_databroker
import (
context "context"
reflect "reflect"
gomock "github.com/golang/mock/gomock"
databroker "github.com/pomerium/pomerium/pkg/grpc/databroker"
)
// MockLeaserHandler is a mock of LeaserHandler interface.
type MockLeaserHandler struct {
ctrl *gomock.Controller
recorder *MockLeaserHandlerMockRecorder
}
// MockLeaserHandlerMockRecorder is the mock recorder for MockLeaserHandler.
type MockLeaserHandlerMockRecorder struct {
mock *MockLeaserHandler
}
// NewMockLeaserHandler creates a new mock instance.
func NewMockLeaserHandler(ctrl *gomock.Controller) *MockLeaserHandler {
mock := &MockLeaserHandler{ctrl: ctrl}
mock.recorder = &MockLeaserHandlerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockLeaserHandler) EXPECT() *MockLeaserHandlerMockRecorder {
return m.recorder
}
// GetDataBrokerServiceClient mocks base method.
func (m *MockLeaserHandler) GetDataBrokerServiceClient() databroker.DataBrokerServiceClient {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetDataBrokerServiceClient")
ret0, _ := ret[0].(databroker.DataBrokerServiceClient)
return ret0
}
// GetDataBrokerServiceClient indicates an expected call of GetDataBrokerServiceClient.
func (mr *MockLeaserHandlerMockRecorder) GetDataBrokerServiceClient() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDataBrokerServiceClient", reflect.TypeOf((*MockLeaserHandler)(nil).GetDataBrokerServiceClient))
}
// RunLeased mocks base method.
func (m *MockLeaserHandler) RunLeased(ctx context.Context) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "RunLeased", ctx)
ret0, _ := ret[0].(error)
return ret0
}
// RunLeased indicates an expected call of RunLeased.
func (mr *MockLeaserHandlerMockRecorder) RunLeased(ctx interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RunLeased", reflect.TypeOf((*MockLeaserHandler)(nil).RunLeased), ctx)
}

View file

@ -3,6 +3,7 @@ package storage
import (
"context"
"crypto/cipher"
"time"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"
@ -97,6 +98,10 @@ func (e *encryptedBackend) GetOptions(ctx context.Context, recordType string) (*
return e.underlying.GetOptions(ctx, recordType)
}
func (e *encryptedBackend) Lease(ctx context.Context, leaseName, leaseID string, ttl time.Duration) (bool, error) {
return e.underlying.Lease(ctx, leaseName, leaseID, ttl)
}
func (e *encryptedBackend) Put(ctx context.Context, record *databroker.Record) (uint64, error) {
encrypted, err := e.encrypt(record.GetData())
if err != nil {

View file

@ -20,6 +20,11 @@ import (
"github.com/pomerium/pomerium/pkg/storage"
)
type lease struct {
id string
expiry time.Time
}
type recordChange struct {
record *databroker.Record
}
@ -47,6 +52,7 @@ type Backend struct {
lookup map[string]*RecordCollection
capacity map[string]*uint64
changes *btree.BTree
leases map[string]*lease
}
// New creates a new in-memory backend storage.
@ -60,6 +66,7 @@ func New(options ...Option) *Backend {
lookup: make(map[string]*RecordCollection),
capacity: map[string]*uint64{},
changes: btree.New(cfg.degree),
leases: make(map[string]*lease),
}
if cfg.expiry != 0 {
go func() {
@ -165,6 +172,37 @@ func (backend *Backend) GetOptions(_ context.Context, recordType string) (*datab
return options, nil
}
// Lease acquires or renews a lease.
func (backend *Backend) Lease(_ context.Context, leaseName, leaseID string, ttl time.Duration) (bool, error) {
backend.mu.Lock()
defer backend.mu.Unlock()
l, ok := backend.leases[leaseName]
// if there is no lease, or its expired, acquire a new one.
if !ok || l.expiry.Before(time.Now()) {
backend.leases[leaseName] = &lease{
id: leaseID,
expiry: time.Now().Add(ttl),
}
return true, nil
}
// if the lease doesn't match, we can't acquire it
if l.id != leaseID {
return false, nil
}
// release the lease
if ttl <= 0 {
delete(backend.leases, leaseName)
return false, nil
}
// update the expiry (renew the lease)
l.expiry = time.Now().Add(ttl)
return true, nil
}
// Put puts a record into the in-memory store.
func (backend *Backend) Put(ctx context.Context, record *databroker.Record) (serverVersion uint64, err error) {
if record == nil {

View file

@ -189,3 +189,28 @@ func TestCapacity(t *testing.T) {
}
assert.Equal(t, []string{"7", "8", "9"}, ids, "should contain recent records")
}
func TestLease(t *testing.T) {
ctx := context.Background()
backend := New()
{
ok, err := backend.Lease(ctx, "test", "a", time.Second*30)
require.NoError(t, err)
assert.True(t, ok, "expected a to acquire the lease")
}
{
ok, err := backend.Lease(ctx, "test", "b", time.Second*30)
require.NoError(t, err)
assert.False(t, ok, "expected b to fail to acquire the lease")
}
{
ok, err := backend.Lease(ctx, "test", "a", 0)
require.NoError(t, err)
assert.False(t, ok, "expected a to clear the lease")
}
{
ok, err := backend.Lease(ctx, "test", "b", time.Second*30)
require.NoError(t, err)
assert.True(t, ok, "expected b to to acquire the lease")
}
}

View file

@ -37,6 +37,7 @@ const (
optionsKey = redisutil.KeyPrefix + "options"
recordTypeChangesKeyTpl = redisutil.KeyPrefix + "changes.%s"
leaseKeyTpl = "{pomerium_v3}.lease.%s"
)
// custom errors
@ -202,6 +203,43 @@ func (backend *Backend) GetOptions(ctx context.Context, recordType string) (*dat
return &options, nil
}
// Lease acquires or renews a lease.
func (backend *Backend) Lease(ctx context.Context, leaseName, leaseID string, ttl time.Duration) (bool, error) {
acquired := false
key := getLeaseKey(leaseName)
err := backend.client.Watch(ctx, func(tx *redis.Tx) error {
currentID, err := tx.Get(ctx, key).Result()
if errors.Is(err, redis.Nil) {
// lease hasn't been set yet
} else if err != nil {
return err
} else if leaseID != currentID {
// lease has already been taken
return nil
}
_, err = tx.Pipelined(ctx, func(p redis.Pipeliner) error {
if ttl <= 0 {
p.Del(ctx, key)
} else {
p.Set(ctx, key, leaseID, ttl)
}
return nil
})
if err != nil {
return err
}
acquired = ttl > 0
return nil
}, key)
// if the transaction failed someone else must've acquired the lease
if errors.Is(err, redis.TxFailedErr) {
acquired = false
err = nil
}
return acquired, err
}
// Put puts a record into redis.
func (backend *Backend) Put(ctx context.Context, record *databroker.Record) (serverVersion uint64, err error) {
ctx, span := trace.StartSpan(ctx, "databroker.redis.Put")
@ -489,6 +527,10 @@ func (backend *Backend) getOrCreateServerVersion(ctx context.Context) (serverVer
return serverVersion, err
}
func getLeaseKey(leaseName string) string {
return fmt.Sprintf(leaseKeyTpl, leaseName)
}
func getRecordTypeChangesKey(recordType string) string {
return fmt.Sprintf(recordTypeChangesKeyTpl, recordType)
}

View file

@ -248,3 +248,39 @@ func TestCapacity(t *testing.T) {
return nil
}))
}
func TestLease(t *testing.T) {
if os.Getenv("GITHUB_ACTION") != "" && runtime.GOOS == "darwin" {
t.Skip("Github action can not run docker on MacOS")
}
ctx := context.Background()
require.NoError(t, testutil.WithTestRedis(false, func(rawURL string) error {
backend, err := New(rawURL)
require.NoError(t, err)
defer func() { _ = backend.Close() }()
{
ok, err := backend.Lease(ctx, "test", "a", time.Second*30)
require.NoError(t, err)
assert.True(t, ok, "expected a to acquire the lease")
}
{
ok, err := backend.Lease(ctx, "test", "b", time.Second*30)
require.NoError(t, err)
assert.False(t, ok, "expected b to fail to acquire the lease")
}
{
ok, err := backend.Lease(ctx, "test", "a", 0)
require.NoError(t, err)
assert.False(t, ok, "expected a to clear the lease")
}
{
ok, err := backend.Lease(ctx, "test", "b", time.Second*30)
require.NoError(t, err)
assert.True(t, ok, "expected b to to acquire the lease")
}
return nil
}))
}

View file

@ -5,6 +5,7 @@ import (
"context"
"errors"
"strings"
"time"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@ -47,6 +48,8 @@ type Backend interface {
GetAll(ctx context.Context) (records []*databroker.Record, version *databroker.Versions, err error)
// GetOptions gets the options for a type.
GetOptions(ctx context.Context, recordType string) (*databroker.Options, error)
// Lease acquires a lease, or renews an existing one. If the lease is acquired true is returned.
Lease(ctx context.Context, leaseName, leaseID string, ttl time.Duration) (bool, error)
// Put is used to insert or update a record.
Put(ctx context.Context, record *databroker.Record) (serverVersion uint64, err error)
// SetOptions sets the options for a type.