async-lambda-unstable 0.6.12__tar.gz → 0.6.13__tar.gz
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.
- async_lambda_unstable-0.6.12/README.md → async_lambda_unstable-0.6.13/PKG-INFO +31 -0
- async_lambda_unstable-0.6.12/PKG-INFO → async_lambda_unstable-0.6.13/README.md +19 -12
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/__init__.py +2 -1
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/config.py +18 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/controller.py +166 -31
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/task.py +25 -14
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/.gitignore +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/build_config.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/cli.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/client.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/defer.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/env.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/middleware.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/__init__.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/api_response.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/case_insensitive_dict.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/events/__init__.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/events/api_event.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/events/base_event.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/events/dynamodb_event.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/events/managed_sqs_batch_event.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/events/managed_sqs_event.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/events/scheduled_event.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/events/unmanaged_sqs_event.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/mock/mock_context.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/mock/mock_event.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/payload_encoder.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/py.typed +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/util.py +0 -0
- {async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/pyproject.toml +0 -0
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: async-lambda-unstable
|
|
3
|
+
Version: 0.6.13
|
|
4
|
+
Summary: A framework for creating AWS Lambda Async Workflows. - Unstable Branch
|
|
5
|
+
Author-email: "Nuclei, Inc" <engineering@nuclei.ai>
|
|
6
|
+
Requires-Dist: click>=8.0.0
|
|
7
|
+
Requires-Dist: typing-extensions>=4.0.0
|
|
8
|
+
Provides-Extra: local
|
|
9
|
+
Requires-Dist: boto3; extra == 'local'
|
|
10
|
+
Requires-Dist: flask<3.0.0,>=2.3.0; extra == 'local'
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
1
13
|
# async-lambda
|
|
2
14
|
|
|
3
15
|
Async-lambda is a Python framework for building scalable, event-driven AWS Lambda applications with first-class support for asynchronous invocation via SQS queues. It provides a high-level abstraction for orchestrating Lambda functions, managing event triggers, and handling complex workflows with minimal boilerplate.
|
|
@@ -406,6 +418,25 @@ def task(event: ManagedSQSEvent):
|
|
|
406
418
|
...
|
|
407
419
|
```
|
|
408
420
|
|
|
421
|
+
### Shared Function Role
|
|
422
|
+
|
|
423
|
+
By default each task declares `Policies`, so SAM generates one `AWS::IAM::Role` per task.
|
|
424
|
+
|
|
425
|
+
`config_set_shared_function_role()` emits a single `AsyncLambdaSharedFunctionRole` and points every task's `Role` at it instead:
|
|
426
|
+
|
|
427
|
+
```python
|
|
428
|
+
from async_lambda import config_set_shared_function_role
|
|
429
|
+
|
|
430
|
+
config_set_shared_function_role()
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
The shared role carries everything the per-task roles carried, with one difference: SQS consume access is granted on the app's queue-name prefix (`{name}-*`) rather than each task's own queues. Unmanaged SQS queues are still listed individually, since they're named by their producer.
|
|
434
|
+
|
|
435
|
+
Two caveats:
|
|
436
|
+
|
|
437
|
+
- A task with task-specific `policies` keeps its own generated role, since the shared role is built from app-wide and stage-wide config only.
|
|
438
|
+
- Every app-wide policy must be either a managed policy ARN or a `{"Statement": [...]}` document. SAM policy templates can't be expressed in a plain IAM role and will fail the build.
|
|
439
|
+
|
|
409
440
|
## Known Limitations
|
|
410
441
|
|
|
411
442
|
- Not all Lambda configuration options are supported (see code for extension points)
|
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: async-lambda-unstable
|
|
3
|
-
Version: 0.6.12
|
|
4
|
-
Summary: A framework for creating AWS Lambda Async Workflows. - Unstable Branch
|
|
5
|
-
Author-email: "Nuclei, Inc" <engineering@nuclei.ai>
|
|
6
|
-
Requires-Dist: click>=8.0.0
|
|
7
|
-
Requires-Dist: typing-extensions>=4.0.0
|
|
8
|
-
Provides-Extra: local
|
|
9
|
-
Requires-Dist: boto3; extra == 'local'
|
|
10
|
-
Requires-Dist: flask<3.0.0,>=2.3.0; extra == 'local'
|
|
11
|
-
Description-Content-Type: text/markdown
|
|
12
|
-
|
|
13
1
|
# async-lambda
|
|
14
2
|
|
|
15
3
|
Async-lambda is a Python framework for building scalable, event-driven AWS Lambda applications with first-class support for asynchronous invocation via SQS queues. It provides a high-level abstraction for orchestrating Lambda functions, managing event triggers, and handling complex workflows with minimal boilerplate.
|
|
@@ -418,6 +406,25 @@ def task(event: ManagedSQSEvent):
|
|
|
418
406
|
...
|
|
419
407
|
```
|
|
420
408
|
|
|
409
|
+
### Shared Function Role
|
|
410
|
+
|
|
411
|
+
By default each task declares `Policies`, so SAM generates one `AWS::IAM::Role` per task.
|
|
412
|
+
|
|
413
|
+
`config_set_shared_function_role()` emits a single `AsyncLambdaSharedFunctionRole` and points every task's `Role` at it instead:
|
|
414
|
+
|
|
415
|
+
```python
|
|
416
|
+
from async_lambda import config_set_shared_function_role
|
|
417
|
+
|
|
418
|
+
config_set_shared_function_role()
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
The shared role carries everything the per-task roles carried, with one difference: SQS consume access is granted on the app's queue-name prefix (`{name}-*`) rather than each task's own queues. Unmanaged SQS queues are still listed individually, since they're named by their producer.
|
|
422
|
+
|
|
423
|
+
Two caveats:
|
|
424
|
+
|
|
425
|
+
- A task with task-specific `policies` keeps its own generated role, since the shared role is built from app-wide and stage-wide config only.
|
|
426
|
+
- Every app-wide policy must be either a managed policy ARN or a `{"Statement": [...]}` document. SAM policy templates can't be expressed in a plain IAM role and will fail the build.
|
|
427
|
+
|
|
421
428
|
## Known Limitations
|
|
422
429
|
|
|
423
430
|
- Not all Lambda configuration options are supported (see code for extension points)
|
|
@@ -2,6 +2,7 @@ from .config import config_set_default_task_memory as config_set_default_task_me
|
|
|
2
2
|
from .config import config_set_name as config_set_name
|
|
3
3
|
from .config import config_set_runtime as config_set_runtime
|
|
4
4
|
from .config import config_set_s3_payload_retention as config_set_s3_payload_retention
|
|
5
|
+
from .config import config_set_shared_function_role as config_set_shared_function_role
|
|
5
6
|
from .controller import AsyncLambdaController as AsyncLambdaController
|
|
6
7
|
from .controller import BatchInvokeException as BatchInvokeException
|
|
7
8
|
from .defer import Defer as Defer
|
|
@@ -21,4 +22,4 @@ from .models.events.managed_sqs_event import ManagedSQSEvent as ManagedSQSEvent
|
|
|
21
22
|
from .models.events.scheduled_event import ScheduledEvent as ScheduledEvent
|
|
22
23
|
from .models.events.unmanaged_sqs_event import UnmanagedSQSEvent as UnmanagedSQSEvent
|
|
23
24
|
|
|
24
|
-
__version__ = "0.6.
|
|
25
|
+
__version__ = "0.6.13"
|
|
@@ -11,6 +11,7 @@ class AsyncLambdaConfig:
|
|
|
11
11
|
s3_payload_retention (int): Days to retain payloads in S3. Defaults to 30.
|
|
12
12
|
default_task_memory (int): Default memory allocation (MB) for tasks. Defaults to 128.
|
|
13
13
|
default_task_ephemeral_storage (int): Default disk allocation (MB) for tasks. Defaults to 512.
|
|
14
|
+
shared_function_role (bool): Whether tasks share a single execution role. Defaults to False.
|
|
14
15
|
"""
|
|
15
16
|
|
|
16
17
|
name: str = "async-lambda"
|
|
@@ -18,6 +19,7 @@ class AsyncLambdaConfig:
|
|
|
18
19
|
s3_payload_retention: Optional[int] = 180
|
|
19
20
|
default_task_memory: int = 128
|
|
20
21
|
default_task_ephemeral_storage: int = 512
|
|
22
|
+
shared_function_role: bool = False
|
|
21
23
|
|
|
22
24
|
|
|
23
25
|
config = AsyncLambdaConfig()
|
|
@@ -71,3 +73,19 @@ def config_set_default_task_ephemeral_storage(ephemeral_storage: int = 512):
|
|
|
71
73
|
ephemeral_storage (int, optional): Disk storage in megabytes to set as default for tasks. Defaults to 512.
|
|
72
74
|
"""
|
|
73
75
|
config.default_task_ephemeral_storage = ephemeral_storage
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def config_set_shared_function_role(enabled: bool = True):
|
|
79
|
+
"""
|
|
80
|
+
Use a single execution role for every task instead of one role per task.
|
|
81
|
+
|
|
82
|
+
SAM generates an IAM role per function when a function declares `Policies`. Sharing one
|
|
83
|
+
role trades per-task SQS scoping (the shared role can consume any of the app's own queues)
|
|
84
|
+
for one CloudFormation resource instead of one per task.
|
|
85
|
+
|
|
86
|
+
Tasks with task-specific `policies` keep their own role.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
enabled (bool, optional): Whether to share a single execution role. Defaults to True.
|
|
90
|
+
"""
|
|
91
|
+
config.shared_function_role = enabled
|
|
@@ -20,7 +20,7 @@ from typing import (
|
|
|
20
20
|
from uuid import uuid4
|
|
21
21
|
|
|
22
22
|
from . import env
|
|
23
|
-
from .build_config import get_build_config_for_stage
|
|
23
|
+
from .build_config import AsyncLambdaBuildConfig, get_build_config_for_stage
|
|
24
24
|
from .client import get_s3_client, get_scheduler_client, get_sqs_client
|
|
25
25
|
from .config import config
|
|
26
26
|
from .middleware import MET, RT, MiddlewareFunction, MiddlewareRegistration
|
|
@@ -33,7 +33,12 @@ from .models.events.scheduled_event import ScheduledEvent
|
|
|
33
33
|
from .models.events.unmanaged_sqs_event import UnmanagedSQSEvent
|
|
34
34
|
from .models.mock.mock_context import MockLambdaContext
|
|
35
35
|
from .models.mock.mock_event import MockSQSLambdaEvent
|
|
36
|
-
from .models.task import
|
|
36
|
+
from .models.task import (
|
|
37
|
+
MANAGED_SQS_TASK_TYPES,
|
|
38
|
+
SHARED_FUNCTION_ROLE_LOGICAL_ID,
|
|
39
|
+
AsyncLambdaTask,
|
|
40
|
+
TaskTriggerType,
|
|
41
|
+
)
|
|
37
42
|
from .payload_encoder import PayloadEncoder
|
|
38
43
|
from .util import make_cf_tags
|
|
39
44
|
|
|
@@ -180,32 +185,26 @@ class AsyncLambdaController:
|
|
|
180
185
|
self.delete_s3_payloads = delete_s3_payloads
|
|
181
186
|
self.controller_name = controller_name
|
|
182
187
|
|
|
183
|
-
# itertools.batched is much cleaner but only available in python 3.12+
|
|
184
|
-
@staticmethod
|
|
185
|
-
def _batched(items: Sequence[dict], batch_size: int) -> List[List[dict]]:
|
|
186
|
-
if batch_size <= 0:
|
|
187
|
-
raise ValueError("batch_size must be greater than 0")
|
|
188
|
-
return [
|
|
189
|
-
list(items[i : i + batch_size]) for i in range(0, len(items), batch_size)
|
|
190
|
-
]
|
|
191
|
-
|
|
192
188
|
@classmethod
|
|
193
189
|
def _build_send_to_all_async_lambda_queues_policies(
|
|
194
190
|
cls,
|
|
195
|
-
|
|
196
|
-
policy_batch_size: int = 30,
|
|
191
|
+
queue_resources: List[dict],
|
|
197
192
|
) -> Dict[str, dict]:
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
193
|
+
"""
|
|
194
|
+
Builds the managed policy granting send access to every managed queue in this app.
|
|
195
|
+
|
|
196
|
+
This app's own queues are covered by a single name-prefix wildcard rather than an
|
|
197
|
+
enumeration, so the policy stays one resource and one document regardless of task
|
|
198
|
+
count. External tasks don't share the prefix, so their ARNs are listed explicitly.
|
|
199
|
+
"""
|
|
200
|
+
if len(queue_resources) == 0:
|
|
201
|
+
return {}
|
|
202
|
+
return {
|
|
203
|
+
"SendToAllAsyncLambdaQueuesPolicy": {
|
|
205
204
|
"Type": "AWS::IAM::ManagedPolicy",
|
|
206
205
|
"Properties": {
|
|
207
206
|
"ManagedPolicyName": {
|
|
208
|
-
"Fn::Sub":
|
|
207
|
+
"Fn::Sub": "${AWS::StackName}-send-to-all-queues"
|
|
209
208
|
},
|
|
210
209
|
"PolicyDocument": {
|
|
211
210
|
"Version": "2012-10-17",
|
|
@@ -214,13 +213,142 @@ class AsyncLambdaController:
|
|
|
214
213
|
"Sid": "SendToAllQueues",
|
|
215
214
|
"Effect": "Allow",
|
|
216
215
|
"Action": ["sqs:SendMessage"],
|
|
217
|
-
"Resource":
|
|
216
|
+
"Resource": queue_resources,
|
|
218
217
|
},
|
|
219
218
|
],
|
|
220
219
|
},
|
|
221
220
|
},
|
|
222
221
|
}
|
|
223
|
-
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
@staticmethod
|
|
225
|
+
def _managed_queue_arn_wildcard() -> dict:
|
|
226
|
+
"""
|
|
227
|
+
An ARN pattern matching every managed queue this app creates.
|
|
228
|
+
"""
|
|
229
|
+
return {
|
|
230
|
+
"Fn::Sub": "arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:"
|
|
231
|
+
+ f"{config.name}-*"
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
@classmethod
|
|
235
|
+
def _build_shared_function_role(
|
|
236
|
+
cls,
|
|
237
|
+
task_list: List[AsyncLambdaTask],
|
|
238
|
+
build_config: AsyncLambdaBuildConfig,
|
|
239
|
+
task_ref_policy_ids: List[str],
|
|
240
|
+
) -> dict:
|
|
241
|
+
"""
|
|
242
|
+
Builds a single execution role shared by every task.
|
|
243
|
+
"""
|
|
244
|
+
sqs_resources: List[Union[str, dict]] = []
|
|
245
|
+
if any(task.trigger_type in MANAGED_SQS_TASK_TYPES for task in task_list):
|
|
246
|
+
sqs_resources.append(cls._managed_queue_arn_wildcard())
|
|
247
|
+
# Unmanaged queues are named by whoever produces to them, so they fall outside the
|
|
248
|
+
# app-name prefix and have to be listed.
|
|
249
|
+
sqs_resources.extend(
|
|
250
|
+
resource
|
|
251
|
+
for task in task_list
|
|
252
|
+
if task.trigger_type == TaskTriggerType.UNMANAGED_SQS
|
|
253
|
+
for resource in task.get_policy_sqs_resources()
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
statements: List[dict] = [
|
|
257
|
+
{
|
|
258
|
+
"Effect": "Allow",
|
|
259
|
+
"Action": ["s3:DeleteObject", "s3:PutObject", "s3:GetObject"],
|
|
260
|
+
"Resource": {
|
|
261
|
+
"Fn::Join": [
|
|
262
|
+
"",
|
|
263
|
+
[
|
|
264
|
+
"arn:aws:s3:::",
|
|
265
|
+
{"Ref": "AsyncLambdaPayloadBucket"},
|
|
266
|
+
"/*",
|
|
267
|
+
],
|
|
268
|
+
]
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
]
|
|
272
|
+
if len(sqs_resources) > 0:
|
|
273
|
+
statements.append(
|
|
274
|
+
{
|
|
275
|
+
"Effect": "Allow",
|
|
276
|
+
"Action": [
|
|
277
|
+
"sqs:ChangeMessageVisibility",
|
|
278
|
+
"sqs:DeleteMessage",
|
|
279
|
+
"sqs:GetQueueAttributes",
|
|
280
|
+
"sqs:GetQueueUrl",
|
|
281
|
+
"sqs:ReceiveMessage",
|
|
282
|
+
],
|
|
283
|
+
"Resource": sqs_resources,
|
|
284
|
+
}
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
inline_policies: List[dict] = [
|
|
288
|
+
{
|
|
289
|
+
"PolicyName": "AsyncLambdaTaskPolicy",
|
|
290
|
+
"PolicyDocument": {
|
|
291
|
+
"Version": "2012-10-17",
|
|
292
|
+
"Statement": statements,
|
|
293
|
+
},
|
|
294
|
+
}
|
|
295
|
+
]
|
|
296
|
+
managed_policy_arns: List[Union[str, dict]] = [
|
|
297
|
+
"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
|
|
298
|
+
]
|
|
299
|
+
if "VpcConfig" in build_config.function_properties:
|
|
300
|
+
managed_policy_arns.append(
|
|
301
|
+
"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
|
|
302
|
+
)
|
|
303
|
+
# SAM attaches this to any lambda function with an SQS event source. Without it, they
|
|
304
|
+
# lose their SQS polling permissions.
|
|
305
|
+
if len(sqs_resources) > 0:
|
|
306
|
+
managed_policy_arns.append(
|
|
307
|
+
"arn:aws:iam::aws:policy/service-role/AWSLambdaSQSQueueExecutionRole"
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
for index, policy in enumerate(build_config.policies):
|
|
311
|
+
if isinstance(policy, str):
|
|
312
|
+
managed_policy_arns.append(policy)
|
|
313
|
+
elif isinstance(policy, dict) and set(policy.keys()) == {"Statement"}:
|
|
314
|
+
inline_policies.append(
|
|
315
|
+
{
|
|
316
|
+
"PolicyName": f"AsyncLambdaBuildConfigPolicy{index}",
|
|
317
|
+
"PolicyDocument": {
|
|
318
|
+
"Version": "2012-10-17",
|
|
319
|
+
"Statement": policy["Statement"],
|
|
320
|
+
},
|
|
321
|
+
}
|
|
322
|
+
)
|
|
323
|
+
else:
|
|
324
|
+
raise Exception(
|
|
325
|
+
f"Unable to build a shared function role. The policy {policy!r} is "
|
|
326
|
+
"neither a managed policy ARN nor a single-key 'Statement' document."
|
|
327
|
+
"SAM policy templates cannot be expressed in a plain IAM role."
|
|
328
|
+
"Rewrite the policy in one of those two forms, or turn off config_set_shared_function_role."
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
managed_policy_arns.extend(
|
|
332
|
+
{"Ref": policy_id} for policy_id in task_ref_policy_ids
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
return {
|
|
336
|
+
"Type": "AWS::IAM::Role",
|
|
337
|
+
"Properties": {
|
|
338
|
+
"AssumeRolePolicyDocument": {
|
|
339
|
+
"Version": "2012-10-17",
|
|
340
|
+
"Statement": [
|
|
341
|
+
{
|
|
342
|
+
"Effect": "Allow",
|
|
343
|
+
"Principal": {"Service": ["lambda.amazonaws.com"]},
|
|
344
|
+
"Action": ["sts:AssumeRole"],
|
|
345
|
+
}
|
|
346
|
+
],
|
|
347
|
+
},
|
|
348
|
+
"ManagedPolicyArns": managed_policy_arns,
|
|
349
|
+
"Policies": inline_policies,
|
|
350
|
+
},
|
|
351
|
+
}
|
|
224
352
|
|
|
225
353
|
def add_middleware(
|
|
226
354
|
self, event_types: List[Type[BaseEvent]], func: MiddlewareFunction[MET, RT]
|
|
@@ -525,22 +653,20 @@ class AsyncLambdaController:
|
|
|
525
653
|
},
|
|
526
654
|
}
|
|
527
655
|
_task_list = list(self.tasks.values())
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
for resource in task.get_policy_sqs_resources()
|
|
533
|
-
] + [
|
|
656
|
+
send_all_queue_resources: List[dict] = []
|
|
657
|
+
if any(task.trigger_type in MANAGED_SQS_TASK_TYPES for task in _task_list):
|
|
658
|
+
send_all_queue_resources.append(self._managed_queue_arn_wildcard())
|
|
659
|
+
send_all_queue_resources.extend(
|
|
534
660
|
resource
|
|
535
661
|
for external_async_task_id in self.external_async_tasks
|
|
536
662
|
for resource in AsyncLambdaTask.get_policy_external_task_resources(
|
|
537
663
|
external_async_task_id
|
|
538
664
|
)
|
|
539
|
-
|
|
665
|
+
)
|
|
540
666
|
|
|
541
667
|
send_all_queues_task_ref_policies = (
|
|
542
668
|
self._build_send_to_all_async_lambda_queues_policies(
|
|
543
|
-
|
|
669
|
+
send_all_queue_resources
|
|
544
670
|
)
|
|
545
671
|
)
|
|
546
672
|
for key in send_all_queues_task_ref_policies.keys():
|
|
@@ -593,6 +719,15 @@ class AsyncLambdaController:
|
|
|
593
719
|
],
|
|
594
720
|
}
|
|
595
721
|
|
|
722
|
+
if config.shared_function_role:
|
|
723
|
+
template["Resources"][SHARED_FUNCTION_ROLE_LOGICAL_ID] = (
|
|
724
|
+
self._build_shared_function_role(
|
|
725
|
+
task_list=_task_list,
|
|
726
|
+
build_config=build_config,
|
|
727
|
+
task_ref_policy_ids=list(task_ref_policies.keys()),
|
|
728
|
+
)
|
|
729
|
+
)
|
|
730
|
+
|
|
596
731
|
has_api_tasks = False
|
|
597
732
|
for task in _task_list:
|
|
598
733
|
if task.trigger_type == TaskTriggerType.API_EVENT:
|
|
@@ -57,6 +57,8 @@ MANAGED_SQS_TASK_TYPES = {
|
|
|
57
57
|
TaskTriggerType.MANAGED_SQS_BATCH,
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
SHARED_FUNCTION_ROLE_LOGICAL_ID = "AsyncLambdaSharedFunctionRole"
|
|
61
|
+
|
|
60
62
|
EventType = TypeVar(
|
|
61
63
|
"EventType",
|
|
62
64
|
bound=Union[
|
|
@@ -610,23 +612,32 @@ class AsyncLambdaTask(Generic[EventType, RT]):
|
|
|
610
612
|
*[{"Ref": policy_id} for policy_id in task_ref_policy_ids],
|
|
611
613
|
]
|
|
612
614
|
|
|
615
|
+
function_properties = {
|
|
616
|
+
"Environment": {
|
|
617
|
+
"Variables": {
|
|
618
|
+
"ASYNC_LAMBDA_TASK_ID": self.task_id,
|
|
619
|
+
**override_config.environment_variables,
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
"FunctionName": self.get_function_name(),
|
|
623
|
+
"Timeout": self.timeout,
|
|
624
|
+
"Events": events,
|
|
625
|
+
"CodeUri": ".async_lambda/build/deployment.zip",
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
# cannot use shared role if the task has its own policies
|
|
629
|
+
if config.shared_function_role and len(override_config.policies) == 0:
|
|
630
|
+
function_properties["Role"] = {
|
|
631
|
+
"Fn::GetAtt": [SHARED_FUNCTION_ROLE_LOGICAL_ID, "Arn"]
|
|
632
|
+
}
|
|
633
|
+
else:
|
|
634
|
+
function_properties["Policies"] = policies
|
|
635
|
+
function_properties.update(override_config.function_properties)
|
|
636
|
+
|
|
613
637
|
template = {
|
|
614
638
|
self.get_function_logical_id(): {
|
|
615
639
|
"Type": "AWS::Serverless::Function",
|
|
616
|
-
"Properties":
|
|
617
|
-
"Environment": {
|
|
618
|
-
"Variables": {
|
|
619
|
-
"ASYNC_LAMBDA_TASK_ID": self.task_id,
|
|
620
|
-
**override_config.environment_variables,
|
|
621
|
-
}
|
|
622
|
-
},
|
|
623
|
-
"FunctionName": self.get_function_name(),
|
|
624
|
-
"Timeout": self.timeout,
|
|
625
|
-
"Events": events,
|
|
626
|
-
"Policies": policies,
|
|
627
|
-
"CodeUri": ".async_lambda/build/deployment.zip",
|
|
628
|
-
**override_config.function_properties,
|
|
629
|
-
},
|
|
640
|
+
"Properties": function_properties,
|
|
630
641
|
}
|
|
631
642
|
}
|
|
632
643
|
if self.memory is not None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/__init__.py
RENAMED
|
File without changes
|
{async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/api_response.py
RENAMED
|
File without changes
|
|
File without changes
|
{async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/events/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/models/mock/mock_event.py
RENAMED
|
File without changes
|
{async_lambda_unstable-0.6.12 → async_lambda_unstable-0.6.13}/async_lambda/payload_encoder.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|