-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch '17-retries' into 18-upload-progress-bar
- Loading branch information
Showing
10 changed files
with
309 additions
and
47 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
const express = require('express'); | ||
|
||
const app = express(); | ||
|
||
// Middleware function to set timeout for all POST requests | ||
const timeoutMiddleware = (req, res, next) => { | ||
const TIMEOUT_DURATION = 1000; | ||
|
||
req.setTimeout(TIMEOUT_DURATION, () => { | ||
// Handle timeout | ||
res.status(408).send('Request Timeout'); | ||
}); | ||
|
||
next(); | ||
}; | ||
|
||
app.post('/_session', (req, res) => { | ||
res.set('Set-Cookie', 'AuthSession=abc123'); | ||
res.status(200).send('OK'); | ||
}); | ||
|
||
app.get('/medic/_design/medic-client/_view/contacts_by_type_freetext', (req, res) => { | ||
const startkey = JSON.parse(req.query.startkey); | ||
console.log('contacts_by_type_freetext', startkey); | ||
const DATA = [ | ||
// eslint-disable-next-line max-len | ||
{ id: 'e847f6e2-6dba-46dd-8128-5b153d0cd75f', key: ['b_sub_county', 'name:malava'], value: 'false false b_sub_county malava', doc: { _id: 'e847f6e2-6dba-46dd-8128-5b153d0cd75f', _rev: '1-cd20b7095c20172237867233b0375eda', parent: { _id: '95d9abd1-7c17-41b1-af98-595509f96631' }, type: 'contact', is_name_generated: 'false', name: 'Malava', external_id: '', contact: { _id: '1e3d8375-6ab4-4409-be3f-3324db7658e9' }, contact_type: 'b_sub_county', reported_date: 1702573623984 } }, | ||
// eslint-disable-next-line max-len | ||
{ id: '2926bf4c-63eb-433d-a2b4-274fd05d2f1c', key: ['c_community_health_unit', 'name:chu'], value: 'false false c_community_health_unit chu', doc: { _id: '2926bf4c-63eb-433d-a2b4-274fd05d2f1c', _rev: '1-c15f26fe064f8357c19d1124286bf4c4', name: 'Chu', PARENT: 'Chepalungu', code: '123456', type: 'contact', contact_type: 'c_community_health_unit', parent: { _id: 'e847f6e2-6dba-46dd-8128-5b153d0cd75f', parent: { _id: '95d9abd1-7c17-41b1-af98-595509f96631' } }, contact: { _id: 'bb9ebc4c6af161ee0f53b42339001fb1' }, reported_date: 1701631255451 } }, | ||
]; | ||
res.json({ | ||
total_rows: 2, | ||
offset: 0, | ||
rows: DATA.filter(r => r.key[0] === startkey[0]) | ||
}); | ||
}); | ||
|
||
app.use(timeoutMiddleware); | ||
|
||
app.all('*', (req, res) => { | ||
setTimeout(() => { | ||
res.status(200).send('OK'); | ||
}, 2000); | ||
}); | ||
|
||
// Start the server | ||
app.listen(3556, () => { | ||
console.log(`Server is listening on port ${3556}`); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { AxiosError, AxiosRequestConfig } from 'axios'; | ||
import isRetryAllowed from 'is-retry-allowed'; | ||
import { UserPayload } from '../services/user-payload'; | ||
import { ChtApi } from './cht-api'; | ||
|
||
const RETRY_COUNT = 4; | ||
|
||
export const axiosRetryConfig = { | ||
retries: RETRY_COUNT, | ||
retryDelay: () => 1000, | ||
retryCondition: (err: AxiosError) => { | ||
const status = err.response?.status; | ||
return (!status || status >= 500) && isRetryAllowed(err); | ||
}, | ||
onRetry: (retryCount: number, error: AxiosError, requestConfig: AxiosRequestConfig) => { | ||
console.log(`${requestConfig.url} failure. Retrying (${retryCount})`); | ||
}, | ||
}; | ||
|
||
export async function retryOnUpdateConflict<T>(funcWithPut: () => Promise<T>): Promise<T> { | ||
for (let retryCount = 0; retryCount < RETRY_COUNT; retryCount++) { | ||
try { | ||
return await funcWithPut(); | ||
} catch (err : any) { | ||
const statusCode = err.response?.status; | ||
if (statusCode === 409) { | ||
console.log(`Retrying on update-conflict (${retryCount})`); | ||
continue; | ||
} | ||
|
||
throw err; | ||
} | ||
} | ||
|
||
throw Error('update-conflict 409 persisted'); | ||
} | ||
|
||
export async function createUserWithRetries(userPayload: UserPayload, chtApi: ChtApi): Promise<{ username: string; password: string }> { | ||
for (let retryCount = 0; retryCount < RETRY_COUNT; ++retryCount) { | ||
try { | ||
await chtApi.createUser(userPayload); | ||
return userPayload; | ||
} catch (err: any) { | ||
if (axiosRetryConfig.retryCondition(err)) { | ||
continue; | ||
} | ||
|
||
if (err.response?.status !== 400) { | ||
throw err; | ||
} | ||
|
||
const translationKey = err.response?.data?.error?.translationKey; | ||
console.error('createUser retry because', translationKey); | ||
if (translationKey === 'username.taken') { | ||
userPayload.makeUsernameMoreComplex(); | ||
continue; | ||
} | ||
|
||
const RETRY_PASSWORD_TRANSLATIONS = ['password.length.minimum', 'password.weak']; | ||
if (RETRY_PASSWORD_TRANSLATIONS.includes(translationKey)) { | ||
userPayload.regeneratePassword(); | ||
continue; | ||
} | ||
|
||
throw err; | ||
} | ||
} | ||
|
||
throw new Error('could not create user ' + userPayload.contact); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.