Skip to content

Commit 798ffb6

Browse files
committed
add support for provisionConcurrency, reservedConcurrency & lambda layers
1 parent 6306d42 commit 798ffb6

File tree

7 files changed

+80
-5
lines changed

7 files changed

+80
-5
lines changed

@generated/schemas/config-schema.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

@generated/schemas/validate-config-schema.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

_test-stacks/simple-lambda/stacktape.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ export default defineConfig(() => {
1111
enabled: true
1212
}
1313
},
14+
provisionedConcurrency: 1,
1415
transforms: {
1516
lambda: (props) => {
1617
return {
1718
...props,
1819
MemorySize: (props.MemorySize ?? 128) * 2,
1920
Description: 'This is a test lambda',
21+
Layers: ['arn:aws:lambda:us-east-1:123456789012:layer:my-layer:1'],
2022
}
2123
}
2224
}

src/domain/calculated-stack-overview-manager/resource-resolvers/functions/index.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@ export const resolveFunction = ({ lambdaProps }: { lambdaProps: StpLambdaFunctio
101101
volumeMounts,
102102
type,
103103
cdn,
104-
architecture
104+
architecture,
105+
provisionedConcurrency,
106+
reservedConcurrency,
107+
layers
105108
} = lambdaProps;
106109

107110
if (nameChain[0] !== PARENT_IDENTIFIER_SHARED_GLOBAL) {
@@ -278,6 +281,27 @@ export const resolveFunction = ({ lambdaProps }: { lambdaProps: StpLambdaFunctio
278281
});
279282
}
280283
}
284+
if (layers) {
285+
lambdaFunctionResource.Properties.Layers = layers;
286+
}
287+
if (reservedConcurrency) {
288+
lambdaFunctionResource.Properties.ReservedConcurrentExecutions = reservedConcurrency;
289+
}
290+
// Provisioned concurrency requires an alias pointing to a specific version.
291+
// If deployment is configured, alias is already created (with code deploy), so we just add provisioned concurrency to it.
292+
// If no deployment, we create version + alias specifically for provisioned concurrency.
293+
if (provisionedConcurrency && !deployment) {
294+
calculatedStackOverviewManager.addCfChildResource({
295+
nameChain,
296+
cfLogicalName: cfLogicalNames.lambdaVersionPublisherCustomResource(name),
297+
resource: getLambdaVersionPublisherCustomResource({ lambdaProps })
298+
});
299+
calculatedStackOverviewManager.addCfChildResource({
300+
nameChain,
301+
cfLogicalName: cfLogicalNames.lambdaStpAlias(name),
302+
resource: getLambdaAliasResource({ lambdaProps, provisionedConcurrency })
303+
});
304+
}
281305
if (
282306
!joinDefaultVpc &&
283307
accessToAtlasMongoClusterResources.length &&

src/domain/calculated-stack-overview-manager/resource-resolvers/functions/utils.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,15 +150,23 @@ export const getLambdaFunctionRole = ({
150150
};
151151

152152
export const getLambdaAliasResource = ({
153-
lambdaProps
153+
lambdaProps,
154+
provisionedConcurrency
154155
}: {
155156
lambdaProps: StpLambdaFunction | StpHelperLambdaFunction;
157+
provisionedConcurrency?: number;
156158
}) => {
157159
const resource = new Alias({
158160
FunctionName: Ref(lambdaProps.cfLogicalName),
159161
FunctionVersion: GetAtt(cfLogicalNames.lambdaVersionPublisherCustomResource(lambdaProps.name), 'version'),
160162
Name: awsResourceNames.lambdaStpAlias()
161163
});
164+
const effectiveProvisionedConcurrency = provisionedConcurrency ?? lambdaProps.provisionedConcurrency;
165+
if (effectiveProvisionedConcurrency) {
166+
resource.Properties.ProvisionedConcurrencyConfig = {
167+
ProvisionedConcurrentExecutions: effectiveProvisionedConcurrency
168+
};
169+
}
162170
if (lambdaProps.deployment) {
163171
resource.UpdatePolicy = {
164172
CodeDeployLambdaAliasUpdate: {

src/domain/config-manager/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ export class ConfigManager {
274274
handler: getLambdaHandler({ name, packaging }),
275275
resourceName: awsResourceNames.lambda(name, globalStateManager.targetStack.stackName),
276276
cfLogicalName: cfLogicalNames.lambda(name),
277-
aliasLogicalName: definition.deployment && cfLogicalNames.lambdaStpAlias(name),
277+
aliasLogicalName: (definition.deployment || definition.provisionedConcurrency) && cfLogicalNames.lambdaStpAlias(name),
278278
events: definition.events || [],
279279
configParentResourceType: 'function'
280280
} as StpLambdaFunction;

types/stacktape-config/functions.d.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,47 @@ interface LambdaFunctionProps extends ResourceAccessProps {
147147
* - Using the `stacktape logs` command to stream logs directly to your terminal.
148148
*/
149149
logging?: LambdaFunctionLogging;
150+
/**
151+
* #### Configures the provisioned concurrency for the function.
152+
*
153+
* ---
154+
*
155+
* This is the number of pre-initialized execution environments allocated to your function.
156+
* These execution environments are ready to respond immediately to incoming function requests.
157+
* Provisioned concurrency is useful for reducing cold start latencies for functions and designed to make functions available with double-digit millisecond response times.
158+
* Generally, interactive workloads benefit the most from the feature.
159+
* Those are applications with users initiating requests, such as web and mobile applications, and are the most sensitive to latency.
160+
* Asynchronous workloads, such as data processing pipelines, are often less latency sensitive and so do not usually need provisioned concurrency.
161+
* Configuring provisioned concurrency incurs additional charges to your AWS account.
162+
*/
163+
provisionedConcurrency?: number;
164+
/**
165+
* #### Configures the reserved concurrency for the function.
166+
*
167+
* ---
168+
*
169+
* This sets both the maximum and minimum number of concurrent instances allocated to your function.
170+
* When a function has reserved concurrency, no other function can use that concurrency.
171+
* Reserved concurrency is useful for ensuring that your most critical functions always have enough concurrency to handle incoming requests.
172+
* Additionally, reserved concurrency can be used for limiting concurrency to prevent overwhelming downstream resources, like database connections.
173+
* Reserved concurrency acts as both a lower and upper bound - it reserves the specified capacity exclusively for your function while also preventing it from scaling beyond that limit.
174+
* Configuring reserved concurrency for a function incurs no additional charges.
175+
*/
176+
reservedConcurrency?: number;
177+
/**
178+
* #### A list of layers to add to the function.
179+
*
180+
* ---
181+
*
182+
* A Lambda layer is a .zip file archive that contains supplementary code or data.
183+
* Layers usually contain library dependencies, a custom runtime, or configuration files.
184+
*
185+
* Using layers:
186+
* 1. Package your layer content. This means creating a .zip file archive. For more information, see [Packaging your layer content](https://docs.aws.amazon.com/lambda/latest/dg/packaging-layers.html).
187+
* 2. Create the layer in Lambda. For more information, see [Creating and deleting layers in Lambda](https://docs.aws.amazon.com/lambda/latest/dg/creating-deleting-layers.html)
188+
* 3. Get the layer ARN and put it in the `layers` property of the function.
189+
*/
190+
layers?: string[];
150191
/**
151192
* #### Configures the deployment strategy for updating the function.
152193
*

0 commit comments

Comments
 (0)