1
1
import type { Sandbox } from "@cloudflare/sandbox" ;
2
+ import { JupyterNotReadyError , isJupyterNotReadyError , isRetryableError } from "@cloudflare/sandbox" ;
2
3
import { corsHeaders , errorResponse , jsonResponse , parseJsonBody } from "../http" ;
3
4
4
5
// Active sessions (in production, use Durable Objects or KV)
@@ -21,6 +22,33 @@ export async function createSession(sandbox: Sandbox, request: Request): Promise
21
22
22
23
return jsonResponse ( { sessionId, language } ) ;
23
24
} 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
24
52
console . error ( "Create session error:" , error ) ;
25
53
return errorResponse ( error . message || "Failed to create session" , 500 ) ;
26
54
}
@@ -94,6 +122,33 @@ export async function executeCell(sandbox: Sandbox, request: Request): Promise<R
94
122
}
95
123
} ) ;
96
124
} 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
97
152
console . error ( "Execute cell error:" , error ) ;
98
153
return errorResponse ( error . message || "Failed to execute code" , 500 ) ;
99
154
}
@@ -113,6 +168,33 @@ export async function deleteSession(sandbox: Sandbox, request: Request): Promise
113
168
114
169
return jsonResponse ( { success : true } ) ;
115
170
} 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
116
198
console . error ( "Delete session error:" , error ) ;
117
199
return errorResponse ( error . message || "Failed to delete session" , 500 ) ;
118
200
}
0 commit comments