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

feat: more information for exceed timeout error #839

Merged
merged 11 commits into from
Jun 2, 2020
3 changes: 2 additions & 1 deletion src/createApiCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ export function createApiCall(
return retryable(
func,
thisSettings.retry!,
thisSettings.otherArgs as GRPCCallOtherArgs
thisSettings.otherArgs as GRPCCallOtherArgs,
thisSettings.apiName
);
}
return addTimeoutArg(
Expand Down
11 changes: 10 additions & 1 deletion src/gax.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export interface CallOptions {
bundleOptions?: BundleOptions | null;
isBundling?: boolean;
longrunning?: BackoffSettings;
apiName?: string;
}

export class CallSettings {
Expand All @@ -138,6 +139,7 @@ export class CallSettings {
bundleOptions?: BundleOptions | null;
isBundling: boolean;
longrunning?: BackoffSettings;
apiName?: string;

/**
* @param {Object} settings - An object containing parameters of this settings.
Expand Down Expand Up @@ -170,6 +172,7 @@ export class CallSettings {
this.isBundling = 'isBundling' in settings ? settings.isBundling! : true;
this.longrunning =
'longrunning' in settings ? settings.longrunning : undefined;
this.apiName = settings.apiName ?? undefined;
}

/**
Expand All @@ -193,6 +196,7 @@ export class CallSettings {
let otherArgs = this.otherArgs;
let isBundling = this.isBundling;
let longrunning = this.longrunning;
let apiName = this.apiName;
if ('timeout' in options) {
timeout = options.timeout!;
}
Expand Down Expand Up @@ -239,6 +243,9 @@ export class CallSettings {
if ('longrunning' in options) {
longrunning = options.longrunning;
}
if ('apiName' in options) {
apiName = options.apiName;
}

return new CallSettings({
timeout,
Expand All @@ -251,6 +258,7 @@ export class CallSettings {
maxResults,
otherArgs,
isBundling,
apiName,
});
}
}
Expand Down Expand Up @@ -650,14 +658,15 @@ export function constructSettings(
)!
);
}

const apiName = serviceName;
defaults[jsName] = new CallSettings({
timeout,
retry,
bundleOptions: bundlingConfig
? createBundleOptions(bundlingConfig)
: null,
otherArgs,
apiName,
});
}

Expand Down
5 changes: 3 additions & 2 deletions src/normalCalls/retries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ import {addTimeoutArg} from './timeout';
export function retryable(
func: GRPCCall,
retry: RetryOptions,
otherArgs: GRPCCallOtherArgs
otherArgs: GRPCCallOtherArgs,
apiName?: string
): SimpleCallbackFunction {
const delayMult = retry.backoffSettings.retryDelayMultiplier;
const maxDelay = retry.backoffSettings.maxRetryDelayMillis;
Expand Down Expand Up @@ -81,7 +82,7 @@ export function retryable(
timeoutId = null;
if (deadline && now.getTime() >= deadline) {
const error = new GoogleError(
'Retry total timeout exceeded before any response was received'
`Total timeout of API ${apiName} exceeded ${retry.backoffSettings.totalTimeoutMillis} milliseconds before any response was received.`
);
error.code = Status.DEADLINE_EXCEEDED;
callback(error);
Expand Down
18 changes: 17 additions & 1 deletion test/unit/apiCallable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@ describe('Promise', () => {

describe('retryable', () => {
const retryOptions = utils.createRetryOptions(0, 0, 0, 0, 0, 0, 100);
const settings = {settings: {timeout: 0, retry: retryOptions}};
const settings = {
settings: {timeout: 0, retry: retryOptions, apiName: 'TestApi'},
};

it('retries the API call', done => {
let toAttempt = 3;
Expand Down Expand Up @@ -364,6 +366,20 @@ describe('retryable', () => {
});
});

it('retry fails for exceeding total timeout', done => {
const spy = sinon.spy(fail);
const apiCall = createApiCall(spy, settings);
apiCall({}, undefined, err => {
assert.ok(err instanceof GoogleError);
assert.strictEqual(
err.message,
'Total timeout of API TestApi exceeded 100 milliseconds before any response was received.'
);
assert.strictEqual(err!.code, status.DEADLINE_EXCEEDED);
done();
});
});

// maxRetries is unsupported, and intended for internal use only.
it('errors when totalTimeoutMillis and maxRetries set', done => {
const maxRetries = 5;
Expand Down
1 change: 1 addition & 0 deletions test/unit/gax.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ describe('gax construct settings', () => {
);
let settings = defaults.bundlingMethod;
assert.strictEqual(settings.timeout, 40000);
assert.strictEqual(settings.apiName, SERVICE_NAME);
expectRetryOptions(settings.retry);
assert.deepStrictEqual(settings.retry.retryCodes, [1, 2]);
assert.strictEqual(settings.otherArgs, otherArgs);
Expand Down