@@ -11,6 +11,8 @@ This doesn't know anything about types, etc.
11
11
12
12
import { join } from "path" ;
13
13
import { appBasePath } from "@cocalc/frontend/customize/app-base-path" ;
14
+ import { delay } from "awaiting" ;
15
+ import { trunc } from "@cocalc/util/misc" ;
14
16
15
17
export default async function api ( endpoint : string , args ?: object ) {
16
18
return await callApi ( join ( "v2" , endpoint ) , args ) ;
@@ -21,9 +23,24 @@ export async function v1(endpoint: string, args?: object) {
21
23
return await callApi ( join ( "v1" , endpoint ) , args ) ;
22
24
}
23
25
26
+ // if api call fails (typically 5xx due to a temporary restart of
27
+ // backend servers e.g., in kubernetes) we wait RETRY_DELAY_MS, then give
28
+ // it NUM_RETRIES many ties before showing the user an error.
29
+ // Setting the third numRetriesOnFail argument to 0 below
30
+ // can be used to disable this behavior.
31
+ // This "api call fails" isn't where you get an error json
32
+ // back, but when actually making the request really is
33
+ // failing, e.g., due to network or server issues.
34
+ const RETRY_DELAY_MS = 2000 ;
35
+ const NUM_RETRIES = 3 ;
36
+
24
37
// NOTE: I made this complicated with respClone, so I can see
25
38
// what the response is if it is not JSON.
26
- async function callApi ( endpoint : string , args ?: object ) {
39
+ async function callApi (
40
+ endpoint : string ,
41
+ args ?: object ,
42
+ numRetriesOnFail ?: number ,
43
+ ) {
27
44
const url = join ( appBasePath , "api" , endpoint ) ;
28
45
const resp = await fetch ( url , {
29
46
method : "POST" ,
@@ -38,9 +55,19 @@ async function callApi(endpoint: string, args?: object) {
38
55
json = await resp . json ( ) ;
39
56
} catch ( e ) {
40
57
console . log ( e ) ;
41
- console . log ( await respClone . text ( ) ) ;
42
- throw Error ( "API server is down -- try again later" ) ;
58
+ const r = await respClone . text ( ) ;
59
+ console . log ( trunc ( r , 2000 ) ) ;
60
+ if ( numRetriesOnFail != null && numRetriesOnFail == 0 ) {
61
+ throw Error ( "API server is down -- try again later" ) ;
62
+ }
63
+ numRetriesOnFail = numRetriesOnFail ?? NUM_RETRIES ;
64
+ console . log (
65
+ `waiting 3s then trying again up to ${ numRetriesOnFail } more times` ,
66
+ ) ;
67
+ await delay ( RETRY_DELAY_MS ) ;
68
+ return await callApi ( endpoint , args , numRetriesOnFail - 1 ) ;
43
69
}
70
+ console . log ( "json = " , json ) ;
44
71
if ( json == null ) {
45
72
throw Error ( "timeout -- try again later" ) ;
46
73
}
0 commit comments