@kensio/yulin 1.21.21 → 1.21.23

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 (85) hide show
  1. package/dist/service/athena/engine/sim-athena-ast-nodes.d.ts +11 -0
  2. package/dist/service/athena/engine/sim-athena-ast-nodes.js +22 -0
  3. package/dist/service/athena/engine/sim-athena-engine-result.d.ts +9 -1
  4. package/dist/service/athena/engine/sim-athena-engine-result.js +15 -4
  5. package/dist/service/athena/engine/sim-athena-engine-run.d.ts +2 -0
  6. package/dist/service/athena/engine/sim-athena-engine-run.js +6 -1
  7. package/dist/service/athena/engine/sim-athena-query-engine.js +1 -0
  8. package/dist/service/athena/engine/sim-athena-result-columns.d.ts +1 -1
  9. package/dist/service/athena/engine/sim-athena-result-columns.js +11 -4
  10. package/dist/service/athena/engine/sim-athena-round-scales.d.ts +19 -0
  11. package/dist/service/athena/engine/sim-athena-round-scales.js +80 -0
  12. package/dist/service/athena/engine/sim-athena-sql-translation.d.ts +9 -0
  13. package/dist/service/athena/engine/sim-athena-sql-translation.js +17 -2
  14. package/dist/service/athena/engine/sim-athena-string-shims.js +29 -1
  15. package/dist/service/athena/engine/sim-athena-unnest-item.js +6 -15
  16. package/dist/service/athena/engine/sim-athena-unnest-rewrite.d.ts +4 -4
  17. package/dist/service/athena/engine/sim-athena-unnest-rewrite.js +4 -4
  18. package/dist/service/athena/engine/sim-athena-unnest-source.d.ts +10 -9
  19. package/dist/service/athena/engine/sim-athena-unnest-source.js +25 -11
  20. package/dist/service/athena/sim-athena-flattened-events.fixture.d.ts +3 -0
  21. package/dist/service/athena/sim-athena-flattened-events.fixture.js +46 -0
  22. package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-properties.js +2 -0
  23. package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-property-names.js +1 -5
  24. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-input.d.ts +5 -0
  25. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-input.js +7 -0
  26. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-refusals.js +0 -1
  27. package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping.handler.js +1 -0
  28. package/dist/service/lambda/command/event-source-mapping/event-source-mapping.command.d.ts +2 -1
  29. package/dist/service/lambda/command/event-source-mapping/event-source-mapping.command.js +0 -6
  30. package/dist/service/lambda/event-source/filter/sim-lambda-filter-criteria.d.ts +48 -0
  31. package/dist/service/lambda/event-source/filter/sim-lambda-filter-criteria.js +129 -0
  32. package/dist/service/lambda/event-source/filter/sim-lambda-filtered-delivery.d.ts +27 -0
  33. package/dist/service/lambda/event-source/filter/sim-lambda-filtered-delivery.js +15 -0
  34. package/dist/service/lambda/event-source/filter/sim-lambda-filtered-records.d.ts +24 -0
  35. package/dist/service/lambda/event-source/filter/sim-lambda-filtered-records.js +35 -0
  36. package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-shard-poller.d.ts +7 -4
  37. package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-shard-poller.js +9 -6
  38. package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-stream-delivery.d.ts +16 -4
  39. package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-stream-delivery.js +36 -5
  40. package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-stream-event-source-poller.d.ts +4 -3
  41. package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-stream-event-source-poller.js +6 -7
  42. package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-stream-event.d.ts +14 -2
  43. package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-stream-event.js +21 -2
  44. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-delivery.d.ts +19 -6
  45. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-delivery.js +41 -7
  46. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event-source-poller.d.ts +7 -3
  47. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event-source-poller.js +10 -9
  48. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event.d.ts +6 -2
  49. package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event.js +6 -2
  50. package/dist/service/lambda/event-source/poll/sim-lambda-event-source-delivery.d.ts +21 -1
  51. package/dist/service/lambda/event-source/poll/sim-lambda-event-source-delivery.js +32 -2
  52. package/dist/service/lambda/event-source/poll/sim-lambda-sqs-delivery.js +1 -0
  53. package/dist/service/lambda/event-source/poll/sim-lambda-sqs-event.d.ts +8 -0
  54. package/dist/service/lambda/event-source/poll/sim-lambda-sqs-event.js +11 -0
  55. package/dist/service/lambda/event-source/sim-lambda-event-source-mapping.d.ts +10 -0
  56. package/dist/service/lambda/event-source/sim-lambda-event-source-mapping.js +11 -0
  57. package/dist/service/lambda/event-source/stream/sim-lambda-stream-cascade-guard.d.ts +35 -8
  58. package/dist/service/lambda/event-source/stream/sim-lambda-stream-cascade-guard.js +35 -12
  59. package/dist/service/lambda/event-source/stream/sim-lambda-stream-cascade.error.d.ts +13 -4
  60. package/dist/service/lambda/event-source/stream/sim-lambda-stream-cascade.error.js +12 -6
  61. package/dist/service/lambda/event-source/stream/sim-lambda-stream-halt.d.ts +18 -0
  62. package/dist/service/lambda/event-source/stream/sim-lambda-stream-halt.js +22 -0
  63. package/dist/service/scheduler/command/schedule/schedule.command.d.ts +1 -0
  64. package/dist/service/scheduler/command/schedule/sim-scheduler-described-schedule.js +1 -0
  65. package/dist/service/scheduler/command/schedule/sim-scheduler-schedule-writer.js +2 -1
  66. package/dist/service/scheduler/command/schedule/sim-scheduler-unsimulated-input.d.ts +3 -3
  67. package/dist/service/scheduler/command/schedule/sim-scheduler-unsimulated-input.js +19 -11
  68. package/dist/service/scheduler/schedule/sim-scheduler-schedule-expression.d.ts +5 -3
  69. package/dist/service/scheduler/schedule/sim-scheduler-schedule-expression.js +6 -4
  70. package/dist/service/scheduler/schedule/sim-scheduler-schedule.d.ts +9 -0
  71. package/dist/service/scheduler/schedule/sim-scheduler-schedule.js +8 -0
  72. package/dist/util/schedule/at/sim-at-expression.d.ts +2 -1
  73. package/dist/util/schedule/at/sim-at-expression.js +7 -3
  74. package/dist/util/schedule/cron/sim-cron-expression.d.ts +6 -3
  75. package/dist/util/schedule/cron/sim-cron-expression.js +24 -21
  76. package/dist/util/schedule/sim-schedule-zone-clock.d.ts +26 -0
  77. package/dist/util/schedule/sim-schedule-zone-clock.js +56 -0
  78. package/dist/util/schedule/sim-schedule-zone.d.ts +58 -0
  79. package/dist/util/schedule/sim-schedule-zone.js +83 -0
  80. package/dist/util/schedule/sim-schedule.d.ts +1 -1
  81. package/dist/util/schedule/sim-schedule.js +6 -5
  82. package/docs/services/athena/README.md +26 -2
  83. package/docs/services/lambda/README.md +159 -15
  84. package/docs/services/scheduler/README.md +35 -6
  85. package/package.json +1 -1
@@ -1,3 +1,4 @@
1
+ import { simLambdaFilterData } from "../../filter/sim-lambda-filtered-records.js";
1
2
  const millisecondsPerSecond = 1000;
2
3
  /**
3
4
  * The schema version every Kinesis event record carries.
@@ -31,7 +32,22 @@ export class SimLambdaKinesisStreamEventBuilder {
31
32
  * The event for a batch of records.
32
33
  */
33
34
  of(records) {
34
- return { Records: records.map((record) => this.record(record)) };
35
+ return { Records: records.map((record) => this.recordOf(record)) };
36
+ }
37
+ /**
38
+ * What a mapping's filters read one record as.
39
+ *
40
+ * The event record carries the payload base64 encoded under `kinesis`, and a
41
+ * Lambda filter pattern addresses it as JSON under a top-level `data`. Both
42
+ * are here, so a pattern can name the payload the way AWS documents it and
43
+ * the record's metadata the way the event carries it.
44
+ */
45
+ filterDocumentOf(record) {
46
+ const eventRecord = this.recordOf(record);
47
+ return {
48
+ ...eventRecord,
49
+ data: simLambdaFilterData(Buffer.from(eventRecord.kinesis.data, "base64").toString("utf8")),
50
+ };
35
51
  }
36
52
  /**
37
53
  * The identifier one record is named by in the event.
@@ -43,7 +59,10 @@ export class SimLambdaKinesisStreamEventBuilder {
43
59
  eventIdOf(record) {
44
60
  return `${this.shardId}:${record.SequenceNumber ?? ""}`;
45
61
  }
46
- record(record) {
62
+ /**
63
+ * The event record one polled record becomes.
64
+ */
65
+ recordOf(record) {
47
66
  return {
48
67
  eventID: this.eventIdOf(record),
49
68
  eventName: "aws:kinesis:record",
@@ -2,7 +2,7 @@ import type { SimLambdaFunction } from "../../function/sim-lambda-function.js";
2
2
  import type { SimLambdaEventSourceMapping } from "../sim-lambda-event-source-mapping.js";
3
3
  import type { SimLambdaDynamoDbStreamEventSourceArn } from "../stream/sim-lambda-dynamodb-stream-event-source-arn.js";
4
4
  import type { SimLambdaEventSourceStreamRecord } from "../stream/sim-lambda-event-source-streams.js";
5
- import type { SimLambdaStreamBatchOutcome } from "./sim-lambda-stream-batch-outcome.js";
5
+ import { SimLambdaStreamBatchOutcome } from "./sim-lambda-stream-batch-outcome.js";
6
6
  interface SimLambdaDynamoDbStreamDeliveryProperties {
7
7
  readonly mapping: SimLambdaEventSourceMapping;
8
8
  readonly eventSourceArn: SimLambdaDynamoDbStreamEventSourceArn;
@@ -19,23 +19,36 @@ interface SimLambdaDynamoDbStreamDeliveryProperties {
19
19
  * what the function said, so the batch response decides it.
20
20
  *
21
21
  * What the function did with the table while it ran is part of the same
22
- * question, so the cascade guard belongs here too: a handler writing back into
23
- * its own source table is refused rather than handled.
22
+ * question, so the cascade guard belongs here too. It counts the deliveries a
23
+ * handler's own writes bring on, and refuses the mapping once that chain is
24
+ * long enough to say the simulation will never settle.
24
25
  */
25
26
  export declare class SimLambdaDynamoDbStreamDelivery {
26
27
  private readonly eventBuilder;
27
28
  private readonly batchResponse;
28
29
  private readonly cascade;
30
+ private readonly halt;
31
+ private readonly filterCriteria;
29
32
  constructor(properties: SimLambdaDynamoDbStreamDeliveryProperties);
30
33
  /**
31
34
  * Deliver a batch, answering with what became of it.
32
35
  */
33
36
  to(simFunction: SimLambdaFunction, records: readonly SimLambdaEventSourceStreamRecord[]): Promise<SimLambdaStreamBatchOutcome>;
34
37
  /**
35
- * Note a record written to the polled stream, answering with whether this
36
- * mapping's own function wrote it.
38
+ * Whether this mapping has finished polling, which deleting it and refusing
39
+ * it both settle.
37
40
  */
38
- noteRecordWritten(): boolean;
41
+ get stopped(): boolean;
42
+ /**
43
+ * Finish this mapping, as deleting it does.
44
+ */
45
+ stop(): void;
46
+ /**
47
+ * Note a record written to the polled stream, which counts only while this
48
+ * mapping's own function is running.
49
+ */
50
+ noteRecordWritten(): void;
39
51
  private handled;
52
+ private invoked;
40
53
  }
41
54
  export {};
@@ -1,7 +1,10 @@
1
+ import { simLambdaFilteredDelivery } from "../filter/sim-lambda-filtered-delivery.js";
1
2
  import { SimLambdaStreamCascadeGuard } from "../stream/sim-lambda-stream-cascade-guard.js";
3
+ import { SimLambdaStreamHalt } from "../stream/sim-lambda-stream-halt.js";
2
4
  import { SimLambdaDynamoDbStreamEventBuilder } from "./sim-lambda-dynamodb-stream-event.js";
3
5
  import { countSimLambdaDynamoDbIteratorAge } from "./sim-lambda-stream-iterator-age.js";
4
- import { simLambdaDynamoDbStreamRecordTimes } from "./sim-lambda-stream-record-times.js";
6
+ import { simLambdaDynamoDbStreamRecordTimes, } from "./sim-lambda-stream-record-times.js";
7
+ import { SimLambdaStreamBatchOutcome } from "./sim-lambda-stream-batch-outcome.js";
5
8
  import { SimLambdaStreamBatchResponse } from "./sim-lambda-stream-batch-response.js";
6
9
  /**
7
10
  * Hands one batch of stream records to a function and says what became of it.
@@ -15,18 +18,23 @@ import { SimLambdaStreamBatchResponse } from "./sim-lambda-stream-batch-response
15
18
  * what the function said, so the batch response decides it.
16
19
  *
17
20
  * What the function did with the table while it ran is part of the same
18
- * question, so the cascade guard belongs here too: a handler writing back into
19
- * its own source table is refused rather than handled.
21
+ * question, so the cascade guard belongs here too. It counts the deliveries a
22
+ * handler's own writes bring on, and refuses the mapping once that chain is
23
+ * long enough to say the simulation will never settle.
20
24
  */
21
25
  export class SimLambdaDynamoDbStreamDelivery {
22
26
  eventBuilder;
23
27
  batchResponse;
24
28
  cascade;
29
+ halt = new SimLambdaStreamHalt();
30
+ filterCriteria;
25
31
  constructor(properties) {
32
+ this.filterCriteria = properties.mapping.filterCriteria;
26
33
  this.eventBuilder = new SimLambdaDynamoDbStreamEventBuilder(properties.eventSourceArn);
27
34
  this.batchResponse = new SimLambdaStreamBatchResponse(properties.mapping.reportsBatchItemFailures);
28
35
  this.cascade = new SimLambdaStreamCascadeGuard({
29
36
  mapping: properties.mapping,
37
+ halt: this.halt,
30
38
  source: {
31
39
  streamArn: properties.eventSourceArn.value,
32
40
  wroteTo: `wrote to the table ${properties.eventSourceArn.tableName}`,
@@ -42,16 +50,42 @@ export class SimLambdaDynamoDbStreamDelivery {
42
50
  return await this.cascade.around(async () => await this.handled(simFunction, records));
43
51
  }
44
52
  /**
45
- * Note a record written to the polled stream, answering with whether this
46
- * mapping's own function wrote it.
53
+ * Whether this mapping has finished polling, which deleting it and refusing
54
+ * it both settle.
55
+ */
56
+ get stopped() {
57
+ return this.halt.stopped;
58
+ }
59
+ /**
60
+ * Finish this mapping, as deleting it does.
61
+ */
62
+ stop() {
63
+ this.halt.stop();
64
+ }
65
+ /**
66
+ * Note a record written to the polled stream, which counts only while this
67
+ * mapping's own function is running.
47
68
  */
48
69
  noteRecordWritten() {
49
- return this.cascade.noteRecordWritten();
70
+ this.cascade.noteRecordWritten();
50
71
  }
51
72
  async handled(simFunction, records) {
52
73
  const times = simLambdaDynamoDbStreamRecordTimes(records);
74
+ return await simLambdaFilteredDelivery({
75
+ criteria: this.filterCriteria,
76
+ records,
77
+ // A pattern reads the record as the function would have received it, so
78
+ // the event builder makes what it matches against.
79
+ documentOf: (record) => ({ ...this.eventBuilder.recordOf(record) }),
80
+ // A batch the filters emptied is finished with even though the function
81
+ // never saw it, as a filtered record advances a real checkpoint too.
82
+ handled: () => SimLambdaStreamBatchOutcome.handled(times),
83
+ invoke: async (delivered) => await this.invoked(simFunction, delivered, times, records),
84
+ });
85
+ }
86
+ async invoked(simFunction, delivered, times, records) {
53
87
  try {
54
- return this.batchResponse.handled(times, await simFunction.invoke(this.eventBuilder.of(records)));
88
+ return this.batchResponse.handled(times, await simFunction.invoke(this.eventBuilder.of(delivered)));
55
89
  }
56
90
  catch {
57
91
  // As on real Lambda, the handler error goes to the function's logs. What
@@ -31,7 +31,6 @@ export declare class SimLambdaDynamoDbStreamEventSourcePoller implements SimLamb
31
31
  private readonly polling;
32
32
  private readonly progress;
33
33
  private readonly turn;
34
- private stopped;
35
34
  constructor(properties: SimLambdaDynamoDbStreamEventSourcePollerProperties);
36
35
  /**
37
36
  * Watch the stream this mapping polls.
@@ -56,8 +55,9 @@ export declare class SimLambdaDynamoDbStreamEventSourcePoller implements SimLamb
56
55
  * Take a record arriving on the stream as something to poll for.
57
56
  *
58
57
  * A record written while this mapping's own function is running is the
59
- * function writing back into its own source table. That never settles, so the
60
- * mapping stops here and the delivery refuses once it is over.
58
+ * function writing back into its own source table. The delivery it brings on
59
+ * is what settles the work or carries the chain on, so the mapping polls for
60
+ * it either way and the guard counts the chain.
61
61
  */
62
62
  recordsAvailable(): void;
63
63
  /**
@@ -65,6 +65,10 @@ export declare class SimLambdaDynamoDbStreamEventSourcePoller implements SimLamb
65
65
  *
66
66
  * Only ever called through the turn, which is what keeps two polls from
67
67
  * reading the same records.
68
+ *
69
+ * A refused mapping polls no further. Its checkpoint stayed where the refused
70
+ * delivery found it, and reading on from there would deliver those records
71
+ * again.
68
72
  */
69
73
  poll(): Promise<void>;
70
74
  }
@@ -22,7 +22,6 @@ export class SimLambdaDynamoDbStreamEventSourcePoller {
22
22
  polling;
23
23
  progress;
24
24
  turn = new SimLambdaEventSourcePollTurn(this);
25
- stopped = false;
26
25
  constructor(properties) {
27
26
  const { eventSourceArn, mapping } = properties;
28
27
  this.stream = new SimLambdaDynamoDbPolledStream(properties.streams, eventSourceArn.value);
@@ -67,21 +66,19 @@ export class SimLambdaDynamoDbStreamEventSourcePoller {
67
66
  * Stop polling, as deleting the mapping does.
68
67
  */
69
68
  stop() {
70
- this.stopped = true;
69
+ this.delivery.stop();
71
70
  this.stream.unwatch(this);
72
71
  }
73
72
  /**
74
73
  * Take a record arriving on the stream as something to poll for.
75
74
  *
76
75
  * A record written while this mapping's own function is running is the
77
- * function writing back into its own source table. That never settles, so the
78
- * mapping stops here and the delivery refuses once it is over.
76
+ * function writing back into its own source table. The delivery it brings on
77
+ * is what settles the work or carries the chain on, so the mapping polls for
78
+ * it either way and the guard counts the chain.
79
79
  */
80
80
  recordsAvailable() {
81
- if (this.delivery.noteRecordWritten()) {
82
- this.stopped = true;
83
- return;
84
- }
81
+ this.delivery.noteRecordWritten();
85
82
  this.progress.pollNow();
86
83
  }
87
84
  /**
@@ -89,8 +86,12 @@ export class SimLambdaDynamoDbStreamEventSourcePoller {
89
86
  *
90
87
  * Only ever called through the turn, which is what keeps two polls from
91
88
  * reading the same records.
89
+ *
90
+ * A refused mapping polls no further. Its checkpoint stayed where the refused
91
+ * delivery found it, and reading on from there would deliver those records
92
+ * again.
92
93
  */
93
94
  async poll() {
94
- await this.polling.poll(this.stopped);
95
+ await this.polling.poll(this.delivery.stopped);
95
96
  }
96
97
  }
@@ -1,5 +1,5 @@
1
1
  import type { SimLambdaDynamoDbStreamEventSourceArn } from "../stream/sim-lambda-dynamodb-stream-event-source-arn.js";
2
- import type { SimLambdaDynamoDbStreamEvent } from "./sim-lambda-dynamodb-stream-event.types.js";
2
+ import type { SimLambdaDynamoDbStreamEvent, SimLambdaDynamoDbStreamEventRecord } from "./sim-lambda-dynamodb-stream-event.types.js";
3
3
  import type { SimLambdaEventSourceStreamRecord } from "../stream/sim-lambda-event-source-streams.js";
4
4
  /**
5
5
  * Builds the DynamoDB stream event for one batch of polled records.
@@ -16,5 +16,9 @@ export declare class SimLambdaDynamoDbStreamEventBuilder {
16
16
  * The event for a batch of records.
17
17
  */
18
18
  of(records: readonly SimLambdaEventSourceStreamRecord[]): SimLambdaDynamoDbStreamEvent;
19
- private record;
19
+ /**
20
+ * The event record one polled record becomes, which is also what a mapping's
21
+ * filters are matched against.
22
+ */
23
+ recordOf(record: SimLambdaEventSourceStreamRecord): SimLambdaDynamoDbStreamEventRecord;
20
24
  }
@@ -17,9 +17,13 @@ export class SimLambdaDynamoDbStreamEventBuilder {
17
17
  * The event for a batch of records.
18
18
  */
19
19
  of(records) {
20
- return { Records: records.map((record) => this.record(record)) };
20
+ return { Records: records.map((record) => this.recordOf(record)) };
21
21
  }
22
- record(record) {
22
+ /**
23
+ * The event record one polled record becomes, which is also what a mapping's
24
+ * filters are matched against.
25
+ */
26
+ recordOf(record) {
23
27
  const identity = record.userIdentity;
24
28
  return {
25
29
  eventID: record.eventID ?? "",
@@ -1,6 +1,7 @@
1
1
  import type { SimLambdaFunction } from "../../function/sim-lambda-function.js";
2
2
  import type { SimSqsPollMessage } from "../../../sqs/poll/sim-sqs-poll-message.js";
3
- import type { SimLambdaEventSourceBatchOutcome, SimLambdaEventSourceBatchResponse } from "./sim-lambda-event-source-batch-response.js";
3
+ import { SimLambdaEventSourceBatchOutcome, type SimLambdaEventSourceBatchResponse } from "./sim-lambda-event-source-batch-response.js";
4
+ import type { SimLambdaFilterCriteria } from "../filter/sim-lambda-filter-criteria.js";
4
5
  /**
5
6
  * One record of an event source event.
6
7
  *
@@ -25,10 +26,16 @@ export interface SimLambdaEventSourceEvent {
25
26
  */
26
27
  export interface SimLambdaEventSourceEventBuilder {
27
28
  of(messages: readonly SimSqsPollMessage[]): SimLambdaEventSourceEvent;
29
+ /**
30
+ * What a mapping's filters read one message as, which is the source's own
31
+ * translation.
32
+ */
33
+ filterDocumentOf(message: SimSqsPollMessage): Record<string, unknown>;
28
34
  }
29
35
  interface SimLambdaEventSourceDeliveryProperties {
30
36
  readonly eventBuilder: SimLambdaEventSourceEventBuilder;
31
37
  readonly batchResponse: SimLambdaEventSourceBatchResponse;
38
+ readonly filterCriteria: SimLambdaFilterCriteria | undefined;
32
39
  }
33
40
  /**
34
41
  * Hands one batch to a function and reads what became of it.
@@ -43,10 +50,23 @@ interface SimLambdaEventSourceDeliveryProperties {
43
50
  export declare class SimLambdaEventSourceDelivery {
44
51
  private readonly eventBuilder;
45
52
  private readonly batchResponse;
53
+ private readonly filterCriteria;
46
54
  constructor(properties: SimLambdaEventSourceDeliveryProperties);
47
55
  /**
48
56
  * Deliver a batch, answering with what to delete and what to leave.
49
57
  */
50
58
  to(simFunction: SimLambdaFunction, messages: readonly SimSqsPollMessage[]): Promise<SimLambdaEventSourceBatchOutcome>;
59
+ /**
60
+ * One batch of matching messages, handed over and read back.
61
+ */
62
+ private invoked;
63
+ /**
64
+ * An outcome with the filtered-out messages counted as handled, which deletes
65
+ * them whatever the function said about the rest.
66
+ *
67
+ * A message the function never saw is in neither list the outcome carries,
68
+ * which is what picks it out of the batch that was read.
69
+ */
70
+ private alsoHandling;
51
71
  }
52
72
  export {};
@@ -1,3 +1,5 @@
1
+ import { SimLambdaEventSourceBatchOutcome, } from "./sim-lambda-event-source-batch-response.js";
2
+ import { simLambdaFilteredDelivery } from "../filter/sim-lambda-filtered-delivery.js";
1
3
  /**
2
4
  * Hands one batch to a function and reads what became of it.
3
5
  *
@@ -11,22 +13,50 @@
11
13
  export class SimLambdaEventSourceDelivery {
12
14
  eventBuilder;
13
15
  batchResponse;
16
+ filterCriteria;
14
17
  constructor(properties) {
15
18
  this.eventBuilder = properties.eventBuilder;
16
19
  this.batchResponse = properties.batchResponse;
20
+ this.filterCriteria = properties.filterCriteria;
17
21
  }
18
22
  /**
19
23
  * Deliver a batch, answering with what to delete and what to leave.
20
24
  */
21
25
  async to(simFunction, messages) {
26
+ return await simLambdaFilteredDelivery({
27
+ criteria: this.filterCriteria,
28
+ records: messages,
29
+ documentOf: (message) => this.eventBuilder.filterDocumentOf(message),
30
+ // A message the filters excluded is deleted from the queue without the
31
+ // function seeing it, the way real Lambda deletes one.
32
+ handled: () => new SimLambdaEventSourceBatchOutcome(messages, []),
33
+ invoke: async (delivered) => this.alsoHandling(messages, await this.invoked(simFunction, delivered)),
34
+ });
35
+ }
36
+ /**
37
+ * One batch of matching messages, handed over and read back.
38
+ */
39
+ async invoked(simFunction, delivered) {
22
40
  try {
23
- return this.batchResponse.handled(messages, await simFunction.invoke(this.eventBuilder.of(messages)));
41
+ return this.batchResponse.handled(delivered, await simFunction.invoke(this.eventBuilder.of(delivered)));
24
42
  }
25
43
  catch {
26
44
  // As on real Lambda, the handler error goes to the function's logs and
27
45
  // not to whoever sent the message. What the sender sees is the batch
28
46
  // coming back to the source.
29
- return this.batchResponse.failed(messages);
47
+ return this.batchResponse.failed(delivered);
30
48
  }
31
49
  }
50
+ /**
51
+ * An outcome with the filtered-out messages counted as handled, which deletes
52
+ * them whatever the function said about the rest.
53
+ *
54
+ * A message the function never saw is in neither list the outcome carries,
55
+ * which is what picks it out of the batch that was read.
56
+ */
57
+ alsoHandling(messages, outcome) {
58
+ const seen = new Set([...outcome.handled, ...outcome.returned]);
59
+ const excluded = messages.filter((message) => !seen.has(message));
60
+ return new SimLambdaEventSourceBatchOutcome([...outcome.handled, ...excluded], outcome.returned);
61
+ }
32
62
  }
@@ -12,5 +12,6 @@ export function makeSimLambdaSqsDelivery(properties) {
12
12
  return new SimLambdaEventSourceDelivery({
13
13
  eventBuilder: new SimLambdaSqsEventBuilder(properties.eventSourceArn),
14
14
  batchResponse: new SimLambdaSqsBatchResponse(properties.mapping.reportsBatchItemFailures),
15
+ filterCriteria: properties.mapping.filterCriteria,
15
16
  });
16
17
  }
@@ -50,6 +50,14 @@ export declare class SimLambdaSqsEventBuilder {
50
50
  * The event for a batch of messages.
51
51
  */
52
52
  of(messages: readonly SimSqsPollMessage[]): SimLambdaSqsEvent;
53
+ /**
54
+ * What a mapping's filters read one message as.
55
+ *
56
+ * Real Lambda filters an SQS message on its body alone, and reads the body as
57
+ * JSON where it holds JSON. Nothing else about the message is here, because a
58
+ * pattern naming anything else was refused when the mapping was created.
59
+ */
60
+ filterDocumentOf(message: SimSqsPollMessage): Record<string, unknown>;
53
61
  private record;
54
62
  private messageAttributes;
55
63
  }
@@ -1,3 +1,4 @@
1
+ import { simLambdaFilterData } from "../filter/sim-lambda-filtered-records.js";
1
2
  /**
2
3
  * Builds the SQS event for one batch of polled messages.
3
4
  *
@@ -17,6 +18,16 @@ export class SimLambdaSqsEventBuilder {
17
18
  of(messages) {
18
19
  return { Records: messages.map((message) => this.record(message)) };
19
20
  }
21
+ /**
22
+ * What a mapping's filters read one message as.
23
+ *
24
+ * Real Lambda filters an SQS message on its body alone, and reads the body as
25
+ * JSON where it holds JSON. Nothing else about the message is here, because a
26
+ * pattern naming anything else was refused when the mapping was created.
27
+ */
28
+ filterDocumentOf(message) {
29
+ return { body: simLambdaFilterData(message.Body) };
30
+ }
20
31
  record(message) {
21
32
  return {
22
33
  messageId: message.MessageId,
@@ -1,6 +1,7 @@
1
1
  import type { SimLambdaStreamDestinationConfiguration } from "./sim-lambda-stream-destination-config.js";
2
2
  import type { SimLambdaDestinationTargets } from "../destination/sim-lambda-destination-targets.js";
3
3
  import type { SimAwsAccountRegionScope } from "../../aws/sim-aws-account-region-scope.js";
4
+ import type { SimLambdaFilterCriteria, SimLambdaFilterCriteriaInput } from "./filter/sim-lambda-filter-criteria.js";
4
5
  import type { SimLambdaFunctionArn } from "../function/sim-lambda-function-configuration.js";
5
6
  import type { SimLambdaStreamRetryLimits, SimLambdaStreamRetryLimitsConfiguration } from "./sim-lambda-stream-retry-limits.js";
6
7
  import type { SimLambdaEventSourceStart, SimLambdaEventSourceStartingPosition } from "./sim-lambda-event-source-starting-position.js";
@@ -35,6 +36,7 @@ interface SimLambdaEventSourceMappingProperties {
35
36
  readonly streamRetryLimits?: SimLambdaStreamRetryLimits | undefined;
36
37
  readonly destinationConfig?: SimLambdaStreamDestinationConfiguration | undefined;
37
38
  readonly destinations?: SimLambdaDestinationTargets | undefined;
39
+ readonly filterCriteria?: SimLambdaFilterCriteria | undefined;
38
40
  readonly createdAt: Date;
39
41
  }
40
42
  /**
@@ -53,6 +55,7 @@ export interface SimLambdaEventSourceMappingConfiguration extends Partial<SimLam
53
55
  readonly StartingPositionTimestamp?: Date | undefined;
54
56
  readonly MaximumBatchingWindowInSeconds: number;
55
57
  readonly FunctionResponseTypes: readonly SimLambdaFunctionResponseType[];
58
+ readonly FilterCriteria?: SimLambdaFilterCriteriaInput | undefined;
56
59
  readonly State: SimLambdaEventSourceMappingState;
57
60
  readonly StateTransitionReason: string;
58
61
  readonly LastModified: Date;
@@ -89,6 +92,13 @@ export declare class SimLambdaEventSourceMapping {
89
92
  */
90
93
  readonly start: SimLambdaEventSourceStart | undefined;
91
94
  readonly functionResponseTypes: readonly SimLambdaFunctionResponseType[];
95
+ /**
96
+ * The filters a record has to match before it is delivered, if this mapping
97
+ * was created with any.
98
+ *
99
+ * A mapping with none delivers every record its source hands it.
100
+ */
101
+ readonly filterCriteria: SimLambdaFilterCriteria | undefined;
92
102
  /**
93
103
  * When this mapping stops delivering a batch its function keeps failing, for
94
104
  * a source that leaves the counting to the mapping.
@@ -31,6 +31,13 @@ export class SimLambdaEventSourceMapping {
31
31
  */
32
32
  start;
33
33
  functionResponseTypes;
34
+ /**
35
+ * The filters a record has to match before it is delivered, if this mapping
36
+ * was created with any.
37
+ *
38
+ * A mapping with none delivers every record its source hands it.
39
+ */
40
+ filterCriteria;
34
41
  /**
35
42
  * When this mapping stops delivering a batch its function keeps failing, for
36
43
  * a source that leaves the counting to the mapping.
@@ -59,6 +66,7 @@ export class SimLambdaEventSourceMapping {
59
66
  // cannot change what this mapping does with a batch afterwards.
60
67
  this.functionResponseTypes = [...(properties.functionResponseTypes ?? [])];
61
68
  this.streamRetryLimits = properties.streamRetryLimits;
69
+ this.filterCriteria = properties.filterCriteria;
62
70
  this.enabled = properties.enabled ?? true;
63
71
  this.lastModified = properties.createdAt;
64
72
  }
@@ -120,6 +128,9 @@ export class SimLambdaEventSourceMapping {
120
128
  // them out rather than reporting a limit it does not have.
121
129
  ...this.streamRetryLimits?.configuration(),
122
130
  FunctionResponseTypes: this.functionResponseTypes,
131
+ // A mapping created without filters reports none, as real Lambda does,
132
+ // rather than reporting an empty list of them.
133
+ FilterCriteria: this.filterCriteria?.configuration(),
123
134
  State: this.#state,
124
135
  StateTransitionReason: "USER_INITIATED",
125
136
  LastModified: this.lastModified,
@@ -1,4 +1,15 @@
1
1
  import type { SimLambdaEventSourceMapping } from "../sim-lambda-event-source-mapping.js";
2
+ import type { SimLambdaStreamHalt } from "./sim-lambda-stream-halt.js";
3
+ /**
4
+ * How many deliveries in a row may feed the source that invoked them before the
5
+ * simulation is refused.
6
+ *
7
+ * One write back is a handler doing its job, and the delivery it causes is the
8
+ * chance for that work to finish. A handler that settles takes two or three
9
+ * links of chain. A handler that loops takes every link there is, and the
10
+ * simulation has to say so before the test times out.
11
+ */
12
+ export declare const simLambdaStreamCascadeLimit = 10;
2
13
  /**
3
14
  * The source a guard watches, said in the terms its own service uses.
4
15
  */
@@ -20,33 +31,49 @@ export interface SimLambdaStreamCascadeSource {
20
31
  interface SimLambdaStreamCascadeGuardProperties {
21
32
  readonly mapping: SimLambdaEventSourceMapping;
22
33
  readonly source: SimLambdaStreamCascadeSource;
34
+ /**
35
+ * What a refusal stops, since a mapping polling on from a checkpoint the
36
+ * refusal left where it was would deliver the same records again.
37
+ */
38
+ readonly halt: SimLambdaStreamHalt;
23
39
  }
24
40
  /**
25
- * Watches one mapping's deliveries for the function writing back into the
41
+ * Watches one mapping's deliveries for a chain of the function feeding the
26
42
  * source whose stream invoked it.
27
43
  *
28
44
  * The delivery runs inside its own asynchronous context, so a record written by
29
45
  * the handler is told apart from one written by anything else that happened to
30
46
  * be running at the same time. That distinction is the whole point: several
31
47
  * records written at once are an ordinary batch, and a handler feeding its own
32
- * source is a loop.
48
+ * source is the start of a chain.
49
+ *
50
+ * What the guard counts is the chain, and never the shape of one write. A
51
+ * handler that writes back and then finds its own work done writes nothing the
52
+ * second time round, the chain ends at one link, and the simulation settles. A
53
+ * handler that writes back every time takes the chain to
54
+ * `simLambdaStreamCascadeLimit` and is refused there.
33
55
  */
34
56
  export declare class SimLambdaStreamCascadeGuard {
35
57
  private readonly properties;
36
- private cascaded;
58
+ private fedRecords;
59
+ private chained;
37
60
  constructor(properties: SimLambdaStreamCascadeGuardProperties);
38
61
  /**
39
- * Run one delivery, refusing afterwards if the function fed its own source.
62
+ * Run one delivery, refusing afterwards if the chain has gone on long enough
63
+ * to say the simulation will never settle.
40
64
  *
41
65
  * The refusal comes after the delivery rather than during it, so the handler
42
- * sees its own write succeed and the loop is reported to whoever is waiting
66
+ * sees its own write succeed and the chain is reported to whoever is waiting
43
67
  * for the simulation to settle.
44
68
  */
45
69
  around<Result>(delivery: () => Promise<Result>): Promise<Result>;
46
70
  /**
47
- * Note a record written to the polled stream, answering with whether this
48
- * mapping's own function wrote it.
71
+ * Note a record written to the polled stream, which counts only while this
72
+ * mapping's own function is the thing that is running.
73
+ *
74
+ * Counted rather than flagged, so a delivery can tell whether the count moved
75
+ * while it ran without the flag having to be put back afterwards.
49
76
  */
50
- noteRecordWritten(): boolean;
77
+ noteRecordWritten(): void;
51
78
  }
52
79
  export {};