From 8848300ffc584eb9fce5aead02f3cf35985af375 Mon Sep 17 00:00:00 2001 From: nicolasgere Date: Mon, 15 Apr 2024 09:27:12 -0700 Subject: [PATCH] [ENH]: Add offset/limit collection sysdb (#1999) ## Description of changes *Summarize the changes made by this PR.* - Improvements & Bug fixes - Add offset and limit support in collection endpoint sysdb ## Test plan *How are these changes tested?* Added test --- go/mocks/Catalog.go | 18 +- go/mocks/DBTX.go | 147 ++++++ go/mocks/ICollectionDb.go | 18 +- go/mocks/ICoordinator.go | 18 +- go/mocks/IMetaDomain.go | 2 - go/mocks/IWatcher.go | 26 +- go/mocks/LogServiceClient.go | 180 ++++++++ go/mocks/LogServiceServer.go | 154 +++++++ go/mocks/UnsafeLogServiceServer.go | 29 ++ go/pkg/coordinator/apis.go | 6 +- go/pkg/coordinator/apis_test.go | 34 +- go/pkg/coordinator/grpc/collection_service.go | 4 +- go/pkg/metastore/catalog.go | 2 +- go/pkg/metastore/coordinator/table_catalog.go | 12 +- .../coordinator/table_catalog_test.go | 5 +- go/pkg/metastore/db/dao/collection.go | 11 +- go/pkg/metastore/db/dao/collection_test.go | 31 +- go/pkg/metastore/db/dao/test_utils.go | 2 +- go/pkg/metastore/db/dbcore/core.go | 37 +- go/pkg/metastore/db/dbmodel/collection.go | 2 +- .../db/dbmodel/mocks/ICollectionDb.go | 20 +- go/pkg/metastore/mocks/Catalog.go | 406 +++++++++++++++-- go/pkg/proto/coordinatorpb/coordinator.pb.go | 419 +++++++++--------- idl/chromadb/proto/coordinator.proto | 2 + rust/worker/src/sysdb/sysdb.rs | 2 + 25 files changed, 1250 insertions(+), 337 deletions(-) create mode 100644 go/mocks/DBTX.go create mode 100644 go/mocks/LogServiceClient.go create mode 100644 go/mocks/LogServiceServer.go create mode 100644 go/mocks/UnsafeLogServiceServer.go diff --git a/go/mocks/Catalog.go b/go/mocks/Catalog.go index d7ce72ebec5..320f207c1dc 100644 --- a/go/mocks/Catalog.go +++ b/go/mocks/Catalog.go @@ -265,9 +265,9 @@ func (_m *Catalog) GetAllTenants(ctx context.Context, ts int64) ([]*model.Tenant return r0, r1 } -// GetCollections provides a mock function with given fields: ctx, collectionID, collectionName, tenantID, databaseName -func (_m *Catalog) GetCollections(ctx context.Context, collectionID types.UniqueID, collectionName *string, tenantID string, databaseName string) ([]*model.Collection, error) { - ret := _m.Called(ctx, collectionID, collectionName, tenantID, databaseName) +// GetCollections provides a mock function with given fields: ctx, collectionID, collectionName, tenantID, databaseName, limit, offset +func (_m *Catalog) GetCollections(ctx context.Context, collectionID types.UniqueID, collectionName *string, tenantID string, databaseName string, limit *int32, offset *int32) ([]*model.Collection, error) { + ret := _m.Called(ctx, collectionID, collectionName, tenantID, databaseName, limit, offset) if len(ret) == 0 { panic("no return value specified for GetCollections") @@ -275,19 +275,19 @@ func (_m *Catalog) GetCollections(ctx context.Context, collectionID types.Unique var r0 []*model.Collection var r1 error - if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string, string, string) ([]*model.Collection, error)); ok { - return rf(ctx, collectionID, collectionName, tenantID, databaseName) + if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string, string, string, *int32, *int32) ([]*model.Collection, error)); ok { + return rf(ctx, collectionID, collectionName, tenantID, databaseName, limit, offset) } - if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string, string, string) []*model.Collection); ok { - r0 = rf(ctx, collectionID, collectionName, tenantID, databaseName) + if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string, string, string, *int32, *int32) []*model.Collection); ok { + r0 = rf(ctx, collectionID, collectionName, tenantID, databaseName, limit, offset) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]*model.Collection) } } - if rf, ok := ret.Get(1).(func(context.Context, types.UniqueID, *string, string, string) error); ok { - r1 = rf(ctx, collectionID, collectionName, tenantID, databaseName) + if rf, ok := ret.Get(1).(func(context.Context, types.UniqueID, *string, string, string, *int32, *int32) error); ok { + r1 = rf(ctx, collectionID, collectionName, tenantID, databaseName, limit, offset) } else { r1 = ret.Error(1) } diff --git a/go/mocks/DBTX.go b/go/mocks/DBTX.go new file mode 100644 index 00000000000..ae69b5036ff --- /dev/null +++ b/go/mocks/DBTX.go @@ -0,0 +1,147 @@ +// Code generated by mockery v2.42.1. DO NOT EDIT. + +package mocks + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + + pgconn "github.com/jackc/pgx/v5/pgconn" + + pgx "github.com/jackc/pgx/v5" +) + +// DBTX is an autogenerated mock type for the DBTX type +type DBTX struct { + mock.Mock +} + +// CopyFrom provides a mock function with given fields: ctx, tableName, columnNames, rowSrc +func (_m *DBTX) CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error) { + ret := _m.Called(ctx, tableName, columnNames, rowSrc) + + if len(ret) == 0 { + panic("no return value specified for CopyFrom") + } + + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) (int64, error)); ok { + return rf(ctx, tableName, columnNames, rowSrc) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) int64); ok { + r0 = rf(ctx, tableName, columnNames, rowSrc) + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) error); ok { + r1 = rf(ctx, tableName, columnNames, rowSrc) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Exec provides a mock function with given fields: _a0, _a1, _a2 +func (_m *DBTX) Exec(_a0 context.Context, _a1 string, _a2 ...interface{}) (pgconn.CommandTag, error) { + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _a2...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for Exec") + } + + var r0 pgconn.CommandTag + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (pgconn.CommandTag, error)); ok { + return rf(_a0, _a1, _a2...) + } + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) pgconn.CommandTag); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + r0 = ret.Get(0).(pgconn.CommandTag) + } + + if rf, ok := ret.Get(1).(func(context.Context, string, ...interface{}) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Query provides a mock function with given fields: _a0, _a1, _a2 +func (_m *DBTX) Query(_a0 context.Context, _a1 string, _a2 ...interface{}) (pgx.Rows, error) { + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _a2...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for Query") + } + + var r0 pgx.Rows + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (pgx.Rows, error)); ok { + return rf(_a0, _a1, _a2...) + } + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) pgx.Rows); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgx.Rows) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, ...interface{}) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// QueryRow provides a mock function with given fields: _a0, _a1, _a2 +func (_m *DBTX) QueryRow(_a0 context.Context, _a1 string, _a2 ...interface{}) pgx.Row { + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _a2...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for QueryRow") + } + + var r0 pgx.Row + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) pgx.Row); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgx.Row) + } + } + + return r0 +} + +// NewDBTX creates a new instance of DBTX. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewDBTX(t interface { + mock.TestingT + Cleanup(func()) +}) *DBTX { + mock := &DBTX{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/go/mocks/ICollectionDb.go b/go/mocks/ICollectionDb.go index 889c99781e4..cd4377a9bd1 100644 --- a/go/mocks/ICollectionDb.go +++ b/go/mocks/ICollectionDb.go @@ -58,9 +58,9 @@ func (_m *ICollectionDb) DeleteCollectionByID(collectionID string) (int, error) return r0, r1 } -// GetCollections provides a mock function with given fields: collectionID, collectionName, tenantID, databaseName -func (_m *ICollectionDb) GetCollections(collectionID *string, collectionName *string, tenantID string, databaseName string) ([]*dbmodel.CollectionAndMetadata, error) { - ret := _m.Called(collectionID, collectionName, tenantID, databaseName) +// GetCollections provides a mock function with given fields: collectionID, collectionName, tenantID, databaseName, limit, offset +func (_m *ICollectionDb) GetCollections(collectionID *string, collectionName *string, tenantID string, databaseName string, limit *int32, offset *int32) ([]*dbmodel.CollectionAndMetadata, error) { + ret := _m.Called(collectionID, collectionName, tenantID, databaseName, limit, offset) if len(ret) == 0 { panic("no return value specified for GetCollections") @@ -68,19 +68,19 @@ func (_m *ICollectionDb) GetCollections(collectionID *string, collectionName *st var r0 []*dbmodel.CollectionAndMetadata var r1 error - if rf, ok := ret.Get(0).(func(*string, *string, string, string) ([]*dbmodel.CollectionAndMetadata, error)); ok { - return rf(collectionID, collectionName, tenantID, databaseName) + if rf, ok := ret.Get(0).(func(*string, *string, string, string, *int32, *int32) ([]*dbmodel.CollectionAndMetadata, error)); ok { + return rf(collectionID, collectionName, tenantID, databaseName, limit, offset) } - if rf, ok := ret.Get(0).(func(*string, *string, string, string) []*dbmodel.CollectionAndMetadata); ok { - r0 = rf(collectionID, collectionName, tenantID, databaseName) + if rf, ok := ret.Get(0).(func(*string, *string, string, string, *int32, *int32) []*dbmodel.CollectionAndMetadata); ok { + r0 = rf(collectionID, collectionName, tenantID, databaseName, limit, offset) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]*dbmodel.CollectionAndMetadata) } } - if rf, ok := ret.Get(1).(func(*string, *string, string, string) error); ok { - r1 = rf(collectionID, collectionName, tenantID, databaseName) + if rf, ok := ret.Get(1).(func(*string, *string, string, string, *int32, *int32) error); ok { + r1 = rf(collectionID, collectionName, tenantID, databaseName, limit, offset) } else { r1 = ret.Error(1) } diff --git a/go/mocks/ICoordinator.go b/go/mocks/ICoordinator.go index 02d51811196..e5049ee7a4c 100644 --- a/go/mocks/ICoordinator.go +++ b/go/mocks/ICoordinator.go @@ -193,9 +193,9 @@ func (_m *ICoordinator) FlushCollectionCompaction(ctx context.Context, flushColl return r0, r1 } -// GetCollections provides a mock function with given fields: ctx, collectionID, collectionName, tenantID, dataName -func (_m *ICoordinator) GetCollections(ctx context.Context, collectionID types.UniqueID, collectionName *string, tenantID string, dataName string) ([]*model.Collection, error) { - ret := _m.Called(ctx, collectionID, collectionName, tenantID, dataName) +// GetCollections provides a mock function with given fields: ctx, collectionID, collectionName, tenantID, dataName, limit, offset +func (_m *ICoordinator) GetCollections(ctx context.Context, collectionID types.UniqueID, collectionName *string, tenantID string, dataName string, limit *int32, offset *int32) ([]*model.Collection, error) { + ret := _m.Called(ctx, collectionID, collectionName, tenantID, dataName, limit, offset) if len(ret) == 0 { panic("no return value specified for GetCollections") @@ -203,19 +203,19 @@ func (_m *ICoordinator) GetCollections(ctx context.Context, collectionID types.U var r0 []*model.Collection var r1 error - if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string, string, string) ([]*model.Collection, error)); ok { - return rf(ctx, collectionID, collectionName, tenantID, dataName) + if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string, string, string, *int32, *int32) ([]*model.Collection, error)); ok { + return rf(ctx, collectionID, collectionName, tenantID, dataName, limit, offset) } - if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string, string, string) []*model.Collection); ok { - r0 = rf(ctx, collectionID, collectionName, tenantID, dataName) + if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string, string, string, *int32, *int32) []*model.Collection); ok { + r0 = rf(ctx, collectionID, collectionName, tenantID, dataName, limit, offset) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]*model.Collection) } } - if rf, ok := ret.Get(1).(func(context.Context, types.UniqueID, *string, string, string) error); ok { - r1 = rf(ctx, collectionID, collectionName, tenantID, dataName) + if rf, ok := ret.Get(1).(func(context.Context, types.UniqueID, *string, string, string, *int32, *int32) error); ok { + r1 = rf(ctx, collectionID, collectionName, tenantID, dataName, limit, offset) } else { r1 = ret.Error(1) } diff --git a/go/mocks/IMetaDomain.go b/go/mocks/IMetaDomain.go index c0c224444ad..6c4653d0204 100644 --- a/go/mocks/IMetaDomain.go +++ b/go/mocks/IMetaDomain.go @@ -94,8 +94,6 @@ func (_m *IMetaDomain) NotificationDb(ctx context.Context) dbmodel.INotification return r0 } - - // SegmentDb provides a mock function with given fields: ctx func (_m *IMetaDomain) SegmentDb(ctx context.Context) dbmodel.ISegmentDb { ret := _m.Called(ctx) diff --git a/go/mocks/IWatcher.go b/go/mocks/IWatcher.go index eba7bd2520e..bab954a22db 100644 --- a/go/mocks/IWatcher.go +++ b/go/mocks/IWatcher.go @@ -12,27 +12,29 @@ type IWatcher struct { mock.Mock } -// GetStatus provides a mock function with given fields: node_ip -func (_m *IWatcher) GetStatus(node_ip string) (memberlist_manager.Status, error) { - ret := _m.Called(node_ip) +// ListReadyMembers provides a mock function with given fields: +func (_m *IWatcher) ListReadyMembers() (memberlist_manager.Memberlist, error) { + ret := _m.Called() if len(ret) == 0 { - panic("no return value specified for GetStatus") + panic("no return value specified for ListReadyMembers") } - var r0 memberlist_manager.Status + var r0 memberlist_manager.Memberlist var r1 error - if rf, ok := ret.Get(0).(func(string) (memberlist_manager.Status, error)); ok { - return rf(node_ip) + if rf, ok := ret.Get(0).(func() (memberlist_manager.Memberlist, error)); ok { + return rf() } - if rf, ok := ret.Get(0).(func(string) memberlist_manager.Status); ok { - r0 = rf(node_ip) + if rf, ok := ret.Get(0).(func() memberlist_manager.Memberlist); ok { + r0 = rf() } else { - r0 = ret.Get(0).(memberlist_manager.Status) + if ret.Get(0) != nil { + r0 = ret.Get(0).(memberlist_manager.Memberlist) + } } - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(node_ip) + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() } else { r1 = ret.Error(1) } diff --git a/go/mocks/LogServiceClient.go b/go/mocks/LogServiceClient.go new file mode 100644 index 00000000000..2137e87772c --- /dev/null +++ b/go/mocks/LogServiceClient.go @@ -0,0 +1,180 @@ +// Code generated by mockery v2.42.1. DO NOT EDIT. + +package mocks + +import ( + context "context" + + grpc "google.golang.org/grpc" + + logservicepb "github.com/chroma-core/chroma/go/pkg/proto/logservicepb" + + mock "github.com/stretchr/testify/mock" +) + +// LogServiceClient is an autogenerated mock type for the LogServiceClient type +type LogServiceClient struct { + mock.Mock +} + +// GetAllCollectionInfoToCompact provides a mock function with given fields: ctx, in, opts +func (_m *LogServiceClient) GetAllCollectionInfoToCompact(ctx context.Context, in *logservicepb.GetAllCollectionInfoToCompactRequest, opts ...grpc.CallOption) (*logservicepb.GetAllCollectionInfoToCompactResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetAllCollectionInfoToCompact") + } + + var r0 *logservicepb.GetAllCollectionInfoToCompactResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.GetAllCollectionInfoToCompactRequest, ...grpc.CallOption) (*logservicepb.GetAllCollectionInfoToCompactResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.GetAllCollectionInfoToCompactRequest, ...grpc.CallOption) *logservicepb.GetAllCollectionInfoToCompactResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*logservicepb.GetAllCollectionInfoToCompactResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *logservicepb.GetAllCollectionInfoToCompactRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PullLogs provides a mock function with given fields: ctx, in, opts +func (_m *LogServiceClient) PullLogs(ctx context.Context, in *logservicepb.PullLogsRequest, opts ...grpc.CallOption) (*logservicepb.PullLogsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for PullLogs") + } + + var r0 *logservicepb.PullLogsResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.PullLogsRequest, ...grpc.CallOption) (*logservicepb.PullLogsResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.PullLogsRequest, ...grpc.CallOption) *logservicepb.PullLogsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*logservicepb.PullLogsResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *logservicepb.PullLogsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PushLogs provides a mock function with given fields: ctx, in, opts +func (_m *LogServiceClient) PushLogs(ctx context.Context, in *logservicepb.PushLogsRequest, opts ...grpc.CallOption) (*logservicepb.PushLogsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for PushLogs") + } + + var r0 *logservicepb.PushLogsResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.PushLogsRequest, ...grpc.CallOption) (*logservicepb.PushLogsResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.PushLogsRequest, ...grpc.CallOption) *logservicepb.PushLogsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*logservicepb.PushLogsResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *logservicepb.PushLogsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UpdateCollectionLogOffset provides a mock function with given fields: ctx, in, opts +func (_m *LogServiceClient) UpdateCollectionLogOffset(ctx context.Context, in *logservicepb.UpdateCollectionLogOffsetRequest, opts ...grpc.CallOption) (*logservicepb.UpdateCollectionLogOffsetResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for UpdateCollectionLogOffset") + } + + var r0 *logservicepb.UpdateCollectionLogOffsetResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.UpdateCollectionLogOffsetRequest, ...grpc.CallOption) (*logservicepb.UpdateCollectionLogOffsetResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.UpdateCollectionLogOffsetRequest, ...grpc.CallOption) *logservicepb.UpdateCollectionLogOffsetResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*logservicepb.UpdateCollectionLogOffsetResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *logservicepb.UpdateCollectionLogOffsetRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewLogServiceClient creates a new instance of LogServiceClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewLogServiceClient(t interface { + mock.TestingT + Cleanup(func()) +}) *LogServiceClient { + mock := &LogServiceClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/go/mocks/LogServiceServer.go b/go/mocks/LogServiceServer.go new file mode 100644 index 00000000000..c1a81f280bd --- /dev/null +++ b/go/mocks/LogServiceServer.go @@ -0,0 +1,154 @@ +// Code generated by mockery v2.42.1. DO NOT EDIT. + +package mocks + +import ( + context "context" + + logservicepb "github.com/chroma-core/chroma/go/pkg/proto/logservicepb" + mock "github.com/stretchr/testify/mock" +) + +// LogServiceServer is an autogenerated mock type for the LogServiceServer type +type LogServiceServer struct { + mock.Mock +} + +// GetAllCollectionInfoToCompact provides a mock function with given fields: _a0, _a1 +func (_m *LogServiceServer) GetAllCollectionInfoToCompact(_a0 context.Context, _a1 *logservicepb.GetAllCollectionInfoToCompactRequest) (*logservicepb.GetAllCollectionInfoToCompactResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for GetAllCollectionInfoToCompact") + } + + var r0 *logservicepb.GetAllCollectionInfoToCompactResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.GetAllCollectionInfoToCompactRequest) (*logservicepb.GetAllCollectionInfoToCompactResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.GetAllCollectionInfoToCompactRequest) *logservicepb.GetAllCollectionInfoToCompactResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*logservicepb.GetAllCollectionInfoToCompactResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *logservicepb.GetAllCollectionInfoToCompactRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PullLogs provides a mock function with given fields: _a0, _a1 +func (_m *LogServiceServer) PullLogs(_a0 context.Context, _a1 *logservicepb.PullLogsRequest) (*logservicepb.PullLogsResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for PullLogs") + } + + var r0 *logservicepb.PullLogsResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.PullLogsRequest) (*logservicepb.PullLogsResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.PullLogsRequest) *logservicepb.PullLogsResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*logservicepb.PullLogsResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *logservicepb.PullLogsRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PushLogs provides a mock function with given fields: _a0, _a1 +func (_m *LogServiceServer) PushLogs(_a0 context.Context, _a1 *logservicepb.PushLogsRequest) (*logservicepb.PushLogsResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for PushLogs") + } + + var r0 *logservicepb.PushLogsResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.PushLogsRequest) (*logservicepb.PushLogsResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.PushLogsRequest) *logservicepb.PushLogsResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*logservicepb.PushLogsResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *logservicepb.PushLogsRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UpdateCollectionLogOffset provides a mock function with given fields: _a0, _a1 +func (_m *LogServiceServer) UpdateCollectionLogOffset(_a0 context.Context, _a1 *logservicepb.UpdateCollectionLogOffsetRequest) (*logservicepb.UpdateCollectionLogOffsetResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for UpdateCollectionLogOffset") + } + + var r0 *logservicepb.UpdateCollectionLogOffsetResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.UpdateCollectionLogOffsetRequest) (*logservicepb.UpdateCollectionLogOffsetResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *logservicepb.UpdateCollectionLogOffsetRequest) *logservicepb.UpdateCollectionLogOffsetResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*logservicepb.UpdateCollectionLogOffsetResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *logservicepb.UpdateCollectionLogOffsetRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mustEmbedUnimplementedLogServiceServer provides a mock function with given fields: +func (_m *LogServiceServer) mustEmbedUnimplementedLogServiceServer() { + _m.Called() +} + +// NewLogServiceServer creates a new instance of LogServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewLogServiceServer(t interface { + mock.TestingT + Cleanup(func()) +}) *LogServiceServer { + mock := &LogServiceServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/go/mocks/UnsafeLogServiceServer.go b/go/mocks/UnsafeLogServiceServer.go new file mode 100644 index 00000000000..92a15424ae0 --- /dev/null +++ b/go/mocks/UnsafeLogServiceServer.go @@ -0,0 +1,29 @@ +// Code generated by mockery v2.42.1. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// UnsafeLogServiceServer is an autogenerated mock type for the UnsafeLogServiceServer type +type UnsafeLogServiceServer struct { + mock.Mock +} + +// mustEmbedUnimplementedLogServiceServer provides a mock function with given fields: +func (_m *UnsafeLogServiceServer) mustEmbedUnimplementedLogServiceServer() { + _m.Called() +} + +// NewUnsafeLogServiceServer creates a new instance of UnsafeLogServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewUnsafeLogServiceServer(t interface { + mock.TestingT + Cleanup(func()) +}) *UnsafeLogServiceServer { + mock := &UnsafeLogServiceServer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/go/pkg/coordinator/apis.go b/go/pkg/coordinator/apis.go index a45dab0102c..40ec49f5d50 100644 --- a/go/pkg/coordinator/apis.go +++ b/go/pkg/coordinator/apis.go @@ -18,7 +18,7 @@ type ICoordinator interface { common.Component ResetState(ctx context.Context) error CreateCollection(ctx context.Context, createCollection *model.CreateCollection) (*model.Collection, error) - GetCollections(ctx context.Context, collectionID types.UniqueID, collectionName *string, tenantID string, dataName string) ([]*model.Collection, error) + GetCollections(ctx context.Context, collectionID types.UniqueID, collectionName *string, tenantID string, dataName string, limit *int32, offset *int32) ([]*model.Collection, error) DeleteCollection(ctx context.Context, deleteCollection *model.DeleteCollection) error UpdateCollection(ctx context.Context, updateCollection *model.UpdateCollection) (*model.Collection, error) CreateSegment(ctx context.Context, createSegment *model.CreateSegment) error @@ -79,8 +79,8 @@ func (s *Coordinator) CreateCollection(ctx context.Context, createCollection *mo return collection, nil } -func (s *Coordinator) GetCollections(ctx context.Context, collectionID types.UniqueID, collectionName *string, tenantID string, databaseName string) ([]*model.Collection, error) { - return s.catalog.GetCollections(ctx, collectionID, collectionName, tenantID, databaseName) +func (s *Coordinator) GetCollections(ctx context.Context, collectionID types.UniqueID, collectionName *string, tenantID string, databaseName string, limit *int32, offset *int32) ([]*model.Collection, error) { + return s.catalog.GetCollections(ctx, collectionID, collectionName, tenantID, databaseName, limit, offset) } func (s *Coordinator) DeleteCollection(ctx context.Context, deleteCollection *model.DeleteCollection) error { diff --git a/go/pkg/coordinator/apis_test.go b/go/pkg/coordinator/apis_test.go index 3b05931f6e5..9a92086853b 100644 --- a/go/pkg/coordinator/apis_test.go +++ b/go/pkg/coordinator/apis_test.go @@ -114,7 +114,7 @@ func testCollection(t *rapid.T) { } if err == nil { // verify the correctness - collectionList, err := c.GetCollections(ctx, collection.ID, nil, common.DefaultTenant, common.DefaultDatabase) + collectionList, err := c.GetCollections(ctx, collection.ID, nil, common.DefaultTenant, common.DefaultDatabase, nil, nil) if err != nil { t.Fatalf("error getting collections: %v", err) } @@ -256,7 +256,7 @@ func SampleCollections(tenantID string, databaseName string) []*model.Collection func (suite *APIsTestSuite) TestCreateGetDeleteCollections() { ctx := context.Background() - results, err := suite.coordinator.GetCollections(ctx, types.NilUniqueID(), nil, suite.tenantName, suite.databaseName) + results, err := suite.coordinator.GetCollections(ctx, types.NilUniqueID(), nil, suite.tenantName, suite.databaseName, nil, nil) suite.NoError(err) sort.Slice(results, func(i, j int) bool { @@ -275,14 +275,14 @@ func (suite *APIsTestSuite) TestCreateGetDeleteCollections() { // Find by name for _, collection := range suite.sampleCollections { - result, err := suite.coordinator.GetCollections(ctx, types.NilUniqueID(), &collection.Name, suite.tenantName, suite.databaseName) + result, err := suite.coordinator.GetCollections(ctx, types.NilUniqueID(), &collection.Name, suite.tenantName, suite.databaseName, nil, nil) suite.NoError(err) suite.Equal([]*model.Collection{collection}, result) } // Find by id for _, collection := range suite.sampleCollections { - result, err := suite.coordinator.GetCollections(ctx, collection.ID, nil, suite.tenantName, suite.databaseName) + result, err := suite.coordinator.GetCollections(ctx, collection.ID, nil, suite.tenantName, suite.databaseName, nil, nil) suite.NoError(err) suite.Equal([]*model.Collection{collection}, result) } @@ -297,13 +297,13 @@ func (suite *APIsTestSuite) TestCreateGetDeleteCollections() { err = suite.coordinator.DeleteCollection(ctx, deleteCollection) suite.NoError(err) - results, err = suite.coordinator.GetCollections(ctx, types.NilUniqueID(), nil, suite.tenantName, suite.databaseName) + results, err = suite.coordinator.GetCollections(ctx, types.NilUniqueID(), nil, suite.tenantName, suite.databaseName, nil, nil) suite.NoError(err) suite.NotContains(results, c1) suite.Len(results, len(suite.sampleCollections)-1) suite.ElementsMatch(results, suite.sampleCollections[1:]) - byIDResult, err := suite.coordinator.GetCollections(ctx, c1.ID, nil, suite.tenantName, suite.databaseName) + byIDResult, err := suite.coordinator.GetCollections(ctx, c1.ID, nil, suite.tenantName, suite.databaseName, nil, nil) suite.NoError(err) suite.Empty(byIDResult) @@ -328,7 +328,7 @@ func (suite *APIsTestSuite) TestUpdateCollections() { result, err := suite.coordinator.UpdateCollection(ctx, &model.UpdateCollection{ID: coll.ID, Name: &coll.Name}) suite.NoError(err) suite.Equal(coll, result) - resultList, err := suite.coordinator.GetCollections(ctx, types.NilUniqueID(), &coll.Name, suite.tenantName, suite.databaseName) + resultList, err := suite.coordinator.GetCollections(ctx, types.NilUniqueID(), &coll.Name, suite.tenantName, suite.databaseName, nil, nil) suite.NoError(err) suite.Equal([]*model.Collection{coll}, resultList) @@ -338,7 +338,7 @@ func (suite *APIsTestSuite) TestUpdateCollections() { result, err = suite.coordinator.UpdateCollection(ctx, &model.UpdateCollection{ID: coll.ID, Dimension: coll.Dimension}) suite.NoError(err) suite.Equal(coll, result) - resultList, err = suite.coordinator.GetCollections(ctx, coll.ID, nil, suite.tenantName, suite.databaseName) + resultList, err = suite.coordinator.GetCollections(ctx, coll.ID, nil, suite.tenantName, suite.databaseName, nil, nil) suite.NoError(err) suite.Equal([]*model.Collection{coll}, resultList) @@ -349,7 +349,7 @@ func (suite *APIsTestSuite) TestUpdateCollections() { result, err = suite.coordinator.UpdateCollection(ctx, &model.UpdateCollection{ID: coll.ID, Metadata: coll.Metadata}) suite.NoError(err) suite.Equal(coll, result) - resultList, err = suite.coordinator.GetCollections(ctx, coll.ID, nil, suite.tenantName, suite.databaseName) + resultList, err = suite.coordinator.GetCollections(ctx, coll.ID, nil, suite.tenantName, suite.databaseName, nil, nil) suite.NoError(err) suite.Equal([]*model.Collection{coll}, resultList) @@ -358,7 +358,7 @@ func (suite *APIsTestSuite) TestUpdateCollections() { result, err = suite.coordinator.UpdateCollection(ctx, &model.UpdateCollection{ID: coll.ID, Metadata: coll.Metadata, ResetMetadata: true}) suite.NoError(err) suite.Equal(coll, result) - resultList, err = suite.coordinator.GetCollections(ctx, coll.ID, nil, suite.tenantName, suite.databaseName) + resultList, err = suite.coordinator.GetCollections(ctx, coll.ID, nil, suite.tenantName, suite.databaseName, nil, nil) suite.NoError(err) suite.Equal([]*model.Collection{coll}, resultList) } @@ -391,7 +391,7 @@ func (suite *APIsTestSuite) TestCreateUpdateWithDatabase() { Name: &newName1, }) suite.NoError(err) - result, err := suite.coordinator.GetCollections(ctx, suite.sampleCollections[1].ID, nil, suite.tenantName, suite.databaseName) + result, err := suite.coordinator.GetCollections(ctx, suite.sampleCollections[1].ID, nil, suite.tenantName, suite.databaseName, nil, nil) suite.NoError(err) suite.Len(result, 1) suite.Equal(newName1, result[0].Name) @@ -403,7 +403,7 @@ func (suite *APIsTestSuite) TestCreateUpdateWithDatabase() { }) suite.NoError(err) //suite.Equal(newName0, collection.Name) - result, err = suite.coordinator.GetCollections(ctx, suite.sampleCollections[0].ID, nil, suite.tenantName, newDatabaseName) + result, err = suite.coordinator.GetCollections(ctx, suite.sampleCollections[0].ID, nil, suite.tenantName, newDatabaseName, nil, nil) suite.NoError(err) suite.Len(result, 1) suite.Equal(newName0, result[0].Name) @@ -441,7 +441,7 @@ func (suite *APIsTestSuite) TestGetMultipleWithDatabase() { suite.NoError(err) suite.sampleCollections[index] = collection } - result, err := suite.coordinator.GetCollections(ctx, types.NilUniqueID(), nil, suite.tenantName, newDatabaseName) + result, err := suite.coordinator.GetCollections(ctx, types.NilUniqueID(), nil, suite.tenantName, newDatabaseName, nil, nil) suite.NoError(err) suite.Equal(len(suite.sampleCollections), len(result)) sort.Slice(result, func(i, j int) bool { @@ -449,7 +449,7 @@ func (suite *APIsTestSuite) TestGetMultipleWithDatabase() { }) suite.Equal(suite.sampleCollections, result) - result, err = suite.coordinator.GetCollections(ctx, types.NilUniqueID(), nil, suite.tenantName, suite.databaseName) + result, err = suite.coordinator.GetCollections(ctx, types.NilUniqueID(), nil, suite.tenantName, suite.databaseName, nil, nil) suite.NoError(err) suite.Equal(len(suite.sampleCollections), len(result)) @@ -526,7 +526,7 @@ func (suite *APIsTestSuite) TestCreateDatabaseWithTenants() { expected := []*model.Collection{suite.sampleCollections[0]} expected[0].TenantID = newTenantName expected[0].DatabaseName = newDatabaseName - result, err := suite.coordinator.GetCollections(ctx, types.NilUniqueID(), nil, newTenantName, newDatabaseName) + result, err := suite.coordinator.GetCollections(ctx, types.NilUniqueID(), nil, newTenantName, newDatabaseName, nil, nil) suite.NoError(err) suite.Len(result, 1) suite.Equal(expected[0], result[0]) @@ -534,14 +534,14 @@ func (suite *APIsTestSuite) TestCreateDatabaseWithTenants() { expected = []*model.Collection{suite.sampleCollections[1]} expected[0].TenantID = suite.tenantName expected[0].DatabaseName = newDatabaseName - result, err = suite.coordinator.GetCollections(ctx, types.NilUniqueID(), nil, suite.tenantName, newDatabaseName) + result, err = suite.coordinator.GetCollections(ctx, types.NilUniqueID(), nil, suite.tenantName, newDatabaseName, nil, nil) suite.NoError(err) suite.Len(result, 1) suite.Equal(expected[0], result[0]) // A new tenant DOES NOT have a default database. This does not error, instead 0 // results are returned - result, err = suite.coordinator.GetCollections(ctx, types.NilUniqueID(), nil, newTenantName, suite.databaseName) + result, err = suite.coordinator.GetCollections(ctx, types.NilUniqueID(), nil, newTenantName, suite.databaseName, nil, nil) suite.NoError(err) suite.Nil(result) diff --git a/go/pkg/coordinator/grpc/collection_service.go b/go/pkg/coordinator/grpc/collection_service.go index ad724a1ca41..de28b5c78e7 100644 --- a/go/pkg/coordinator/grpc/collection_service.go +++ b/go/pkg/coordinator/grpc/collection_service.go @@ -100,6 +100,8 @@ func (s *Server) GetCollections(ctx context.Context, req *coordinatorpb.GetColle collectionName := req.Name tenantID := req.Tenant databaseName := req.Database + limit := req.Limit + offset := req.Offset res := &coordinatorpb.GetCollectionsResponse{} @@ -110,7 +112,7 @@ func (s *Server) GetCollections(ctx context.Context, req *coordinatorpb.GetColle return res, nil } - collections, err := s.coordinator.GetCollections(ctx, parsedCollectionID, collectionName, tenantID, databaseName) + collections, err := s.coordinator.GetCollections(ctx, parsedCollectionID, collectionName, tenantID, databaseName, limit, offset) if err != nil { log.Error("error getting collections", zap.Error(err)) res.Status = failResponseWithError(err, errorCode) diff --git a/go/pkg/metastore/catalog.go b/go/pkg/metastore/catalog.go index 52a5d91037a..3c0958974f5 100644 --- a/go/pkg/metastore/catalog.go +++ b/go/pkg/metastore/catalog.go @@ -15,7 +15,7 @@ import ( type Catalog interface { ResetState(ctx context.Context) error CreateCollection(ctx context.Context, createCollection *model.CreateCollection, ts types.Timestamp) (*model.Collection, error) - GetCollections(ctx context.Context, collectionID types.UniqueID, collectionName *string, tenantID string, databaseName string) ([]*model.Collection, error) + GetCollections(ctx context.Context, collectionID types.UniqueID, collectionName *string, tenantID string, databaseName string, limit *int32, offset *int32) ([]*model.Collection, error) DeleteCollection(ctx context.Context, deleteCollection *model.DeleteCollection) error UpdateCollection(ctx context.Context, updateCollection *model.UpdateCollection, ts types.Timestamp) (*model.Collection, error) CreateSegment(ctx context.Context, createSegment *model.CreateSegment, ts types.Timestamp) (*model.Segment, error) diff --git a/go/pkg/metastore/coordinator/table_catalog.go b/go/pkg/metastore/coordinator/table_catalog.go index fcbe8e76774..5ed9ed11270 100644 --- a/go/pkg/metastore/coordinator/table_catalog.go +++ b/go/pkg/metastore/coordinator/table_catalog.go @@ -228,7 +228,7 @@ func (tc *Catalog) CreateCollection(ctx context.Context, createCollection *model } collectionName := createCollection.Name - existing, err := tc.metaDomain.CollectionDb(txCtx).GetCollections(nil, &collectionName, tenantID, databaseName) + existing, err := tc.metaDomain.CollectionDb(txCtx).GetCollections(nil, &collectionName, tenantID, databaseName, nil, nil) if err != nil { log.Error("error getting collection", zap.Error(err)) return err @@ -280,7 +280,7 @@ func (tc *Catalog) CreateCollection(ctx context.Context, createCollection *model } } // get collection - collectionList, err := tc.metaDomain.CollectionDb(txCtx).GetCollections(types.FromUniqueID(createCollection.ID), nil, tenantID, databaseName) + collectionList, err := tc.metaDomain.CollectionDb(txCtx).GetCollections(types.FromUniqueID(createCollection.ID), nil, tenantID, databaseName, nil, nil) if err != nil { log.Error("error getting collection", zap.Error(err)) return err @@ -306,8 +306,8 @@ func (tc *Catalog) CreateCollection(ctx context.Context, createCollection *model return result, nil } -func (tc *Catalog) GetCollections(ctx context.Context, collectionID types.UniqueID, collectionName *string, tenantID string, databaseName string) ([]*model.Collection, error) { - collectionAndMetadataList, err := tc.metaDomain.CollectionDb(ctx).GetCollections(types.FromUniqueID(collectionID), collectionName, tenantID, databaseName) +func (tc *Catalog) GetCollections(ctx context.Context, collectionID types.UniqueID, collectionName *string, tenantID string, databaseName string, limit *int32, offset *int32) ([]*model.Collection, error) { + collectionAndMetadataList, err := tc.metaDomain.CollectionDb(ctx).GetCollections(types.FromUniqueID(collectionID), collectionName, tenantID, databaseName, limit, offset) if err != nil { return nil, err } @@ -319,7 +319,7 @@ func (tc *Catalog) DeleteCollection(ctx context.Context, deleteCollection *model log.Info("deleting collection", zap.Any("deleteCollection", deleteCollection)) return tc.txImpl.Transaction(ctx, func(txCtx context.Context) error { collectionID := deleteCollection.ID - collectionAndMetadata, err := tc.metaDomain.CollectionDb(txCtx).GetCollections(types.FromUniqueID(collectionID), nil, deleteCollection.TenantID, deleteCollection.DatabaseName) + collectionAndMetadata, err := tc.metaDomain.CollectionDb(txCtx).GetCollections(types.FromUniqueID(collectionID), nil, deleteCollection.TenantID, deleteCollection.DatabaseName, nil, nil) if err != nil { return err } @@ -399,7 +399,7 @@ func (tc *Catalog) UpdateCollection(ctx context.Context, updateCollection *model } databaseName := updateCollection.DatabaseName tenantID := updateCollection.TenantID - collectionList, err := tc.metaDomain.CollectionDb(txCtx).GetCollections(types.FromUniqueID(updateCollection.ID), nil, tenantID, databaseName) + collectionList, err := tc.metaDomain.CollectionDb(txCtx).GetCollections(types.FromUniqueID(updateCollection.ID), nil, tenantID, databaseName, nil, nil) if err != nil { return err } diff --git a/go/pkg/metastore/coordinator/table_catalog_test.go b/go/pkg/metastore/coordinator/table_catalog_test.go index d913925550e..71cfb34c800 100644 --- a/go/pkg/metastore/coordinator/table_catalog_test.go +++ b/go/pkg/metastore/coordinator/table_catalog_test.go @@ -110,10 +110,11 @@ func TestCatalog_GetCollections(t *testing.T) { // mock the get collections method mockMetaDomain.On("CollectionDb", context.Background()).Return(&mocks.ICollectionDb{}) - mockMetaDomain.CollectionDb(context.Background()).(*mocks.ICollectionDb).On("GetCollections", types.FromUniqueID(collectionID), &collectionName, common.DefaultTenant, common.DefaultDatabase).Return(collectionAndMetadataList, nil) + var n *int32 + mockMetaDomain.CollectionDb(context.Background()).(*mocks.ICollectionDb).On("GetCollections", types.FromUniqueID(collectionID), &collectionName, common.DefaultTenant, common.DefaultDatabase, n, n).Return(collectionAndMetadataList, nil) // call the GetCollections method - collections, err := catalog.GetCollections(context.Background(), collectionID, &collectionName, defaultTenant, defaultDatabase) + collections, err := catalog.GetCollections(context.Background(), collectionID, &collectionName, defaultTenant, defaultDatabase, nil, nil) // assert that the method returned no error assert.NoError(t, err) diff --git a/go/pkg/metastore/db/dao/collection.go b/go/pkg/metastore/db/dao/collection.go index 3a41b833022..82a12110f2e 100644 --- a/go/pkg/metastore/db/dao/collection.go +++ b/go/pkg/metastore/db/dao/collection.go @@ -26,7 +26,7 @@ func (s *collectionDb) DeleteAll() error { return s.db.Where("1 = 1").Delete(&dbmodel.Collection{}).Error } -func (s *collectionDb) GetCollections(id *string, name *string, tenantID string, databaseName string) ([]*dbmodel.CollectionAndMetadata, error) { +func (s *collectionDb) GetCollections(id *string, name *string, tenantID string, databaseName string, limit *int32, offset *int32) ([]*dbmodel.CollectionAndMetadata, error) { var getCollectionInput strings.Builder getCollectionInput.WriteString("GetCollections input: ") @@ -37,6 +37,15 @@ func (s *collectionDb) GetCollections(id *string, name *string, tenantID string, Joins("LEFT JOIN collection_metadata ON collections.id = collection_metadata.collection_id"). Joins("INNER JOIN databases ON collections.database_id = databases.id"). Order("collections.id") + if limit != nil { + query = query.Limit(int(*limit)) + getCollectionInput.WriteString("limit: " + string(*limit) + ", ") + } + + if offset != nil { + query = query.Offset(int(*offset)) + getCollectionInput.WriteString("offset: " + string(*offset) + ", ") + } if databaseName != "" { query = query.Where("databases.name = ?", databaseName) diff --git a/go/pkg/metastore/db/dao/collection_test.go b/go/pkg/metastore/db/dao/collection_test.go index 7be7828e225..95665e13419 100644 --- a/go/pkg/metastore/db/dao/collection_test.go +++ b/go/pkg/metastore/db/dao/collection_test.go @@ -65,7 +65,7 @@ func (suite *CollectionDbTestSuite) TestCollectionDb_GetCollections() { suite.NoError(err) suite.Equal(collectionID, scanedCollectionID) } - collections, err := suite.collectionDb.GetCollections(nil, nil, suite.tenantName, suite.databaseName) + collections, err := suite.collectionDb.GetCollections(nil, nil, suite.tenantName, suite.databaseName, nil, nil) suite.NoError(err) suite.Len(collections, 1) suite.Equal(collectionID, collections[0].Collection.ID) @@ -75,17 +75,38 @@ func (suite *CollectionDbTestSuite) TestCollectionDb_GetCollections() { suite.Equal(metadata.StrValue, collections[0].CollectionMetadata[0].StrValue) // Test when filtering by ID - collections, err = suite.collectionDb.GetCollections(nil, nil, suite.tenantName, suite.databaseName) + collections, err = suite.collectionDb.GetCollections(nil, nil, suite.tenantName, suite.databaseName, nil, nil) suite.NoError(err) suite.Len(collections, 1) suite.Equal(collectionID, collections[0].Collection.ID) // Test when filtering by name - collections, err = suite.collectionDb.GetCollections(nil, &collectionName, suite.tenantName, suite.databaseName) + collections, err = suite.collectionDb.GetCollections(nil, &collectionName, suite.tenantName, suite.databaseName, nil, nil) suite.NoError(err) suite.Len(collections, 1) suite.Equal(collectionID, collections[0].Collection.ID) + // Test limit and offset + collection2, err := CreateTestCollection(suite.db, "test_collection_get_collections2", 128, suite.databaseId) + suite.NoError(err) + collections, err = suite.collectionDb.GetCollections(nil, nil, suite.tenantName, suite.databaseName, nil, nil) + suite.NoError(err) + suite.Len(collections, 2) + limit := int32(1) + offset := int32(1) + collections, err = suite.collectionDb.GetCollections(nil, nil, suite.tenantName, suite.databaseName, &limit, nil) + suite.NoError(err) + suite.Len(collections, 1) + suite.Equal(collectionID, collections[0].Collection.ID) + collections, err = suite.collectionDb.GetCollections(nil, nil, suite.tenantName, suite.databaseName, &limit, &offset) + suite.NoError(err) + suite.Len(collections, 1) + suite.Equal(collection2, collections[0].Collection.ID) + offset = int32(2) + collections, err = suite.collectionDb.GetCollections(nil, nil, suite.tenantName, suite.databaseName, &limit, &offset) + suite.NoError(err) + suite.Nil(collections) + // clean up err = CleanUpTestCollection(suite.db, collectionID) suite.NoError(err) @@ -95,7 +116,7 @@ func (suite *CollectionDbTestSuite) TestCollectionDb_UpdateLogPositionAndVersion collectionName := "test_collection_get_collections" collectionID, err := CreateTestCollection(suite.db, collectionName, 128, suite.databaseId) // verify default values - collections, err := suite.collectionDb.GetCollections(&collectionID, nil, "", "") + collections, err := suite.collectionDb.GetCollections(&collectionID, nil, "", "", nil, nil) suite.NoError(err) suite.Len(collections, 1) suite.Equal(int64(0), collections[0].Collection.LogPosition) @@ -105,7 +126,7 @@ func (suite *CollectionDbTestSuite) TestCollectionDb_UpdateLogPositionAndVersion version, err := suite.collectionDb.UpdateLogPositionAndVersion(collectionID, int64(10), 0) suite.NoError(err) suite.Equal(int32(1), version) - collections, err = suite.collectionDb.GetCollections(&collectionID, nil, "", "") + collections, err = suite.collectionDb.GetCollections(&collectionID, nil, "", "", nil, nil) suite.Len(collections, 1) suite.Equal(int64(10), collections[0].Collection.LogPosition) suite.Equal(int32(1), collections[0].Collection.Version) diff --git a/go/pkg/metastore/db/dao/test_utils.go b/go/pkg/metastore/db/dao/test_utils.go index 874dcabc112..5cb5734b183 100644 --- a/go/pkg/metastore/db/dao/test_utils.go +++ b/go/pkg/metastore/db/dao/test_utils.go @@ -52,7 +52,7 @@ func CleanUpTestDatabase(db *gorm.DB, tenantName string, databaseName string) er collectionDb := &collectionDb{ db: db, } - collections, err := collectionDb.GetCollections(nil, nil, tenantName, databaseName) + collections, err := collectionDb.GetCollections(nil, nil, tenantName, databaseName, nil, nil) log.Info("clean up test database", zap.Int("collections", len(collections))) if err != nil { return err diff --git a/go/pkg/metastore/db/dbcore/core.go b/go/pkg/metastore/db/dbcore/core.go index 956df311253..77bc37cff1d 100644 --- a/go/pkg/metastore/db/dbcore/core.go +++ b/go/pkg/metastore/db/dbcore/core.go @@ -3,13 +3,15 @@ package dbcore import ( "context" "fmt" - "os" + "github.com/chroma-core/chroma/go/pkg/types" + "github.com/docker/go-connections/nat" + "github.com/testcontainers/testcontainers-go" + postgres2 "github.com/testcontainers/testcontainers-go/modules/postgres" + "github.com/testcontainers/testcontainers-go/wait" "reflect" "strconv" "time" - "github.com/chroma-core/chroma/go/pkg/types" - "github.com/chroma-core/chroma/go/pkg/common" "github.com/chroma-core/chroma/go/pkg/metastore/db/dbmodel" "github.com/pingcap/log" @@ -188,13 +190,34 @@ func CreateTestTables(db *gorm.DB) { } func GetDBConfigForTesting() DBConfig { - dbAddress := os.Getenv("POSTGRES_HOST") - dbPort, _ := strconv.Atoi(os.Getenv("POSTGRES_PORT")) + var container *postgres2.PostgresContainer + dbName := "chroma" + dbUsername := "chroma" + dbPassword := "chroma" + container, _ = postgres2.RunContainer(context.Background(), + testcontainers.WithImage("docker.io/postgres:15.2-alpine"), + postgres2.WithDatabase(dbName), + postgres2.WithUsername(dbUsername), + postgres2.WithPassword(dbPassword), + testcontainers.WithWaitStrategy( + wait.ForLog("database system is ready to accept connections"). + WithOccurrence(2). + WithStartupTimeout(5*time.Second)), + ) + + var ports nat.PortMap + ports, _ = container.Ports(context.Background()) + + if _, ok := ports["5432/tcp"]; !ok { + + } + port := ports["5432/tcp"][0].HostPort + p, _ := strconv.Atoi(port) return DBConfig{ Username: "chroma", Password: "chroma", - Address: dbAddress, - Port: dbPort, + Address: "localhost", + Port: p, DBName: "chroma", MaxIdleConns: 10, MaxOpenConns: 100, diff --git a/go/pkg/metastore/db/dbmodel/collection.go b/go/pkg/metastore/db/dbmodel/collection.go index c6c769b4fa2..ca5ad284607 100644 --- a/go/pkg/metastore/db/dbmodel/collection.go +++ b/go/pkg/metastore/db/dbmodel/collection.go @@ -32,7 +32,7 @@ type CollectionAndMetadata struct { //go:generate mockery --name=ICollectionDb type ICollectionDb interface { - GetCollections(collectionID *string, collectionName *string, tenantID string, databaseName string) ([]*CollectionAndMetadata, error) + GetCollections(collectionID *string, collectionName *string, tenantID string, databaseName string, limit *int32, offset *int32) ([]*CollectionAndMetadata, error) DeleteCollectionByID(collectionID string) (int, error) Insert(in *Collection) error Update(in *Collection) error diff --git a/go/pkg/metastore/db/dbmodel/mocks/ICollectionDb.go b/go/pkg/metastore/db/dbmodel/mocks/ICollectionDb.go index 18624756268..83561df29d0 100644 --- a/go/pkg/metastore/db/dbmodel/mocks/ICollectionDb.go +++ b/go/pkg/metastore/db/dbmodel/mocks/ICollectionDb.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks @@ -58,9 +58,9 @@ func (_m *ICollectionDb) DeleteCollectionByID(collectionID string) (int, error) return r0, r1 } -// GetCollections provides a mock function with given fields: collectionID, collectionName, tenantID, databaseName -func (_m *ICollectionDb) GetCollections(collectionID *string, collectionName *string, tenantID string, databaseName string) ([]*dbmodel.CollectionAndMetadata, error) { - ret := _m.Called(collectionID, collectionName, tenantID, databaseName) +// GetCollections provides a mock function with given fields: collectionID, collectionName, tenantID, databaseName, limit, offset +func (_m *ICollectionDb) GetCollections(collectionID *string, collectionName *string, tenantID string, databaseName string, limit *int32, offset *int32) ([]*dbmodel.CollectionAndMetadata, error) { + ret := _m.Called(collectionID, collectionName, tenantID, databaseName, limit, offset) if len(ret) == 0 { panic("no return value specified for GetCollections") @@ -68,19 +68,19 @@ func (_m *ICollectionDb) GetCollections(collectionID *string, collectionName *st var r0 []*dbmodel.CollectionAndMetadata var r1 error - if rf, ok := ret.Get(0).(func(*string, *string, string, string) ([]*dbmodel.CollectionAndMetadata, error)); ok { - return rf(collectionID, collectionName, tenantID, databaseName) + if rf, ok := ret.Get(0).(func(*string, *string, string, string, *int32, *int32) ([]*dbmodel.CollectionAndMetadata, error)); ok { + return rf(collectionID, collectionName, tenantID, databaseName, limit, offset) } - if rf, ok := ret.Get(0).(func(*string, *string, string, string) []*dbmodel.CollectionAndMetadata); ok { - r0 = rf(collectionID, collectionName, tenantID, databaseName) + if rf, ok := ret.Get(0).(func(*string, *string, string, string, *int32, *int32) []*dbmodel.CollectionAndMetadata); ok { + r0 = rf(collectionID, collectionName, tenantID, databaseName, limit, offset) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]*dbmodel.CollectionAndMetadata) } } - if rf, ok := ret.Get(1).(func(*string, *string, string, string) error); ok { - r1 = rf(collectionID, collectionName, tenantID, databaseName) + if rf, ok := ret.Get(1).(func(*string, *string, string, string, *int32, *int32) error); ok { + r1 = rf(collectionID, collectionName, tenantID, databaseName, limit, offset) } else { r1 = ret.Error(1) } diff --git a/go/pkg/metastore/mocks/Catalog.go b/go/pkg/metastore/mocks/Catalog.go index 596d2b6a33f..99f1d2dc6d0 100644 --- a/go/pkg/metastore/mocks/Catalog.go +++ b/go/pkg/metastore/mocks/Catalog.go @@ -1,10 +1,12 @@ -// Code generated by mockery v2.33.3. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks import ( context "context" + dbmodel "github.com/chroma-core/chroma/go/pkg/metastore/db/dbmodel" + mock "github.com/stretchr/testify/mock" model "github.com/chroma-core/chroma/go/pkg/model" @@ -17,17 +19,21 @@ type Catalog struct { mock.Mock } -// CreateCollection provides a mock function with given fields: ctx, collectionInfo, ts -func (_m *Catalog) CreateCollection(ctx context.Context, collectionInfo *model.CreateCollection, ts int64) (*model.Collection, error) { - ret := _m.Called(ctx, collectionInfo, ts) +// CreateCollection provides a mock function with given fields: ctx, createCollection, ts +func (_m *Catalog) CreateCollection(ctx context.Context, createCollection *model.CreateCollection, ts int64) (*model.Collection, error) { + ret := _m.Called(ctx, createCollection, ts) + + if len(ret) == 0 { + panic("no return value specified for CreateCollection") + } var r0 *model.Collection var r1 error if rf, ok := ret.Get(0).(func(context.Context, *model.CreateCollection, int64) (*model.Collection, error)); ok { - return rf(ctx, collectionInfo, ts) + return rf(ctx, createCollection, ts) } if rf, ok := ret.Get(0).(func(context.Context, *model.CreateCollection, int64) *model.Collection); ok { - r0 = rf(ctx, collectionInfo, ts) + r0 = rf(ctx, createCollection, ts) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*model.Collection) @@ -35,7 +41,7 @@ func (_m *Catalog) CreateCollection(ctx context.Context, collectionInfo *model.C } if rf, ok := ret.Get(1).(func(context.Context, *model.CreateCollection, int64) error); ok { - r1 = rf(ctx, collectionInfo, ts) + r1 = rf(ctx, createCollection, ts) } else { r1 = ret.Error(1) } @@ -43,17 +49,51 @@ func (_m *Catalog) CreateCollection(ctx context.Context, collectionInfo *model.C return r0, r1 } -// CreateSegment provides a mock function with given fields: ctx, segmentInfo, ts -func (_m *Catalog) CreateSegment(ctx context.Context, segmentInfo *model.CreateSegment, ts int64) (*model.Segment, error) { - ret := _m.Called(ctx, segmentInfo, ts) +// CreateDatabase provides a mock function with given fields: ctx, createDatabase, ts +func (_m *Catalog) CreateDatabase(ctx context.Context, createDatabase *model.CreateDatabase, ts int64) (*model.Database, error) { + ret := _m.Called(ctx, createDatabase, ts) + + if len(ret) == 0 { + panic("no return value specified for CreateDatabase") + } + + var r0 *model.Database + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *model.CreateDatabase, int64) (*model.Database, error)); ok { + return rf(ctx, createDatabase, ts) + } + if rf, ok := ret.Get(0).(func(context.Context, *model.CreateDatabase, int64) *model.Database); ok { + r0 = rf(ctx, createDatabase, ts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Database) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *model.CreateDatabase, int64) error); ok { + r1 = rf(ctx, createDatabase, ts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateSegment provides a mock function with given fields: ctx, createSegment, ts +func (_m *Catalog) CreateSegment(ctx context.Context, createSegment *model.CreateSegment, ts int64) (*model.Segment, error) { + ret := _m.Called(ctx, createSegment, ts) + + if len(ret) == 0 { + panic("no return value specified for CreateSegment") + } var r0 *model.Segment var r1 error if rf, ok := ret.Get(0).(func(context.Context, *model.CreateSegment, int64) (*model.Segment, error)); ok { - return rf(ctx, segmentInfo, ts) + return rf(ctx, createSegment, ts) } if rf, ok := ret.Get(0).(func(context.Context, *model.CreateSegment, int64) *model.Segment); ok { - r0 = rf(ctx, segmentInfo, ts) + r0 = rf(ctx, createSegment, ts) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*model.Segment) @@ -61,7 +101,37 @@ func (_m *Catalog) CreateSegment(ctx context.Context, segmentInfo *model.CreateS } if rf, ok := ret.Get(1).(func(context.Context, *model.CreateSegment, int64) error); ok { - r1 = rf(ctx, segmentInfo, ts) + r1 = rf(ctx, createSegment, ts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateTenant provides a mock function with given fields: ctx, createTenant, ts +func (_m *Catalog) CreateTenant(ctx context.Context, createTenant *model.CreateTenant, ts int64) (*model.Tenant, error) { + ret := _m.Called(ctx, createTenant, ts) + + if len(ret) == 0 { + panic("no return value specified for CreateTenant") + } + + var r0 *model.Tenant + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *model.CreateTenant, int64) (*model.Tenant, error)); ok { + return rf(ctx, createTenant, ts) + } + if rf, ok := ret.Get(0).(func(context.Context, *model.CreateTenant, int64) *model.Tenant); ok { + r0 = rf(ctx, createTenant, ts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Tenant) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *model.CreateTenant, int64) error); ok { + r1 = rf(ctx, createTenant, ts) } else { r1 = ret.Error(1) } @@ -69,13 +139,17 @@ func (_m *Catalog) CreateSegment(ctx context.Context, segmentInfo *model.CreateS return r0, r1 } -// DeleteCollection provides a mock function with given fields: ctx, collectionID -func (_m *Catalog) DeleteCollection(ctx context.Context, collectionID types.UniqueID) error { - ret := _m.Called(ctx, collectionID) +// DeleteCollection provides a mock function with given fields: ctx, deleteCollection +func (_m *Catalog) DeleteCollection(ctx context.Context, deleteCollection *model.DeleteCollection) error { + ret := _m.Called(ctx, deleteCollection) + + if len(ret) == 0 { + panic("no return value specified for DeleteCollection") + } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID) error); ok { - r0 = rf(ctx, collectionID) + if rf, ok := ret.Get(0).(func(context.Context, *model.DeleteCollection) error); ok { + r0 = rf(ctx, deleteCollection) } else { r0 = ret.Error(0) } @@ -87,6 +161,10 @@ func (_m *Catalog) DeleteCollection(ctx context.Context, collectionID types.Uniq func (_m *Catalog) DeleteSegment(ctx context.Context, segmentID types.UniqueID) error { ret := _m.Called(ctx, segmentID) + if len(ret) == 0 { + panic("no return value specified for DeleteSegment") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID) error); ok { r0 = rf(ctx, segmentID) @@ -97,25 +175,149 @@ func (_m *Catalog) DeleteSegment(ctx context.Context, segmentID types.UniqueID) return r0 } -// GetCollections provides a mock function with given fields: ctx, collectionID, collectionName -func (_m *Catalog) GetCollections(ctx context.Context, collectionID types.UniqueID, collectionName *string) ([]*model.Collection, error) { - ret := _m.Called(ctx, collectionID, collectionName) +// FlushCollectionCompaction provides a mock function with given fields: ctx, flushCollectionCompaction +func (_m *Catalog) FlushCollectionCompaction(ctx context.Context, flushCollectionCompaction *model.FlushCollectionCompaction) (*model.FlushCollectionInfo, error) { + ret := _m.Called(ctx, flushCollectionCompaction) + + if len(ret) == 0 { + panic("no return value specified for FlushCollectionCompaction") + } + + var r0 *model.FlushCollectionInfo + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *model.FlushCollectionCompaction) (*model.FlushCollectionInfo, error)); ok { + return rf(ctx, flushCollectionCompaction) + } + if rf, ok := ret.Get(0).(func(context.Context, *model.FlushCollectionCompaction) *model.FlushCollectionInfo); ok { + r0 = rf(ctx, flushCollectionCompaction) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.FlushCollectionInfo) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *model.FlushCollectionCompaction) error); ok { + r1 = rf(ctx, flushCollectionCompaction) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetAllDatabases provides a mock function with given fields: ctx, ts +func (_m *Catalog) GetAllDatabases(ctx context.Context, ts int64) ([]*model.Database, error) { + ret := _m.Called(ctx, ts) + + if len(ret) == 0 { + panic("no return value specified for GetAllDatabases") + } + + var r0 []*model.Database + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int64) ([]*model.Database, error)); ok { + return rf(ctx, ts) + } + if rf, ok := ret.Get(0).(func(context.Context, int64) []*model.Database); ok { + r0 = rf(ctx, ts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*model.Database) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, ts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetAllTenants provides a mock function with given fields: ctx, ts +func (_m *Catalog) GetAllTenants(ctx context.Context, ts int64) ([]*model.Tenant, error) { + ret := _m.Called(ctx, ts) + + if len(ret) == 0 { + panic("no return value specified for GetAllTenants") + } + + var r0 []*model.Tenant + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int64) ([]*model.Tenant, error)); ok { + return rf(ctx, ts) + } + if rf, ok := ret.Get(0).(func(context.Context, int64) []*model.Tenant); ok { + r0 = rf(ctx, ts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*model.Tenant) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, ts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetCollections provides a mock function with given fields: ctx, collectionID, collectionName, tenantID, databaseName, limit, offset +func (_m *Catalog) GetCollections(ctx context.Context, collectionID types.UniqueID, collectionName *string, tenantID string, databaseName string, limit *int32, offset *int32) ([]*model.Collection, error) { + ret := _m.Called(ctx, collectionID, collectionName, tenantID, databaseName, limit, offset) + + if len(ret) == 0 { + panic("no return value specified for GetCollections") + } var r0 []*model.Collection var r1 error - if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string) ([]*model.Collection, error)); ok { - return rf(ctx, collectionID, collectionName) + if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string, string, string, *int32, *int32) ([]*model.Collection, error)); ok { + return rf(ctx, collectionID, collectionName, tenantID, databaseName, limit, offset) } - if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string) []*model.Collection); ok { - r0 = rf(ctx, collectionID, collectionName) + if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string, string, string, *int32, *int32) []*model.Collection); ok { + r0 = rf(ctx, collectionID, collectionName, tenantID, databaseName, limit, offset) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]*model.Collection) } } - if rf, ok := ret.Get(1).(func(context.Context, types.UniqueID, *string) error); ok { - r1 = rf(ctx, collectionID, collectionName) + if rf, ok := ret.Get(1).(func(context.Context, types.UniqueID, *string, string, string, *int32, *int32) error); ok { + r1 = rf(ctx, collectionID, collectionName, tenantID, databaseName, limit, offset) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetDatabases provides a mock function with given fields: ctx, getDatabase, ts +func (_m *Catalog) GetDatabases(ctx context.Context, getDatabase *model.GetDatabase, ts int64) (*model.Database, error) { + ret := _m.Called(ctx, getDatabase, ts) + + if len(ret) == 0 { + panic("no return value specified for GetDatabases") + } + + var r0 *model.Database + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *model.GetDatabase, int64) (*model.Database, error)); ok { + return rf(ctx, getDatabase, ts) + } + if rf, ok := ret.Get(0).(func(context.Context, *model.GetDatabase, int64) *model.Database); ok { + r0 = rf(ctx, getDatabase, ts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Database) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *model.GetDatabase, int64) error); ok { + r1 = rf(ctx, getDatabase, ts) } else { r1 = ret.Error(1) } @@ -123,25 +325,89 @@ func (_m *Catalog) GetCollections(ctx context.Context, collectionID types.Unique return r0, r1 } -// GetSegments provides a mock function with given fields: ctx, segmentID, segmentType, scope, collectionID, ts -func (_m *Catalog) GetSegments(ctx context.Context, segmentID types.UniqueID, segmentType *string, scope *string, collectionID types.UniqueID, ts int64) ([]*model.Segment, error) { - ret := _m.Called(ctx, segmentID, segmentType, scope, collectionID, ts) +// GetSegments provides a mock function with given fields: ctx, segmentID, segmentType, scope, collectionID +func (_m *Catalog) GetSegments(ctx context.Context, segmentID types.UniqueID, segmentType *string, scope *string, collectionID types.UniqueID) ([]*model.Segment, error) { + ret := _m.Called(ctx, segmentID, segmentType, scope, collectionID) + + if len(ret) == 0 { + panic("no return value specified for GetSegments") + } var r0 []*model.Segment var r1 error - if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string, *string, types.UniqueID, int64) ([]*model.Segment, error)); ok { - return rf(ctx, segmentID, segmentType, scope, collectionID, ts) + if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string, *string, types.UniqueID) ([]*model.Segment, error)); ok { + return rf(ctx, segmentID, segmentType, scope, collectionID) } - if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string, *string, types.UniqueID, int64) []*model.Segment); ok { - r0 = rf(ctx, segmentID, segmentType, scope, collectionID, ts) + if rf, ok := ret.Get(0).(func(context.Context, types.UniqueID, *string, *string, types.UniqueID) []*model.Segment); ok { + r0 = rf(ctx, segmentID, segmentType, scope, collectionID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]*model.Segment) } } - if rf, ok := ret.Get(1).(func(context.Context, types.UniqueID, *string, *string, types.UniqueID, int64) error); ok { - r1 = rf(ctx, segmentID, segmentType, scope, collectionID, ts) + if rf, ok := ret.Get(1).(func(context.Context, types.UniqueID, *string, *string, types.UniqueID) error); ok { + r1 = rf(ctx, segmentID, segmentType, scope, collectionID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetTenants provides a mock function with given fields: ctx, getTenant, ts +func (_m *Catalog) GetTenants(ctx context.Context, getTenant *model.GetTenant, ts int64) (*model.Tenant, error) { + ret := _m.Called(ctx, getTenant, ts) + + if len(ret) == 0 { + panic("no return value specified for GetTenants") + } + + var r0 *model.Tenant + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *model.GetTenant, int64) (*model.Tenant, error)); ok { + return rf(ctx, getTenant, ts) + } + if rf, ok := ret.Get(0).(func(context.Context, *model.GetTenant, int64) *model.Tenant); ok { + r0 = rf(ctx, getTenant, ts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Tenant) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *model.GetTenant, int64) error); ok { + r1 = rf(ctx, getTenant, ts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetTenantsLastCompactionTime provides a mock function with given fields: ctx, tenantIDs +func (_m *Catalog) GetTenantsLastCompactionTime(ctx context.Context, tenantIDs []string) ([]*dbmodel.Tenant, error) { + ret := _m.Called(ctx, tenantIDs) + + if len(ret) == 0 { + panic("no return value specified for GetTenantsLastCompactionTime") + } + + var r0 []*dbmodel.Tenant + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []string) ([]*dbmodel.Tenant, error)); ok { + return rf(ctx, tenantIDs) + } + if rf, ok := ret.Get(0).(func(context.Context, []string) []*dbmodel.Tenant); ok { + r0 = rf(ctx, tenantIDs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*dbmodel.Tenant) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []string) error); ok { + r1 = rf(ctx, tenantIDs) } else { r1 = ret.Error(1) } @@ -153,6 +419,10 @@ func (_m *Catalog) GetSegments(ctx context.Context, segmentID types.UniqueID, se func (_m *Catalog) ResetState(ctx context.Context) error { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for ResetState") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context) error); ok { r0 = rf(ctx) @@ -163,17 +433,39 @@ func (_m *Catalog) ResetState(ctx context.Context) error { return r0 } -// UpdateCollection provides a mock function with given fields: ctx, collectionInfo, ts -func (_m *Catalog) UpdateCollection(ctx context.Context, collectionInfo *model.UpdateCollection, ts int64) (*model.Collection, error) { - ret := _m.Called(ctx, collectionInfo, ts) +// SetTenantLastCompactionTime provides a mock function with given fields: ctx, tenantID, lastCompactionTime +func (_m *Catalog) SetTenantLastCompactionTime(ctx context.Context, tenantID string, lastCompactionTime int64) error { + ret := _m.Called(ctx, tenantID, lastCompactionTime) + + if len(ret) == 0 { + panic("no return value specified for SetTenantLastCompactionTime") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, int64) error); ok { + r0 = rf(ctx, tenantID, lastCompactionTime) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UpdateCollection provides a mock function with given fields: ctx, updateCollection, ts +func (_m *Catalog) UpdateCollection(ctx context.Context, updateCollection *model.UpdateCollection, ts int64) (*model.Collection, error) { + ret := _m.Called(ctx, updateCollection, ts) + + if len(ret) == 0 { + panic("no return value specified for UpdateCollection") + } var r0 *model.Collection var r1 error if rf, ok := ret.Get(0).(func(context.Context, *model.UpdateCollection, int64) (*model.Collection, error)); ok { - return rf(ctx, collectionInfo, ts) + return rf(ctx, updateCollection, ts) } if rf, ok := ret.Get(0).(func(context.Context, *model.UpdateCollection, int64) *model.Collection); ok { - r0 = rf(ctx, collectionInfo, ts) + r0 = rf(ctx, updateCollection, ts) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*model.Collection) @@ -181,7 +473,37 @@ func (_m *Catalog) UpdateCollection(ctx context.Context, collectionInfo *model.U } if rf, ok := ret.Get(1).(func(context.Context, *model.UpdateCollection, int64) error); ok { - r1 = rf(ctx, collectionInfo, ts) + r1 = rf(ctx, updateCollection, ts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UpdateSegment provides a mock function with given fields: ctx, segmentInfo, ts +func (_m *Catalog) UpdateSegment(ctx context.Context, segmentInfo *model.UpdateSegment, ts int64) (*model.Segment, error) { + ret := _m.Called(ctx, segmentInfo, ts) + + if len(ret) == 0 { + panic("no return value specified for UpdateSegment") + } + + var r0 *model.Segment + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *model.UpdateSegment, int64) (*model.Segment, error)); ok { + return rf(ctx, segmentInfo, ts) + } + if rf, ok := ret.Get(0).(func(context.Context, *model.UpdateSegment, int64) *model.Segment); ok { + r0 = rf(ctx, segmentInfo, ts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*model.Segment) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *model.UpdateSegment, int64) error); ok { + r1 = rf(ctx, segmentInfo, ts) } else { r1 = ret.Error(1) } diff --git a/go/pkg/proto/coordinatorpb/coordinator.pb.go b/go/pkg/proto/coordinatorpb/coordinator.pb.go index 29d4fe94433..ea393c353f0 100644 --- a/go/pkg/proto/coordinatorpb/coordinator.pb.go +++ b/go/pkg/proto/coordinatorpb/coordinator.pb.go @@ -1206,6 +1206,8 @@ type GetCollectionsRequest struct { Name *string `protobuf:"bytes,2,opt,name=name,proto3,oneof" json:"name,omitempty"` Tenant string `protobuf:"bytes,4,opt,name=tenant,proto3" json:"tenant,omitempty"` Database string `protobuf:"bytes,5,opt,name=database,proto3" json:"database,omitempty"` + Limit *int32 `protobuf:"varint,6,opt,name=limit,proto3,oneof" json:"limit,omitempty"` + Offset *int32 `protobuf:"varint,7,opt,name=offset,proto3,oneof" json:"offset,omitempty"` } func (x *GetCollectionsRequest) Reset() { @@ -1268,6 +1270,20 @@ func (x *GetCollectionsRequest) GetDatabase() string { return "" } +func (x *GetCollectionsRequest) GetLimit() int32 { + if x != nil && x.Limit != nil { + return *x.Limit + } + return 0 +} + +func (x *GetCollectionsRequest) GetOffset() int32 { + if x != nil && x.Offset != nil { + return *x.Offset + } + return 0 +} + type GetCollectionsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2122,7 +2138,7 @@ var file_chromadb_proto_coordinator_proto_rawDesc = []byte{ 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x89, 0x01, 0x0a, 0x15, + 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xd6, 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x13, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, @@ -2130,208 +2146,213 @@ var file_chromadb_proto_coordinator_proto_rawDesc = []byte{ 0x88, 0x01, 0x01, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, - 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x69, 0x64, 0x42, 0x07, - 0x0a, 0x05, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x76, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x43, 0x6f, - 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x34, 0x0a, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, - 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, - 0xee, 0x01, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x17, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x88, 0x01, 0x01, 0x12, 0x21, 0x0a, 0x09, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x48, 0x02, 0x52, 0x09, 0x64, 0x69, 0x6d, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x68, 0x72, 0x6f, - 0x6d, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x48, 0x00, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x27, 0x0a, - 0x0e, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x11, 0x0a, 0x0f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, - 0x22, 0x42, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, - 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x22, 0x6f, 0x0a, 0x0c, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6c, - 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3c, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x68, - 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0x44, 0x0a, 0x25, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, - 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x54, - 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, - 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x69, 0x0a, 0x18, 0x54, 0x65, 0x6e, - 0x61, 0x6e, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, - 0x49, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x69, 0x6d, 0x65, 0x22, 0x89, 0x01, 0x0a, 0x26, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, - 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x6f, - 0x72, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x5f, 0x0a, 0x1b, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, - 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x54, 0x65, - 0x6e, 0x61, 0x6e, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x18, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x4c, 0x61, - 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, - 0x22, 0x88, 0x01, 0x0a, 0x25, 0x53, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x54, 0x65, 0x6e, - 0x61, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5f, 0x0a, 0x1b, 0x74, 0x65, - 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x20, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x4c, + 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x48, 0x02, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x88, + 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x05, 0x48, 0x03, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x88, 0x01, 0x01, 0x42, + 0x05, 0x0a, 0x03, 0x5f, 0x69, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, + 0x08, 0x0a, 0x06, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x6f, 0x66, + 0x66, 0x73, 0x65, 0x74, 0x22, 0x76, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6c, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, + 0x0a, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x43, 0x6f, 0x6c, + 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xee, 0x01, 0x0a, + 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, + 0x01, 0x12, 0x21, 0x0a, 0x09, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x05, 0x48, 0x02, 0x52, 0x09, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, + 0x6e, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00, + 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x27, 0x0a, 0x0e, 0x72, 0x65, + 0x73, 0x65, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x08, 0x48, 0x00, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x42, 0x11, 0x0a, 0x0f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, + 0x0c, 0x0a, 0x0a, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x42, 0x0a, + 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x68, 0x72, 0x6f, + 0x6d, 0x61, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x22, 0x6f, 0x0a, 0x0c, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x22, 0x3c, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, + 0x61, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x22, 0x44, 0x0a, 0x25, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x54, 0x65, 0x6e, 0x61, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, + 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, + 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x69, 0x0a, 0x18, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, + 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, + 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, + 0x30, 0x0a, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, - 0x65, 0x52, 0x18, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, - 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, 0xde, 0x01, 0x0a, 0x1a, - 0x46, 0x6c, 0x75, 0x73, 0x68, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x70, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, - 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x50, 0x0a, 0x0a, 0x66, 0x69, 0x6c, - 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, - 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x53, 0x65, 0x67, 0x6d, - 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, - 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x1a, 0x4f, 0x0a, 0x0e, 0x46, - 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x27, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, - 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, - 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x92, 0x02, 0x0a, - 0x20, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x23, - 0x0a, 0x0d, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6c, 0x6f, 0x67, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6c, 0x6f, 0x67, 0x50, 0x6f, - 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x11, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x5a, 0x0a, 0x17, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, - 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, - 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, - 0x46, 0x6c, 0x75, 0x73, 0x68, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x70, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x15, 0x73, 0x65, 0x67, 0x6d, - 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, - 0x6f, 0x22, 0xa9, 0x01, 0x0a, 0x21, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x6f, 0x6c, 0x6c, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6c, 0x6c, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x12, - 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x14, 0x6c, - 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x43, - 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x32, 0xf4, 0x0a, - 0x0a, 0x05, 0x53, 0x79, 0x73, 0x44, 0x42, 0x12, 0x51, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x1d, 0x2e, 0x63, 0x68, 0x72, 0x6f, - 0x6d, 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, - 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x0b, 0x47, 0x65, - 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x68, 0x72, 0x6f, - 0x6d, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, - 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, - 0x6e, 0x61, 0x6e, 0x74, 0x12, 0x1b, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x42, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x12, 0x18, - 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x65, 0x6e, 0x61, 0x6e, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, - 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, - 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, - 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, 0x65, 0x67, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, 0x65, - 0x74, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1b, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x67, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x4e, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, - 0x12, 0x1c, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, - 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x57, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x63, - 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, - 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6c, - 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x51, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, 0x65, 0x74, - 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x43, - 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, - 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, - 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x68, 0x72, 0x6f, - 0x6d, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x42, 0x0a, - 0x0a, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x52, 0x65, 0x73, - 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x81, 0x01, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, + 0x65, 0x22, 0x89, 0x01, 0x0a, 0x26, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x54, 0x65, - 0x6e, 0x61, 0x6e, 0x74, 0x12, 0x2d, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, 0x65, + 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x1b, + 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, + 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, + 0x69, 0x6d, 0x65, 0x52, 0x18, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, + 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x88, 0x01, + 0x0a, 0x25, 0x53, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5f, 0x0a, 0x1b, 0x74, 0x65, 0x6e, 0x61, 0x6e, + 0x74, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, + 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x4c, 0x61, 0x73, 0x74, + 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x18, + 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, 0xde, 0x01, 0x0a, 0x1a, 0x46, 0x6c, 0x75, + 0x73, 0x68, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x67, 0x6d, 0x65, + 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x67, + 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x50, 0x0a, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, + 0x61, 0x74, 0x68, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x63, 0x68, 0x72, + 0x6f, 0x6d, 0x61, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, + 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x46, + 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x66, + 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x1a, 0x4f, 0x0a, 0x0e, 0x46, 0x69, 0x6c, 0x65, + 0x50, 0x61, 0x74, 0x68, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x27, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x68, + 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x92, 0x02, 0x0a, 0x20, 0x46, 0x6c, + 0x75, 0x73, 0x68, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, + 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, + 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, + 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x12, 0x21, 0x0a, 0x0c, 0x6c, 0x6f, 0x67, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6c, 0x6f, 0x67, 0x50, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x11, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x5a, 0x0a, 0x17, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, + 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x05, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x46, 0x6c, 0x75, + 0x73, 0x68, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x15, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, + 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xa9, + 0x01, 0x0a, 0x21, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6c, + 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x6f, 0x6c, + 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x14, 0x6c, 0x61, 0x73, 0x74, + 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x32, 0xf4, 0x0a, 0x0a, 0x05, 0x53, + 0x79, 0x73, 0x44, 0x42, 0x12, 0x51, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x61, + 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x1d, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x44, 0x61, + 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, + 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x44, + 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x4b, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x6e, 0x61, 0x6e, + 0x74, 0x12, 0x1b, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, + 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, + 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x42, + 0x0a, 0x09, 0x47, 0x65, 0x74, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x12, 0x18, 0x2e, 0x63, 0x68, + 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, + 0x65, 0x74, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x67, 0x6d, + 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x67, 0x6d, + 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x48, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, + 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, + 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0d, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x2e, + 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x67, + 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x68, + 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x67, 0x6d, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x10, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x1f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, + 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x63, 0x68, 0x72, 0x6f, + 0x6d, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x68, 0x72, + 0x6f, 0x6d, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, + 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x1d, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6c, + 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1e, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6c, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x57, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0a, 0x52, 0x65, + 0x73, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x1a, 0x1a, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x81, + 0x01, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x54, 0x65, 0x6e, 0x61, 0x6e, + 0x74, 0x12, 0x2d, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x61, + 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, + 0x46, 0x6f, 0x72, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2e, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x73, + 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x46, + 0x6f, 0x72, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x69, 0x0a, 0x1e, 0x53, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, + 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x54, 0x65, + 0x6e, 0x61, 0x6e, 0x74, 0x12, 0x2d, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x53, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x47, 0x65, 0x74, - 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, - 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x69, 0x0a, 0x1e, 0x53, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, - 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x6f, - 0x72, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x12, 0x2d, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, - 0x2e, 0x53, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x54, 0x65, 0x6e, 0x61, 0x6e, 0x74, 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, 0x22, 0x00, - 0x12, 0x72, 0x0a, 0x19, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x2e, - 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x6f, 0x6c, 0x6c, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, - 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x42, 0x3a, 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, - 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x70, 0x62, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 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, 0x22, 0x00, 0x12, 0x72, 0x0a, + 0x19, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x2e, 0x63, 0x68, 0x72, + 0x6f, 0x6d, 0x61, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2e, 0x46, 0x6c, + 0x75, 0x73, 0x68, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, + 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x42, 0x3a, 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x68, 0x72, 0x6f, + 0x6d, 0x61, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x70, 0x62, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/idl/chromadb/proto/coordinator.proto b/idl/chromadb/proto/coordinator.proto index 43668bdfad2..56d74743464 100644 --- a/idl/chromadb/proto/coordinator.proto +++ b/idl/chromadb/proto/coordinator.proto @@ -120,6 +120,8 @@ message GetCollectionsRequest { optional string name = 2; string tenant = 4; string database = 5; + optional int32 limit = 6; + optional int32 offset = 7; } message GetCollectionsResponse { diff --git a/rust/worker/src/sysdb/sysdb.rs b/rust/worker/src/sysdb/sysdb.rs index 7112f452126..3028b91fbfb 100644 --- a/rust/worker/src/sysdb/sysdb.rs +++ b/rust/worker/src/sysdb/sysdb.rs @@ -148,6 +148,8 @@ impl SysDb for GrpcSysDb { .get_collections(chroma_proto::GetCollectionsRequest { id: collection_id_str, name: name, + limit: None, + offset: None, tenant: if tenant.is_some() { tenant.unwrap() } else {