@kensio/yulin 1.21.26 → 1.21.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/service/eventbridge/bus/sim-event-bus-name.d.ts +4 -0
- package/dist/service/eventbridge/bus/sim-event-bus-name.js +17 -12
- package/dist/service/eventbridge/cfn/bus/sim-cfn-event-bus-creator.js +8 -1
- package/dist/service/eventbridge/cfn/bus/sim-cfn-event-bus-properties.d.ts +5 -0
- package/dist/service/eventbridge/cfn/bus/sim-cfn-event-bus-properties.js +14 -1
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-creator.js +2 -0
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-target-delivery.d.ts +15 -0
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-target-delivery.js +53 -0
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-targets.d.ts +4 -0
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-targets.js +7 -3
- package/dist/service/eventbridge/command/authorize/sim-event-bridge-authorizer.d.ts +5 -0
- package/dist/service/eventbridge/command/authorize/sim-event-bridge-authorizer.js +7 -0
- package/dist/service/eventbridge/command/bus/sim-event-bridge-create-event-bus.d.ts +7 -1
- package/dist/service/eventbridge/command/bus/sim-event-bridge-create-event-bus.js +7 -1
- package/dist/service/eventbridge/command/bus/sim-event-bridge-partner-bus.d.ts +24 -0
- package/dist/service/eventbridge/command/bus/sim-event-bridge-partner-bus.js +44 -0
- package/dist/service/eventbridge/command/bus/sim-event-bridge-unsimulated-bus-input.js +0 -5
- package/dist/service/eventbridge/command/put-events/sim-event-bridge-authorized-entries.js +8 -0
- package/dist/service/eventbridge/command/sim-event-bridge-command.types.d.ts +1 -0
- package/dist/service/eventbridge/command/sim-event-bridge-commands.d.ts +6 -0
- package/dist/service/eventbridge/command/sim-event-bridge-commands.js +19 -1
- package/dist/service/eventbridge/command/source/sim-event-bridge-describe-event-source.d.ts +35 -0
- package/dist/service/eventbridge/command/source/sim-event-bridge-describe-event-source.js +46 -0
- package/dist/service/eventbridge/command/source/sim-event-bridge-put-partner-events.d.ts +41 -0
- package/dist/service/eventbridge/command/source/sim-event-bridge-put-partner-events.js +82 -0
- package/dist/service/eventbridge/command/source/source.command.d.ts +59 -0
- package/dist/service/eventbridge/command/source/source.command.js +1 -0
- package/dist/service/eventbridge/command/target/sim-event-bridge-target-commands.js +2 -0
- package/dist/service/eventbridge/command/target/sim-event-bridge-unsimulated-target-input.js +2 -12
- package/dist/service/eventbridge/command/target/target.command.d.ts +8 -5
- package/dist/service/eventbridge/delivery/sim-aws-event-bridge-delivery-targets.d.ts +6 -1
- package/dist/service/eventbridge/delivery/sim-aws-event-bridge-delivery-targets.js +16 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-dead-letter-attributes.d.ts +9 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-dead-letter-attributes.js +47 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-dead-letter-queue.d.ts +24 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-dead-letter-queue.js +28 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-delivery-attempt.d.ts +41 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-delivery-attempt.js +97 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-delivery-queue.js +7 -37
- package/dist/service/eventbridge/delivery/sim-event-bridge-delivery-retries.test-support.d.ts +25 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-delivery-retries.test-support.js +60 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-delivery.d.ts +22 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-failing-targets.test-support.d.ts +23 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-failing-targets.test-support.js +28 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-no-delivery-targets.d.ts +5 -1
- package/dist/service/eventbridge/delivery/sim-event-bridge-no-delivery-targets.js +9 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-queue-message.d.ts +28 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-queue-message.js +45 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-target-delivery.d.ts +4 -1
- package/dist/service/eventbridge/delivery/sim-event-bridge-target-delivery.js +19 -14
- package/dist/service/eventbridge/index.d.ts +2 -0
- package/dist/service/eventbridge/index.js +2 -0
- package/dist/service/eventbridge/routing/sim-event-bridge-router.js +1 -0
- package/dist/service/eventbridge/sdk/sim-event-bridge-sdk-command-router.js +4 -0
- package/dist/service/eventbridge/sim-event-bridge-inspection.d.ts +10 -0
- package/dist/service/eventbridge/sim-event-bridge-inspection.js +9 -0
- package/dist/service/eventbridge/sim-event-bridge-partners.d.ts +38 -0
- package/dist/service/eventbridge/sim-event-bridge-partners.js +43 -0
- package/dist/service/eventbridge/sim-event-bridge.d.ts +12 -12
- package/dist/service/eventbridge/sim-event-bridge.js +14 -11
- package/dist/service/eventbridge/source/sim-partner-event-source-name.d.ts +28 -0
- package/dist/service/eventbridge/source/sim-partner-event-source-name.js +62 -0
- package/dist/service/eventbridge/source/sim-partner-event-source-store.d.ts +18 -0
- package/dist/service/eventbridge/source/sim-partner-event-source-store.js +29 -0
- package/dist/service/eventbridge/source/sim-partner-event-source.d.ts +46 -0
- package/dist/service/eventbridge/source/sim-partner-event-source.js +43 -0
- package/dist/service/eventbridge/target/sim-event-target-dead-letter-config.d.ts +28 -0
- package/dist/service/eventbridge/target/sim-event-target-dead-letter-config.js +42 -0
- package/dist/service/eventbridge/target/sim-event-target-retry-policy.d.ts +28 -0
- package/dist/service/eventbridge/target/sim-event-target-retry-policy.js +53 -0
- package/dist/service/eventbridge/target/sim-event-target.d.ts +17 -0
- package/dist/service/eventbridge/target/sim-event-target.js +19 -0
- package/docs/services/eventbridge/README.md +223 -6
- package/package.json +1 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { BackgroundScheduler } from "../../../../util/background/background.js";
|
|
2
|
+
import type { SimAwsAccountRegionScope } from "../../../aws/sim-aws-account-region-scope.js";
|
|
3
|
+
import type { SimEventBridgeRouter } from "../../routing/sim-event-bridge-router.js";
|
|
4
|
+
import type { SimPartnerEventSourceStore } from "../../source/sim-partner-event-source-store.js";
|
|
5
|
+
import type { SimPutPartnerEventsCommand, SimPutPartnerEventsCommandOutput } from "./source.command.js";
|
|
6
|
+
interface SimEventBridgePutPartnerEventsProperties {
|
|
7
|
+
readonly sources: SimPartnerEventSourceStore;
|
|
8
|
+
readonly accountRegionScope: SimAwsAccountRegionScope;
|
|
9
|
+
readonly clock: BackgroundScheduler;
|
|
10
|
+
readonly router: SimEventBridgeRouter;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Puts events onto partner event buses as their SaaS partner would.
|
|
14
|
+
*
|
|
15
|
+
* Each entry's `Source` names the partner event source it comes from, and the
|
|
16
|
+
* event goes to the bus of the same name. An event for a source with no bus is
|
|
17
|
+
* dropped. Real EventBridge documents that it keeps nothing a partner sends
|
|
18
|
+
* before the receiving Account creates the bus.
|
|
19
|
+
*
|
|
20
|
+
* Nothing is authorized. The partner sends from its own Account, which is
|
|
21
|
+
* outside the simulation, and the receiving Account's IAM has no say in it.
|
|
22
|
+
*/
|
|
23
|
+
export declare class SimEventBridgePutPartnerEvents {
|
|
24
|
+
private readonly sources;
|
|
25
|
+
private readonly clock;
|
|
26
|
+
private readonly router;
|
|
27
|
+
private readonly reader;
|
|
28
|
+
constructor(properties: SimEventBridgePutPartnerEventsProperties);
|
|
29
|
+
/**
|
|
30
|
+
* Put a partner's events onto the buses of their sources.
|
|
31
|
+
*
|
|
32
|
+
* Every `Source` is resolved before any event is put, so a request naming a
|
|
33
|
+
* source that was never registered changes nothing.
|
|
34
|
+
*/
|
|
35
|
+
handle(command: SimPutPartnerEventsCommand): SimPutPartnerEventsCommandOutput;
|
|
36
|
+
/**
|
|
37
|
+
* Put one entry onto the bus its source names.
|
|
38
|
+
*/
|
|
39
|
+
private put;
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { SimEventBridgeValidationException } from "../../error/sim-event-bridge.error.js";
|
|
2
|
+
import { SimEventBridgeEntryFailure } from "../put-events/sim-event-bridge-entry-failure.js";
|
|
3
|
+
import { SimEventBridgeEntryReader } from "../put-events/sim-event-bridge-entry-reader.js";
|
|
4
|
+
import { simEventBridgeMaximumRequestBytes, simEventBridgeRequestSize, } from "../put-events/sim-event-bridge-entry-size.js";
|
|
5
|
+
/**
|
|
6
|
+
* The most entries one PutPartnerEvents request may carry.
|
|
7
|
+
*/
|
|
8
|
+
const maximumEntries = 20;
|
|
9
|
+
/**
|
|
10
|
+
* Puts events onto partner event buses as their SaaS partner would.
|
|
11
|
+
*
|
|
12
|
+
* Each entry's `Source` names the partner event source it comes from, and the
|
|
13
|
+
* event goes to the bus of the same name. An event for a source with no bus is
|
|
14
|
+
* dropped. Real EventBridge documents that it keeps nothing a partner sends
|
|
15
|
+
* before the receiving Account creates the bus.
|
|
16
|
+
*
|
|
17
|
+
* Nothing is authorized. The partner sends from its own Account, which is
|
|
18
|
+
* outside the simulation, and the receiving Account's IAM has no say in it.
|
|
19
|
+
*/
|
|
20
|
+
export class SimEventBridgePutPartnerEvents {
|
|
21
|
+
sources;
|
|
22
|
+
clock;
|
|
23
|
+
router;
|
|
24
|
+
reader;
|
|
25
|
+
constructor(properties) {
|
|
26
|
+
this.sources = properties.sources;
|
|
27
|
+
this.clock = properties.clock;
|
|
28
|
+
this.router = properties.router;
|
|
29
|
+
this.reader = new SimEventBridgeEntryReader({
|
|
30
|
+
accountRegionScope: properties.accountRegionScope,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Put a partner's events onto the buses of their sources.
|
|
35
|
+
*
|
|
36
|
+
* Every `Source` is resolved before any event is put, so a request naming a
|
|
37
|
+
* source that was never registered changes nothing.
|
|
38
|
+
*/
|
|
39
|
+
handle(command) {
|
|
40
|
+
const entries = partnerRequestEntries(command.input.Entries ?? []);
|
|
41
|
+
for (const entry of entries) {
|
|
42
|
+
if (entry.Source !== undefined) {
|
|
43
|
+
this.sources.require(entry.Source);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const at = this.clock.now();
|
|
47
|
+
const results = entries.map((entry) => this.put(entry, at));
|
|
48
|
+
return {
|
|
49
|
+
$metadata: {},
|
|
50
|
+
Entries: results,
|
|
51
|
+
FailedEntryCount: results.filter((result) => result.ErrorCode !== undefined).length,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Put one entry onto the bus its source names.
|
|
56
|
+
*/
|
|
57
|
+
put(entry, at) {
|
|
58
|
+
const read = this.reader.read(entry, at);
|
|
59
|
+
if (read instanceof SimEventBridgeEntryFailure) {
|
|
60
|
+
return read.toResultEntry();
|
|
61
|
+
}
|
|
62
|
+
this.router.deliver(read.source, read);
|
|
63
|
+
return { EventId: read.id };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Refuse a request carrying no entries, too many, or too many bytes.
|
|
68
|
+
*/
|
|
69
|
+
function partnerRequestEntries(entries) {
|
|
70
|
+
if (entries.length === 0 || entries.length > maximumEntries) {
|
|
71
|
+
throw new SimEventBridgeValidationException(`Invalid parameter: Entries Reason: a PutPartnerEvents request carries ` +
|
|
72
|
+
`between 1 and ${String(maximumEntries)} entries, and this one ` +
|
|
73
|
+
`carries ${String(entries.length)}`);
|
|
74
|
+
}
|
|
75
|
+
const size = simEventBridgeRequestSize(entries);
|
|
76
|
+
if (size > simEventBridgeMaximumRequestBytes) {
|
|
77
|
+
throw new SimEventBridgeValidationException(`Total size of the entries in the request is ${String(size)} bytes, ` +
|
|
78
|
+
`which is over the ${String(simEventBridgeMaximumRequestBytes)} byte ` +
|
|
79
|
+
`limit.`);
|
|
80
|
+
}
|
|
81
|
+
return entries;
|
|
82
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { SimResponseMetadata } from "../../../aws/metadata/response-metadata.type.js";
|
|
2
|
+
/**
|
|
3
|
+
* Minimal structural sim EventBridge DescribeEventSource command.
|
|
4
|
+
*
|
|
5
|
+
* https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/eventbridge/command/DescribeEventSourceCommand/
|
|
6
|
+
*/
|
|
7
|
+
export interface SimDescribeEventSourceCommand {
|
|
8
|
+
readonly input: SimDescribeEventSourceCommandInput;
|
|
9
|
+
}
|
|
10
|
+
export interface SimDescribeEventSourceCommandInput {
|
|
11
|
+
readonly Name?: string | undefined;
|
|
12
|
+
}
|
|
13
|
+
export interface SimDescribeEventSourceCommandOutput {
|
|
14
|
+
readonly Arn?: string | undefined;
|
|
15
|
+
readonly CreatedBy?: string | undefined;
|
|
16
|
+
readonly CreationTime?: Date | undefined;
|
|
17
|
+
readonly Name?: string | undefined;
|
|
18
|
+
readonly State?: string | undefined;
|
|
19
|
+
readonly $metadata: SimResponseMetadata;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* One event as a partner's PutPartnerEvents request carries it.
|
|
23
|
+
*
|
|
24
|
+
* https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutPartnerEventsRequestEntry.html
|
|
25
|
+
*/
|
|
26
|
+
export interface SimPutPartnerEventsRequestEntry {
|
|
27
|
+
readonly Source?: string | undefined;
|
|
28
|
+
readonly DetailType?: string | undefined;
|
|
29
|
+
readonly Detail?: string | undefined;
|
|
30
|
+
readonly Resources?: readonly string[] | undefined;
|
|
31
|
+
readonly Time?: Date | undefined;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* One partner entry's result, which carries either an event id or a failure.
|
|
35
|
+
*/
|
|
36
|
+
export interface SimPutPartnerEventsResultEntry {
|
|
37
|
+
readonly EventId?: string | undefined;
|
|
38
|
+
readonly ErrorCode?: string | undefined;
|
|
39
|
+
readonly ErrorMessage?: string | undefined;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Minimal structural sim EventBridge PutPartnerEvents command.
|
|
43
|
+
*
|
|
44
|
+
* A SaaS partner sends this from its own Account. In a simulation it is a
|
|
45
|
+
* test acting as the partner, through `SimEventBridge.putPartnerEvents`.
|
|
46
|
+
*
|
|
47
|
+
* https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/eventbridge/command/PutPartnerEventsCommand/
|
|
48
|
+
*/
|
|
49
|
+
export interface SimPutPartnerEventsCommand {
|
|
50
|
+
readonly input: SimPutPartnerEventsCommandInput;
|
|
51
|
+
}
|
|
52
|
+
export interface SimPutPartnerEventsCommandInput {
|
|
53
|
+
readonly Entries?: readonly SimPutPartnerEventsRequestEntry[] | undefined;
|
|
54
|
+
}
|
|
55
|
+
export interface SimPutPartnerEventsCommandOutput {
|
|
56
|
+
readonly Entries?: readonly SimPutPartnerEventsResultEntry[] | undefined;
|
|
57
|
+
readonly FailedEntryCount?: number | undefined;
|
|
58
|
+
readonly $metadata: SimResponseMetadata;
|
|
59
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -54,6 +54,8 @@ export class SimEventBridgeTargetCommands {
|
|
|
54
54
|
Input: target.input,
|
|
55
55
|
RoleArn: target.ecs?.roleArn,
|
|
56
56
|
EcsParameters: target.ecs?.task.parameters.declared,
|
|
57
|
+
RetryPolicy: target.retryPolicy?.declared,
|
|
58
|
+
DeadLetterConfig: target.deadLetterConfig?.declared,
|
|
57
59
|
}));
|
|
58
60
|
const page = new SimEventBridgePage(listed, input.Limit, input.NextToken);
|
|
59
61
|
return {
|
package/dist/service/eventbridge/command/target/sim-event-bridge-unsimulated-target-input.js
CHANGED
|
@@ -3,8 +3,8 @@ import { SimEventBridgeUnsimulatedInputException } from "../../error/sim-event-b
|
|
|
3
3
|
* The properties that change what a target receives, or whether it receives
|
|
4
4
|
* anything at all.
|
|
5
5
|
*
|
|
6
|
-
* Ignoring one would leave a test believing in a transformation
|
|
7
|
-
*
|
|
6
|
+
* Ignoring one would leave a test believing in a transformation that never
|
|
7
|
+
* happened.
|
|
8
8
|
*/
|
|
9
9
|
const behaviourRefusals = [
|
|
10
10
|
[
|
|
@@ -17,16 +17,6 @@ const behaviourRefusals = [
|
|
|
17
17
|
"Target InputTransformer is not simulated, so PutTargets refuses one " +
|
|
18
18
|
"rather than sending the untransformed event",
|
|
19
19
|
],
|
|
20
|
-
[
|
|
21
|
-
(target) => target.DeadLetterConfig,
|
|
22
|
-
"Target dead letter queues are not simulated, so PutTargets refuses a " +
|
|
23
|
-
"DeadLetterConfig rather than dropping undelivered events silently",
|
|
24
|
-
],
|
|
25
|
-
[
|
|
26
|
-
(target) => target.RetryPolicy,
|
|
27
|
-
"Target retry policies are not simulated, so PutTargets refuses a " +
|
|
28
|
-
"RetryPolicy rather than delivering once and calling it retried",
|
|
29
|
-
],
|
|
30
20
|
[
|
|
31
21
|
(target) => target.SqsParameters,
|
|
32
22
|
"SqsParameters names a FIFO queue's message group, and FIFO queues are " +
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { SimResponseMetadata } from "../../../aws/metadata/response-metadata.type.js";
|
|
2
2
|
import type { SimEcsTargetParametersType } from "../../../ecs/target/sim-ecs-target-parameters.js";
|
|
3
|
+
import type { SimEventTargetDeadLetterConfigInput } from "../../target/sim-event-target-dead-letter-config.js";
|
|
4
|
+
import type { SimEventTargetRetryPolicyInput } from "../../target/sim-event-target-retry-policy.js";
|
|
3
5
|
/**
|
|
4
6
|
* One target as a request carries it, and as ListTargetsByRule reports it.
|
|
5
7
|
*
|
|
6
|
-
* The properties beyond `Id`, `Arn`, `Input`, `RoleArn
|
|
7
|
-
* are the ones real EventBridge takes and
|
|
8
|
-
*
|
|
8
|
+
* The properties beyond `Id`, `Arn`, `Input`, `RoleArn`, `EcsParameters`,
|
|
9
|
+
* `DeadLetterConfig` and `RetryPolicy` are the ones real EventBridge takes and
|
|
10
|
+
* this simulation refuses. They are kept in the shape so a request carrying
|
|
11
|
+
* one is recognised and named.
|
|
9
12
|
*/
|
|
10
13
|
export interface SimEventBridgeTarget {
|
|
11
14
|
readonly Id?: string | undefined;
|
|
@@ -14,8 +17,8 @@ export interface SimEventBridgeTarget {
|
|
|
14
17
|
readonly InputPath?: string | undefined;
|
|
15
18
|
readonly InputTransformer?: object | undefined;
|
|
16
19
|
readonly RoleArn?: string | undefined;
|
|
17
|
-
readonly DeadLetterConfig?:
|
|
18
|
-
readonly RetryPolicy?:
|
|
20
|
+
readonly DeadLetterConfig?: SimEventTargetDeadLetterConfigInput | undefined;
|
|
21
|
+
readonly RetryPolicy?: SimEventTargetRetryPolicyInput | undefined;
|
|
19
22
|
readonly SqsParameters?: object | undefined;
|
|
20
23
|
readonly KinesisParameters?: object | undefined;
|
|
21
24
|
readonly EcsParameters?: SimEcsTargetParametersType | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SimAws } from "../../aws/sim-aws.js";
|
|
2
|
-
import type { SimEventBridgeDeliveryRequest, SimEventBridgeDeliveryTargets } from "./sim-event-bridge-delivery.js";
|
|
2
|
+
import type { SimEventBridgeDeadLetterRequest, SimEventBridgeDeliveryRequest, SimEventBridgeDeliveryTargets } from "./sim-event-bridge-delivery.js";
|
|
3
3
|
interface SimAwsEventBridgeDeliveryTargetsProperties {
|
|
4
4
|
readonly simAws: SimAws;
|
|
5
5
|
}
|
|
@@ -21,6 +21,11 @@ export declare class SimAwsEventBridgeDeliveryTargets implements SimEventBridgeD
|
|
|
21
21
|
* Send one event to the target its ARN names.
|
|
22
22
|
*/
|
|
23
23
|
deliver(request: SimEventBridgeDeliveryRequest): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Send an event EventBridge gave up on to the dead-letter queue its target
|
|
26
|
+
* names, in the queue's own Account and Region.
|
|
27
|
+
*/
|
|
28
|
+
deadLetter(request: SimEventBridgeDeadLetterRequest): Promise<void>;
|
|
24
29
|
/**
|
|
25
30
|
* Hand the delivery to the one destination that knows this service.
|
|
26
31
|
*/
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { assertDefined } from "../../../util/type-guard/defined.js";
|
|
1
2
|
import { SimEventBridgeDeliveryFunction } from "./sim-event-bridge-delivery-function.js";
|
|
3
|
+
import { SimEventBridgeDeadLetterQueue } from "./sim-event-bridge-dead-letter-queue.js";
|
|
2
4
|
import { SimEventBridgeDeliveryQueue } from "./sim-event-bridge-delivery-queue.js";
|
|
3
5
|
import { SimEventBridgeDeliveryTask } from "./sim-event-bridge-delivery-task.js";
|
|
4
6
|
import { SimEventBridgeDeliveryTopic } from "./sim-event-bridge-delivery-topic.js";
|
|
@@ -26,6 +28,20 @@ export class SimAwsEventBridgeDeliveryTargets {
|
|
|
26
28
|
const scope = this.simAws.accountRegionScope(arn.accountId, arn.regionName);
|
|
27
29
|
await this.deliverTo(arn.service, { request, scope });
|
|
28
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Send an event EventBridge gave up on to the dead-letter queue its target
|
|
33
|
+
* names, in the queue's own Account and Region.
|
|
34
|
+
*/
|
|
35
|
+
async deadLetter(request) {
|
|
36
|
+
const config = request.delivery.target.deadLetterConfig;
|
|
37
|
+
assertDefined(config, "A dead letter requires a dead-letter queue");
|
|
38
|
+
const { accountId, regionName, name } = config.queue;
|
|
39
|
+
const scope = this.simAws.accountRegionScope(accountId, regionName);
|
|
40
|
+
await new SimEventBridgeDeadLetterQueue({ scope }).deliver(request, {
|
|
41
|
+
name,
|
|
42
|
+
arn: config.arn,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
29
45
|
/**
|
|
30
46
|
* Hand the delivery to the one destination that knows this service.
|
|
31
47
|
*/
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SimEventBridgeDeadLetterRequest } from "./sim-event-bridge-delivery.js";
|
|
2
|
+
import type { SimEventBridgeStringAttribute } from "./sim-event-bridge-queue-message.js";
|
|
3
|
+
/**
|
|
4
|
+
* The message attributes EventBridge documents for a dead letter.
|
|
5
|
+
*
|
|
6
|
+
* `EXHAUSTED_RETRY_CONDITION` is there only for a failure that was retried
|
|
7
|
+
* until a limit ran out.
|
|
8
|
+
*/
|
|
9
|
+
export declare function simEventBridgeDeadLetterAttributes(request: SimEventBridgeDeadLetterRequest): Readonly<Record<string, SimEventBridgeStringAttribute>>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { SimEventBridgeDeliveryNotPermitted, SimEventBridgeTargetNotFound, } from "../error/sim-event-bridge-delivery.error.js";
|
|
2
|
+
/**
|
|
3
|
+
* The `ERROR_CODE` a dead letter carries for a failure.
|
|
4
|
+
*
|
|
5
|
+
* EventBridge documents a list of codes without saying which failure gets
|
|
6
|
+
* which. A target that refuses EventBridge is `NO_PERMISSIONS`, a target that
|
|
7
|
+
* is not there is `NO_RESOURCE`, and anything else the target answered with
|
|
8
|
+
* is `ERROR_FROM_TARGET`.
|
|
9
|
+
*/
|
|
10
|
+
function errorCode(error) {
|
|
11
|
+
if (error instanceof SimEventBridgeDeliveryNotPermitted) {
|
|
12
|
+
return "NO_PERMISSIONS";
|
|
13
|
+
}
|
|
14
|
+
if (error instanceof SimEventBridgeTargetNotFound) {
|
|
15
|
+
return "NO_RESOURCE";
|
|
16
|
+
}
|
|
17
|
+
return "ERROR_FROM_TARGET";
|
|
18
|
+
}
|
|
19
|
+
function errorMessage(error) {
|
|
20
|
+
if (error instanceof Error) {
|
|
21
|
+
return error.message;
|
|
22
|
+
}
|
|
23
|
+
return String(error);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The message attributes EventBridge documents for a dead letter.
|
|
27
|
+
*
|
|
28
|
+
* `EXHAUSTED_RETRY_CONDITION` is there only for a failure that was retried
|
|
29
|
+
* until a limit ran out.
|
|
30
|
+
*/
|
|
31
|
+
export function simEventBridgeDeadLetterAttributes(request) {
|
|
32
|
+
const { delivery, error, retryAttempts, exhaustedCondition } = request;
|
|
33
|
+
const attributes = {
|
|
34
|
+
RULE_ARN: delivery.ruleArn,
|
|
35
|
+
TARGET_ARN: delivery.target.arn.value,
|
|
36
|
+
ERROR_CODE: errorCode(error),
|
|
37
|
+
ERROR_MESSAGE: errorMessage(error),
|
|
38
|
+
RETRY_ATTEMPTS: String(retryAttempts),
|
|
39
|
+
...(exhaustedCondition !== undefined && {
|
|
40
|
+
EXHAUSTED_RETRY_CONDITION: exhaustedCondition,
|
|
41
|
+
}),
|
|
42
|
+
};
|
|
43
|
+
return Object.fromEntries(Object.entries(attributes).map(([name, value]) => [
|
|
44
|
+
name,
|
|
45
|
+
{ DataType: "String", StringValue: value },
|
|
46
|
+
]));
|
|
47
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { SimAwsAccountRegionContainer } from "../../aws/sim-aws-account-region-scope.js";
|
|
2
|
+
import { type SimEventBridgeDeadLetterRequest } from "./sim-event-bridge-delivery.js";
|
|
3
|
+
interface SimEventBridgeDeadLetterQueueProperties {
|
|
4
|
+
readonly scope: SimAwsAccountRegionContainer;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* A target's dead-letter queue, in the Account and Region its ARN names.
|
|
8
|
+
*
|
|
9
|
+
* The message body is the event, as JSON, whatever `Input` the target had.
|
|
10
|
+
* The message attributes say which rule and target gave up on it, and why.
|
|
11
|
+
*/
|
|
12
|
+
export declare class SimEventBridgeDeadLetterQueue {
|
|
13
|
+
private readonly scope;
|
|
14
|
+
constructor(properties: SimEventBridgeDeadLetterQueueProperties);
|
|
15
|
+
/**
|
|
16
|
+
* Put an event EventBridge gave up on onto the queue, if it admits
|
|
17
|
+
* EventBridge for this rule.
|
|
18
|
+
*/
|
|
19
|
+
deliver(request: SimEventBridgeDeadLetterRequest, queue: {
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly arn: string;
|
|
22
|
+
}): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { simEventBridgeDeadLetterAttributes } from "./sim-event-bridge-dead-letter-attributes.js";
|
|
2
|
+
import { simEventBridgeDeliverySource, } from "./sim-event-bridge-delivery.js";
|
|
3
|
+
import { sendEventBridgeQueueMessage } from "./sim-event-bridge-queue-message.js";
|
|
4
|
+
/**
|
|
5
|
+
* A target's dead-letter queue, in the Account and Region its ARN names.
|
|
6
|
+
*
|
|
7
|
+
* The message body is the event, as JSON, whatever `Input` the target had.
|
|
8
|
+
* The message attributes say which rule and target gave up on it, and why.
|
|
9
|
+
*/
|
|
10
|
+
export class SimEventBridgeDeadLetterQueue {
|
|
11
|
+
scope;
|
|
12
|
+
constructor(properties) {
|
|
13
|
+
this.scope = properties.scope;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Put an event EventBridge gave up on onto the queue, if it admits
|
|
17
|
+
* EventBridge for this rule.
|
|
18
|
+
*/
|
|
19
|
+
async deliver(request, queue) {
|
|
20
|
+
await sendEventBridgeQueueMessage(this.scope, {
|
|
21
|
+
queueName: queue.name,
|
|
22
|
+
queueArn: queue.arn,
|
|
23
|
+
body: JSON.stringify(request.delivery.event.toEnvelope()),
|
|
24
|
+
attributes: simEventBridgeDeadLetterAttributes(request),
|
|
25
|
+
source: simEventBridgeDeliverySource(request.delivery),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { BackgroundScheduler } from "../../../util/background/background.js";
|
|
2
|
+
import type { SimEventBridgeDeliveryRequest, SimEventBridgeDeliveryTargets } from "./sim-event-bridge-delivery.js";
|
|
3
|
+
interface SimEventBridgeDeliveryAttemptProperties {
|
|
4
|
+
readonly request: SimEventBridgeDeliveryRequest;
|
|
5
|
+
readonly endpoints: SimEventBridgeDeliveryTargets;
|
|
6
|
+
readonly background: BackgroundScheduler;
|
|
7
|
+
readonly record: (error: unknown) => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* One event's delivery to one target, across its first attempt and any
|
|
11
|
+
* retries.
|
|
12
|
+
*
|
|
13
|
+
* A target with a `RetryPolicy` has a failed attempt retried on the
|
|
14
|
+
* simulation's clock, one second later, then two, four and so on. Retries stop
|
|
15
|
+
* at the policy's retry limit, or at its event age counted from the first
|
|
16
|
+
* attempt. A missing target or a refusal is never retried, because the same
|
|
17
|
+
* request gets the same answer, and EventBridge sends those straight to the
|
|
18
|
+
* dead-letter queue.
|
|
19
|
+
*
|
|
20
|
+
* An event given up on goes to the target's dead-letter queue where it names
|
|
21
|
+
* one. A failure is recorded where it names none, or where the dead-letter
|
|
22
|
+
* queue refuses it in turn.
|
|
23
|
+
*/
|
|
24
|
+
export declare class SimEventBridgeDeliveryAttempt {
|
|
25
|
+
private readonly properties;
|
|
26
|
+
private readonly firstAttemptAt;
|
|
27
|
+
private retryAttempts;
|
|
28
|
+
constructor(properties: SimEventBridgeDeliveryAttemptProperties);
|
|
29
|
+
/**
|
|
30
|
+
* Make the first attempt.
|
|
31
|
+
*/
|
|
32
|
+
start(): Promise<void>;
|
|
33
|
+
private attempt;
|
|
34
|
+
private failed;
|
|
35
|
+
/**
|
|
36
|
+
* The first retry waits one second, and every following wait doubles.
|
|
37
|
+
*/
|
|
38
|
+
private retryDueTime;
|
|
39
|
+
private abandon;
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { SimEventBridgeDeliveryNotPermitted, SimEventBridgeTargetNotFound, } from "../error/sim-event-bridge-delivery.error.js";
|
|
2
|
+
const millisecondsPerSecond = 1000;
|
|
3
|
+
/**
|
|
4
|
+
* One event's delivery to one target, across its first attempt and any
|
|
5
|
+
* retries.
|
|
6
|
+
*
|
|
7
|
+
* A target with a `RetryPolicy` has a failed attempt retried on the
|
|
8
|
+
* simulation's clock, one second later, then two, four and so on. Retries stop
|
|
9
|
+
* at the policy's retry limit, or at its event age counted from the first
|
|
10
|
+
* attempt. A missing target or a refusal is never retried, because the same
|
|
11
|
+
* request gets the same answer, and EventBridge sends those straight to the
|
|
12
|
+
* dead-letter queue.
|
|
13
|
+
*
|
|
14
|
+
* An event given up on goes to the target's dead-letter queue where it names
|
|
15
|
+
* one. A failure is recorded where it names none, or where the dead-letter
|
|
16
|
+
* queue refuses it in turn.
|
|
17
|
+
*/
|
|
18
|
+
export class SimEventBridgeDeliveryAttempt {
|
|
19
|
+
properties;
|
|
20
|
+
firstAttemptAt;
|
|
21
|
+
retryAttempts = 0;
|
|
22
|
+
constructor(properties) {
|
|
23
|
+
this.properties = properties;
|
|
24
|
+
this.firstAttemptAt = properties.background.now();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Make the first attempt.
|
|
28
|
+
*/
|
|
29
|
+
async start() {
|
|
30
|
+
await this.attempt();
|
|
31
|
+
}
|
|
32
|
+
async attempt() {
|
|
33
|
+
try {
|
|
34
|
+
await this.properties.endpoints.deliver(this.properties.request);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
await this.failed(error);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async failed(error) {
|
|
41
|
+
const policy = this.properties.request.target.retryPolicy;
|
|
42
|
+
if (policy === undefined || isPermanent(error)) {
|
|
43
|
+
await this.abandon(error, undefined);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (this.retryAttempts >= policy.maximumRetryAttempts) {
|
|
47
|
+
await this.abandon(error, "MaximumRetryAttempts");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const retryDue = this.retryDueTime();
|
|
51
|
+
const expiresAt = new Date(this.firstAttemptAt.getTime() +
|
|
52
|
+
policy.maximumEventAgeInSeconds * millisecondsPerSecond);
|
|
53
|
+
if (retryDue > expiresAt) {
|
|
54
|
+
this.properties.background.scheduleAt(expiresAt, async () => {
|
|
55
|
+
await this.abandon(error, "MaximumEventAgeInSeconds");
|
|
56
|
+
});
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this.properties.background.scheduleAt(retryDue, async () => {
|
|
60
|
+
this.retryAttempts += 1;
|
|
61
|
+
await this.attempt();
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The first retry waits one second, and every following wait doubles.
|
|
66
|
+
*/
|
|
67
|
+
retryDueTime() {
|
|
68
|
+
const delaySeconds = 2 ** this.retryAttempts;
|
|
69
|
+
return new Date(this.properties.background.now().getTime() +
|
|
70
|
+
delaySeconds * millisecondsPerSecond);
|
|
71
|
+
}
|
|
72
|
+
async abandon(error, exhaustedCondition) {
|
|
73
|
+
const { request, endpoints, record } = this.properties;
|
|
74
|
+
if (request.target.deadLetterConfig === undefined) {
|
|
75
|
+
record(error);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
await endpoints.deadLetter({
|
|
80
|
+
delivery: request,
|
|
81
|
+
error,
|
|
82
|
+
retryAttempts: this.retryAttempts,
|
|
83
|
+
exhaustedCondition,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch (deadLetterError) {
|
|
87
|
+
record(deadLetterError);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Whether a failure would come back the same however often it was retried.
|
|
93
|
+
*/
|
|
94
|
+
function isPermanent(error) {
|
|
95
|
+
return (error instanceof SimEventBridgeDeliveryNotPermitted ||
|
|
96
|
+
error instanceof SimEventBridgeTargetNotFound);
|
|
97
|
+
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { simEventBridgeDeliveryJson, simEventBridgeDeliverySource, simEventBridgeServicePrincipal, } from "./sim-event-bridge-delivery.js";
|
|
4
|
-
import { simScopeIamAuthZ } from "../../iam/authorize/sim-iam-region-auth-z.js";
|
|
1
|
+
import { simEventBridgeDeliveryJson, simEventBridgeDeliverySource, } from "./sim-event-bridge-delivery.js";
|
|
2
|
+
import { sendEventBridgeQueueMessage } from "./sim-event-bridge-queue-message.js";
|
|
5
3
|
/**
|
|
6
4
|
* A queue a simulated rule is sending an event to, in the Account and Region
|
|
7
5
|
* the target ARN names.
|
|
@@ -19,39 +17,11 @@ export class SimEventBridgeDeliveryQueue {
|
|
|
19
17
|
* Put the event on the queue, if it admits EventBridge for this rule.
|
|
20
18
|
*/
|
|
21
19
|
async deliver(request) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
const decision = new SimSqsServiceSendAuthorizer({
|
|
29
|
-
iam: simScopeIamAuthZ(this.scope),
|
|
30
|
-
}).authorize({
|
|
31
|
-
queue,
|
|
32
|
-
servicePrincipal: simEventBridgeServicePrincipal,
|
|
33
|
-
...source,
|
|
34
|
-
});
|
|
35
|
-
if (decision.isDenied) {
|
|
36
|
-
throw new SimEventBridgeDeliveryNotPermitted(`The queue policy of ${targetArn.value} does not allow ` +
|
|
37
|
-
`${simEventBridgeServicePrincipal} to send to it for ` +
|
|
38
|
-
`${source.sourceArn}. Grant sqs:SendMessage with the queue's ` +
|
|
39
|
-
`Policy attribute.`);
|
|
40
|
-
}
|
|
41
|
-
// Sent through the ordinary SendMessage path, so a delivered event is the
|
|
42
|
-
// same thing an SDK caller would have sent, and is authorized again on the
|
|
43
|
-
// way in.
|
|
44
|
-
await this.scope.sqs().sendMessage({
|
|
45
|
-
input: {
|
|
46
|
-
QueueUrl: queue.arn.url,
|
|
47
|
-
MessageBody: simEventBridgeDeliveryJson(request),
|
|
48
|
-
},
|
|
49
|
-
}, {
|
|
50
|
-
caller: {
|
|
51
|
-
kind: "service",
|
|
52
|
-
service: simEventBridgeServicePrincipal,
|
|
53
|
-
},
|
|
54
|
-
...source,
|
|
20
|
+
await sendEventBridgeQueueMessage(this.scope, {
|
|
21
|
+
queueName: request.target.arn.resource,
|
|
22
|
+
queueArn: request.target.arn.value,
|
|
23
|
+
body: simEventBridgeDeliveryJson(request),
|
|
24
|
+
source: simEventBridgeDeliverySource(request),
|
|
55
25
|
});
|
|
56
26
|
}
|
|
57
27
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SimClockControl } from "../../../util/clock/sim-clock-control.js";
|
|
2
|
+
import { SimEventBridge } from "../sim-event-bridge.js";
|
|
3
|
+
import type { SimEventTargetRetryPolicyInput } from "../target/sim-event-target-retry-policy.js";
|
|
4
|
+
import type { SimEventBridgeDeadLetterRequest } from "./sim-event-bridge-delivery.js";
|
|
5
|
+
import { type SimEventBridgeFailingTargetsOptions } from "./sim-event-bridge-failing-targets.test-support.js";
|
|
6
|
+
export interface RetrySimulation {
|
|
7
|
+
readonly eventBridge: SimEventBridge;
|
|
8
|
+
readonly clock: SimClockControl;
|
|
9
|
+
readonly attempts: Date[];
|
|
10
|
+
readonly deadLetters: SimEventBridgeDeadLetterRequest[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A simulated EventBridge whose targets fail as the options say.
|
|
14
|
+
*/
|
|
15
|
+
export declare function retrySimulation(options: SimEventBridgeFailingTargetsOptions): RetrySimulation;
|
|
16
|
+
/**
|
|
17
|
+
* Add a rule with one target carrying the given retry policy and a
|
|
18
|
+
* dead-letter queue, and put one matching event.
|
|
19
|
+
*/
|
|
20
|
+
export declare function putOrder(simulation: RetrySimulation, target: {
|
|
21
|
+
readonly RetryPolicy?: SimEventTargetRetryPolicyInput;
|
|
22
|
+
readonly DeadLetterConfig?: {
|
|
23
|
+
readonly Arn: string;
|
|
24
|
+
};
|
|
25
|
+
}): Promise<void>;
|