@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.
- package/dist/service/athena/engine/sim-athena-ast-nodes.d.ts +11 -0
- package/dist/service/athena/engine/sim-athena-ast-nodes.js +22 -0
- package/dist/service/athena/engine/sim-athena-engine-result.d.ts +9 -1
- package/dist/service/athena/engine/sim-athena-engine-result.js +15 -4
- package/dist/service/athena/engine/sim-athena-engine-run.d.ts +2 -0
- package/dist/service/athena/engine/sim-athena-engine-run.js +6 -1
- package/dist/service/athena/engine/sim-athena-query-engine.js +1 -0
- package/dist/service/athena/engine/sim-athena-result-columns.d.ts +1 -1
- package/dist/service/athena/engine/sim-athena-result-columns.js +11 -4
- package/dist/service/athena/engine/sim-athena-round-scales.d.ts +19 -0
- package/dist/service/athena/engine/sim-athena-round-scales.js +80 -0
- package/dist/service/athena/engine/sim-athena-sql-translation.d.ts +9 -0
- package/dist/service/athena/engine/sim-athena-sql-translation.js +17 -2
- package/dist/service/athena/engine/sim-athena-string-shims.js +29 -1
- package/dist/service/athena/engine/sim-athena-unnest-item.js +6 -15
- package/dist/service/athena/engine/sim-athena-unnest-rewrite.d.ts +4 -4
- package/dist/service/athena/engine/sim-athena-unnest-rewrite.js +4 -4
- package/dist/service/athena/engine/sim-athena-unnest-source.d.ts +10 -9
- package/dist/service/athena/engine/sim-athena-unnest-source.js +25 -11
- package/dist/service/athena/sim-athena-flattened-events.fixture.d.ts +3 -0
- package/dist/service/athena/sim-athena-flattened-events.fixture.js +46 -0
- package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-properties.js +2 -0
- package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-property-names.js +1 -5
- package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-input.d.ts +5 -0
- package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-input.js +7 -0
- package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-refusals.js +0 -1
- package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping.handler.js +1 -0
- package/dist/service/lambda/command/event-source-mapping/event-source-mapping.command.d.ts +2 -1
- package/dist/service/lambda/command/event-source-mapping/event-source-mapping.command.js +0 -6
- package/dist/service/lambda/event-source/filter/sim-lambda-filter-criteria.d.ts +48 -0
- package/dist/service/lambda/event-source/filter/sim-lambda-filter-criteria.js +129 -0
- package/dist/service/lambda/event-source/filter/sim-lambda-filtered-delivery.d.ts +27 -0
- package/dist/service/lambda/event-source/filter/sim-lambda-filtered-delivery.js +15 -0
- package/dist/service/lambda/event-source/filter/sim-lambda-filtered-records.d.ts +24 -0
- package/dist/service/lambda/event-source/filter/sim-lambda-filtered-records.js +35 -0
- package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-shard-poller.d.ts +7 -4
- package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-shard-poller.js +9 -6
- package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-stream-delivery.d.ts +16 -4
- package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-stream-delivery.js +36 -5
- package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-stream-event-source-poller.d.ts +4 -3
- package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-stream-event-source-poller.js +6 -7
- package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-stream-event.d.ts +14 -2
- package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-stream-event.js +21 -2
- package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-delivery.d.ts +19 -6
- package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-delivery.js +41 -7
- package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event-source-poller.d.ts +7 -3
- package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event-source-poller.js +10 -9
- package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event.d.ts +6 -2
- package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event.js +6 -2
- package/dist/service/lambda/event-source/poll/sim-lambda-event-source-delivery.d.ts +21 -1
- package/dist/service/lambda/event-source/poll/sim-lambda-event-source-delivery.js +32 -2
- package/dist/service/lambda/event-source/poll/sim-lambda-sqs-delivery.js +1 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-sqs-event.d.ts +8 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-sqs-event.js +11 -0
- package/dist/service/lambda/event-source/sim-lambda-event-source-mapping.d.ts +10 -0
- package/dist/service/lambda/event-source/sim-lambda-event-source-mapping.js +11 -0
- package/dist/service/lambda/event-source/stream/sim-lambda-stream-cascade-guard.d.ts +35 -8
- package/dist/service/lambda/event-source/stream/sim-lambda-stream-cascade-guard.js +35 -12
- package/dist/service/lambda/event-source/stream/sim-lambda-stream-cascade.error.d.ts +13 -4
- package/dist/service/lambda/event-source/stream/sim-lambda-stream-cascade.error.js +12 -6
- package/dist/service/lambda/event-source/stream/sim-lambda-stream-halt.d.ts +18 -0
- package/dist/service/lambda/event-source/stream/sim-lambda-stream-halt.js +22 -0
- package/dist/service/scheduler/command/schedule/schedule.command.d.ts +1 -0
- package/dist/service/scheduler/command/schedule/sim-scheduler-described-schedule.js +1 -0
- package/dist/service/scheduler/command/schedule/sim-scheduler-schedule-writer.js +2 -1
- package/dist/service/scheduler/command/schedule/sim-scheduler-unsimulated-input.d.ts +3 -3
- package/dist/service/scheduler/command/schedule/sim-scheduler-unsimulated-input.js +19 -11
- package/dist/service/scheduler/schedule/sim-scheduler-schedule-expression.d.ts +5 -3
- package/dist/service/scheduler/schedule/sim-scheduler-schedule-expression.js +6 -4
- package/dist/service/scheduler/schedule/sim-scheduler-schedule.d.ts +9 -0
- package/dist/service/scheduler/schedule/sim-scheduler-schedule.js +8 -0
- package/dist/util/schedule/at/sim-at-expression.d.ts +2 -1
- package/dist/util/schedule/at/sim-at-expression.js +7 -3
- package/dist/util/schedule/cron/sim-cron-expression.d.ts +6 -3
- package/dist/util/schedule/cron/sim-cron-expression.js +24 -21
- package/dist/util/schedule/sim-schedule-zone-clock.d.ts +26 -0
- package/dist/util/schedule/sim-schedule-zone-clock.js +56 -0
- package/dist/util/schedule/sim-schedule-zone.d.ts +58 -0
- package/dist/util/schedule/sim-schedule-zone.js +83 -0
- package/dist/util/schedule/sim-schedule.d.ts +1 -1
- package/dist/util/schedule/sim-schedule.js +6 -5
- package/docs/services/athena/README.md +26 -2
- package/docs/services/lambda/README.md +159 -15
- package/docs/services/scheduler/README.md +35 -6
- package/package.json +1 -1
package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-input.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type SimLambdaStreamDestinationConfiguration } from "../../event-source
|
|
|
2
2
|
import type { SimAwsAccountRegionScope } from "../../../aws/sim-aws-account-region-scope.js";
|
|
3
3
|
import { type SimLambdaEventSourceArn } from "../../event-source/sim-lambda-event-source-arn.js";
|
|
4
4
|
import type { SimLambdaFunctionResponseType } from "../../event-source/sim-lambda-event-source-mapping.js";
|
|
5
|
+
import { SimLambdaFilterCriteria } from "../../event-source/filter/sim-lambda-filter-criteria.js";
|
|
5
6
|
import type { SimLambdaStreamRetryLimits } from "../../event-source/sim-lambda-stream-retry-limits.js";
|
|
6
7
|
import type { SimLambdaEventSourceStart } from "../../event-source/sim-lambda-event-source-starting-position.js";
|
|
7
8
|
import type { SimCreateEventSourceMappingCommandInput } from "./event-source-mapping.command.js";
|
|
@@ -36,6 +37,10 @@ export declare class SimLambdaEventSourceMappingInput {
|
|
|
36
37
|
* the counting to the mapping.
|
|
37
38
|
*/
|
|
38
39
|
readonly streamRetryLimits: SimLambdaStreamRetryLimits | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* The filters this mapping delivers through, if it was created with any.
|
|
42
|
+
*/
|
|
43
|
+
readonly filterCriteria: SimLambdaFilterCriteria | undefined;
|
|
39
44
|
private constructor();
|
|
40
45
|
/**
|
|
41
46
|
* Read a CreateEventSourceMapping request, refusing what this simulation
|
package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-input.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { simLambdaStreamDestinationConfig, } from "../../event-source/sim-lambda-stream-destination-config.js";
|
|
2
2
|
import { simLambdaEventSourceArnOf, } from "../../event-source/sim-lambda-event-source-arn.js";
|
|
3
|
+
import { SimLambdaFilterCriteria } from "../../event-source/filter/sim-lambda-filter-criteria.js";
|
|
3
4
|
import { SimLambdaInvalidParameterValueException } from "../../error/sim-lambda.error.js";
|
|
4
5
|
import { simLambdaFunctionReferenceOf } from "../../function/sim-lambda-function-reference.js";
|
|
5
6
|
import { functionResponseTypesIn, requiredString, } from "./create-event-source-mapping-values.js";
|
|
@@ -35,6 +36,10 @@ export class SimLambdaEventSourceMappingInput {
|
|
|
35
36
|
* the counting to the mapping.
|
|
36
37
|
*/
|
|
37
38
|
streamRetryLimits;
|
|
39
|
+
/**
|
|
40
|
+
* The filters this mapping delivers through, if it was created with any.
|
|
41
|
+
*/
|
|
42
|
+
filterCriteria;
|
|
38
43
|
constructor(properties) {
|
|
39
44
|
this.eventSourceArn = properties.eventSourceArn;
|
|
40
45
|
this.functionName = properties.functionName;
|
|
@@ -45,6 +50,7 @@ export class SimLambdaEventSourceMappingInput {
|
|
|
45
50
|
this.functionResponseTypes = properties.functionResponseTypes;
|
|
46
51
|
this.destinationConfig = properties.destinationConfig;
|
|
47
52
|
this.streamRetryLimits = properties.streamRetryLimits;
|
|
53
|
+
this.filterCriteria = properties.filterCriteria;
|
|
48
54
|
}
|
|
49
55
|
/**
|
|
50
56
|
* Read a CreateEventSourceMapping request, refusing what this simulation
|
|
@@ -65,6 +71,7 @@ export class SimLambdaEventSourceMappingInput {
|
|
|
65
71
|
}),
|
|
66
72
|
enabled: input.Enabled ?? true,
|
|
67
73
|
functionResponseTypes: functionResponseTypesIn(input),
|
|
74
|
+
filterCriteria: SimLambdaFilterCriteria.of(input.FilterCriteria, eventSourceArn.kind),
|
|
68
75
|
streamRetryLimits: eventSourceArn.retryLimitRules.limitsIn({
|
|
69
76
|
maximumRetryAttempts: input.MaximumRetryAttempts,
|
|
70
77
|
maximumRecordAgeInSeconds: input.MaximumRecordAgeInSeconds,
|
package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-refusals.js
CHANGED
|
@@ -9,7 +9,6 @@ import { SimLambdaInvalidParameterValueException } from "../../error/sim-lambda.
|
|
|
9
9
|
* would not have.
|
|
10
10
|
*/
|
|
11
11
|
const unsimulatedInputs = new Map([
|
|
12
|
-
["FilterCriteria", "event filtering is not simulated"],
|
|
13
12
|
["ScalingConfig", "polling concurrency is not simulated"],
|
|
14
13
|
["ProvisionedPollerConfig", "polling concurrency is not simulated"],
|
|
15
14
|
[
|
package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping.handler.js
CHANGED
|
@@ -81,6 +81,7 @@ export class CreateEventSourceMappingCommandHandler {
|
|
|
81
81
|
enabled: input.enabled,
|
|
82
82
|
functionResponseTypes: input.functionResponseTypes,
|
|
83
83
|
streamRetryLimits: input.streamRetryLimits,
|
|
84
|
+
filterCriteria: input.filterCriteria,
|
|
84
85
|
destinationConfig: input.destinationConfig,
|
|
85
86
|
destinations: this.properties.destinations,
|
|
86
87
|
createdAt: this.properties.background.now(),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SimLambdaFilterCriteriaInput } from "../../event-source/filter/sim-lambda-filter-criteria.js";
|
|
1
2
|
/**
|
|
2
3
|
* https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/lambda/command/CreateEventSourceMappingCommand/
|
|
3
4
|
*
|
|
@@ -31,7 +32,7 @@ export interface SimCreateEventSourceMappingCommandInput {
|
|
|
31
32
|
readonly BatchSize?: number | undefined;
|
|
32
33
|
readonly MaximumBatchingWindowInSeconds?: number | undefined;
|
|
33
34
|
readonly FunctionResponseTypes?: readonly string[] | undefined;
|
|
34
|
-
readonly FilterCriteria?:
|
|
35
|
+
readonly FilterCriteria?: SimLambdaFilterCriteriaInput | undefined;
|
|
35
36
|
readonly ScalingConfig?: object | undefined;
|
|
36
37
|
readonly DestinationConfig?: object | undefined;
|
|
37
38
|
readonly SelfManagedEventSource?: object | undefined;
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/lambda/command/CreateEventSourceMappingCommand/
|
|
3
|
-
*
|
|
4
|
-
* The event source mapping commands share their output shape, because every one
|
|
5
|
-
* of them reports the mapping it acted on, so they share one module.
|
|
6
|
-
*/
|
|
7
1
|
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `FilterCriteria` a CreateEventSourceMapping request carries, as the
|
|
3
|
+
* command takes it.
|
|
4
|
+
*/
|
|
5
|
+
export interface SimLambdaFilterCriteriaInput {
|
|
6
|
+
readonly Filters?: readonly {
|
|
7
|
+
readonly Pattern?: string | undefined;
|
|
8
|
+
}[] | undefined;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Read a `FilterCriteria` value of unknown shape, as a template carries one.
|
|
12
|
+
*
|
|
13
|
+
* The same shape check for an SDK request and a CloudFormation Resource, so a
|
|
14
|
+
* mapping a template deployed filters the way an SDK caller's would.
|
|
15
|
+
*/
|
|
16
|
+
export declare function simLambdaFilterCriteriaInput(value: unknown): SimLambdaFilterCriteriaInput | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* The filters a mapping delivers through, read from what a request asked for.
|
|
19
|
+
*
|
|
20
|
+
* A record is delivered when any one of the filters matches it, which is how
|
|
21
|
+
* real Lambda ORs a list of patterns together. A mapping with no criteria has
|
|
22
|
+
* none of these, and delivers everything.
|
|
23
|
+
*
|
|
24
|
+
* The patterns are EventBridge event patterns. Lambda documents its filter
|
|
25
|
+
* rules as EventBridge's own syntax, so simulated EventBridge's matcher is what
|
|
26
|
+
* evaluates them, down to the operators it refuses.
|
|
27
|
+
*/
|
|
28
|
+
export declare class SimLambdaFilterCriteria {
|
|
29
|
+
private readonly patterns;
|
|
30
|
+
private constructor();
|
|
31
|
+
/**
|
|
32
|
+
* Read the criteria a request carries, refusing a pattern this simulation
|
|
33
|
+
* cannot evaluate.
|
|
34
|
+
*
|
|
35
|
+
* The refusal comes before the mapping exists, because a mapping created
|
|
36
|
+
* with a filter it cannot apply would deliver the wrong records rather than
|
|
37
|
+
* none.
|
|
38
|
+
*/
|
|
39
|
+
static of(criteria: SimLambdaFilterCriteriaInput | undefined, eventSourceKind: string): SimLambdaFilterCriteria | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* The criteria as Create, Get and List report them back.
|
|
42
|
+
*/
|
|
43
|
+
configuration(): SimLambdaFilterCriteriaInput;
|
|
44
|
+
/**
|
|
45
|
+
* Whether a record, as a pattern reads it, passes any of these filters.
|
|
46
|
+
*/
|
|
47
|
+
matches(document: Record<string, unknown>): boolean;
|
|
48
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { SimEventPattern } from "../../../eventbridge/pattern/sim-event-pattern.js";
|
|
2
|
+
import { SimLambdaInvalidParameterValueException } from "../../error/sim-lambda.error.js";
|
|
3
|
+
import { isRecord } from "../../../../util/type-guard/record.js";
|
|
4
|
+
/**
|
|
5
|
+
* The one key an SQS mapping may filter on.
|
|
6
|
+
*
|
|
7
|
+
* Real Lambda filters an SQS message on its body alone, where a stream mapping
|
|
8
|
+
* filters on the whole record. A pattern naming anything else is refused here,
|
|
9
|
+
* since accepting one would match nothing and read as a pattern that was
|
|
10
|
+
* simply too specific.
|
|
11
|
+
*/
|
|
12
|
+
const sqsFilterKey = "body";
|
|
13
|
+
/**
|
|
14
|
+
* Read a `FilterCriteria` value of unknown shape, as a template carries one.
|
|
15
|
+
*
|
|
16
|
+
* The same shape check for an SDK request and a CloudFormation Resource, so a
|
|
17
|
+
* mapping a template deployed filters the way an SDK caller's would.
|
|
18
|
+
*/
|
|
19
|
+
export function simLambdaFilterCriteriaInput(value) {
|
|
20
|
+
if (value === undefined) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
const filters = isRecord(value) ? value["Filters"] : undefined;
|
|
24
|
+
if (!Array.isArray(filters)) {
|
|
25
|
+
throw new SimLambdaInvalidParameterValueException(`FilterCriteria carries a Filters list, and this one carries ${JSON.stringify(value)}`);
|
|
26
|
+
}
|
|
27
|
+
return { Filters: filters.map((filter) => ({ Pattern: patternIn(filter) })) };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The pattern one filter of a list carries.
|
|
31
|
+
*/
|
|
32
|
+
function patternIn(filter) {
|
|
33
|
+
const pattern = isRecord(filter) ? filter["Pattern"] : undefined;
|
|
34
|
+
if (pattern !== undefined && typeof pattern !== "string") {
|
|
35
|
+
throw new SimLambdaInvalidParameterValueException("A filter in FilterCriteria carries a Pattern string, and this one " +
|
|
36
|
+
`carries ${JSON.stringify(pattern)}`);
|
|
37
|
+
}
|
|
38
|
+
return pattern;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The filters a mapping delivers through, read from what a request asked for.
|
|
42
|
+
*
|
|
43
|
+
* A record is delivered when any one of the filters matches it, which is how
|
|
44
|
+
* real Lambda ORs a list of patterns together. A mapping with no criteria has
|
|
45
|
+
* none of these, and delivers everything.
|
|
46
|
+
*
|
|
47
|
+
* The patterns are EventBridge event patterns. Lambda documents its filter
|
|
48
|
+
* rules as EventBridge's own syntax, so simulated EventBridge's matcher is what
|
|
49
|
+
* evaluates them, down to the operators it refuses.
|
|
50
|
+
*/
|
|
51
|
+
export class SimLambdaFilterCriteria {
|
|
52
|
+
patterns;
|
|
53
|
+
constructor(patterns) {
|
|
54
|
+
this.patterns = patterns;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Read the criteria a request carries, refusing a pattern this simulation
|
|
58
|
+
* cannot evaluate.
|
|
59
|
+
*
|
|
60
|
+
* The refusal comes before the mapping exists, because a mapping created
|
|
61
|
+
* with a filter it cannot apply would deliver the wrong records rather than
|
|
62
|
+
* none.
|
|
63
|
+
*/
|
|
64
|
+
static of(criteria, eventSourceKind) {
|
|
65
|
+
const filters = criteria?.Filters ?? [];
|
|
66
|
+
if (filters.length === 0) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
return new this(filters.map((filter) => patternOf(filter.Pattern, eventSourceKind)));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The criteria as Create, Get and List report them back.
|
|
73
|
+
*/
|
|
74
|
+
configuration() {
|
|
75
|
+
return {
|
|
76
|
+
Filters: this.patterns.map((pattern) => ({ Pattern: pattern.source })),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Whether a record, as a pattern reads it, passes any of these filters.
|
|
81
|
+
*/
|
|
82
|
+
matches(document) {
|
|
83
|
+
return this.patterns.some((pattern) => pattern.matches(document));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* One filter's pattern, refused as a Lambda parameter rather than as an
|
|
88
|
+
* EventBridge one.
|
|
89
|
+
*
|
|
90
|
+
* The matcher is EventBridge's and says so when it refuses a pattern, and the
|
|
91
|
+
* caller here sent a Lambda request. The reason survives and the exception type
|
|
92
|
+
* changes.
|
|
93
|
+
*/
|
|
94
|
+
function patternOf(source, eventSourceKind) {
|
|
95
|
+
if (source === undefined || source === "") {
|
|
96
|
+
throw new SimLambdaInvalidParameterValueException("A filter in FilterCriteria carries a Pattern, and this one carries " +
|
|
97
|
+
"none");
|
|
98
|
+
}
|
|
99
|
+
refuseUnfilterableKeys(source, eventSourceKind);
|
|
100
|
+
try {
|
|
101
|
+
return SimEventPattern.of(source);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
105
|
+
throw new SimLambdaInvalidParameterValueException(`FilterCriteria pattern ${source} cannot be evaluated. ${reason}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Refuse a pattern naming a key the event source does not filter on.
|
|
110
|
+
*/
|
|
111
|
+
function refuseUnfilterableKeys(source, eventSourceKind) {
|
|
112
|
+
if (eventSourceKind !== "sqs") {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
let parsed;
|
|
116
|
+
try {
|
|
117
|
+
parsed = JSON.parse(source);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// An unparseable pattern is the matcher's refusal to make, in its own
|
|
121
|
+
// words, and it is about to make it.
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const named = isRecord(parsed) ? Object.keys(parsed) : [];
|
|
125
|
+
const unfilterable = named.filter((key) => key !== sqsFilterKey);
|
|
126
|
+
if (unfilterable.length > 0) {
|
|
127
|
+
throw new SimLambdaInvalidParameterValueException(`FilterCriteria on an SQS event source mapping filters on ${sqsFilterKey} alone, and this pattern names ${unfilterable.join(", ")}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SimLambdaFilterCriteria } from "./sim-lambda-filter-criteria.js";
|
|
2
|
+
interface SimLambdaFilteredDeliveryProperties<RecordType, Outcome> {
|
|
3
|
+
readonly criteria: SimLambdaFilterCriteria | undefined;
|
|
4
|
+
readonly records: readonly RecordType[];
|
|
5
|
+
/**
|
|
6
|
+
* What a pattern reads one record as, which is the source's translation.
|
|
7
|
+
*/
|
|
8
|
+
readonly documentOf: (record: RecordType) => Record<string, unknown>;
|
|
9
|
+
/**
|
|
10
|
+
* What becomes of a batch the filters emptied.
|
|
11
|
+
*/
|
|
12
|
+
readonly handled: () => Outcome;
|
|
13
|
+
/**
|
|
14
|
+
* Hand the records that matched to the function.
|
|
15
|
+
*/
|
|
16
|
+
readonly invoke: (delivered: readonly RecordType[]) => Promise<Outcome>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Deliver the records of a batch a mapping's filters let through.
|
|
20
|
+
*
|
|
21
|
+
* A batch the filters emptied is finished with and the function is never
|
|
22
|
+
* invoked, which is the one rule every source shares. What being finished with
|
|
23
|
+
* means is the source's own, and so is what a pattern reads a record as, so
|
|
24
|
+
* both are handed in.
|
|
25
|
+
*/
|
|
26
|
+
export declare function simLambdaFilteredDelivery<RecordType, Outcome>(properties: SimLambdaFilteredDeliveryProperties<RecordType, Outcome>): Promise<Outcome>;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { simLambdaFilteredRecords } from "./sim-lambda-filtered-records.js";
|
|
2
|
+
/**
|
|
3
|
+
* Deliver the records of a batch a mapping's filters let through.
|
|
4
|
+
*
|
|
5
|
+
* A batch the filters emptied is finished with and the function is never
|
|
6
|
+
* invoked, which is the one rule every source shares. What being finished with
|
|
7
|
+
* means is the source's own, and so is what a pattern reads a record as, so
|
|
8
|
+
* both are handed in.
|
|
9
|
+
*/
|
|
10
|
+
export async function simLambdaFilteredDelivery(properties) {
|
|
11
|
+
const delivered = simLambdaFilteredRecords(properties.criteria, properties.records, properties.documentOf);
|
|
12
|
+
return delivered.length === 0
|
|
13
|
+
? properties.handled()
|
|
14
|
+
: await properties.invoke(delivered);
|
|
15
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { SimLambdaFilterCriteria } from "./sim-lambda-filter-criteria.js";
|
|
2
|
+
/**
|
|
3
|
+
* The records of a batch a mapping's filters let through.
|
|
4
|
+
*
|
|
5
|
+
* A mapping with no criteria delivers the batch it read. One with criteria
|
|
6
|
+
* delivers the records that match, and treats the rest as handled: a stream
|
|
7
|
+
* moves its checkpoint past them and a queue deletes them, which is what real
|
|
8
|
+
* Lambda does with a record it filtered out.
|
|
9
|
+
*
|
|
10
|
+
* What a pattern reads is the record as the function would have received it,
|
|
11
|
+
* with the source's own data field decoded. That translation is the source's,
|
|
12
|
+
* so it is handed in.
|
|
13
|
+
*/
|
|
14
|
+
export declare function simLambdaFilteredRecords<RecordType>(criteria: SimLambdaFilterCriteria | undefined, records: readonly RecordType[], documentOf: (record: RecordType) => Record<string, unknown>): readonly RecordType[];
|
|
15
|
+
/**
|
|
16
|
+
* The JSON a data field holds, or the text it is when it holds no JSON.
|
|
17
|
+
*
|
|
18
|
+
* Real Lambda filters a record's data only when both the data and the pattern
|
|
19
|
+
* for it are JSON. Text that parses is handed to the pattern as the object it
|
|
20
|
+
* parses to, and text that does not is handed over as itself, which a pattern
|
|
21
|
+
* written for an object then fails to match. Either way the record is dropped
|
|
22
|
+
* exactly where AWS drops it.
|
|
23
|
+
*/
|
|
24
|
+
export declare function simLambdaFilterData(text: string): unknown;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The records of a batch a mapping's filters let through.
|
|
3
|
+
*
|
|
4
|
+
* A mapping with no criteria delivers the batch it read. One with criteria
|
|
5
|
+
* delivers the records that match, and treats the rest as handled: a stream
|
|
6
|
+
* moves its checkpoint past them and a queue deletes them, which is what real
|
|
7
|
+
* Lambda does with a record it filtered out.
|
|
8
|
+
*
|
|
9
|
+
* What a pattern reads is the record as the function would have received it,
|
|
10
|
+
* with the source's own data field decoded. That translation is the source's,
|
|
11
|
+
* so it is handed in.
|
|
12
|
+
*/
|
|
13
|
+
export function simLambdaFilteredRecords(criteria, records, documentOf) {
|
|
14
|
+
if (criteria === undefined) {
|
|
15
|
+
return records;
|
|
16
|
+
}
|
|
17
|
+
return records.filter((record) => criteria.matches(documentOf(record)));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The JSON a data field holds, or the text it is when it holds no JSON.
|
|
21
|
+
*
|
|
22
|
+
* Real Lambda filters a record's data only when both the data and the pattern
|
|
23
|
+
* for it are JSON. Text that parses is handed to the pattern as the object it
|
|
24
|
+
* parses to, and text that does not is handed over as itself, which a pattern
|
|
25
|
+
* written for an object then fails to match. Either way the record is dropped
|
|
26
|
+
* exactly where AWS drops it.
|
|
27
|
+
*/
|
|
28
|
+
export function simLambdaFilterData(text) {
|
|
29
|
+
try {
|
|
30
|
+
return JSON.parse(text);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return text;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -31,22 +31,25 @@ export declare class SimLambdaKinesisShardPoller implements SimLambdaEventSource
|
|
|
31
31
|
private readonly delivery;
|
|
32
32
|
private readonly progress;
|
|
33
33
|
private readonly turn;
|
|
34
|
-
private stopped;
|
|
35
34
|
constructor(properties: SimLambdaKinesisShardPollerProperties);
|
|
36
35
|
/** Poll this shard as soon as the simulation gets to it. */
|
|
37
36
|
pollNow(): void;
|
|
38
37
|
/** Stop polling this shard. */
|
|
39
38
|
stop(): void;
|
|
40
39
|
/**
|
|
41
|
-
* Note a record put onto the stream,
|
|
42
|
-
*
|
|
40
|
+
* Note a record put onto the stream, which counts only while this shard is
|
|
41
|
+
* mid-delivery.
|
|
43
42
|
*/
|
|
44
|
-
noteRecordWritten():
|
|
43
|
+
noteRecordWritten(): void;
|
|
45
44
|
/**
|
|
46
45
|
* Read one batch off this shard, deliver it, and decide what happens next.
|
|
47
46
|
*
|
|
48
47
|
* Only ever called through the turn, which is what keeps two polls from
|
|
49
48
|
* reading the same records.
|
|
49
|
+
*
|
|
50
|
+
* A refused shard polls no further. Its checkpoint stayed where the refused
|
|
51
|
+
* delivery found it, and reading on from there would deliver those records
|
|
52
|
+
* again.
|
|
50
53
|
*/
|
|
51
54
|
poll(): Promise<void>;
|
|
52
55
|
}
|
|
@@ -23,7 +23,6 @@ export class SimLambdaKinesisShardPoller {
|
|
|
23
23
|
delivery;
|
|
24
24
|
progress;
|
|
25
25
|
turn = new SimLambdaEventSourcePollTurn(this);
|
|
26
|
-
stopped = false;
|
|
27
26
|
constructor(properties) {
|
|
28
27
|
this.mapping = properties.mapping;
|
|
29
28
|
this.functions = properties.functions;
|
|
@@ -43,23 +42,27 @@ export class SimLambdaKinesisShardPoller {
|
|
|
43
42
|
}
|
|
44
43
|
/** Stop polling this shard. */
|
|
45
44
|
stop() {
|
|
46
|
-
this.
|
|
45
|
+
this.delivery.stop();
|
|
47
46
|
}
|
|
48
47
|
/**
|
|
49
|
-
* Note a record put onto the stream,
|
|
50
|
-
*
|
|
48
|
+
* Note a record put onto the stream, which counts only while this shard is
|
|
49
|
+
* mid-delivery.
|
|
51
50
|
*/
|
|
52
51
|
noteRecordWritten() {
|
|
53
|
-
|
|
52
|
+
this.delivery.noteRecordWritten();
|
|
54
53
|
}
|
|
55
54
|
/**
|
|
56
55
|
* Read one batch off this shard, deliver it, and decide what happens next.
|
|
57
56
|
*
|
|
58
57
|
* Only ever called through the turn, which is what keeps two polls from
|
|
59
58
|
* reading the same records.
|
|
59
|
+
*
|
|
60
|
+
* A refused shard polls no further. Its checkpoint stayed where the refused
|
|
61
|
+
* delivery found it, and reading on from there would deliver those records
|
|
62
|
+
* again.
|
|
60
63
|
*/
|
|
61
64
|
async poll() {
|
|
62
|
-
const simFunction = simLambdaEventSourceFunction(this.functions, this.mapping, this.stopped);
|
|
65
|
+
const simFunction = simLambdaEventSourceFunction(this.functions, this.mapping, this.delivery.stopped);
|
|
63
66
|
if (simFunction === undefined) {
|
|
64
67
|
return;
|
|
65
68
|
}
|
package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-stream-delivery.d.ts
CHANGED
|
@@ -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 { SimLambdaKinesisEventSourceArn } from "../../stream/kinesis/sim-lambda-kinesis-event-source-arn.js";
|
|
4
4
|
import type { SimLambdaKinesisStreamRecord } from "../../stream/kinesis/sim-lambda-kinesis-streams.js";
|
|
5
|
-
import
|
|
5
|
+
import { SimLambdaStreamBatchOutcome } from "../sim-lambda-stream-batch-outcome.js";
|
|
6
6
|
interface SimLambdaKinesisStreamDeliveryProperties {
|
|
7
7
|
readonly mapping: SimLambdaEventSourceMapping;
|
|
8
8
|
readonly eventSourceArn: SimLambdaKinesisEventSourceArn;
|
|
@@ -24,16 +24,28 @@ export declare class SimLambdaKinesisStreamDelivery {
|
|
|
24
24
|
private readonly eventBuilder;
|
|
25
25
|
private readonly batchResponse;
|
|
26
26
|
private readonly cascade;
|
|
27
|
+
private readonly halt;
|
|
28
|
+
private readonly filterCriteria;
|
|
27
29
|
constructor(properties: SimLambdaKinesisStreamDeliveryProperties);
|
|
28
30
|
/**
|
|
29
31
|
* Deliver a batch, answering with what became of it.
|
|
30
32
|
*/
|
|
31
33
|
to(simFunction: SimLambdaFunction, records: readonly SimLambdaKinesisStreamRecord[]): Promise<SimLambdaStreamBatchOutcome>;
|
|
32
34
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
+
* Whether this shard has finished polling, which stopping it and refusing it
|
|
36
|
+
* both settle.
|
|
35
37
|
*/
|
|
36
|
-
|
|
38
|
+
get stopped(): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Finish this shard, as stopping the mapping does.
|
|
41
|
+
*/
|
|
42
|
+
stop(): void;
|
|
43
|
+
/**
|
|
44
|
+
* Note a record put onto the polled stream, which counts only while this
|
|
45
|
+
* mapping's own function is running.
|
|
46
|
+
*/
|
|
47
|
+
noteRecordWritten(): void;
|
|
37
48
|
private handled;
|
|
49
|
+
private invoked;
|
|
38
50
|
}
|
|
39
51
|
export {};
|
|
@@ -1,6 +1,9 @@
|
|
|
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 { countSimLambdaKinesisIteratorAge } from "../sim-lambda-stream-iterator-age.js";
|
|
3
|
-
import { simLambdaKinesisStreamRecordTimes } from "../sim-lambda-stream-record-times.js";
|
|
5
|
+
import { simLambdaKinesisStreamRecordTimes, } from "../sim-lambda-stream-record-times.js";
|
|
6
|
+
import { SimLambdaStreamBatchOutcome } from "../sim-lambda-stream-batch-outcome.js";
|
|
4
7
|
import { SimLambdaStreamBatchResponse } from "../sim-lambda-stream-batch-response.js";
|
|
5
8
|
import { SimLambdaKinesisStreamEventBuilder } from "./sim-lambda-kinesis-stream-event.js";
|
|
6
9
|
/**
|
|
@@ -18,8 +21,11 @@ export class SimLambdaKinesisStreamDelivery {
|
|
|
18
21
|
eventBuilder;
|
|
19
22
|
batchResponse;
|
|
20
23
|
cascade;
|
|
24
|
+
halt = new SimLambdaStreamHalt();
|
|
25
|
+
filterCriteria;
|
|
21
26
|
constructor(properties) {
|
|
22
27
|
const { eventSourceArn } = properties;
|
|
28
|
+
this.filterCriteria = properties.mapping.filterCriteria;
|
|
23
29
|
this.eventBuilder = new SimLambdaKinesisStreamEventBuilder({
|
|
24
30
|
eventSourceArn,
|
|
25
31
|
shardId: properties.shardId,
|
|
@@ -28,6 +34,7 @@ export class SimLambdaKinesisStreamDelivery {
|
|
|
28
34
|
this.batchResponse = new SimLambdaStreamBatchResponse(properties.mapping.reportsBatchItemFailures);
|
|
29
35
|
this.cascade = new SimLambdaStreamCascadeGuard({
|
|
30
36
|
mapping: properties.mapping,
|
|
37
|
+
halt: this.halt,
|
|
31
38
|
source: {
|
|
32
39
|
streamArn: eventSourceArn.value,
|
|
33
40
|
wroteTo: `put a record onto the stream ${eventSourceArn.streamName}`,
|
|
@@ -43,16 +50,40 @@ export class SimLambdaKinesisStreamDelivery {
|
|
|
43
50
|
return await this.cascade.around(async () => await this.handled(simFunction, records));
|
|
44
51
|
}
|
|
45
52
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
53
|
+
* Whether this shard has finished polling, which stopping it and refusing it
|
|
54
|
+
* both settle.
|
|
55
|
+
*/
|
|
56
|
+
get stopped() {
|
|
57
|
+
return this.halt.stopped;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Finish this shard, as stopping the mapping does.
|
|
61
|
+
*/
|
|
62
|
+
stop() {
|
|
63
|
+
this.halt.stop();
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Note a record put onto the polled stream, which counts only while this
|
|
67
|
+
* mapping's own function is running.
|
|
48
68
|
*/
|
|
49
69
|
noteRecordWritten() {
|
|
50
|
-
|
|
70
|
+
this.cascade.noteRecordWritten();
|
|
51
71
|
}
|
|
52
72
|
async handled(simFunction, records) {
|
|
53
73
|
const times = simLambdaKinesisStreamRecordTimes(records);
|
|
74
|
+
return await simLambdaFilteredDelivery({
|
|
75
|
+
criteria: this.filterCriteria,
|
|
76
|
+
records,
|
|
77
|
+
documentOf: (record) => this.eventBuilder.filterDocumentOf(record),
|
|
78
|
+
// A batch the filters emptied is finished with even though the function
|
|
79
|
+
// never saw it, as a filtered record advances a real checkpoint too.
|
|
80
|
+
handled: () => SimLambdaStreamBatchOutcome.handled(times),
|
|
81
|
+
invoke: async (delivered) => await this.invoked(simFunction, delivered, times, records),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
async invoked(simFunction, delivered, times, records) {
|
|
54
85
|
try {
|
|
55
|
-
return this.batchResponse.handled(times, await simFunction.invoke(this.eventBuilder.of(
|
|
86
|
+
return this.batchResponse.handled(times, await simFunction.invoke(this.eventBuilder.of(delivered)));
|
|
56
87
|
}
|
|
57
88
|
catch {
|
|
58
89
|
// As on real Lambda, the handler error goes to the function's logs. What
|
|
@@ -51,9 +51,10 @@ export declare class SimLambdaKinesisStreamEventSourcePoller implements SimLambd
|
|
|
51
51
|
* Take a record arriving on the stream as something to poll for.
|
|
52
52
|
*
|
|
53
53
|
* A record put while this mapping's own function is running is the function
|
|
54
|
-
* writing back into its own source stream.
|
|
55
|
-
*
|
|
56
|
-
*
|
|
54
|
+
* writing back into its own source stream. The delivery it brings on is what
|
|
55
|
+
* settles the work or carries the chain on, so the mapping polls for it
|
|
56
|
+
* either way and the guard counts the chain. Every shard is told, and only
|
|
57
|
+
* the one that is mid-delivery counts it.
|
|
57
58
|
*/
|
|
58
59
|
recordsAvailable(): void;
|
|
59
60
|
/**
|
|
@@ -58,15 +58,14 @@ export class SimLambdaKinesisStreamEventSourcePoller {
|
|
|
58
58
|
* Take a record arriving on the stream as something to poll for.
|
|
59
59
|
*
|
|
60
60
|
* A record put while this mapping's own function is running is the function
|
|
61
|
-
* writing back into its own source stream.
|
|
62
|
-
*
|
|
63
|
-
*
|
|
61
|
+
* writing back into its own source stream. The delivery it brings on is what
|
|
62
|
+
* settles the work or carries the chain on, so the mapping polls for it
|
|
63
|
+
* either way and the guard counts the chain. Every shard is told, and only
|
|
64
|
+
* the one that is mid-delivery counts it.
|
|
64
65
|
*/
|
|
65
66
|
recordsAvailable() {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
this.stop();
|
|
69
|
-
return;
|
|
67
|
+
for (const shardPoller of this.shardPollers.made) {
|
|
68
|
+
shardPoller.noteRecordWritten();
|
|
70
69
|
}
|
|
71
70
|
this.schedule.now();
|
|
72
71
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { SimLambdaKinesisEventSourceArn } from "../../stream/kinesis/sim-lambda-kinesis-event-source-arn.js";
|
|
2
2
|
import type { SimLambdaKinesisStreamRecord } from "../../stream/kinesis/sim-lambda-kinesis-streams.js";
|
|
3
|
-
import type { SimLambdaKinesisStreamEvent } from "./sim-lambda-kinesis-stream-event.types.js";
|
|
3
|
+
import type { SimLambdaKinesisStreamEvent, SimLambdaKinesisStreamEventRecord } from "./sim-lambda-kinesis-stream-event.types.js";
|
|
4
4
|
interface SimLambdaKinesisStreamEventBuilderProperties {
|
|
5
5
|
readonly eventSourceArn: SimLambdaKinesisEventSourceArn;
|
|
6
6
|
readonly shardId: string;
|
|
@@ -27,6 +27,15 @@ export declare class SimLambdaKinesisStreamEventBuilder {
|
|
|
27
27
|
* The event for a batch of records.
|
|
28
28
|
*/
|
|
29
29
|
of(records: readonly SimLambdaKinesisStreamRecord[]): SimLambdaKinesisStreamEvent;
|
|
30
|
+
/**
|
|
31
|
+
* What a mapping's filters read one record as.
|
|
32
|
+
*
|
|
33
|
+
* The event record carries the payload base64 encoded under `kinesis`, and a
|
|
34
|
+
* Lambda filter pattern addresses it as JSON under a top-level `data`. Both
|
|
35
|
+
* are here, so a pattern can name the payload the way AWS documents it and
|
|
36
|
+
* the record's metadata the way the event carries it.
|
|
37
|
+
*/
|
|
38
|
+
filterDocumentOf(record: SimLambdaKinesisStreamRecord): Record<string, unknown>;
|
|
30
39
|
/**
|
|
31
40
|
* The identifier one record is named by in the event.
|
|
32
41
|
*
|
|
@@ -35,6 +44,9 @@ export declare class SimLambdaKinesisStreamEventBuilder {
|
|
|
35
44
|
* one shard.
|
|
36
45
|
*/
|
|
37
46
|
eventIdOf(record: SimLambdaKinesisStreamRecord): string;
|
|
38
|
-
|
|
47
|
+
/**
|
|
48
|
+
* The event record one polled record becomes.
|
|
49
|
+
*/
|
|
50
|
+
recordOf(record: SimLambdaKinesisStreamRecord): SimLambdaKinesisStreamEventRecord;
|
|
39
51
|
}
|
|
40
52
|
export {};
|