@@ -19,11 +19,35 @@ export class DualBlobStorage implements BlobStorage {
1919 contentType : string ;
2020 metadata ?: Metadata ;
2121 } ) : Promise < void > {
22- await Promise . all ( [ this . primary . putObject ( data ) , this . secondary . putObject ( data ) ] ) ;
22+ const results = await Promise . allSettled ( [ this . primary . putObject ( data ) , this . secondary . putObject ( data ) ] ) ;
23+ const [ primaryResult , secondaryResult ] = results ;
24+
25+ if ( primaryResult . status === 'fulfilled' && secondaryResult . status === 'fulfilled' ) {
26+ return ;
27+ }
28+
29+ // Roll back successful writes before throwing
30+ if ( primaryResult . status === 'fulfilled' ) {
31+ await this . primary . deleteObject ( { key : data . key , abortSignal : data . abortSignal } ) ;
32+ }
33+ if ( secondaryResult . status === 'fulfilled' ) {
34+ await this . secondary . deleteObject ( { key : data . key , abortSignal : data . abortSignal } ) ;
35+ }
36+
37+ const errors = results . filter ( ( r ) : r is PromiseRejectedResult => r . status === 'rejected' ) . map ( ( r ) => r . reason ) ;
38+ throw new AggregateError ( errors , 'Failed to put object into storage' ) ;
2339 }
2440
2541 async getObject ( data : { key : string ; abortSignal ?: AbortSignal } ) : Promise < BlobObject > {
26- return await Promise . any ( [ this . primary . getObject ( data ) , this . secondary . getObject ( data ) ] ) ;
42+ try {
43+ return await this . primary . getObject ( data ) ;
44+ } catch ( primaryError ) {
45+ try {
46+ return await this . secondary . getObject ( data ) ;
47+ } catch ( secondaryError ) {
48+ throw new AggregateError ( [ primaryError , secondaryError ] , 'Both primary and secondary storage failed to get object' ) ;
49+ }
50+ }
2751 }
2852
2953 async removeDirectory ( data : { key : string ; abortSignal ?: AbortSignal } ) : Promise < number > {
0 commit comments