satellite/metainfo/metabase: add UpdateObjectMetadata request

Change-Id: Iec73000e58f373294f37ef3e4470412d1c5f1340
This commit is contained in:
Michal Niewrzal 2020-11-02 17:32:24 +01:00
parent 89cefa9045
commit 4134100d80
3 changed files with 163 additions and 0 deletions

View File

@ -546,3 +546,59 @@ func (db *DB) commitObjectWithProofs(ctx context.Context, opts CommitObject) (ob
defer mon.Task()(&ctx)(&err)
return Object{}, Error.New("unimplemented")
}
// UpdateObjectMetadata contains arguments necessary for updating an object metadata.
type UpdateObjectMetadata struct {
ObjectStream
EncryptedMetadata []byte
EncryptedMetadataNonce []byte
}
// UpdateObjectMetadata updates an object metadata.
func (db *DB) UpdateObjectMetadata(ctx context.Context, opts UpdateObjectMetadata) (err error) {
defer mon.Task()(&ctx)(&err)
if err := opts.ObjectStream.Verify(); err != nil {
return err
}
if opts.ObjectStream.Version <= 0 {
return ErrInvalidRequest.New("Version invalid: %v", opts.Version)
}
// TODO So the issue is that during a multipart upload of an object,
// uplink can update object metadata. If we add the arguments EncryptedMetadata
// to CommitObject, they will need to account for them being optional.
// Leading to scenarios where uplink calls update metadata, but wants to clear them
// during commit object.
result, err := db.db.ExecContext(ctx, `
UPDATE objects SET
encrypted_metadata_nonce = $6,
encrypted_metadata = $7
WHERE
project_id = $1 AND
bucket_name = $2 AND
object_key = $3 AND
version = $4 AND
stream_id = $5 AND
status = 1
`, opts.ProjectID, opts.BucketName, []byte(opts.ObjectKey), opts.Version, opts.StreamID,
opts.EncryptedMetadataNonce, opts.EncryptedMetadata)
if err != nil {
return Error.New("unable to update object metadata: %w", err)
}
affected, err := result.RowsAffected()
if err != nil {
return Error.New("failed to get rows affected: %w", err)
}
if affected == 0 {
return storj.ErrObjectNotFound.Wrap(
Error.New("object with specified version and committed status is missing"),
)
}
return nil
}

View File

@ -1466,3 +1466,99 @@ func TestCommitObject(t *testing.T) {
})
})
}
func TestUpdateObjectMetadata(t *testing.T) {
All(t, func(ctx *testcontext.Context, t *testing.T, db *metabase.DB) {
obj := randObjectStream()
now := time.Now()
for _, test := range invalidObjectStreams(obj) {
test := test
t.Run(test.Name, func(t *testing.T) {
defer DeleteAll{}.Check(ctx, t, db)
UpdateObjectMetadata{
Opts: metabase.UpdateObjectMetadata{
ObjectStream: test.ObjectStream,
},
ErrClass: test.ErrClass,
ErrText: test.ErrText,
}.Check(ctx, t, db)
Verify{}.Check(ctx, t, db)
})
}
t.Run("Version invalid", func(t *testing.T) {
defer DeleteAll{}.Check(ctx, t, db)
UpdateObjectMetadata{
Opts: metabase.UpdateObjectMetadata{
ObjectStream: metabase.ObjectStream{
ProjectID: obj.ProjectID,
BucketName: obj.BucketName,
ObjectKey: obj.ObjectKey,
Version: 0,
StreamID: obj.StreamID,
},
},
ErrClass: &metabase.ErrInvalidRequest,
ErrText: "Version invalid: 0",
}.Check(ctx, t, db)
Verify{}.Check(ctx, t, db)
})
t.Run("Object missing", func(t *testing.T) {
defer DeleteAll{}.Check(ctx, t, db)
UpdateObjectMetadata{
Opts: metabase.UpdateObjectMetadata{
ObjectStream: obj,
},
ErrClass: &storj.ErrObjectNotFound,
ErrText: "metabase: object with specified version and committed status is missing",
}.Check(ctx, t, db)
Verify{}.Check(ctx, t, db)
})
t.Run("Update metadata", func(t *testing.T) {
defer DeleteAll{}.Check(ctx, t, db)
CreateTestObject{}.Run(ctx, t, db, obj, 0)
encryptedMetadata := testrand.Bytes(1024)
encryptedMetadataNonce := testrand.Nonce()
Verify{
Objects: []metabase.RawObject{
{
ObjectStream: obj,
CreatedAt: now,
Status: metabase.Committed,
Encryption: defaultTestEncryption,
},
},
}.Check(ctx, t, db)
UpdateObjectMetadata{
Opts: metabase.UpdateObjectMetadata{
ObjectStream: obj,
EncryptedMetadata: encryptedMetadata,
EncryptedMetadataNonce: encryptedMetadataNonce[:],
},
}.Check(ctx, t, db)
Verify{
Objects: []metabase.RawObject{
{
ObjectStream: obj,
CreatedAt: now,
Status: metabase.Committed,
Encryption: defaultTestEncryption,
EncryptedMetadata: encryptedMetadata,
EncryptedMetadataNonce: encryptedMetadataNonce[:],
},
},
}.Check(ctx, t, db)
})
})
}

View File

@ -92,6 +92,17 @@ func (step CommitInlineSegment) Check(ctx *testcontext.Context, t *testing.T, db
checkError(t, err, step.ErrClass, step.ErrText)
}
type UpdateObjectMetadata struct {
Opts metabase.UpdateObjectMetadata
ErrClass *errs.Class
ErrText string
}
func (step UpdateObjectMetadata) Check(ctx *testcontext.Context, t *testing.T, db *metabase.DB) {
err := db.UpdateObjectMetadata(ctx, step.Opts)
checkError(t, err, step.ErrClass, step.ErrText)
}
type GetObjectExactVersion struct {
Opts metabase.GetObjectExactVersion
Result metabase.Object