11import { logger , field } from "@coder/logger" ;
22import { NotificationService , INotificationHandle , INotificationService , Severity } from "./fill/notification" ;
33
4+ // tslint:disable no-any can have different return values
5+
46interface IRetryItem {
7+ /**
8+ * How many times this item has been retried.
9+ */
510 count ?: number ;
6- delay ?: number ; // In seconds.
7- end ?: number ; // In ms.
8- fn ( ) : any | Promise < any > ; // tslint:disable-line no-any can have different return values
11+
12+ /**
13+ * In seconds.
14+ */
15+ delay ?: number ;
16+
17+ /**
18+ * In milliseconds.
19+ */
20+ end ?: number ;
21+
22+ /**
23+ * Function to run when retrying.
24+ */
25+ fn ( ) : any ;
26+
27+ /**
28+ * Timer for running this item.
29+ */
930 timeout ?: number | NodeJS . Timer ;
31+
32+ /**
33+ * Whether the item is retrying or waiting to retry.
34+ */
1035 running ?: boolean ;
11- showInNotification : boolean ;
36+ }
37+
38+ /**
39+ * An retry-able instance.
40+ */
41+ export interface RetryInstance {
42+ /**
43+ * Run this retry.
44+ */
45+ run ( error ?: Error ) : void ;
46+
47+ /**
48+ * Block on this instance.
49+ */
50+ block ( ) : void ;
51+ }
52+
53+ /**
54+ * A retry-able instance that doesn't use a promise so it must be manually
55+ * ran again on failure and recovered on success.
56+ */
57+ export interface ManualRetryInstance extends RetryInstance {
58+ /**
59+ * Mark this item as recovered.
60+ */
61+ recover ( ) : void ;
1262}
1363
1464/**
@@ -21,7 +71,7 @@ interface IRetryItem {
2171 * to the user explaining what is happening with an option to immediately retry.
2272 */
2373export class Retry {
24- private items = new Map < string , IRetryItem > ( ) ;
74+ private readonly items = new Map < string , IRetryItem > ( ) ;
2575
2676 // Times are in seconds.
2777 private readonly retryMinDelay = 1 ;
@@ -50,13 +100,54 @@ export class Retry {
50100 }
51101
52102 /**
53- * Block retries when we know they will fail (for example when starting Wush
54- * back up). If a name is passed, that service will still be allowed to retry
103+ * Register a function to retry that starts/connects to a service.
104+ *
105+ * The service is automatically retried or recovered when the promise resolves
106+ * or rejects. If the service dies after starting, it must be manually
107+ * retried.
108+ */
109+ public register ( name : string , fn : ( ) => Promise < any > ) : RetryInstance ;
110+ /**
111+ * Register a function to retry that starts/connects to a service.
112+ *
113+ * Must manually retry if it fails to start again or dies after restarting and
114+ * manually recover if it succeeds in starting again.
115+ */
116+ public register ( name : string , fn : ( ) => any ) : ManualRetryInstance ;
117+ /**
118+ * Register a function to retry that starts/connects to a service.
119+ */
120+ public register ( name : string , fn : ( ) => any ) : RetryInstance | ManualRetryInstance {
121+ if ( this . items . has ( name ) ) {
122+ throw new Error ( `"${ name } " is already registered` ) ;
123+ }
124+ this . items . set ( name , { fn } ) ;
125+
126+ return {
127+ block : ( ) : void => this . block ( name ) ,
128+ run : ( error ?: Error ) : void => this . run ( name , error ) ,
129+ recover : ( ) : void => this . recover ( name ) ,
130+ } ;
131+ }
132+
133+ /**
134+ * Un-register a function to retry.
135+ */
136+ public unregister ( name : string ) : void {
137+ if ( ! this . items . has ( name ) ) {
138+ throw new Error ( `"${ name } " is not registered` ) ;
139+ }
140+ this . items . delete ( name ) ;
141+ }
142+
143+ /**
144+ * Block retries when we know they will fail (for example when the socket is
145+ * down ). If a name is passed, that service will still be allowed to retry
55146 * (unless we have already blocked).
56147 *
57148 * Blocking without a name will override a block with a name.
58149 */
59- public block ( name ?: string ) : void {
150+ private block ( name ?: string ) : void {
60151 if ( ! this . blocked || ! name ) {
61152 this . blocked = name || true ;
62153 this . items . forEach ( ( item ) => {
@@ -68,7 +159,7 @@ export class Retry {
68159 /**
69160 * Unblock retries and run any that are pending.
70161 */
71- public unblock ( ) : void {
162+ private unblock ( ) : void {
72163 this . blocked = false ;
73164 this . items . forEach ( ( item , name ) => {
74165 if ( item . running ) {
@@ -77,35 +168,10 @@ export class Retry {
77168 } ) ;
78169 }
79170
80- /**
81- * Register a function to retry that starts/connects to a service.
82- *
83- * If the function returns a promise, it will automatically be retried,
84- * recover, & unblock after calling `run` once (otherwise they need to be
85- * called manually).
86- */
87- // tslint:disable-next-line no-any can have different return values
88- public register ( name : string , fn : ( ) => any | Promise < any > , showInNotification : boolean = true ) : void {
89- if ( this . items . has ( name ) ) {
90- throw new Error ( `"${ name } " is already registered` ) ;
91- }
92- this . items . set ( name , { fn, showInNotification } ) ;
93- }
94-
95- /**
96- * Unregister a function to retry.
97- */
98- public unregister ( name : string ) : void {
99- if ( ! this . items . has ( name ) ) {
100- throw new Error ( `"${ name } " is not registered` ) ;
101- }
102- this . items . delete ( name ) ;
103- }
104-
105171 /**
106172 * Retry a service.
107173 */
108- public run ( name : string , error ?: Error ) : void {
174+ private run ( name : string , error ?: Error ) : void {
109175 if ( ! this . items . has ( name ) ) {
110176 throw new Error ( `"${ name } " is not registered` ) ;
111177 }
@@ -149,7 +215,7 @@ export class Retry {
149215 /**
150216 * Reset a service after a successfully recovering.
151217 */
152- public recover ( name : string ) : void {
218+ private recover ( name : string ) : void {
153219 if ( ! this . items . has ( name ) ) {
154220 throw new Error ( `"${ name } " is not registered` ) ;
155221 }
@@ -191,9 +257,9 @@ export class Retry {
191257 if ( this . blocked === name ) {
192258 this . unblock ( ) ;
193259 }
194- } ) . catch ( ( ) => {
260+ } ) . catch ( ( error ) => {
195261 endItem ( ) ;
196- this . run ( name ) ;
262+ this . run ( name , error ) ;
197263 } ) ;
198264 } else {
199265 endItem ( ) ;
@@ -214,8 +280,7 @@ export class Retry {
214280
215281 const now = Date . now ( ) ;
216282 const items = Array . from ( this . items . entries ( ) ) . filter ( ( [ _ , item ] ) => {
217- return item . showInNotification
218- && typeof item . end !== "undefined"
283+ return typeof item . end !== "undefined"
219284 && item . end > now
220285 && item . delay && item . delay >= this . notificationThreshold ;
221286 } ) . sort ( ( a , b ) => {
0 commit comments