@@ -26,38 +26,15 @@ import {
2626import * as isStreamEnded from 'is-stream-ended' ;
2727import { PassThrough } from 'stream' ;
2828
29- import { PullResponse , Subscriber } from './subscriber' ;
29+ import { PullRetry } from './pull-retry' ;
30+ import { Subscriber } from './subscriber' ;
31+ import { google } from '../proto/pubsub' ;
3032
3133/*!
3234 * Frequency to ping streams.
3335 */
3436const KEEP_ALIVE_INTERVAL = 30000 ;
3537
36- /*!
37- * Deadline Exceeded status code
38- */
39- const DEADLINE : status = 4 ;
40-
41- /*!
42- * Unknown status code
43- */
44- const UNKNOWN : status = 2 ;
45-
46- /*!
47- * codes to retry streams
48- */
49- const RETRY_CODES : status [ ] = [
50- 0 , // ok
51- 1 , // canceled
52- 2 , // unknown
53- 4 , // deadline exceeded
54- 8 , // resource exhausted
55- 10 , // aborted
56- 13 , // internal error
57- 14 , // unavailable
58- 15 , // dataloss
59- ] ;
60-
6138/*!
6239 * Deadline for the stream.
6340 */
@@ -79,14 +56,8 @@ interface StreamState {
7956 highWaterMark : number ;
8057}
8158
82- interface StreamingPullRequest {
83- subscription ?: string ;
84- ackIds ?: string [ ] ;
85- modifyDeadlineSeconds ?: number [ ] ;
86- modifyDeadlineAckIds ?: string [ ] ;
87- streamAckDeadlineSeconds ?: number ;
88- }
89-
59+ type StreamingPullRequest = google . pubsub . v1 . IStreamingPullRequest ;
60+ type PullResponse = google . pubsub . v1 . IPullResponse ;
9061type PullStream = ClientDuplexStream < StreamingPullRequest , PullResponse > & {
9162 _readableState : StreamState ;
9263} ;
@@ -119,7 +90,9 @@ export class ChannelError extends Error implements ServiceError {
11990 code : status ;
12091 constructor ( err : Error ) {
12192 super ( `Failed to connect to channel. Reason: ${ err . message } ` ) ;
122- this . code = err . message . includes ( 'deadline' ) ? DEADLINE : UNKNOWN ;
93+ this . code = err . message . includes ( 'deadline' )
94+ ? status . DEADLINE_EXCEEDED
95+ : status . UNKNOWN ;
12396 }
12497}
12598
@@ -154,7 +127,9 @@ export interface MessageStreamOptions {
154127export class MessageStream extends PassThrough {
155128 destroyed : boolean ;
156129 private _keepAliveHandle : NodeJS . Timer ;
130+ private _fillHandle ?: NodeJS . Timer ;
157131 private _options : MessageStreamOptions ;
132+ private _retrier : PullRetry ;
158133 private _streams : Map < PullStream , boolean > ;
159134 private _subscriber : Subscriber ;
160135 constructor ( sub : Subscriber , options = { } as MessageStreamOptions ) {
@@ -164,6 +139,7 @@ export class MessageStream extends PassThrough {
164139
165140 this . destroyed = false ;
166141 this . _options = options ;
142+ this . _retrier = new PullRetry ( ) ;
167143 this . _streams = new Map ( ) ;
168144 this . _subscriber = sub ;
169145
@@ -253,6 +229,8 @@ export class MessageStream extends PassThrough {
253229 streamAckDeadlineSeconds : this . _subscriber . ackDeadline ,
254230 } ;
255231
232+ delete this . _fillHandle ;
233+
256234 for ( let i = this . _streams . size ; i < this . _options . maxStreams ! ; i ++ ) {
257235 const stream : PullStream = client . streamingPull ( { deadline} ) ;
258236 this . _addStream ( stream ) ;
@@ -302,8 +280,13 @@ export class MessageStream extends PassThrough {
302280 private _onEnd ( stream : PullStream , status : StatusObject ) : void {
303281 this . _removeStream ( stream ) ;
304282
305- if ( RETRY_CODES . includes ( status . code ) ) {
306- this . _fillStreamPool ( ) ;
283+ if ( this . _fillHandle ) {
284+ return ;
285+ }
286+
287+ if ( this . _retrier . retry ( status ) ) {
288+ const delay = this . _retrier . createTimeout ( ) ;
289+ this . _fillHandle = setTimeout ( ( ) => this . _fillStreamPool ( ) , delay ) ;
307290 } else if ( ! this . _streams . size ) {
308291 this . destroy ( new StatusError ( status ) ) ;
309292 }
0 commit comments