@@ -3,9 +3,21 @@ import { listOnePageLogResources } from '../api/logs';
3
3
import { TwilioServerlessApiClient } from '../client' ;
4
4
import { Sid } from '../types' ;
5
5
import { LogsConfig } from '../types/logs' ;
6
+ import debug from 'debug' ;
7
+
8
+ const log = debug ( 'twilio-serverless-api:client:logs' ) ;
9
+
10
+ const pollsBeforeBackOff = 10 ;
11
+ const defaultPollingFrequency = 1000 ;
12
+ // This default max allows the command to get to polling once every 32 seconds
13
+ const defaultMaxPollingFrequency = 30000 ;
14
+ const defaultLogCacheSize = 1000 ;
6
15
7
16
export class LogsStream extends Readable {
17
+ private _initialPollingFrequency : number ;
8
18
private _pollingFrequency : number ;
19
+ private _maxPollingFrequency : number ;
20
+ private _pollsWithoutResults : number ;
9
21
private _pollingCacheSize : number ;
10
22
private _interval : NodeJS . Timeout | undefined ;
11
23
private _viewedSids : Set < Sid > ;
@@ -21,8 +33,12 @@ export class LogsStream extends Readable {
21
33
this . _interval = undefined ;
22
34
this . _viewedSids = new Set ( ) ;
23
35
this . _viewedLogs = [ ] ;
24
- this . _pollingFrequency = config . pollingFrequency || 1000 ;
25
- this . _pollingCacheSize = config . logCacheSize || 1000 ;
36
+ this . _pollingFrequency = this . _initialPollingFrequency =
37
+ config . pollingFrequency || defaultPollingFrequency ;
38
+ this . _maxPollingFrequency =
39
+ config . maxPollingFrequency || defaultMaxPollingFrequency ;
40
+ this . _pollsWithoutResults = 0 ;
41
+ this . _pollingCacheSize = config . logCacheSize || defaultLogCacheSize ;
26
42
}
27
43
28
44
set pollingFrequency ( frequency : number ) {
@@ -46,12 +62,33 @@ export class LogsStream extends Readable {
46
62
pageSize : this . config . limit ,
47
63
}
48
64
) ;
49
- logs
50
- . filter ( log => ! this . _viewedSids . has ( log . sid ) )
51
- . reverse ( )
52
- . forEach ( log => {
65
+ const unviewedLogs = logs . filter ( ( log ) => ! this . _viewedSids . has ( log . sid ) ) ;
66
+ if ( unviewedLogs . length > 0 ) {
67
+ this . _pollsWithoutResults = 0 ;
68
+ this . pollingFrequency = this . _initialPollingFrequency ;
69
+ log (
70
+ `New log received. Now polling once every ${ this . _pollingFrequency } milliseconds.`
71
+ ) ;
72
+ unviewedLogs . reverse ( ) . forEach ( ( log ) => {
53
73
this . push ( log ) ;
54
74
} ) ;
75
+ } else {
76
+ if ( this . _pollsWithoutResults < pollsBeforeBackOff ) {
77
+ this . _pollsWithoutResults ++ ;
78
+ } else {
79
+ if ( this . _pollingFrequency < this . _maxPollingFrequency ) {
80
+ log (
81
+ `No new logs for ${
82
+ this . _pollsWithoutResults * this . _pollingFrequency
83
+ } milliseconds. Now polling once every ${
84
+ this . _pollingFrequency * 2
85
+ } milliseconds.`
86
+ ) ;
87
+ this . pollingFrequency = this . _pollingFrequency * 2 ;
88
+ this . _pollsWithoutResults = 0 ;
89
+ }
90
+ }
91
+ }
55
92
56
93
// The logs endpoint is not reliably returning logs in the same order
57
94
// Therefore we need to keep a set of all previously seen log entries
@@ -68,22 +105,22 @@ export class LogsStream extends Readable {
68
105
// and new logs by stringifying the sid and the date together.
69
106
const viewedLogsSet = new Set ( [
70
107
...this . _viewedLogs . map (
71
- log => `${ log . sid } -${ log . dateCreated . toISOString ( ) } `
108
+ ( log ) => `${ log . sid } -${ log . dateCreated . toISOString ( ) } `
72
109
) ,
73
- ...logs . map ( log => `${ log . sid } -${ log . date_created } ` ) ,
110
+ ...logs . map ( ( log ) => `${ log . sid } -${ log . date_created } ` ) ,
74
111
] ) ;
75
112
// Then we take that set, map over the logs and split them up into sid and
76
113
// date again, sort them most to least recent and chop off the oldest if
77
114
// they are beyond the polling cache size.
78
115
this . _viewedLogs = [ ...viewedLogsSet ]
79
- . map ( logString => {
116
+ . map ( ( logString ) => {
80
117
const [ sid , dateCreated ] = logString . split ( '-' ) ;
81
118
return { sid, dateCreated : new Date ( dateCreated ) } ;
82
119
} )
83
120
. sort ( ( a , b ) => b . dateCreated . valueOf ( ) - a . dateCreated . valueOf ( ) )
84
121
. slice ( 0 , this . _pollingCacheSize ) ;
85
122
// Finally we create a set of just SIDs to compare against.
86
- this . _viewedSids = new Set ( this . _viewedLogs . map ( log => log . sid ) ) ;
123
+ this . _viewedSids = new Set ( this . _viewedLogs . map ( ( log ) => log . sid ) ) ;
87
124
88
125
if ( ! this . config . tail ) {
89
126
this . push ( null ) ;
0 commit comments