@@ -102,39 +102,43 @@ async function seedParquetFile(filePath: string, r2Key?: string): Promise<void>
102102 }
103103}
104104
105+ /** Upload file via Worker's /upload endpoint (writes through R2 binding, avoids miniflare list() inconsistency). */
106+ async function uploadViaWorker ( r2Key : string , data : Uint8Array ) : Promise < void > {
107+ const resp = await fetch ( `${ BASE_URL } /upload?key=${ encodeURIComponent ( r2Key ) } ` , {
108+ method : "POST" ,
109+ body : data ,
110+ } ) ;
111+ if ( ! resp . ok ) throw new Error ( `Upload failed: ${ resp . status } ` ) ;
112+ }
113+
105114async function seedIcebergTable ( dir : string ) : Promise < void > {
106115 const name = basename ( dir ) ;
107116 console . log ( `\nSeeding Iceberg table: ${ name } ` ) ;
117+ // Upload via Worker's R2 binding (not wrangler CLI) so R2 list() sees the objects
108118 for ( const file of walkDir ( dir ) ) {
109119 const relPath = relative ( dir , file ) ;
110120 const r2Key = `${ name } /${ relPath } ` ;
111121 const data = readFileSync ( file ) ;
112122 console . log ( ` PUT ${ r2Key } (${ ( data . length / 1024 ) . toFixed ( 0 ) } KB)` ) ;
113- uploadFile ( r2Key , data ) ;
123+ await uploadViaWorker ( r2Key , data ) ;
114124 }
115- // Trigger Iceberg discovery immediately after upload (R2 list() needs objects to be visible).
116- // Retry with delays since miniflare R2 list() has eventual consistency.
117- let ok = false ;
118- for ( let attempt = 0 ; attempt < 8 && ! ok ; attempt ++ ) {
119- if ( attempt > 0 ) await new Promise ( r => setTimeout ( r , 2000 ) ) ;
120- try {
121- const resp = await fetch ( `${ BASE_URL } /query` , {
122- method : "POST" ,
123- headers : { "content-type" : "application/json" } ,
124- body : JSON . stringify ( { table : name , filters : [ ] , projections : [ "id" ] , limit : 1 } ) ,
125- } ) ;
126- if ( resp . ok ) {
127- console . log ( ` Iceberg registered: ${ name } ` ) ;
128- ok = true ;
129- } else if ( attempt >= 2 ) {
130- // Only log after a few attempts to reduce noise
131- console . log ( ` Iceberg attempt ${ attempt + 1 } : ${ resp . status } ` ) ;
132- }
133- } catch {
134- if ( attempt >= 2 ) console . log ( ` Iceberg attempt ${ attempt + 1 } : fetch error` ) ;
125+ // Trigger Iceberg discovery via query (should work immediately since R2 list() sees objects)
126+ await new Promise ( r => setTimeout ( r , 500 ) ) ;
127+ try {
128+ const resp = await fetch ( `${ BASE_URL } /query` , {
129+ method : "POST" ,
130+ headers : { "content-type" : "application/json" } ,
131+ body : JSON . stringify ( { table : name , filters : [ ] , projections : [ "id" ] , limit : 1 } ) ,
132+ } ) ;
133+ if ( resp . ok ) {
134+ console . log ( ` Iceberg registered: ${ name } ` ) ;
135+ } else {
136+ const text = await resp . text ( ) ;
137+ console . log ( ` Iceberg registration: ${ resp . status } (${ text . slice ( 0 , 80 ) } )` ) ;
135138 }
139+ } catch ( err ) {
140+ console . log ( ` Iceberg registration error: ${ String ( err ) . slice ( 0 , 80 ) } ` ) ;
136141 }
137- if ( ! ok ) console . log ( ` Iceberg lazy-load deferred (will retry in bench)` ) ;
138142}
139143
140144async function main ( ) : Promise < void > {
0 commit comments