Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSUI-2153 Adding BackOff module with queuing logic #862

Merged
merged 20 commits into from Jul 17, 2018
Merged

Conversation

samisayegh
Copy link
Contributor

Deploy

@coveralls
Copy link

coveralls commented Jun 29, 2018

Coverage Status

Coverage decreased (-0.03%) to 86.193% when pulling f67e0fe on JSUI-2153 into a2d3e52 on master.

}
}

throw {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

? That's pretty weird.

_.defer(function() {
return '';
});
const tokenWasRenewed = await this.renewAccessTokenIfExpired(error);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd expect the code to read more like a big switch case on the error code, versus trying one error handler function. and if it does not work, go to the next error handler.

Seems much more straightforward to execute all error handler only when they are actually needed.

throw this.handleErrorResponse(error) as any;
}
}

private is429Error(error: IErrorResponse) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd call this "isThrottled" versus the error code number.

private static queue: Request[] = [];
private static clearingQueue = false;

public static enqueue(request: IBackOffRequest): Promise<ISuccessResponse<{}>> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd change the definition to use the generics you are "semi" using.

type Request<T> = () => Promise<ISuccessResponse<T>>;

export interface IBackOffRequest<T> {
  fn: Request<T>;
  retry?: (e, attemptNumber: number) => boolean;
}

enqueue<T>(request: IBackOffRequest<T>): Promise<ISuccessResponse<T>>

That kinda stuff, so you would not have to cast when you use it inside SearchEndpoint :

const backOffRequest = { fn: request, retry: this.retryIf429Error };
const response = await BackOffRequest.enqueue<T>(backOffRequest);
return response.data;

return this.accessToken.isExpired(e) && this.accessToken.doRenew();
}

private async backOff429Request<T>(request: () => Promise<ISuccessResponse<{}>>) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment about the 429 in the method name, I'd change the naming to "throttled".


private retryIf429Error(e: IErrorResponse, attempt: number) {
if (this.is429Error(e)) {
new Logger(this).info(`Resending the request because it was throttled. Retry attempt ${attempt}`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should already have a Logger instantiated in the SearchEndpoint constructor which you can re-use..


const defaultOptions: IBackOffOptions = {
numOfAttempts: 10,
timeStep: 2,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that a bit too low ? 🤔 Not 100% sure TBH, just wondering.

@@ -0,0 +1,31 @@
import { backOff } from '../../src/misc/BackOff';

export function BackOffTest() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hum seems like we are not testing an awful lot in that utility module.

Can we check that we have sane default ? (eg: 10 number of retry, don't have to pass in a retryConditionOption, etc.).

We should also be checking that all the possible options on that module works correctly.

Eg: number of attempts, delay, retryCondition being called, etc.

data: {}
};

beforeAll(() => stubBackOffDependency());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we make sure that we change the dependency back to the original module on afterEach()?

BackOffRequest.enqueue({ fn: () => resolveInOneTimeUnit() });
const secondRequest = BackOffRequest.enqueue({ fn: () => resolveInOneTimeUnit() });

secondRequest.then(response => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we have a test that does something like this ?

const firstRequest = ()=> resolveIn5TimeUnits();
const secondRequest = ()=> resolveInOneTimeUnits();

firstRequest.then(()=> {
expect second request to not be resolved
})

And then another one where you add a retryCondition on the first and second request, and you check that the retry condition on the second request is not called before the first request is finished ?

@samisayegh samisayegh merged commit e91e79c into master Jul 17, 2018
@samisayegh samisayegh deleted the JSUI-2153 branch July 17, 2018 14:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants