@@ -33,6 +33,7 @@ interface CopyObjectParams {
3333 destinationKey : string
3434 owner ?: string
3535 copyMetadata ?: boolean
36+ upsert ?: boolean
3637 conditions ?: {
3738 ifMatch ?: string
3839 ifNoneMatch ?: string
@@ -280,6 +281,7 @@ export class ObjectStorage {
280281 owner,
281282 conditions,
282283 copyMetadata,
284+ upsert,
283285 } : CopyObjectParams ) {
284286 mustBeValidKey ( destinationKey )
285287
@@ -310,7 +312,7 @@ export class ObjectStorage {
310312 bucketId : destinationBucket ,
311313 objectName : destinationKey ,
312314 owner,
313- isUpsert : false ,
315+ isUpsert : upsert ,
314316 } )
315317
316318 try {
@@ -325,14 +327,42 @@ export class ObjectStorage {
325327
326328 const metadata = await this . backend . headObject ( storageS3Bucket , s3DestinationKey , newVersion )
327329
328- const destObject = await this . db . createObject ( {
329- ...originObject ,
330- bucket_id : destinationBucket ,
331- name : destinationKey ,
332- owner,
333- metadata,
334- user_metadata : copyMetadata ? originObject . user_metadata : undefined ,
335- version : newVersion ,
330+ const destinationObject = await this . db . asSuperUser ( ) . withTransaction ( async ( db ) => {
331+ await db . waitObjectLock ( destinationBucket , destinationKey , undefined , {
332+ timeout : 3000 ,
333+ } )
334+
335+ const existingDestObject = await db . findObject (
336+ this . bucketId ,
337+ destinationKey ,
338+ 'id,name,metadata,version,bucket_id' ,
339+ {
340+ dontErrorOnEmpty : true ,
341+ forUpdate : true ,
342+ }
343+ )
344+
345+ const destinationObject = await db . upsertObject ( {
346+ ...originObject ,
347+ bucket_id : destinationBucket ,
348+ name : destinationKey ,
349+ owner,
350+ metadata,
351+ user_metadata : copyMetadata ? originObject . user_metadata : undefined ,
352+ version : newVersion ,
353+ } )
354+
355+ if ( existingDestObject ) {
356+ await ObjectAdminDelete . send ( {
357+ name : existingDestObject . name ,
358+ bucketId : existingDestObject . bucket_id ,
359+ tenant : this . db . tenant ( ) ,
360+ version : existingDestObject . version ,
361+ reqId : this . db . reqId ,
362+ } )
363+ }
364+
365+ return destinationObject
336366 } )
337367
338368 await ObjectCreatedCopyEvent . sendWebhook ( {
@@ -345,7 +375,7 @@ export class ObjectStorage {
345375 } )
346376
347377 return {
348- destObject,
378+ destObject : destinationObject ,
349379 httpStatusCode : copyResult . httpStatusCode ,
350380 eTag : copyResult . eTag ,
351381 lastModified : copyResult . lastModified ,
0 commit comments