diff --git a/gax/src/streamingCalls/streaming.ts b/gax/src/streamingCalls/streaming.ts index c55b5ffe2..1381b9d9c 100644 --- a/gax/src/streamingCalls/streaming.ts +++ b/gax/src/streamingCalls/streaming.ts @@ -342,8 +342,9 @@ export class StreamProxy extends duplexify implements GRPCCallResult { defaultShouldRetry(error: GoogleError, retry: RetryOptions) { if ( - retry.retryCodes.length > 0 && - retry.retryCodes.indexOf(error!.code!) < 0 + (retry.retryCodes.length > 0 && + retry.retryCodes.indexOf(error!.code!) < 0) || + retry.retryCodes.length === 0 ) { return false; } diff --git a/gax/test/unit/streaming.ts b/gax/test/unit/streaming.ts index 576ab3b83..d9c8a10f6 100644 --- a/gax/test/unit/streaming.ts +++ b/gax/test/unit/streaming.ts @@ -1265,6 +1265,60 @@ describe('handles server streaming retries in gax when gaxStreamingRetries is en } }); }); + it('does not retry when there is no shouldRetryFn and retryCodes is an empty array', done => { + const retrySpy = sinon.spy(streaming.StreamProxy.prototype, 'retry'); + const firstError = Object.assign(new GoogleError('UNAVAILABLE'), { + code: 14, + details: 'UNAVAILABLE', + metadata: new Metadata(), + }); + + const spy = sinon.spy((...args: Array<{}>) => { + assert.strictEqual(args.length, 3); + const s = new PassThrough({ + objectMode: true, + }); + s.push('hello'); + setImmediate(() => { + s.emit('metadata'); + }); + setImmediate(() => { + s.emit('error', firstError); + }); + return s; + }); + + const apiCall = createApiCallStreaming( + spy, + streaming.StreamType.SERVER_STREAMING, + false, + true + ); + + const call = apiCall( + {}, + { + // pass an empty array for retryCodes + retry: gax.createRetryOptions([], { + initialRetryDelayMillis: 100, + retryDelayMultiplier: 1.2, + maxRetryDelayMillis: 1000, + rpcTimeoutMultiplier: 1.5, + maxRpcTimeoutMillis: 3000, + maxRetries: 2, + }), + } + ); + + call.on('error', err => { + assert(err instanceof GoogleError); + if (err.code === 14) { + assert.strictEqual(err.code, 14); + assert.strictEqual(retrySpy.callCount, 0); + done(); + } + }); + }); it('server streaming call retries until exceeding total timeout', done => { const firstError = Object.assign(new GoogleError('UNAVAILABLE'), {