11import type { Sandbox } from "@cloudflare/sandbox" ;
2+ import { JupyterNotReadyError , isJupyterNotReadyError , isRetryableError } from "@cloudflare/sandbox" ;
23import { corsHeaders , errorResponse , jsonResponse , parseJsonBody } from "../http" ;
34
45// Active sessions (in production, use Durable Objects or KV)
@@ -21,6 +22,33 @@ export async function createSession(sandbox: Sandbox, request: Request): Promise
2122
2223 return jsonResponse ( { sessionId, language } ) ;
2324 } catch ( error : any ) {
25+ // Handle Jupyter initialization timeout (request waited but Jupyter wasn't ready in time)
26+ if ( isJupyterNotReadyError ( error ) ) {
27+ console . log ( "[Notebook] Request timed out waiting for Jupyter initialization" ) ;
28+ return new Response (
29+ JSON . stringify ( {
30+ error : error . message ,
31+ retryAfter : error . retryAfter ,
32+ progress : error . progress
33+ } ) ,
34+ {
35+ status : 503 ,
36+ headers : {
37+ "Content-Type" : "application/json" ,
38+ "Retry-After" : String ( error . retryAfter ) ,
39+ ...corsHeaders ( )
40+ }
41+ }
42+ ) ;
43+ }
44+
45+ // Check if error is retryable
46+ if ( isRetryableError ( error ) ) {
47+ console . log ( "[Notebook] Retryable error:" , error . message ) ;
48+ return errorResponse ( error . message , 503 ) ;
49+ }
50+
51+ // Log actual errors
2452 console . error ( "Create session error:" , error ) ;
2553 return errorResponse ( error . message || "Failed to create session" , 500 ) ;
2654 }
@@ -94,6 +122,33 @@ export async function executeCell(sandbox: Sandbox, request: Request): Promise<R
94122 }
95123 } ) ;
96124 } catch ( error : any ) {
125+ // Handle Jupyter initialization timeout (request waited but Jupyter wasn't ready in time)
126+ if ( isJupyterNotReadyError ( error ) ) {
127+ console . log ( "[Notebook] Request timed out waiting for Jupyter initialization" ) ;
128+ return new Response (
129+ JSON . stringify ( {
130+ error : error . message ,
131+ retryAfter : error . retryAfter ,
132+ progress : error . progress
133+ } ) ,
134+ {
135+ status : 503 ,
136+ headers : {
137+ "Content-Type" : "application/json" ,
138+ "Retry-After" : String ( error . retryAfter ) ,
139+ ...corsHeaders ( )
140+ }
141+ }
142+ ) ;
143+ }
144+
145+ // Check if error is retryable
146+ if ( isRetryableError ( error ) ) {
147+ console . log ( "[Notebook] Retryable error:" , error . message ) ;
148+ return errorResponse ( error . message , 503 ) ;
149+ }
150+
151+ // Log actual errors
97152 console . error ( "Execute cell error:" , error ) ;
98153 return errorResponse ( error . message || "Failed to execute code" , 500 ) ;
99154 }
@@ -113,6 +168,33 @@ export async function deleteSession(sandbox: Sandbox, request: Request): Promise
113168
114169 return jsonResponse ( { success : true } ) ;
115170 } catch ( error : any ) {
171+ // Handle Jupyter initialization timeout (request waited but Jupyter wasn't ready in time)
172+ if ( isJupyterNotReadyError ( error ) ) {
173+ console . log ( "[Notebook] Request timed out waiting for Jupyter initialization" ) ;
174+ return new Response (
175+ JSON . stringify ( {
176+ error : error . message ,
177+ retryAfter : error . retryAfter ,
178+ progress : error . progress
179+ } ) ,
180+ {
181+ status : 503 ,
182+ headers : {
183+ "Content-Type" : "application/json" ,
184+ "Retry-After" : String ( error . retryAfter ) ,
185+ ...corsHeaders ( )
186+ }
187+ }
188+ ) ;
189+ }
190+
191+ // Check if error is retryable
192+ if ( isRetryableError ( error ) ) {
193+ console . log ( "[Notebook] Retryable error:" , error . message ) ;
194+ return errorResponse ( error . message , 503 ) ;
195+ }
196+
197+ // Log actual errors
116198 console . error ( "Delete session error:" , error ) ;
117199 return errorResponse ( error . message || "Failed to delete session" , 500 ) ;
118200 }
0 commit comments