-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[ENH] GetCollectionSize on SysDB read replica #3503
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ import ( | |
type APIsTestSuite struct { | ||
suite.Suite | ||
db *gorm.DB | ||
read_db *gorm.DB | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do you think it's worth using gorm's DBResolver or is that too much framework overhead? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't want to cutover all of our reads to the read replica, which it seems DBResolver does automatically. Probably not worth at this point There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it looked like you could configure it to not use the replica by default and then explicitly use the replica with tx := db.Clauses(dbresolver.Use("secondary"), dbresolver.Write).Begin() but not strongly advocating for it |
||
collectionId1 types.UniqueID | ||
collectionId2 types.UniqueID | ||
records [][]byte | ||
|
@@ -37,7 +38,7 @@ type APIsTestSuite struct { | |
|
||
func (suite *APIsTestSuite) SetupSuite() { | ||
log.Info("setup suite") | ||
suite.db = dbcore.ConfigDatabaseForTesting() | ||
suite.db, suite.read_db = dbcore.ConfigDatabaseForTesting() | ||
} | ||
|
||
func (suite *APIsTestSuite) SetupTest() { | ||
|
@@ -53,7 +54,7 @@ func (suite *APIsTestSuite) SetupTest() { | |
collection.Name = "collection_" + suite.T().Name() + strconv.Itoa(index) | ||
} | ||
ctx := context.Background() | ||
c, err := NewCoordinator(ctx, suite.db, SoftDelete) | ||
c, err := NewCoordinator(ctx, SoftDelete) | ||
if err != nil { | ||
suite.T().Fatalf("error creating coordinator: %v", err) | ||
} | ||
|
@@ -82,9 +83,9 @@ func (suite *APIsTestSuite) TearDownTest() { | |
// TODO: This is not complete yet. We need to add more tests for the other APIs. | ||
// We will deprecate the example based tests once we have enough tests here. | ||
func testCollection(t *rapid.T) { | ||
db := dbcore.ConfigDatabaseForTesting() | ||
dbcore.ConfigDatabaseForTesting() | ||
ctx := context.Background() | ||
c, err := NewCoordinator(ctx, db, HardDelete) | ||
c, err := NewCoordinator(ctx, HardDelete) | ||
if err != nil { | ||
t.Fatalf("error creating coordinator: %v", err) | ||
} | ||
|
@@ -135,9 +136,9 @@ func testCollection(t *rapid.T) { | |
} | ||
|
||
func testSegment(t *rapid.T) { | ||
db := dbcore.ConfigDatabaseForTesting() | ||
dbcore.ConfigDatabaseForTesting() | ||
ctx := context.Background() | ||
c, err := NewCoordinator(ctx, db, HardDelete) | ||
c, err := NewCoordinator(ctx, HardDelete) | ||
if err != nil { | ||
t.Fatalf("error creating coordinator: %v", err) | ||
} | ||
|
@@ -493,6 +494,16 @@ func (suite *APIsTestSuite) TestCreateGetDeleteCollections() { | |
suite.Empty(segments) | ||
} | ||
|
||
func (suite *APIsTestSuite) TestCollectionSize() { | ||
ctx := context.Background() | ||
|
||
for _, collection := range suite.sampleCollections { | ||
result, err := suite.coordinator.GetCollectionSize(ctx, collection.ID) | ||
suite.NoError(err) | ||
suite.Equal(uint64(0), result) | ||
} | ||
} | ||
|
||
func (suite *APIsTestSuite) TestUpdateCollections() { | ||
ctx := context.Background() | ||
coll := &model.Collection{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -367,6 +367,20 @@ func (tc *Catalog) GetCollections(ctx context.Context, collectionID types.Unique | |
return collections, nil | ||
} | ||
|
||
func (tc *Catalog) GetCollectionSize(ctx context.Context, collectionID types.UniqueID) (uint64, error) { | ||
tracer := otel.Tracer | ||
if tracer != nil { | ||
_, span := tracer.Start(ctx, "Catalog.GetCollectionSize") | ||
defer span.End() | ||
} | ||
|
||
total_records_post_compaction, err := tc.metaDomain.CollectionDb(ctx).GetCollectionSize(*types.FromUniqueID(collectionID)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated to use |
||
if err != nil { | ||
return 0, err | ||
} | ||
return total_records_post_compaction, nil | ||
} | ||
|
||
func (tc *Catalog) GetCollectionWithSegments(ctx context.Context, collectionID types.UniqueID) (*model.Collection, []*model.Segment, error) { | ||
tracer := otel.Tracer | ||
if tracer != nil { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,8 @@ import ( | |
) | ||
|
||
type collectionDb struct { | ||
db *gorm.DB | ||
db *gorm.DB | ||
read_db *gorm.DB | ||
} | ||
|
||
var _ dbmodel.ICollectionDb = &collectionDb{} | ||
|
@@ -142,6 +143,29 @@ func (s *collectionDb) getCollections(id *string, name *string, tenantID string, | |
return | ||
} | ||
|
||
func (s *collectionDb) GetCollectionSize(id string) (uint64, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there some magical reason why some of these methods take a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated the call site to not require a deref. I think the use of |
||
query := s.read_db.Table("collections"). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note the use of |
||
Select("collections.total_records_post_compaction"). | ||
Where("collections.id = ?", id) | ||
|
||
rows, err := query.Rows() | ||
if err != nil { | ||
return 0, err | ||
} | ||
|
||
var totalRecordsPostCompaction uint64 | ||
|
||
for rows.Next() { | ||
err := rows.Scan(&totalRecordsPostCompaction) | ||
if err != nil { | ||
log.Error("scan collection failed", zap.Error(err)) | ||
return 0, err | ||
} | ||
} | ||
rows.Close() | ||
return totalRecordsPostCompaction, nil | ||
} | ||
|
||
func (s *collectionDb) GetSoftDeletedCollections(collectionID *string, tenantID string, databaseName string, limit int32) ([]*dbmodel.CollectionAndMetadata, error) { | ||
return s.getCollections(collectionID, nil, tenantID, databaseName, &limit, nil, true) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit of clean up—we don't actually use the
db
in the coordinator since we access theglobalDB
.