@@ -142,9 +142,10 @@ export class S3StorageDriver implements StorageDriver {
142142
143143 async store ( context : StorageDriverStoreContext , payloads : Payload [ ] ) : Promise < StorageDriverClaim [ ] > {
144144 const contextSegments = buildContextSegments ( context . target ) ;
145- return runAllWithAbortOnError ( context . abortSignal , ( signal ) =>
146- payloads . map ( ( payload ) => this . storePayload ( context , payload , contextSegments , signal ) )
147- ) ;
145+ return runAllWithAbortOnError ( context . abortSignal , ( signal ) => {
146+ const uploads = new Map < string , Promise < void > > ( ) ;
147+ return payloads . map ( ( payload ) => this . storePayload ( context , payload , contextSegments , signal , uploads ) ) ;
148+ } ) ;
148149 }
149150
150151 async retrieve ( context : StorageDriverRetrieveContext , claims : StorageDriverClaim [ ] ) : Promise < Payload [ ] > {
@@ -157,7 +158,8 @@ export class S3StorageDriver implements StorageDriver {
157158 context : StorageDriverStoreContext ,
158159 payload : Payload ,
159160 contextSegments : string ,
160- abortSignal : AbortSignal
161+ abortSignal : AbortSignal ,
162+ uploads : Map < string , Promise < void > >
161163 ) : Promise < StorageDriverClaim > {
162164 const bucket = this . bucket ( context , payload ) ;
163165
@@ -172,9 +174,13 @@ export class S3StorageDriver implements StorageDriver {
172174 const key = `v0${ contextSegments } /d/sha256/${ hashValue } ` ;
173175
174176 try {
175- if ( ! ( await this . client . objectExists ( bucket , key , { abortSignal } ) ) ) {
176- await this . client . putObject ( bucket , key , payloadBytes , { abortSignal } ) ;
177+ const dedupeKey = `${ bucket } ${ key } ` ;
178+ let upload = uploads . get ( dedupeKey ) ;
179+ if ( ! upload ) {
180+ upload = this . uploadIfAbsent ( bucket , key , payloadBytes , abortSignal ) ;
181+ uploads . set ( dedupeKey , upload ) ;
177182 }
183+ await upload ;
178184 } catch ( err ) {
179185 throw new Error (
180186 `S3StorageDriver store failed [bucket=${ bucket } , key=${ key } ${ formatClientContext ( this . client ) } ]` ,
@@ -185,6 +191,17 @@ export class S3StorageDriver implements StorageDriver {
185191 return new StorageDriverClaim ( { bucket, key, hashAlgorithm : 'sha256' , hashValue } ) ;
186192 }
187193
194+ private async uploadIfAbsent (
195+ bucket : string ,
196+ key : string ,
197+ payloadBytes : Uint8Array ,
198+ abortSignal : AbortSignal
199+ ) : Promise < void > {
200+ if ( ! ( await this . client . objectExists ( bucket , key , { abortSignal } ) ) ) {
201+ await this . client . putObject ( bucket , key , payloadBytes , { abortSignal } ) ;
202+ }
203+ }
204+
188205 private async retrievePayload ( claim : StorageDriverClaim , abortSignal : AbortSignal ) : Promise < Payload > {
189206 const { bucket, key, hashAlgorithm, hashValue : expectedHash } = claim . claimData ;
190207 if ( ! bucket || ! key ) {
0 commit comments