satellite/metabase: add version tests for GetLatestObjectLastSegment

Change-Id: Ia7ed1f6b23bcdc9e83fec288cbf3571b382d5e13
This commit is contained in:
Egon Elbre 2023-10-24 18:13:41 +03:00
parent a7e1378f89
commit 504d5c5651
2 changed files with 162 additions and 13 deletions

View File

@ -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,
&params,
&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)

View File

@ -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)
})
})
}