@@ -93,7 +93,30 @@ const main = async () => {
9393 } ) ;
9494 } ) ;
9595
96+ // Stands in for R2 so the binary's production store path actually runs.
97+ const bucket = new Map ( ) ;
98+ const s3 = createServer ( ( req , res ) => {
99+ const chunks = [ ] ;
100+ req . on ( 'data' , ( c ) => chunks . push ( c ) ) ;
101+ req . on ( 'end' , ( ) => {
102+ const key = new URL ( req . url , 'http://x' ) . pathname . replace ( '/pet-art/' , '' ) ;
103+ if ( req . method === 'PUT' ) {
104+ bucket . set ( key , Buffer . concat ( chunks ) ) ;
105+ res . writeHead ( 200 ) ; res . end ( ) ; return ;
106+ }
107+ const found = bucket . get ( key ) ;
108+ if ( ! found ) {
109+ res . writeHead ( 404 , { 'content-type' : 'application/xml' } ) ;
110+ res . end ( '<?xml version="1.0"?><Error><Code>NoSuchKey</Code><Message>no</Message></Error>' ) ;
111+ return ;
112+ }
113+ res . writeHead ( 200 , { 'content-type' : 'image/png' } ) ;
114+ res . end ( found ) ;
115+ } ) ;
116+ } ) ;
117+
96118 const aiPort = await listen ( ai ) ;
119+ const s3Port = await listen ( s3 ) ;
97120 const rpcPort = await listen ( rpc ) ;
98121 const artRoot = await mkdtemp ( join ( tmpdir ( ) , 'smoke-art-' ) ) ;
99122 const port = 8931 ;
@@ -212,9 +235,55 @@ const main = async () => {
212235 const solana = await warm ( [ '--chain=solana' , '--from=1' , '--to=3' ] ) ;
213236 check ( 'warming solana by id range fails' , solana . code , 1 ) ;
214237 check ( 'and says why' , / n o t a d d r e s s e d b y n u m b e r / . test ( solana . out ) , true ) ;
238+ // Production runs on R2, and until now only the filesystem store had ever
239+ // booted: a mistake in the r2 branch of storeFactory or its config would
240+ // have surfaced for the first time in production.
241+ console . log ( '\nr2 store:' ) ;
242+ const r2Env = {
243+ ...childEnv ,
244+ PORT : String ( port + 1 ) ,
245+ PUBLIC_BASE_URL : `http://127.0.0.1:${ port + 1 } ` ,
246+ IMAGE_STORE : 'r2' ,
247+ R2_BUCKET : 'pet-art' ,
248+ R2_ACCESS_KEY_ID : 'key' ,
249+ R2_SECRET_ACCESS_KEY : 'secret' ,
250+ R2_ENDPOINT : `http://127.0.0.1:${ s3Port } ` ,
251+ R2_PUBLIC_BASE_URL : 'https://cdn.example' ,
252+ } ;
253+ const r2Server = spawn ( process . execPath , [ 'dist/main.js' ] , { env : r2Env , stdio : [ 'ignore' , 'pipe' , 'pipe' ] } ) ;
254+ const r2Logs = [ ] ;
255+ r2Server . stdout . on ( 'data' , ( d ) => r2Logs . push ( String ( d ) ) ) ;
256+ r2Server . stderr . on ( 'data' , ( d ) => r2Logs . push ( String ( d ) ) ) ;
257+ const r2Base = `http://127.0.0.1:${ port + 1 } ` ;
258+
259+ try {
260+ let alive = false ;
261+ for ( let i = 0 ; i < 60 && ! alive ; i ++ ) {
262+ try { await fetch ( `${ r2Base } /health` ) ; alive = true ; } catch { await new Promise ( ( r ) => setTimeout ( r , 100 ) ) ; }
263+ }
264+ check ( 'boots on the r2 store' , alive , true ) ;
265+ if ( ! alive ) console . log ( r2Logs . join ( '' ) ) ;
266+
267+ check ( 'readiness reaches the bucket' , ( await fetch ( `${ r2Base } /ready` ) ) . status , 200 ) ;
268+
269+ const before = generations ;
270+ // Redirect rather than proxy: with a public bucket the bytes never
271+ // pass through the service.
272+ const img = await fetch ( `${ r2Base } /image/evm/5.png` , { redirect : 'manual' } ) ;
273+ check ( 'image 302s to the public bucket' , img . status , 302 ) ;
274+ check ( 'and points at the configured domain' , ( img . headers . get ( 'location' ) ?? '' ) . startsWith ( 'https://cdn.example/art/v1/' ) , true ) ;
275+ check ( 'generated once into the bucket' , generations - before , 1 ) ;
276+ check ( 'bucket holds the image and its manifest' , bucket . size , 2 ) ;
277+
278+ const again = await fetch ( `${ r2Base } /image/evm/5.png` , { redirect : 'manual' } ) ;
279+ check ( 'second request still redirects' , again . status , 302 ) ;
280+ check ( 'and bills nothing more' , generations - before , 1 ) ;
281+ } finally {
282+ r2Server . kill ( ) ;
283+ }
215284 } finally {
216285 server . kill ( ) ;
217- await Promise . all ( [ shut ( ai ) , shut ( rpc ) ] ) ;
286+ await Promise . all ( [ shut ( ai ) , shut ( rpc ) , shut ( s3 ) ] ) ;
218287 await rm ( artRoot , { recursive : true , force : true } ) ;
219288 }
220289
0 commit comments