-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(HyperRequest): Add retry handling to HyperRequests
HyperRequests can now be set to retry requests. You can provide either a number of retries and a retry delay value (in milliseconds) or an array of retry delay values (to account for exponential backoffs). Additionally, a predicate function can be provided to determine if a request should be retried and to even modify the next request to be sent. (The default predicate function is `return HyperResponse.isError();`.)
- Loading branch information
Showing
5 changed files
with
315 additions
and
68 deletions.
There are no files selected for viewing
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 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 |
---|---|---|
@@ -1,6 +1,6 @@ | ||
{ | ||
"app":{ | ||
"cfengine":"adobe@2018" | ||
"cfengine":"adobe@2023" | ||
}, | ||
"web":{ | ||
"http":{ | ||
|
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,150 @@ | ||
component extends="tests.resources.ModuleIntegrationSpec" appMapping="/app" { | ||
|
||
function beforeAll() { | ||
super.beforeAll(); | ||
addMatchers( "hyper.models.TestBoxMatchers" ); | ||
} | ||
|
||
function run() { | ||
describe( "retry requests", () => { | ||
it( "can retry requests", () => { | ||
var hyper = new hyper.models.HyperBuilder(); | ||
hyper | ||
.fake( { | ||
"https://needs-retry.dev/" : function( createFakeResponse ) { | ||
return [ | ||
createFakeResponse( 500, "Internal Server Error" ), | ||
createFakeResponse( 200, "OK" ) | ||
]; | ||
} | ||
} ) | ||
.preventStrayRequests(); | ||
|
||
var retryDelays = []; | ||
var onHyperRequestCalls = []; | ||
var onHyperResponseCalls = []; | ||
|
||
var res = hyper | ||
.retry( 3, 100 ) | ||
.withRequestCallback( ( req ) => retryDelays.append( req.getRetries()[ req.getCurrentRequestCount() ] ) ) | ||
.withRequestCallback( ( req ) => onHyperRequestCalls.append( req.getMemento() ) ) | ||
.withResponseCallback( ( res ) => onHyperResponseCalls.append( res.getMemento() ) ) | ||
.get( "https://needs-retry.dev/" ); | ||
|
||
expect( res.getStatusCode() ).toBe( 200 ); | ||
expect( res.getStatusText() ).toBe( "OK" ); | ||
|
||
expect( retryDelays ).toBe( [ 100, 100 ] ); | ||
expect( onHyperRequestCalls ).toHaveLength( 2 ); | ||
expect( onHyperResponseCalls ).toHaveLength( 2 ); | ||
} ); | ||
|
||
it( "can provide a custom array of retry delays", () => { | ||
var hyper = new hyper.models.HyperBuilder(); | ||
hyper | ||
.fake( { | ||
"https://needs-retry.dev/" : function( createFakeResponse ) { | ||
return [ | ||
createFakeResponse( 500, "Internal Server Error" ), | ||
createFakeResponse( 500, "Internal Server Error" ), | ||
createFakeResponse( 200, "OK" ) | ||
]; | ||
} | ||
} ) | ||
.preventStrayRequests(); | ||
|
||
var retryDelays = []; | ||
var onHyperRequestCalls = []; | ||
var onHyperResponseCalls = []; | ||
|
||
var res = hyper | ||
.retry( [ 100, 200, 300 ] ) | ||
.withRequestCallback( ( req ) => retryDelays.append( req.getRetries()[ req.getCurrentRequestCount() ] ) ) | ||
.withRequestCallback( ( req ) => onHyperRequestCalls.append( req.getMemento() ) ) | ||
.withResponseCallback( ( res ) => onHyperResponseCalls.append( res.getMemento() ) ) | ||
.get( "https://needs-retry.dev/" ); | ||
|
||
expect( res.getStatusCode() ).toBe( 200 ); | ||
expect( res.getStatusText() ).toBe( "OK" ); | ||
|
||
expect( retryDelays ).toBe( [ 100, 200, 300 ] ); | ||
expect( onHyperRequestCalls ).toHaveLength( 3 ); | ||
expect( onHyperResponseCalls ).toHaveLength( 3 ); | ||
} ); | ||
|
||
it( "can provide a predicate function to determine if a request should be retried", () => { | ||
var hyper = new hyper.models.HyperBuilder(); | ||
hyper | ||
.fake( { | ||
"https://needs-retry.dev/" : function( createFakeResponse ) { | ||
return [ | ||
createFakeResponse( 500, "Internal Server Error" ), | ||
createFakeResponse( 429, "Too Many Requests" ), | ||
createFakeResponse( 200, "OK" ) | ||
]; | ||
} | ||
} ) | ||
.preventStrayRequests(); | ||
|
||
var onHyperRequestCalls = []; | ||
var onHyperResponseCalls = []; | ||
|
||
var res = hyper | ||
.retry( | ||
3, | ||
100, | ||
function( res, req ) { | ||
return res.isServerError(); | ||
} | ||
) | ||
.withRequestCallback( ( req ) => onHyperRequestCalls.append( req.getMemento() ) ) | ||
.withResponseCallback( ( res ) => onHyperResponseCalls.append( res.getMemento() ) ) | ||
.get( "https://needs-retry.dev/" ); | ||
|
||
expect( res.getStatusCode() ).toBe( 429 ); | ||
expect( res.getStatusText() ).toBe( "Too Many Requests" ); | ||
|
||
expect( onHyperRequestCalls ).toHaveLength( 2 ); | ||
expect( onHyperResponseCalls ).toHaveLength( 2 ); | ||
} ); | ||
|
||
it( "can modify the next request from the predicate function", () => { | ||
var hyper = new hyper.models.HyperBuilder(); | ||
hyper | ||
.fake( { | ||
"https://needs-retry.dev/failure" : function( createFakeResponse ) { | ||
return createFakeResponse( 500, "Internal Server Error" ); | ||
}, | ||
"https://needs-retry.dev/success" : function( createFakeResponse ) { | ||
return createFakeResponse( 200, "OK" ); | ||
} | ||
} ) | ||
.preventStrayRequests(); | ||
|
||
var onHyperRequestCalls = []; | ||
var onHyperResponseCalls = []; | ||
|
||
var res = hyper | ||
.setBaseUrl( "https://needs-retry.dev" ) | ||
.retry( | ||
3, | ||
100, | ||
function( res, req ) { | ||
req.setUrl( "/success" ); | ||
return res.isError(); | ||
} | ||
) | ||
.withRequestCallback( ( req ) => onHyperRequestCalls.append( req.getMemento() ) ) | ||
.withResponseCallback( ( res ) => onHyperResponseCalls.append( res.getMemento() ) ) | ||
.get( "/failure" ); | ||
|
||
expect( res.getStatusCode() ).toBe( 200 ); | ||
expect( res.getStatusText() ).toBe( "OK" ); | ||
|
||
expect( onHyperRequestCalls ).toHaveLength( 2 ); | ||
expect( onHyperResponseCalls ).toHaveLength( 2 ); | ||
} ); | ||
} ); | ||
} | ||
|
||
} |
Oops, something went wrong.