1
+ import * as cdk from '@aws-cdk/core' ;
1
2
import { CfnRoute } from './appmesh.generated' ;
2
3
import { Protocol , HttpTimeout , GrpcTimeout , TcpTimeout } from './shared-interfaces' ;
3
4
import { IVirtualNode } from './virtual-node' ;
@@ -68,6 +69,81 @@ export interface HttpRouteSpecOptions {
68
69
* @default - None
69
70
*/
70
71
readonly timeout ?: HttpTimeout ;
72
+
73
+ /**
74
+ * The retry policy
75
+ *
76
+ * @default - no retry policy
77
+ */
78
+ readonly retryPolicy ?: HttpRetryPolicy ;
79
+ }
80
+
81
+ /**
82
+ * HTTP retry policy
83
+ */
84
+ export interface HttpRetryPolicy {
85
+ /**
86
+ * Specify HTTP events on which to retry. You must specify at least one value
87
+ * for at least one types of retry events.
88
+ *
89
+ * @default - no retries for http events
90
+ */
91
+ readonly httpRetryEvents ?: HttpRetryEvent [ ] ;
92
+
93
+ /**
94
+ * The maximum number of retry attempts
95
+ */
96
+ readonly retryAttempts : number ;
97
+
98
+ /**
99
+ * The timeout for each retry attempt
100
+ */
101
+ readonly retryTimeout : cdk . Duration ;
102
+
103
+ /**
104
+ * TCP events on which to retry. The event occurs before any processing of a
105
+ * request has started and is encountered when the upstream is temporarily or
106
+ * permanently unavailable. You must specify at least one value for at least
107
+ * one types of retry events.
108
+ *
109
+ * @default - no retries for tcp events
110
+ */
111
+ readonly tcpRetryEvents ?: TcpRetryEvent [ ] ;
112
+ }
113
+
114
+ /**
115
+ * HTTP events on which to retry.
116
+ */
117
+ export enum HttpRetryEvent {
118
+ /**
119
+ * HTTP status codes 500, 501, 502, 503, 504, 505, 506, 507, 508, 510, and 511
120
+ */
121
+ SERVER_ERROR = 'server-error' ,
122
+
123
+ /**
124
+ * HTTP status codes 502, 503, and 504
125
+ */
126
+ GATEWAY_ERROR = 'gateway-error' ,
127
+
128
+ /**
129
+ * HTTP status code 409
130
+ */
131
+ CLIENT_ERROR = 'client-error' ,
132
+
133
+ /**
134
+ * Retry on refused stream
135
+ */
136
+ STREAM_ERROR = 'stream-error' ,
137
+ }
138
+
139
+ /**
140
+ * TCP events on which you may retry
141
+ */
142
+ export enum TcpRetryEvent {
143
+ /**
144
+ * A connection error
145
+ */
146
+ CONNECTION_ERROR = 'connection-error' ,
71
147
}
72
148
73
149
/**
@@ -107,6 +183,64 @@ export interface GrpcRouteSpecOptions {
107
183
* List of targets that traffic is routed to when a request matches the route
108
184
*/
109
185
readonly weightedTargets : WeightedTarget [ ] ;
186
+
187
+ /**
188
+ * The retry policy
189
+ *
190
+ * @default - no retry policy
191
+ */
192
+ readonly retryPolicy ?: GrpcRetryPolicy ;
193
+ }
194
+
195
+ /** gRPC retry policy */
196
+ export interface GrpcRetryPolicy extends HttpRetryPolicy {
197
+ /**
198
+ * gRPC events on which to retry. You must specify at least one value
199
+ * for at least one types of retry events.
200
+ *
201
+ * @default - no retries for gRPC events
202
+ */
203
+ readonly grpcRetryEvents ?: GrpcRetryEvent [ ] ;
204
+ }
205
+
206
+ /**
207
+ * gRPC events
208
+ */
209
+ export enum GrpcRetryEvent {
210
+ /**
211
+ * Request was cancelled
212
+ *
213
+ * @see https://grpc.github.io/grpc/core/md_doc_statuscodes.html
214
+ */
215
+ CANCELLED = 'cancelled' ,
216
+
217
+ /**
218
+ * The deadline was exceeded
219
+ *
220
+ * @see https://grpc.github.io/grpc/core/md_doc_statuscodes.html
221
+ */
222
+ DEADLINE_EXCEEDED = 'deadline-exceeded' ,
223
+
224
+ /**
225
+ * Internal error
226
+ *
227
+ * @see https://grpc.github.io/grpc/core/md_doc_statuscodes.html
228
+ */
229
+ INTERNAL_ERROR = 'internal' ,
230
+
231
+ /**
232
+ * A resource was exhausted
233
+ *
234
+ * @see https://grpc.github.io/grpc/core/md_doc_statuscodes.html
235
+ */
236
+ RESOURCE_EXHAUSTED = 'resource-exhausted' ,
237
+
238
+ /**
239
+ * The service is unavailable
240
+ *
241
+ * @see https://grpc.github.io/grpc/core/md_doc_statuscodes.html
242
+ */
243
+ UNAVAILABLE = 'unavailable' ,
110
244
}
111
245
112
246
/**
@@ -203,19 +337,40 @@ class HttpRouteSpec extends RouteSpec {
203
337
*/
204
338
public readonly weightedTargets : WeightedTarget [ ] ;
205
339
340
+ /**
341
+ * The retry policy
342
+ */
343
+ public readonly retryPolicy ?: HttpRetryPolicy ;
344
+
206
345
constructor ( props : HttpRouteSpecOptions , protocol : Protocol ) {
207
346
super ( ) ;
208
347
this . protocol = protocol ;
209
348
this . match = props . match ;
210
349
this . weightedTargets = props . weightedTargets ;
211
350
this . timeout = props . timeout ;
351
+
352
+ if ( props . retryPolicy ) {
353
+ const httpRetryEvents = props . retryPolicy . httpRetryEvents ?? [ ] ;
354
+ const tcpRetryEvents = props . retryPolicy . tcpRetryEvents ?? [ ] ;
355
+
356
+ if ( httpRetryEvents . length + tcpRetryEvents . length === 0 ) {
357
+ throw new Error ( 'You must specify one value for at least one of `httpRetryEvents` or `tcpRetryEvents`' ) ;
358
+ }
359
+
360
+ this . retryPolicy = {
361
+ ...props . retryPolicy ,
362
+ httpRetryEvents : httpRetryEvents . length > 0 ? httpRetryEvents : undefined ,
363
+ tcpRetryEvents : tcpRetryEvents . length > 0 ? tcpRetryEvents : undefined ,
364
+ } ;
365
+ }
212
366
}
213
367
214
368
public bind ( _scope : Construct ) : RouteSpecConfig {
215
369
const prefixPath = this . match ? this . match . prefixPath : '/' ;
216
370
if ( prefixPath [ 0 ] != '/' ) {
217
371
throw new Error ( `Prefix Path must start with \'/\', got: ${ prefixPath } ` ) ;
218
372
}
373
+
219
374
const httpConfig : CfnRoute . HttpRouteProperty = {
220
375
action : {
221
376
weightedTargets : renderWeightedTargets ( this . weightedTargets ) ,
@@ -224,6 +379,7 @@ class HttpRouteSpec extends RouteSpec {
224
379
prefix : prefixPath ,
225
380
} ,
226
381
timeout : renderTimeout ( this . timeout ) ,
382
+ retryPolicy : this . retryPolicy ? renderHttpRetryPolicy ( this . retryPolicy ) : undefined ,
227
383
} ;
228
384
return {
229
385
httpRouteSpec : this . protocol === Protocol . HTTP ? httpConfig : undefined ,
@@ -266,11 +422,33 @@ class GrpcRouteSpec extends RouteSpec {
266
422
public readonly match : GrpcRouteMatch ;
267
423
public readonly timeout ?: GrpcTimeout ;
268
424
425
+ /**
426
+ * The retry policy.
427
+ */
428
+ public readonly retryPolicy ?: GrpcRetryPolicy ;
429
+
269
430
constructor ( props : GrpcRouteSpecOptions ) {
270
431
super ( ) ;
271
432
this . weightedTargets = props . weightedTargets ;
272
433
this . match = props . match ;
273
434
this . timeout = props . timeout ;
435
+
436
+ if ( props . retryPolicy ) {
437
+ const grpcRetryEvents = props . retryPolicy . grpcRetryEvents ?? [ ] ;
438
+ const httpRetryEvents = props . retryPolicy . httpRetryEvents ?? [ ] ;
439
+ const tcpRetryEvents = props . retryPolicy . tcpRetryEvents ?? [ ] ;
440
+
441
+ if ( grpcRetryEvents . length + httpRetryEvents . length + tcpRetryEvents . length === 0 ) {
442
+ throw new Error ( 'You must specify one value for at least one of `grpcRetryEvents`, `httpRetryEvents` or `tcpRetryEvents`' ) ;
443
+ }
444
+
445
+ this . retryPolicy = {
446
+ ...props . retryPolicy ,
447
+ grpcRetryEvents : grpcRetryEvents . length > 0 ? grpcRetryEvents : undefined ,
448
+ httpRetryEvents : httpRetryEvents . length > 0 ? httpRetryEvents : undefined ,
449
+ tcpRetryEvents : tcpRetryEvents . length > 0 ? tcpRetryEvents : undefined ,
450
+ } ;
451
+ }
274
452
}
275
453
276
454
public bind ( _scope : Construct ) : RouteSpecConfig {
@@ -283,6 +461,7 @@ class GrpcRouteSpec extends RouteSpec {
283
461
serviceName : this . match . serviceName ,
284
462
} ,
285
463
timeout : renderTimeout ( this . timeout ) ,
464
+ retryPolicy : this . retryPolicy ? renderGrpcRetryPolicy ( this . retryPolicy ) : undefined ,
286
465
} ,
287
466
} ;
288
467
}
@@ -323,3 +502,22 @@ function renderTimeout(timeout?: HttpTimeout): CfnRoute.HttpTimeoutProperty | un
323
502
}
324
503
: undefined ;
325
504
}
505
+
506
+ function renderHttpRetryPolicy ( retryPolicy : HttpRetryPolicy ) : CfnRoute . HttpRetryPolicyProperty {
507
+ return {
508
+ maxRetries : retryPolicy . retryAttempts ,
509
+ perRetryTimeout : {
510
+ unit : 'ms' ,
511
+ value : retryPolicy . retryTimeout . toMilliseconds ( ) ,
512
+ } ,
513
+ httpRetryEvents : retryPolicy . httpRetryEvents ,
514
+ tcpRetryEvents : retryPolicy . tcpRetryEvents ,
515
+ } ;
516
+ }
517
+
518
+ function renderGrpcRetryPolicy ( retryPolicy : GrpcRetryPolicy ) : CfnRoute . GrpcRetryPolicyProperty {
519
+ return {
520
+ ...renderHttpRetryPolicy ( retryPolicy ) ,
521
+ grpcRetryEvents : retryPolicy . grpcRetryEvents ,
522
+ } ;
523
+ }
0 commit comments