@@ -65,11 +65,16 @@ export class ArtifactStorageReader {
65
65
endpoint : string ;
66
66
bucketName : string ;
67
67
} ,
68
+ // private s3Mirror: {
69
+ // client: AwsClient;
70
+ // endpoint: string;
71
+ // bucketName: string;
72
+ // },
68
73
private analytics : Analytics | null ,
69
74
) { }
70
75
71
- /** Generate a pre-signed url for reading an artifact from a bucket for a limited time period. */
72
- async generateArtifactReadUrl (
76
+ /** Read an artifact from S3 */
77
+ async readArtifact (
73
78
targetId : string ,
74
79
contractName : string | null ,
75
80
artifactType : ArtifactsType ,
@@ -81,55 +86,57 @@ export class ArtifactStorageReader {
81
86
82
87
const key = buildArtifactStorageKey ( targetId , artifactType , contractName ) ;
83
88
84
- const headResponse = await this . s3 . client . fetch (
89
+ const headers : HeadersInit = { } ;
90
+
91
+ if ( etagValue ) {
92
+ headers [ 'if-none-match' ] = etagValue ;
93
+ }
94
+
95
+ const response = await this . s3 . client . fetch (
85
96
[ this . s3 . endpoint , this . s3 . bucketName , key ] . join ( '/' ) ,
86
97
{
87
- method : 'HEAD' ,
98
+ method : 'GET' ,
99
+ headers,
88
100
aws : {
89
101
signQuery : true ,
90
102
} ,
91
103
timeout : READ_TIMEOUT_MS ,
104
+ onAttempt : args => {
105
+ this . analytics ?. track (
106
+ {
107
+ type : 'r2' ,
108
+ statusCodeOrErrCode :
109
+ args . result . type === 'error'
110
+ ? String ( args . result . error . name ?? 'unknown' )
111
+ : args . result . response . status ,
112
+ action : 'GET artifact' ,
113
+ duration : args . duration ,
114
+ } ,
115
+ targetId ,
116
+ ) ;
117
+ } ,
92
118
} ,
93
119
) ;
94
- this . analytics ?. track (
95
- {
96
- type : 'r2' ,
97
- statusCode : headResponse . status ,
98
- action : 'HEAD artifact' ,
99
- } ,
100
- targetId ,
101
- ) ;
102
-
103
- if ( headResponse . status === 200 ) {
104
- if ( etagValue && headResponse . headers . get ( 'etag' ) === etagValue ) {
105
- return { type : 'notModified' } as const ;
106
- }
107
-
108
- const getResponse = await this . s3 . client . fetch (
109
- [ this . s3 . endpoint , this . s3 . bucketName , key ] . join ( '/' ) ,
110
- {
111
- method : 'GET' ,
112
- aws : {
113
- signQuery : true ,
114
- } ,
115
- timeout : READ_TIMEOUT_MS ,
116
- } ,
117
- ) ;
118
120
119
- if ( getResponse . ok ) {
120
- return {
121
- type : 'response' ,
122
- response : getResponse ,
123
- } as const ;
124
- }
121
+ if ( response . status === 404 ) {
122
+ return { type : 'notFound' } as const ;
123
+ }
125
124
126
- throw new Error ( `GET request failed with status ${ getResponse . status } ` ) ;
125
+ if ( response . status === 304 ) {
126
+ return {
127
+ type : 'notModified' ,
128
+ } as const ;
127
129
}
128
- if ( headResponse . status === 404 ) {
129
- return { type : 'notFound' } as const ;
130
+
131
+ if ( response . status === 200 ) {
132
+ return {
133
+ type : 'response' ,
134
+ response,
135
+ } as const ;
130
136
}
131
- const body = await headResponse . text ( ) ;
132
- throw new Error ( `HEAD request failed with status ${ headResponse . status } : ${ body } ` ) ;
137
+
138
+ const body = await response . text ( ) ;
139
+ throw new Error ( `GET request failed with status ${ response . status } : ${ body } ` ) ;
133
140
}
134
141
135
142
async isAppDeploymentEnabled ( targetId : string , appName : string , appVersion : string ) {
@@ -143,16 +150,22 @@ export class ArtifactStorageReader {
143
150
signQuery : true ,
144
151
} ,
145
152
timeout : READ_TIMEOUT_MS ,
153
+ onAttempt : args => {
154
+ this . analytics ?. track (
155
+ {
156
+ type : 'r2' ,
157
+ statusCodeOrErrCode :
158
+ args . result . type === 'error'
159
+ ? String ( args . result . error . name ?? 'unknown' )
160
+ : args . result . response . status ,
161
+ action : 'HEAD appDeploymentIsEnabled' ,
162
+ duration : args . duration ,
163
+ } ,
164
+ targetId ,
165
+ ) ;
166
+ } ,
146
167
} ,
147
168
) ;
148
- this . analytics ?. track (
149
- {
150
- type : 'r2' ,
151
- statusCode : response . status ,
152
- action : 'HEAD appDeploymentIsEnabled' ,
153
- } ,
154
- targetId ,
155
- ) ;
156
169
157
170
return response . status === 200 ;
158
171
}
@@ -180,18 +193,23 @@ export class ArtifactStorageReader {
180
193
} ,
181
194
headers,
182
195
timeout : READ_TIMEOUT_MS ,
196
+ onAttempt : args => {
197
+ this . analytics ?. track (
198
+ {
199
+ type : 'r2' ,
200
+ statusCodeOrErrCode :
201
+ args . result . type === 'error'
202
+ ? String ( args . result . error . name ?? 'unknown' )
203
+ : args . result . response . status ,
204
+ action : 'GET persistedOperation' ,
205
+ duration : args . duration ,
206
+ } ,
207
+ targetId ,
208
+ ) ;
209
+ } ,
183
210
} ,
184
211
) ;
185
212
186
- this . analytics ?. track (
187
- {
188
- type : 'r2' ,
189
- statusCode : response . status ,
190
- action : 'GET persistedOperation' ,
191
- } ,
192
- targetId ,
193
- ) ;
194
-
195
213
if ( etagValue && response . status === 304 ) {
196
214
return { type : 'notModified' } as const ;
197
215
}
@@ -211,4 +229,62 @@ export class ArtifactStorageReader {
211
229
const body = await response . text ( ) ;
212
230
throw new Error ( `HEAD request failed with status ${ response . status } : ${ body } ` ) ;
213
231
}
232
+
233
+ async readLegacyAccessKey ( targetId : string ) {
234
+ const response = await this . s3 . client . fetch (
235
+ [ this . s3 . endpoint , this . s3 . bucketName , 'cdn-legacy-keys' , targetId ] . join ( '/' ) ,
236
+ {
237
+ method : 'GET' ,
238
+ timeout : READ_TIMEOUT_MS ,
239
+ onAttempt : args => {
240
+ this . analytics ?. track (
241
+ {
242
+ type : 'r2' ,
243
+ statusCodeOrErrCode :
244
+ args . result . type === 'error'
245
+ ? String ( args . result . error . name ?? 'unknown' )
246
+ : args . result . response . status ,
247
+ action : 'GET cdn-legacy-keys' ,
248
+ duration : args . duration ,
249
+ } ,
250
+ targetId ,
251
+ ) ;
252
+ } ,
253
+ } ,
254
+ ) ;
255
+
256
+ return response ;
257
+ }
258
+
259
+ async readAccessKey ( targetId : string , keyId : string ) {
260
+ const s3KeyParts = [ 'cdn-keys' , targetId , keyId ] ;
261
+
262
+ const response = await this . s3 . client . fetch (
263
+ [ this . s3 . endpoint , this . s3 . bucketName , ...s3KeyParts ] . join ( '/' ) ,
264
+ {
265
+ method : 'GET' ,
266
+ aws : {
267
+ // This boolean makes Google Cloud Storage & AWS happy.
268
+ signQuery : true ,
269
+ } ,
270
+ timeout : READ_TIMEOUT_MS ,
271
+ onAttempt : args => {
272
+ this . analytics ?. track (
273
+ {
274
+ type : 'r2' ,
275
+ statusCodeOrErrCode :
276
+ args . result . type === 'error'
277
+ ? String ( args . result . error . name ?? 'unknown' )
278
+ : args . result . response . status ,
279
+ action : 'GET cdn-access-token' ,
280
+ duration : args . duration ,
281
+ } ,
282
+ targetId ,
283
+ ) ;
284
+ } ,
285
+ } ,
286
+ ) ;
287
+
288
+ return response ;
289
+ }
214
290
}
0 commit comments