Skip to content

Commit

Permalink
Fix: [AEA-4175] - use axios-retry to retry failures (#124)
Browse files Browse the repository at this point in the history
  • Loading branch information
anthony-nhs authored Jun 14, 2024
1 parent e78a32d commit a747244
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 2 deletions.
23 changes: 23 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@aws-lambda-powertools/logger": "^2.2.0",
"aws-lambda": "^1.0.7",
"axios": "^1.7.2",
"axios-retry": "^4.4.0",
"conventional-changelog-eslint": "^6.0.0"
},
"bugs": {
Expand Down
14 changes: 12 additions & 2 deletions src/live-spine-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import {serviceHealthCheck} from "./status"
import {SpineClient, SpineStatus} from "./spine-client"
import {Agent} from "https"
import axios, {
Axios,
AxiosError,
AxiosInstance,
AxiosRequestConfig,
AxiosResponse
} from "axios"
import {APIGatewayProxyEventHeaders} from "aws-lambda"
import axiosRetry from "axios-retry"

// timeout in ms to wait for response from spine to avoid lambda timeout
const SPINE_TIMEOUT = 45000
Expand All @@ -19,7 +20,7 @@ export class LiveSpineClient implements SpineClient {
private readonly spineASID: string | undefined
private readonly httpsAgent: Agent
private readonly spinePartyKey: string | undefined
private readonly axiosInstance: Axios
private readonly axiosInstance: AxiosInstance
private readonly logger: Logger

constructor(logger: Logger) {
Expand All @@ -34,6 +35,10 @@ export class LiveSpineClient implements SpineClient {
})
this.logger = logger
this.axiosInstance = axios.create()
axiosRetry(this.axiosInstance, {
retries: 3,
onRetry: this.onAxiosRetry
})
this.axiosInstance.interceptors.request.use((config) => {
config.headers["request-startTime"] = new Date().getTime()
return config
Expand Down Expand Up @@ -164,4 +169,9 @@ export class LiveSpineClient implements SpineClient {
process.env.SpineCAChain !== "ChangeMe"
)
}

onAxiosRetry = (retryCount, error) => {
this.logger.warn(error)
this.logger.warn(`Call to spine failed - retrying. Retry count ${retryCount}`)
}
}
35 changes: 35 additions & 0 deletions tests/live-spine-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,39 @@ describe("live spine client", () => {
}
await expect(spineClient.getPrescriptions(headers)).rejects.toThrow("timeout of 45000ms exceeded")
})

test("should not throw error when one unsuccessful and one successful http request", async () => {
mock
.onGet("https://spine/mm/patientfacingprescriptions").networkErrorOnce()
.onGet("https://spine/mm/patientfacingprescriptions").reply(200, {resourceType: "Bundle"})

const mockLoggerWarn = jest.spyOn(Logger.prototype, "warn")

const spineClient = new LiveSpineClient(logger)
const headers: APIGatewayProxyEventHeaders = {
"nhsd-nhslogin-user": "P9:9912003071"
}
const spineResponse = await spineClient.getPrescriptions(headers)

expect(spineResponse.status).toBe(200)
expect(spineResponse.data).toStrictEqual({resourceType: "Bundle"})
expect(mockLoggerWarn).toHaveBeenCalledWith("Call to spine failed - retrying. Retry count 1")
})

test("should retry only 3 times when http request errors", async () => {
mock.onGet("https://spine/mm/patientfacingprescriptions").networkError()
const mockLoggerWarn = jest.spyOn(Logger.prototype, "warn")

const spineClient = new LiveSpineClient(logger)
const headers: APIGatewayProxyEventHeaders = {
"nhsd-nhslogin-user": "P9:9912003071"
}
await expect(spineClient.getPrescriptions(headers)).rejects.toThrow("Network Error")
expect(mockLoggerWarn).toHaveBeenCalledWith("Call to spine failed - retrying. Retry count 1")
expect(mockLoggerWarn).toHaveBeenCalledWith("Call to spine failed - retrying. Retry count 2")
expect(mockLoggerWarn).toHaveBeenCalledWith("Call to spine failed - retrying. Retry count 3")
expect(mockLoggerWarn).not.toHaveBeenCalledWith("Call to spine failed - retrying. Retry count 4")
})


})

0 comments on commit a747244

Please sign in to comment.