@kensio/yulin 1.21.8 → 1.21.10

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.
Files changed (64) hide show
  1. package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-properties.d.ts +1 -1
  2. package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-properties.js +6 -3
  3. package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-property-names.d.ts +30 -0
  4. package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-property-names.js +91 -0
  5. package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-property-rules.d.ts +7 -12
  6. package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-property-rules.js +12 -92
  7. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-input.d.ts +2 -0
  8. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-input.js +5 -0
  9. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-refusals.js +0 -10
  10. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping.handler.d.ts +2 -0
  11. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping.handler.js +2 -0
  12. package/dist/service/lambda/command/event-source-mapping/sim-lambda-event-source-mapping-commands.d.ts +2 -0
  13. package/dist/service/lambda/destination/sim-lambda-destination-targets.d.ts +2 -1
  14. package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-shard-poller.d.ts +0 -4
  15. package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-shard-poller.js +11 -16
  16. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event-source-poller.d.ts +1 -6
  17. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event-source-poller.js +9 -27
  18. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-polling.d.ts +19 -0
  19. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-polling.js +27 -0
  20. package/dist/service/lambda/event-source/poll/sim-lambda-event-source-function.d.ts +1 -1
  21. package/dist/service/lambda/event-source/poll/sim-lambda-event-source-function.js +3 -1
  22. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-age.d.ts +13 -0
  23. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-age.js +27 -0
  24. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-info.d.ts +15 -0
  25. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-info.js +26 -0
  26. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-outcome.d.ts +1 -0
  27. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-outcome.js +7 -1
  28. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-processing.d.ts +17 -0
  29. package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-processing.js +12 -0
  30. package/dist/service/lambda/event-source/poll/sim-lambda-stream-bisect.d.ts +53 -0
  31. package/dist/service/lambda/event-source/poll/sim-lambda-stream-bisect.js +79 -0
  32. package/dist/service/lambda/event-source/poll/sim-lambda-stream-cursor.d.ts +15 -0
  33. package/dist/service/lambda/event-source/poll/sim-lambda-stream-cursor.js +28 -0
  34. package/dist/service/lambda/event-source/poll/sim-lambda-stream-expiry.d.ts +19 -0
  35. package/dist/service/lambda/event-source/poll/sim-lambda-stream-expiry.js +23 -0
  36. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-context.d.ts +3 -0
  37. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-context.js +19 -0
  38. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-destination.d.ts +15 -0
  39. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-destination.js +38 -0
  40. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-record.d.ts +41 -0
  41. package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-record.js +17 -0
  42. package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress-state.d.ts +23 -0
  43. package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress-state.js +42 -0
  44. package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress.d.ts +21 -38
  45. package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress.js +45 -63
  46. package/dist/service/lambda/event-source/poll/sim-lambda-stream-retry.d.ts +4 -39
  47. package/dist/service/lambda/event-source/poll/sim-lambda-stream-retry.js +12 -64
  48. package/dist/service/lambda/event-source/sim-lambda-event-source-mapping.d.ts +10 -3
  49. package/dist/service/lambda/event-source/sim-lambda-event-source-mapping.js +12 -3
  50. package/dist/service/lambda/event-source/sim-lambda-event-source-retry-limits.d.ts +8 -7
  51. package/dist/service/lambda/event-source/sim-lambda-event-source-retry-limits.js +6 -3
  52. package/dist/service/lambda/event-source/sim-lambda-stream-destination-config.d.ts +7 -0
  53. package/dist/service/lambda/event-source/sim-lambda-stream-destination-config.js +38 -0
  54. package/dist/service/lambda/event-source/sim-lambda-stream-retry-limits.d.ts +15 -7
  55. package/dist/service/lambda/event-source/sim-lambda-stream-retry-limits.js +15 -7
  56. package/dist/service/lambda/event-source/stream/kinesis/sim-kinesis-event-source-streams.js +1 -0
  57. package/dist/service/lambda/event-source/stream/sim-dynamodb-event-source-stream-reader.js +1 -0
  58. package/dist/service/lambda/event-source/stream/sim-dynamodb-event-source-stream-shard.d.ts +1 -0
  59. package/dist/service/lambda/event-source/stream/sim-dynamodb-event-source-stream-shard.js +7 -0
  60. package/dist/service/lambda/event-source/stream/sim-lambda-event-source-streams.d.ts +1 -0
  61. package/dist/service/lambda/index.d.ts +1 -0
  62. package/dist/service/lambda/sim-lambda-commands.js +1 -0
  63. package/docs/services/lambda/README.md +111 -11
  64. package/package.json +1 -1
@@ -1,27 +1,11 @@
1
- import type { BackgroundScheduler, BackgroundTask } from "../../../../util/background/background.js";
2
- import type { SimLambdaEventSourceMapping } from "../sim-lambda-event-source-mapping.js";
1
+ import { type SimLambdaStreamProgressProperties } from "./sim-lambda-stream-progress-state.js";
2
+ import type { SimLambdaStreamRecordTime } from "./sim-lambda-stream-record-times.js";
3
+ import type { SimLambdaFunction } from "../../function/sim-lambda-function.js";
3
4
  import type { SimLambdaEventSourceStreamPosition, SimLambdaEventSourceStreamProgressBatch } from "../stream/sim-lambda-event-source-streams.js";
4
5
  import type { SimLambdaStreamBatchOutcome } from "./sim-lambda-stream-batch-outcome.js";
5
- interface SimLambdaStreamProgressProperties {
6
- readonly mapping: SimLambdaEventSourceMapping;
7
- readonly background: BackgroundScheduler;
8
- readonly poll: BackgroundTask;
9
- }
10
- /**
11
- * How far along its stream one mapping has got, and what it does next.
12
- *
13
- * The two belong together because they are the same decision. A batch the
14
- * function took moves the checkpoint and the mapping reads on; a batch it threw
15
- * on leaves the checkpoint where it is and the mapping tries the same records
16
- * again after a wait; a batch it reported failing partway through moves the
17
- * checkpoint back to the record it named. Nothing behind a failing batch is
18
- * read until it is through, which is what it means for a stream mapping to
19
- * block its shard.
20
- */
6
+ /** Apply a stream batch outcome to its checkpoint and retry schedule. */
21
7
  export declare class SimLambdaStreamProgress {
22
- private readonly checkpoint;
23
- private readonly retry;
24
- private readonly schedule;
8
+ private readonly state;
25
9
  constructor(properties: SimLambdaStreamProgressProperties);
26
10
  /**
27
11
  * Poll as soon as the simulation gets to it.
@@ -31,6 +15,11 @@ export declare class SimLambdaStreamProgress {
31
15
  * Where the next read starts.
32
16
  */
33
17
  get position(): SimLambdaEventSourceStreamPosition;
18
+ /**
19
+ * How many records the next read may take, which is the mapping's batch size
20
+ * until a batch is being bisected.
21
+ */
22
+ batchSizeWithin(batchSize: number): number;
34
23
  /**
35
24
  * Take a read that came back with nothing.
36
25
  *
@@ -40,9 +29,18 @@ export declare class SimLambdaStreamProgress {
40
29
  */
41
30
  caughtUp(batch: SimLambdaEventSourceStreamProgressBatch): void;
42
31
  /**
43
- * Take what became of a batch: move past it, or wait and try it again.
32
+ * Drop the records at the front of a batch that are too old to hand over,
33
+ * answering with where the live ones start.
34
+ *
35
+ * Records that aged out are as finished with as records the function took, so
36
+ * a batch being split counts them off its remainder too.
37
+ */
38
+ before(records: readonly SimLambdaStreamRecordTime[], batch: SimLambdaEventSourceStreamProgressBatch, simFunction: SimLambdaFunction): Promise<number>;
39
+ /**
40
+ * Take what became of a batch: move past it, split it, or wait and try it
41
+ * again.
44
42
  */
45
- after(outcome: SimLambdaStreamBatchOutcome, batch: SimLambdaEventSourceStreamProgressBatch): void;
43
+ after(outcome: SimLambdaStreamBatchOutcome, batch: SimLambdaEventSourceStreamProgressBatch, simFunction: SimLambdaFunction): Promise<void>;
46
44
  /**
47
45
  * Move past a batch that is finished with, and read on.
48
46
  *
@@ -50,19 +48,4 @@ export declare class SimLambdaStreamProgress {
50
48
  * given up on.
51
49
  */
52
50
  handled(batch: SimLambdaEventSourceStreamProgressBatch): void;
53
- /**
54
- * Wait and hand a failed batch over again, or give up on it.
55
- *
56
- * Giving up discards the records and carries on with the stream, which is
57
- * what AWS does when a stream mapping's error handling runs out. Parking the
58
- * shard instead would be a simulator invention.
59
- *
60
- * A batch runs out either by having had its retries or by every record left
61
- * in it being older than the mapping will carry. Records that aged out of the
62
- * front of a batch are left behind, and the ones behind them go over again,
63
- * so a mapping given a record age keeps working through its shard rather than
64
- * stalling on the oldest record on it.
65
- */
66
- failed(outcome: SimLambdaStreamBatchOutcome, batch: SimLambdaEventSourceStreamProgressBatch): void;
67
51
  }
68
- export {};
@@ -1,47 +1,28 @@
1
- import { assertDefined } from "../../../../util/type-guard/defined.js";
2
- import { PollSchedule } from "../../../../util/background/poll-schedule.js";
3
- import { SimLambdaStreamCheckpoint } from "./sim-lambda-stream-checkpoint.js";
4
- import { SimLambdaStreamRetry } from "./sim-lambda-stream-retry.js";
5
- /**
6
- * How far along its stream one mapping has got, and what it does next.
7
- *
8
- * The two belong together because they are the same decision. A batch the
9
- * function took moves the checkpoint and the mapping reads on; a batch it threw
10
- * on leaves the checkpoint where it is and the mapping tries the same records
11
- * again after a wait; a batch it reported failing partway through moves the
12
- * checkpoint back to the record it named. Nothing behind a failing batch is
13
- * read until it is through, which is what it means for a stream mapping to
14
- * block its shard.
15
- */
1
+ import { SimLambdaStreamProgressState, } from "./sim-lambda-stream-progress-state.js";
2
+ /** Apply a stream batch outcome to its checkpoint and retry schedule. */
16
3
  export class SimLambdaStreamProgress {
17
- checkpoint;
18
- retry;
19
- schedule;
4
+ state;
20
5
  constructor(properties) {
21
- // A stream mapping is refused at creation unless it names a starting
22
- // position, so one that has got this far without one is the simulator
23
- // having gone wrong rather than a request having been wrong.
24
- const { start, streamRetryLimits } = properties.mapping;
25
- assertDefined(start, "stream mapping start position");
26
- assertDefined(streamRetryLimits, "stream mapping retry limits");
27
- this.checkpoint = new SimLambdaStreamCheckpoint(start);
28
- this.retry = new SimLambdaStreamRetry({
29
- limits: streamRetryLimits,
30
- clock: properties.background,
31
- });
32
- this.schedule = new PollSchedule(properties);
6
+ this.state = new SimLambdaStreamProgressState(properties);
33
7
  }
34
8
  /**
35
9
  * Poll as soon as the simulation gets to it.
36
10
  */
37
11
  pollNow() {
38
- this.schedule.now();
12
+ this.state.cursor.pollNow();
39
13
  }
40
14
  /**
41
15
  * Where the next read starts.
42
16
  */
43
17
  get position() {
44
- return this.checkpoint.position;
18
+ return this.state.cursor.position;
19
+ }
20
+ /**
21
+ * How many records the next read may take, which is the mapping's batch size
22
+ * until a batch is being bisected.
23
+ */
24
+ batchSizeWithin(batchSize) {
25
+ return this.state.bisect.sizeWithin(batchSize);
45
26
  }
46
27
  /**
47
28
  * Take a read that came back with nothing.
@@ -51,17 +32,44 @@ export class SimLambdaStreamProgress {
51
32
  * than working out a new one each time.
52
33
  */
53
34
  caughtUp(batch) {
54
- this.checkpoint.advanceTo(batch.next);
35
+ this.state.cursor.advanceTo(batch.next);
55
36
  }
56
37
  /**
57
- * Take what became of a batch: move past it, or wait and try it again.
38
+ * Drop the records at the front of a batch that are too old to hand over,
39
+ * answering with where the live ones start.
40
+ *
41
+ * Records that aged out are as finished with as records the function took, so
42
+ * a batch being split counts them off its remainder too.
58
43
  */
59
- after(outcome, batch) {
44
+ async before(records, batch, simFunction) {
45
+ const firstLive = await this.state.expiry.before(records, batch, simFunction);
46
+ this.state.bisect.finished(firstLive);
47
+ return firstLive;
48
+ }
49
+ /**
50
+ * Take what became of a batch: move past it, split it, or wait and try it
51
+ * again.
52
+ */
53
+ async after(outcome, batch, simFunction) {
54
+ this.state.failures.invoked(outcome);
60
55
  if (outcome.isHandled) {
56
+ this.state.bisect.finished(outcome.records.length);
61
57
  this.handled(batch);
62
58
  return;
63
59
  }
64
- this.failed(outcome, batch);
60
+ if (this.state.bisect.split(outcome)) {
61
+ this.state.retry.reset();
62
+ }
63
+ const again = this.state.retry.after(outcome, this.position);
64
+ const notification = this.state.failures.deliver(this.state.retry.discarded, batch, simFunction);
65
+ if (again === undefined) {
66
+ this.state.bisect.finished(outcome.records.length);
67
+ this.handled(batch);
68
+ }
69
+ else {
70
+ this.state.cursor.resume(again);
71
+ }
72
+ await notification;
65
73
  }
66
74
  /**
67
75
  * Move past a batch that is finished with, and read on.
@@ -70,32 +78,6 @@ export class SimLambdaStreamProgress {
70
78
  * given up on.
71
79
  */
72
80
  handled(batch) {
73
- this.retry.reset();
74
- this.checkpoint.advanceTo(batch.next);
75
- if (!batch.drained) {
76
- this.schedule.now();
77
- }
78
- }
79
- /**
80
- * Wait and hand a failed batch over again, or give up on it.
81
- *
82
- * Giving up discards the records and carries on with the stream, which is
83
- * what AWS does when a stream mapping's error handling runs out. Parking the
84
- * shard instead would be a simulator invention.
85
- *
86
- * A batch runs out either by having had its retries or by every record left
87
- * in it being older than the mapping will carry. Records that aged out of the
88
- * front of a batch are left behind, and the ones behind them go over again,
89
- * so a mapping given a record age keeps working through its shard rather than
90
- * stalling on the oldest record on it.
91
- */
92
- failed(outcome, batch) {
93
- const again = this.retry.after(outcome, this.checkpoint.position);
94
- if (again === undefined) {
95
- this.handled(batch);
96
- return;
97
- }
98
- this.checkpoint.advanceTo(again.position);
99
- this.schedule.afterSeconds(again.afterSeconds);
81
+ this.state.handled(batch);
100
82
  }
101
83
  }
@@ -1,11 +1,8 @@
1
+ import type { SimLambdaStreamDiscard } from "./sim-lambda-stream-failure-record.js";
1
2
  import type { SimClock } from "../../../../util/clock/sim-clock.js";
2
3
  import type { SimLambdaStreamRetryLimits } from "../sim-lambda-stream-retry-limits.js";
3
4
  import type { SimLambdaEventSourceStreamPosition } from "../stream/sim-lambda-event-source-streams.js";
4
5
  import type { SimLambdaStreamBatchOutcome } from "./sim-lambda-stream-batch-outcome.js";
5
- interface SimLambdaStreamRetryProperties {
6
- readonly limits: SimLambdaStreamRetryLimits;
7
- readonly clock: SimClock;
8
- }
9
6
  /**
10
7
  * One more delivery of a failed batch: where it starts, and how long the
11
8
  * mapping waits first.
@@ -14,26 +11,12 @@ export interface SimLambdaStreamRetryAttempt {
14
11
  readonly position: SimLambdaEventSourceStreamPosition;
15
12
  readonly afterSeconds: number;
16
13
  }
17
- /**
18
- * Whether a failed batch is handed over again, and from which record.
19
- *
20
- * Both of Lambda's failed-batch limits end here because they end the same
21
- * thing. A batch stops being delivered when it has had its retries, and a
22
- * record stops being delivered when it is older than the mapping will carry;
23
- * whichever comes first, what is left of the batch is discarded and the mapping
24
- * reads on. Records age out of the front of a batch, because a batch is in
25
- * stream order, so the answer is one record to start from rather than a list of
26
- * survivors.
27
- *
28
- * Ages are read at the instant the next delivery falls due rather than now,
29
- * because the wait before it is what ages the records out. A record judged now
30
- * would be handed to the function and only then found to be too old.
31
- */
14
+ /** Tracks the retry quota and checkpoint of one failed stream batch. */
32
15
  export declare class SimLambdaStreamRetry {
33
- private readonly limits;
16
+ discarded: SimLambdaStreamDiscard | undefined;
34
17
  private readonly clock;
35
18
  private readonly backoff;
36
- constructor(properties: SimLambdaStreamRetryProperties);
19
+ constructor(limits: SimLambdaStreamRetryLimits, clock: SimClock);
37
20
  /**
38
21
  * The next delivery of a failed batch, or nothing when the batch is finished
39
22
  * with.
@@ -43,22 +26,4 @@ export declare class SimLambdaStreamRetry {
43
26
  * Start counting again, which a batch that is finished with does.
44
27
  */
45
28
  reset(): void;
46
- /**
47
- * Where the next delivery starts, or nothing when every record left in the
48
- * batch has aged out.
49
- */
50
- private retryPosition;
51
- /**
52
- * The first record from `from` on that is still young enough to deliver.
53
- */
54
- private firstLiveIndex;
55
- /**
56
- * When the next delivery falls due, which is what a record's age is judged
57
- * against.
58
- *
59
- * Judging it now would hand a record over and only then notice that it was
60
- * too old to be worth handing over, since the wait is what makes it too old.
61
- */
62
- private deliveryAt;
63
29
  }
64
- export {};
@@ -1,44 +1,29 @@
1
1
  import { SimLambdaStreamRetryBackoff } from "./sim-lambda-stream-retry-backoff.js";
2
- const millisecondsPerSecond = 1000;
3
- /**
4
- * Whether a failed batch is handed over again, and from which record.
5
- *
6
- * Both of Lambda's failed-batch limits end here because they end the same
7
- * thing. A batch stops being delivered when it has had its retries, and a
8
- * record stops being delivered when it is older than the mapping will carry;
9
- * whichever comes first, what is left of the batch is discarded and the mapping
10
- * reads on. Records age out of the front of a batch, because a batch is in
11
- * stream order, so the answer is one record to start from rather than a list of
12
- * survivors.
13
- *
14
- * Ages are read at the instant the next delivery falls due rather than now,
15
- * because the wait before it is what ages the records out. A record judged now
16
- * would be handed to the function and only then found to be too old.
17
- */
2
+ /** Tracks the retry quota and checkpoint of one failed stream batch. */
18
3
  export class SimLambdaStreamRetry {
19
- limits;
4
+ discarded;
20
5
  clock;
21
6
  backoff;
22
- constructor(properties) {
23
- this.limits = properties.limits;
24
- this.clock = properties.clock;
25
- this.backoff = new SimLambdaStreamRetryBackoff(properties.limits.attemptLimit);
7
+ constructor(limits, clock) {
8
+ this.clock = clock;
9
+ this.backoff = new SimLambdaStreamRetryBackoff(limits.attemptLimit);
26
10
  }
27
11
  /**
28
12
  * The next delivery of a failed batch, or nothing when the batch is finished
29
13
  * with.
30
14
  */
31
15
  after(outcome, readFrom) {
16
+ this.discarded = undefined;
32
17
  if (this.backoff.isExhausted) {
18
+ this.discarded = {
19
+ records: outcome.records.slice(outcome.retryIndex),
20
+ condition: "RetryAttemptsExhausted",
21
+ at: this.clock.now(),
22
+ };
33
23
  return undefined;
34
24
  }
35
25
  const afterSeconds = this.backoff.nextSeconds();
36
- const deliveryAt = this.deliveryAt(afterSeconds);
37
- const position = this.retryPosition(outcome, readFrom, deliveryAt);
38
- if (position === undefined) {
39
- return undefined;
40
- }
41
- return { position, afterSeconds };
26
+ return { position: outcome.retryPosition(readFrom), afterSeconds };
42
27
  }
43
28
  /**
44
29
  * Start counting again, which a batch that is finished with does.
@@ -46,41 +31,4 @@ export class SimLambdaStreamRetry {
46
31
  reset() {
47
32
  this.backoff.reset();
48
33
  }
49
- /**
50
- * Where the next delivery starts, or nothing when every record left in the
51
- * batch has aged out.
52
- */
53
- retryPosition(outcome, readFrom, deliveryAt) {
54
- const { records, retryIndex } = outcome;
55
- const live = this.firstLiveIndex(records, retryIndex, deliveryAt);
56
- if (live === undefined) {
57
- return undefined;
58
- }
59
- const sequenceNumber = records.at(live)?.sequenceNumber;
60
- // Nothing aged out of the front, so the batch goes back exactly where the
61
- // report left it. A record that aged out but cannot be named leaves the
62
- // batch where it was too, since skipping past a record the mapping cannot
63
- // name would skip the records after it as well.
64
- if (live === retryIndex || sequenceNumber === undefined) {
65
- return outcome.retryPosition(readFrom);
66
- }
67
- return { kind: "sequence", sequenceNumber };
68
- }
69
- /**
70
- * The first record from `from` on that is still young enough to deliver.
71
- */
72
- firstLiveIndex(records, from, deliveryAt) {
73
- const index = records.findIndex((record, position) => position >= from && !this.limits.hasAgedOut(record.at, deliveryAt));
74
- return index === -1 ? undefined : index;
75
- }
76
- /**
77
- * When the next delivery falls due, which is what a record's age is judged
78
- * against.
79
- *
80
- * Judging it now would hand a record over and only then notice that it was
81
- * too old to be worth handing over, since the wait is what makes it too old.
82
- */
83
- deliveryAt(afterSeconds) {
84
- return new Date(this.clock.now().getTime() + afterSeconds * millisecondsPerSecond);
85
- }
86
34
  }
@@ -1,3 +1,5 @@
1
+ import type { SimLambdaStreamDestinationConfiguration } from "./sim-lambda-stream-destination-config.js";
2
+ import type { SimLambdaDestinationTargets } from "../destination/sim-lambda-destination-targets.js";
1
3
  import type { SimAwsAccountRegionScope } from "../../aws/sim-aws-account-region-scope.js";
2
4
  import type { SimLambdaFunctionArn } from "../function/sim-lambda-function-configuration.js";
3
5
  import type { SimLambdaStreamRetryLimits, SimLambdaStreamRetryLimitsConfiguration } from "./sim-lambda-stream-retry-limits.js";
@@ -31,6 +33,8 @@ interface SimLambdaEventSourceMappingProperties {
31
33
  readonly enabled?: boolean | undefined;
32
34
  readonly functionResponseTypes?: readonly SimLambdaFunctionResponseType[] | undefined;
33
35
  readonly streamRetryLimits?: SimLambdaStreamRetryLimits | undefined;
36
+ readonly destinationConfig?: SimLambdaStreamDestinationConfiguration | undefined;
37
+ readonly destinations?: SimLambdaDestinationTargets | undefined;
34
38
  readonly createdAt: Date;
35
39
  }
36
40
  /**
@@ -39,6 +43,7 @@ interface SimLambdaEventSourceMappingProperties {
39
43
  * DeleteEventSourceMapping responses all report it.
40
44
  */
41
45
  export interface SimLambdaEventSourceMappingConfiguration extends Partial<SimLambdaStreamRetryLimitsConfiguration> {
46
+ readonly DestinationConfig?: SimLambdaStreamDestinationConfiguration | undefined;
42
47
  readonly UUID: string;
43
48
  readonly EventSourceMappingArn: SimLambdaEventSourceMappingArn;
44
49
  readonly EventSourceArn: string;
@@ -64,6 +69,7 @@ export interface SimLambdaEventSourceMappingConfiguration extends Partial<SimLam
64
69
  */
65
70
  export declare class SimLambdaEventSourceMapping {
66
71
  #private;
72
+ readonly destinations: SimLambdaDestinationTargets;
67
73
  readonly uuid: string;
68
74
  readonly eventSourceArn: string;
69
75
  readonly functionName: string;
@@ -91,13 +97,14 @@ export declare class SimLambdaEventSourceMapping {
91
97
  * the queue's own problem once the batch comes back.
92
98
  */
93
99
  readonly streamRetryLimits: SimLambdaStreamRetryLimits | undefined;
100
+ private readonly destinationConfig;
94
101
  private readonly accountRegionScope;
95
102
  private readonly enabled;
96
103
  private readonly lastModified;
97
104
  constructor(properties: SimLambdaEventSourceMappingProperties);
98
- /**
99
- * The ARN naming this mapping.
100
- */
105
+ /** The configured failure queue or topic ARN. */
106
+ get failureDestinationArn(): string | undefined;
107
+ /** The ARN naming this mapping. */
101
108
  get arn(): SimLambdaEventSourceMappingArn;
102
109
  /**
103
110
  * The state this mapping is in.
@@ -1,3 +1,4 @@
1
+ import { SimLambdaNoDestinationTargets } from "../destination/sim-lambda-destination-targets.js";
1
2
  import { randomUUID } from "node:crypto";
2
3
  /**
3
4
  * One simulated Lambda event source mapping, from an event source to a
@@ -10,6 +11,7 @@ import { randomUUID } from "node:crypto";
10
11
  * it.
11
12
  */
12
13
  export class SimLambdaEventSourceMapping {
14
+ destinations;
13
15
  uuid = randomUUID();
14
16
  eventSourceArn;
15
17
  functionName;
@@ -37,11 +39,15 @@ export class SimLambdaEventSourceMapping {
37
39
  * the queue's own problem once the batch comes back.
38
40
  */
39
41
  streamRetryLimits;
42
+ destinationConfig;
40
43
  accountRegionScope;
41
44
  enabled;
42
45
  lastModified;
43
46
  #state = "Creating";
44
47
  constructor(properties) {
48
+ this.destinationConfig = properties.destinationConfig;
49
+ this.destinations =
50
+ properties.destinations ?? new SimLambdaNoDestinationTargets();
45
51
  this.accountRegionScope = properties.accountRegionScope;
46
52
  this.eventSourceArn = properties.eventSourceArn;
47
53
  this.functionName = properties.functionName;
@@ -56,9 +62,11 @@ export class SimLambdaEventSourceMapping {
56
62
  this.enabled = properties.enabled ?? true;
57
63
  this.lastModified = properties.createdAt;
58
64
  }
59
- /**
60
- * The ARN naming this mapping.
61
- */
65
+ /** The configured failure queue or topic ARN. */
66
+ get failureDestinationArn() {
67
+ return this.destinationConfig?.OnFailure?.Destination;
68
+ }
69
+ /** The ARN naming this mapping. */
62
70
  get arn() {
63
71
  const { regionName, accountId } = this.accountRegionScope;
64
72
  return `arn:aws:lambda:${regionName}:${accountId}:event-source-mapping:${this.uuid}`;
@@ -96,6 +104,7 @@ export class SimLambdaEventSourceMapping {
96
104
  */
97
105
  configuration() {
98
106
  return {
107
+ DestinationConfig: structuredClone(this.destinationConfig),
99
108
  UUID: this.uuid,
100
109
  EventSourceMappingArn: this.arn,
101
110
  EventSourceArn: this.eventSourceArn,
@@ -1,12 +1,13 @@
1
1
  import { type SimLambdaEventSourceRetryLimitsInput, SimLambdaStreamRetryLimits } from "./sim-lambda-stream-retry-limits.js";
2
2
  /**
3
- * Whether the event source a mapping names has failed-batch limits at all.
3
+ * Whether the event source a mapping names decides for itself what becomes of
4
+ * a failed batch.
4
5
  *
5
- * A stream does: a record stays on the stream whatever the function makes of
6
- * it, so the mapping is the only thing that decides when to stop trying. A
7
- * queue does not, because a message the function never handles goes to the
8
- * queue's own redrive policy, and real Lambda refuses a request that names
9
- * either limit for one.
6
+ * A stream leaves it to the mapping: a record stays on the stream whatever the
7
+ * function makes of it, so the mapping is the only thing that decides when to
8
+ * stop trying and whether to split the batch first. A queue does not, because a
9
+ * message the function never handles goes to the queue's own redrive policy,
10
+ * and real Lambda refuses a request that names any of the three for one.
10
11
  */
11
12
  export interface SimLambdaEventSourceRetryLimitRules {
12
13
  /**
@@ -23,7 +24,7 @@ export declare class SimLambdaNoRetryLimits implements SimLambdaEventSourceRetry
23
24
  private readonly insteadDescription;
24
25
  constructor(sourceDescription: string, insteadDescription: string);
25
26
  /**
26
- * Refuse both limits, since this source is not the one counting.
27
+ * Refuse all three, since this source is not the one counting.
27
28
  */
28
29
  limitsIn(input: SimLambdaEventSourceRetryLimitsInput): SimLambdaStreamRetryLimits | undefined;
29
30
  }
@@ -11,7 +11,7 @@ export class SimLambdaNoRetryLimits {
11
11
  this.insteadDescription = insteadDescription;
12
12
  }
13
13
  /**
14
- * Refuse both limits, since this source is not the one counting.
14
+ * Refuse all three, since this source is not the one counting.
15
15
  */
16
16
  limitsIn(input) {
17
17
  const named = namedLimit(input);
@@ -40,7 +40,10 @@ function namedLimit(input) {
40
40
  if (input.maximumRetryAttempts !== undefined) {
41
41
  return "MaximumRetryAttempts";
42
42
  }
43
- return input.maximumRecordAgeInSeconds === undefined
43
+ if (input.maximumRecordAgeInSeconds !== undefined) {
44
+ return "MaximumRecordAgeInSeconds";
45
+ }
46
+ return input.bisectBatchOnFunctionError === undefined
44
47
  ? undefined
45
- : "MaximumRecordAgeInSeconds";
48
+ : "BisectBatchOnFunctionError";
46
49
  }
@@ -0,0 +1,7 @@
1
+ export interface SimLambdaStreamDestinationConfiguration {
2
+ readonly OnFailure?: {
3
+ readonly Destination?: string | undefined;
4
+ } | undefined;
5
+ }
6
+ /** Validate the same destination shape for SDK and CloudFormation requests. */
7
+ export declare function simLambdaStreamDestinationConfig(value: unknown, sourceKind?: string): SimLambdaStreamDestinationConfiguration | undefined;
@@ -0,0 +1,38 @@
1
+ import { isRecord } from "../../../util/type-guard/record.js";
2
+ import { SimLambdaDestinationArn } from "../destination/sim-lambda-destination-arn.js";
3
+ import { SimLambdaInvalidParameterValueException } from "../error/sim-lambda.error.js";
4
+ /** Validate the same destination shape for SDK and CloudFormation requests. */
5
+ export function simLambdaStreamDestinationConfig(value, sourceKind) {
6
+ if (value === undefined)
7
+ return undefined;
8
+ if (sourceKind === "sqs") {
9
+ throw new SimLambdaInvalidParameterValueException("DestinationConfig is not supported for SQS event source mappings.");
10
+ }
11
+ if (!isRecord(value) ||
12
+ Object.keys(value).some((key) => key !== "OnFailure")) {
13
+ throw invalid();
14
+ }
15
+ const failure = value["OnFailure"];
16
+ if (failure === undefined)
17
+ return {};
18
+ if (!isRecord(failure) ||
19
+ Object.keys(failure).some((key) => key !== "Destination")) {
20
+ throw invalid();
21
+ }
22
+ const destination = failure["Destination"];
23
+ if (destination === undefined)
24
+ return { OnFailure: {} };
25
+ if (typeof destination !== "string")
26
+ throw invalid();
27
+ if (destination !== "") {
28
+ const arn = SimLambdaDestinationArn.of(destination);
29
+ if ((arn.service !== "sqs" && arn.service !== "sns") ||
30
+ arn.resource.endsWith(".fifo")) {
31
+ throw invalid();
32
+ }
33
+ }
34
+ return { OnFailure: { Destination: destination } };
35
+ }
36
+ function invalid() {
37
+ return new SimLambdaInvalidParameterValueException("DestinationConfig supports only OnFailure with a standard SQS queue or SNS topic ARN.");
38
+ }
@@ -9,6 +9,7 @@
9
9
  export interface SimLambdaEventSourceRetryLimitsInput {
10
10
  readonly maximumRetryAttempts?: number | undefined;
11
11
  readonly maximumRecordAgeInSeconds?: number | undefined;
12
+ readonly bisectBatchOnFunctionError?: boolean | undefined;
12
13
  }
13
14
  /**
14
15
  * The failed-batch limits a mapping reports back, as Lambda names them.
@@ -16,22 +17,29 @@ export interface SimLambdaEventSourceRetryLimitsInput {
16
17
  export interface SimLambdaStreamRetryLimitsConfiguration {
17
18
  readonly MaximumRetryAttempts: number;
18
19
  readonly MaximumRecordAgeInSeconds: number;
20
+ readonly BisectBatchOnFunctionError: boolean;
19
21
  }
20
22
  /**
21
- * When a stream mapping stops delivering a batch its function keeps failing.
23
+ * What a stream mapping does with a batch its function keeps failing.
22
24
  *
23
- * The two limits are one thing rather than two, because they end the same
24
- * lifecycle: a record leaves the mapping when it has had its retries or when it
25
- * is too old to be worth another, whichever comes first. Both are held as
26
- * Lambda states them, with `-1` for no limit, so a Get or a List reports back
27
- * exactly what was asked for.
25
+ * The three settings are one thing rather than three, because they run the same
26
+ * lifecycle. A failing batch is split around the record that broke it where the
27
+ * mapping was asked to bisect, and a record leaves the mapping when it has had
28
+ * its retries or when it is too old to be worth another, whichever comes first.
29
+ * The limits are held as Lambda states them, with `-1` for no limit, so a Get
30
+ * or a List reports back exactly what was asked for.
28
31
  */
29
32
  export declare class SimLambdaStreamRetryLimits {
30
33
  readonly maximumRetryAttempts: number;
31
34
  readonly maximumRecordAgeInSeconds: number;
35
+ /**
36
+ * Whether a batch the function threw on is split in half and delivered again
37
+ * as two batches.
38
+ */
39
+ readonly bisectBatchOnFunctionError: boolean;
32
40
  constructor(input?: SimLambdaEventSourceRetryLimitsInput);
33
41
  /**
34
- * The two limits as a Get, a List or a create response reports them.
42
+ * The three settings as a Get, a List or a create response reports them.
35
43
  */
36
44
  configuration(): SimLambdaStreamRetryLimitsConfiguration;
37
45
  /**