satellite/metainfo/metabase: add UpdateObjectMetadata request
Change-Id: Iec73000e58f373294f37ef3e4470412d1c5f1340
This commit is contained in:
parent
89cefa9045
commit
4134100d80
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user