From 504d5c565100143ea62ba79085647589ede7c529 Mon Sep 17 00:00:00 2001 From: Egon Elbre Date: Tue, 24 Oct 2023 18:13:41 +0300 Subject: [PATCH] satellite/metabase: add version tests for GetLatestObjectLastSegment Change-Id: Ia7ed1f6b23bcdc9e83fec288cbf3571b382d5e13 --- satellite/metabase/delete.go | 39 +++++++--- satellite/metabase/get_test.go | 136 ++++++++++++++++++++++++++++++++- 2 files changed, 162 insertions(+), 13 deletions(-) diff --git a/satellite/metabase/delete.go b/satellite/metabase/delete.go index ef945fc91..9998b57a7 100644 --- a/satellite/metabase/delete.go +++ b/satellite/metabase/delete.go @@ -272,12 +272,16 @@ func (db *DB) deleteObjectUnversionedCommitted(ctx context.Context, loc ObjectLo var deleted Object + // TODO(ver): this scanning can probably simplified somehow. + var version sql.NullInt64 var streamID uuid.NullUUID var createdAt sql.NullTime + var segmentCount, fixedSegmentSize sql.NullInt32 + var totalPlainSize, totalEncryptedSize sql.NullInt64 var status sql.NullByte - var params nullableValue[encryptionParameters] - params.value.EncryptionParameters = &deleted.Encryption + var encryptionParams nullableValue[encryptionParameters] + encryptionParams.value.EncryptionParameters = &deleted.Encryption err = stmt.QueryRowContext(ctx, ` WITH highest_object AS ( @@ -290,8 +294,11 @@ func (db *DB) deleteObjectUnversionedCommitted(ctx context.Context, loc ObjectLo (project_id, bucket_name, object_key) = ($1, $2, $3) AND status IN `+statusesUnversioned+` RETURNING - version, stream_id, status, created_at, expires_at, + version, stream_id, + created_at, expires_at, + status, segment_count, encrypted_metadata_nonce, encrypted_metadata, encrypted_metadata_encrypted_key, + total_plain_size, total_encrypted_size, fixed_segment_size, encryption ), deleted_segments AS ( DELETE FROM segments @@ -301,12 +308,16 @@ func (db *DB) deleteObjectUnversionedCommitted(ctx context.Context, loc ObjectLo SELECT (SELECT version FROM deleted_objects), (SELECT stream_id FROM deleted_objects), - (SELECT status FROM deleted_objects), (SELECT created_at FROM deleted_objects), (SELECT expires_at FROM deleted_objects), + (SELECT status FROM deleted_objects), + (SELECT segment_count FROM deleted_objects), (SELECT encrypted_metadata_nonce FROM deleted_objects), (SELECT encrypted_metadata FROM deleted_objects), (SELECT encrypted_metadata_encrypted_key FROM deleted_objects), + (SELECT total_plain_size FROM deleted_objects), + (SELECT total_encrypted_size FROM deleted_objects), + (SELECT fixed_segment_size FROM deleted_objects), (SELECT encryption FROM deleted_objects), (SELECT count(*) FROM deleted_objects), (SELECT count(*) FROM deleted_segments), @@ -315,19 +326,26 @@ func (db *DB) deleteObjectUnversionedCommitted(ctx context.Context, loc ObjectLo Scan( &version, &streamID, - &status, &createdAt, &deleted.ExpiresAt, + &status, + &segmentCount, &deleted.EncryptedMetadataNonce, &deleted.EncryptedMetadata, &deleted.EncryptedMetadataEncryptedKey, - ¶ms, - + &totalPlainSize, + &totalEncryptedSize, + &fixedSegmentSize, + &encryptionParams, &result.DeletedObjectCount, &result.DeletedSegmentCount, &result.MaxVersion, ) + if err != nil { + return deleteObjectUnversionedCommittedResult{}, Error.Wrap(err) + } + deleted.ProjectID = loc.ProjectID deleted.BucketName = loc.BucketName deleted.ObjectKey = loc.ObjectKey @@ -336,10 +354,11 @@ func (db *DB) deleteObjectUnversionedCommitted(ctx context.Context, loc ObjectLo deleted.Status = ObjectStatus(status.Byte) deleted.StreamID = streamID.UUID deleted.CreatedAt = createdAt.Time + deleted.SegmentCount = segmentCount.Int32 - if err != nil { - return deleteObjectUnversionedCommittedResult{}, Error.Wrap(err) - } + deleted.TotalPlainSize = totalPlainSize.Int64 + deleted.TotalEncryptedSize = totalEncryptedSize.Int64 + deleted.FixedSegmentSize = fixedSegmentSize.Int32 // TODO: this should happen outside of this func mon.Meter("object_delete").Mark(result.DeletedObjectCount) diff --git a/satellite/metabase/get_test.go b/satellite/metabase/get_test.go index 46af5d169..8ce45a95b 100644 --- a/satellite/metabase/get_test.go +++ b/satellite/metabase/get_test.go @@ -4,6 +4,7 @@ package metabase_test import ( + "slices" "testing" "time" @@ -1607,9 +1608,138 @@ func TestGetLatestObjectLastSegment(t *testing.T) { }.Check(ctx, t, db) }) - // TODO(ver): add test for committed versioned - // TODO(ver): add test for delete marker versioned - // TODO(ver): add test for delete marker unversioned + t.Run("versioned", func(t *testing.T) { + defer metabasetest.DeleteAll{}.Check(ctx, t, db) + + object := metabasetest.CreateObjectVersioned(ctx, t, db, obj, 2) + + segments, err := db.TestingAllSegments(ctx) + require.NoError(t, err) + require.Len(t, segments, 2) + + metabasetest.GetLatestObjectLastSegment{ + Opts: metabase.GetLatestObjectLastSegment{ + ObjectLocation: location, + }, + Result: segments[1], + }.Check(ctx, t, db) + + metabasetest.Verify{ + Objects: []metabase.RawObject{ + metabase.RawObject(object), + }, + Segments: metabasetest.SegmentsToRaw(segments), + }.Check(ctx, t, db) + }) + + t.Run("versioned delete marker", func(t *testing.T) { + defer metabasetest.DeleteAll{}.Check(ctx, t, db) + + object := metabasetest.CreateObjectVersioned(ctx, t, db, obj, 2) + + segments, err := db.TestingAllSegments(ctx) + require.NoError(t, err) + require.Len(t, segments, 2) + + markerLocation := obj + markerLocation.StreamID = uuid.UUID{} + markerLocation.Version = object.Version + 1 + marker := metabase.Object{ + ObjectStream: markerLocation, + CreatedAt: time.Now(), + Status: metabase.DeleteMarkerVersioned, + } + + // this creates a versioned delete marker + metabasetest.DeleteObjectLastCommitted{ + Opts: metabase.DeleteObjectLastCommitted{ + ObjectLocation: location, + Versioned: true, + }, + Result: metabase.DeleteObjectResult{ + Markers: []metabase.Object{marker}, + }, + }.Check(ctx, t, db) + + metabasetest.GetLatestObjectLastSegment{ + Opts: metabase.GetLatestObjectLastSegment{ + ObjectLocation: location, + }, + ErrClass: &metabase.ErrObjectNotFound, + ErrText: "metabase: object or segment missing", + }.Check(ctx, t, db) + + metabasetest.Verify{ + Objects: []metabase.RawObject{ + metabase.RawObject(object), + metabase.RawObject(marker), + }, + Segments: metabasetest.SegmentsToRaw(segments), + }.Check(ctx, t, db) + }) + t.Run("unversioned delete marker", func(t *testing.T) { + defer metabasetest.DeleteAll{}.Check(ctx, t, db) + + unversioned := metabasetest.CreateObject(ctx, t, db, obj, 2) + versionedobj := obj + versionedobj.Version++ + versionedobj.StreamID = testrand.UUID() + versioned := metabasetest.CreateObjectVersioned(ctx, t, db, versionedobj, 2) + + segments, err := db.TestingAllSegments(ctx) + require.NoError(t, err) + require.Len(t, segments, 4) + + metabasetest.Verify{ + Objects: []metabase.RawObject{ + metabase.RawObject(unversioned), + metabase.RawObject(versioned), + }, + Segments: metabasetest.SegmentsToRaw(segments), + }.Check(ctx, t, db) + + markerLocation := obj + markerLocation.StreamID = uuid.UUID{} + markerLocation.Version = unversioned.Version + 2 + marker := metabase.Object{ + ObjectStream: markerLocation, + CreatedAt: time.Now(), + Status: metabase.DeleteMarkerUnversioned, + } + + // this creates a versioned delete marker + metabasetest.DeleteObjectLastCommitted{ + Opts: metabase.DeleteObjectLastCommitted{ + ObjectLocation: location, + Versioned: false, + Suspended: true, + }, + Result: metabase.DeleteObjectResult{ + Markers: []metabase.Object{marker}, + Removed: []metabase.Object{unversioned}, + }, + }.Check(ctx, t, db) + + metabasetest.GetLatestObjectLastSegment{ + Opts: metabase.GetLatestObjectLastSegment{ + ObjectLocation: location, + }, + ErrClass: &metabase.ErrObjectNotFound, + ErrText: "metabase: object or segment missing", + }.Check(ctx, t, db) + + segments = slices.DeleteFunc(segments, func(seg metabase.Segment) bool { + return seg.StreamID == unversioned.StreamID + }) + + metabasetest.Verify{ + Objects: []metabase.RawObject{ + metabase.RawObject(versioned), + metabase.RawObject(marker), + }, + Segments: metabasetest.SegmentsToRaw(segments), + }.Check(ctx, t, db) + }) }) }