async-lambda-unstable 0.3.12__tar.gz → 0.4.3__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.3.12 → async-lambda-unstable-0.4.3}/PKG-INFO +76 -1
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/README.md +75 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/__init__.py +2 -1
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/controller.py +29 -2
- async-lambda-unstable-0.4.3/async_lambda/middleware.py +30 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/task.py +10 -5
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda_unstable.egg-info/PKG-INFO +76 -1
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda_unstable.egg-info/SOURCES.txt +1 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/build_config.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/cli.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/client.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/config.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/defer.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/env.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/__init__.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/case_insensitive_dict.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/events/__init__.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/events/api_event.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/events/base_event.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/events/dynamodb_event.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/events/managed_sqs_event.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/events/scheduled_event.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/events/unmanaged_sqs_event.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/mock/mock_context.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/mock/mock_event.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/py.typed +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/util.py +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda_unstable.egg-info/dependency_links.txt +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda_unstable.egg-info/entry_points.txt +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda_unstable.egg-info/requires.txt +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda_unstable.egg-info/top_level.txt +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/pyproject.toml +0 -0
- {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: async-lambda-unstable
|
|
3
|
-
Version: 0.3
|
|
3
|
+
Version: 0.4.3
|
|
4
4
|
Summary: A framework for creating AWS Lambda Async Workflows. - Unstable Branch
|
|
5
5
|
Author-email: "Nuclei, Inc" <engineering@nuclei.ai>
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -186,8 +186,83 @@ def api_task(event: APIEvent):
|
|
|
186
186
|
event.headers # request headers
|
|
187
187
|
event.querystring_params # request querystring params
|
|
188
188
|
event.body # request body
|
|
189
|
+
event.headers # This is a case insensitive dict
|
|
189
190
|
```
|
|
190
191
|
|
|
192
|
+
# Middleware
|
|
193
|
+
|
|
194
|
+
Middleware functions can be registered with controllers which will wrap the execution of tasks.
|
|
195
|
+
These functions can be configured to trigger on specific types of tasks and can trigger
|
|
196
|
+
side effects and modify the `event` or `response` objects.
|
|
197
|
+
|
|
198
|
+
Middleware functions must have the signature `Callable[[BaseEvent, Callable[[BaseEvent], T]], T]`.
|
|
199
|
+
The first argument is the `event`, and the second argument (`call_next`) is a function which will propagate the
|
|
200
|
+
calls down the middleware/task stack. The `call_next` function must be called, and its result in most cases be returned.
|
|
201
|
+
If this is not done then tasks will not run as expected.
|
|
202
|
+
|
|
203
|
+
**Extreme care should be taken with middleware as a simple mistake can have catastrophic effects.**
|
|
204
|
+
|
|
205
|
+
- Middleware functions are run in the order which they were registered and parent controller middleware will be run first.
|
|
206
|
+
|
|
207
|
+
- Middleware functions which are registered more than once will only be run once.
|
|
208
|
+
|
|
209
|
+
Registration can be done when the `AsyncLambdaController` is initialized with the parameter `middleware` or by using the `add_middleware` method.
|
|
210
|
+
|
|
211
|
+
Middleware functions have three sections:
|
|
212
|
+
|
|
213
|
+
1. Pre task
|
|
214
|
+
2. Task execution
|
|
215
|
+
3. Post task
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
def async_lambda_middleware(event: BaseEvent, call_next):
|
|
219
|
+
# pre task
|
|
220
|
+
result = call_next(event) # task execution
|
|
221
|
+
# post task
|
|
222
|
+
return result
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
If there are multiple middleware functions then `call_next` will actually be calling the next middleware function in the stack.
|
|
226
|
+
|
|
227
|
+
For example if there is middleware functions `A` and `B` registered in that order.
|
|
228
|
+
Then the execution order would go:
|
|
229
|
+
|
|
230
|
+
`A(Pre)` -> `B(Pre)` -> `Task` -> `B(Post)` -> `A(Post)`
|
|
231
|
+
|
|
232
|
+
EX:
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
def async_task_only_middleware(event: ManagedSQSEvent, call_next):
|
|
236
|
+
print(f"Invocation Payload: {event}")
|
|
237
|
+
result = call_next(event)
|
|
238
|
+
print(f"Invocation Result: {result}")
|
|
239
|
+
return result
|
|
240
|
+
|
|
241
|
+
def all_task_types_middleware(event: BaseEvent, call_next):
|
|
242
|
+
print(f"This event is of the type {type(event)}")
|
|
243
|
+
result = call_next(event)
|
|
244
|
+
print(f"The result is of the type {type(result)}")
|
|
245
|
+
return event
|
|
246
|
+
|
|
247
|
+
controller = AsyncLambdaController(middleware=[([BaseEvent], all_task_types_middleware)])
|
|
248
|
+
|
|
249
|
+
controller.add_middleware([ManagedSQSEvent], async_task_only_middleware)
|
|
250
|
+
|
|
251
|
+
@controller.async_task("ATask")
|
|
252
|
+
def a_task(event: ManagedSQSEvent):
|
|
253
|
+
pass
|
|
254
|
+
|
|
255
|
+
@controller.api_task("BTask", "/test", "get")
|
|
256
|
+
def b_task(event: APIEvent):
|
|
257
|
+
return "hello world"
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
In this scenario when `ATask` is invoked first `all_task_types_middleware` will be run, then
|
|
261
|
+
`async_task_only_middleware` will be run and finally the `a_task` function will be executed.
|
|
262
|
+
|
|
263
|
+
When `BTask` is invoked first `all_task_types_middleware` will be run, and then the `b_task`
|
|
264
|
+
function will be executed
|
|
265
|
+
|
|
191
266
|
# `async-lambda` config
|
|
192
267
|
|
|
193
268
|
Configuration options can be set with the `.async_lambda/config.json` file.
|
|
@@ -178,8 +178,83 @@ def api_task(event: APIEvent):
|
|
|
178
178
|
event.headers # request headers
|
|
179
179
|
event.querystring_params # request querystring params
|
|
180
180
|
event.body # request body
|
|
181
|
+
event.headers # This is a case insensitive dict
|
|
181
182
|
```
|
|
182
183
|
|
|
184
|
+
# Middleware
|
|
185
|
+
|
|
186
|
+
Middleware functions can be registered with controllers which will wrap the execution of tasks.
|
|
187
|
+
These functions can be configured to trigger on specific types of tasks and can trigger
|
|
188
|
+
side effects and modify the `event` or `response` objects.
|
|
189
|
+
|
|
190
|
+
Middleware functions must have the signature `Callable[[BaseEvent, Callable[[BaseEvent], T]], T]`.
|
|
191
|
+
The first argument is the `event`, and the second argument (`call_next`) is a function which will propagate the
|
|
192
|
+
calls down the middleware/task stack. The `call_next` function must be called, and its result in most cases be returned.
|
|
193
|
+
If this is not done then tasks will not run as expected.
|
|
194
|
+
|
|
195
|
+
**Extreme care should be taken with middleware as a simple mistake can have catastrophic effects.**
|
|
196
|
+
|
|
197
|
+
- Middleware functions are run in the order which they were registered and parent controller middleware will be run first.
|
|
198
|
+
|
|
199
|
+
- Middleware functions which are registered more than once will only be run once.
|
|
200
|
+
|
|
201
|
+
Registration can be done when the `AsyncLambdaController` is initialized with the parameter `middleware` or by using the `add_middleware` method.
|
|
202
|
+
|
|
203
|
+
Middleware functions have three sections:
|
|
204
|
+
|
|
205
|
+
1. Pre task
|
|
206
|
+
2. Task execution
|
|
207
|
+
3. Post task
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
def async_lambda_middleware(event: BaseEvent, call_next):
|
|
211
|
+
# pre task
|
|
212
|
+
result = call_next(event) # task execution
|
|
213
|
+
# post task
|
|
214
|
+
return result
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
If there are multiple middleware functions then `call_next` will actually be calling the next middleware function in the stack.
|
|
218
|
+
|
|
219
|
+
For example if there is middleware functions `A` and `B` registered in that order.
|
|
220
|
+
Then the execution order would go:
|
|
221
|
+
|
|
222
|
+
`A(Pre)` -> `B(Pre)` -> `Task` -> `B(Post)` -> `A(Post)`
|
|
223
|
+
|
|
224
|
+
EX:
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
def async_task_only_middleware(event: ManagedSQSEvent, call_next):
|
|
228
|
+
print(f"Invocation Payload: {event}")
|
|
229
|
+
result = call_next(event)
|
|
230
|
+
print(f"Invocation Result: {result}")
|
|
231
|
+
return result
|
|
232
|
+
|
|
233
|
+
def all_task_types_middleware(event: BaseEvent, call_next):
|
|
234
|
+
print(f"This event is of the type {type(event)}")
|
|
235
|
+
result = call_next(event)
|
|
236
|
+
print(f"The result is of the type {type(result)}")
|
|
237
|
+
return event
|
|
238
|
+
|
|
239
|
+
controller = AsyncLambdaController(middleware=[([BaseEvent], all_task_types_middleware)])
|
|
240
|
+
|
|
241
|
+
controller.add_middleware([ManagedSQSEvent], async_task_only_middleware)
|
|
242
|
+
|
|
243
|
+
@controller.async_task("ATask")
|
|
244
|
+
def a_task(event: ManagedSQSEvent):
|
|
245
|
+
pass
|
|
246
|
+
|
|
247
|
+
@controller.api_task("BTask", "/test", "get")
|
|
248
|
+
def b_task(event: APIEvent):
|
|
249
|
+
return "hello world"
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
In this scenario when `ATask` is invoked first `all_task_types_middleware` will be run, then
|
|
253
|
+
`async_task_only_middleware` will be run and finally the `a_task` function will be executed.
|
|
254
|
+
|
|
255
|
+
When `BTask` is invoked first `all_task_types_middleware` will be run, and then the `b_task`
|
|
256
|
+
function will be executed
|
|
257
|
+
|
|
183
258
|
# `async-lambda` config
|
|
184
259
|
|
|
185
260
|
Configuration options can be set with the `.async_lambda/config.json` file.
|
|
@@ -7,9 +7,10 @@ from .env import enable_force_sync_mode as enable_force_sync_mode
|
|
|
7
7
|
from .env import is_build_mode as is_build_mode
|
|
8
8
|
from .models.case_insensitive_dict import CaseInsensitiveDict as CaseInsensitiveDict
|
|
9
9
|
from .models.events.api_event import APIEvent as APIEvent
|
|
10
|
+
from .models.events.base_event import BaseEvent as BaseEvent
|
|
10
11
|
from .models.events.dynamodb_event import DynamoDBEvent as DynamoDBEvent
|
|
11
12
|
from .models.events.managed_sqs_event import ManagedSQSEvent as ManagedSQSEvent
|
|
12
13
|
from .models.events.scheduled_event import ScheduledEvent as ScheduledEvent
|
|
13
14
|
from .models.events.unmanaged_sqs_event import UnmanagedSQSEvent as UnmanagedSQSEvent
|
|
14
15
|
|
|
15
|
-
__version__ = "0.3
|
|
16
|
+
__version__ = "0.4.3"
|
|
@@ -4,13 +4,15 @@ import logging
|
|
|
4
4
|
import re
|
|
5
5
|
import time
|
|
6
6
|
from datetime import datetime, timezone
|
|
7
|
-
from typing import Any, Callable, Dict, Optional, Tuple
|
|
7
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple, Type
|
|
8
8
|
from uuid import uuid4
|
|
9
9
|
|
|
10
10
|
from . import env
|
|
11
11
|
from .build_config import get_build_config_for_stage
|
|
12
12
|
from .client import get_s3_client, get_sqs_client
|
|
13
|
+
from .middleware import MET, RT, MiddlewareFunction, MiddlewareRegistration
|
|
13
14
|
from .models.events.api_event import APIEvent
|
|
15
|
+
from .models.events.base_event import BaseEvent
|
|
14
16
|
from .models.events.dynamodb_event import DynamoDBEvent
|
|
15
17
|
from .models.events.managed_sqs_event import ManagedSQSEvent
|
|
16
18
|
from .models.events.scheduled_event import ScheduledEvent
|
|
@@ -32,6 +34,8 @@ class AsyncLambdaController:
|
|
|
32
34
|
current_lane: Optional[int] = None
|
|
33
35
|
current_invocation_id: Optional[str] = None
|
|
34
36
|
parent_controller: Optional["AsyncLambdaController"] = None
|
|
37
|
+
middleware: List[MiddlewareRegistration]
|
|
38
|
+
|
|
35
39
|
dlq_task_id: Optional[str] = None
|
|
36
40
|
|
|
37
41
|
def __init__(
|
|
@@ -39,11 +43,34 @@ class AsyncLambdaController:
|
|
|
39
43
|
is_sub: bool = False,
|
|
40
44
|
lane_count: Optional[int] = None,
|
|
41
45
|
propagate_lane_assignment: Optional[bool] = None,
|
|
46
|
+
middleware: Optional[List[MiddlewareRegistration]] = None,
|
|
47
|
+
exception_handler: Optional[Callable[[Exception], None]] = None,
|
|
42
48
|
):
|
|
43
49
|
self.tasks = dict()
|
|
44
50
|
self.is_sub = is_sub
|
|
45
51
|
self.lane_count = lane_count
|
|
46
52
|
self.propagate_lane_assignment = propagate_lane_assignment
|
|
53
|
+
self.middleware = middleware or list()
|
|
54
|
+
self.exception_handler = exception_handler
|
|
55
|
+
|
|
56
|
+
def add_middleware(
|
|
57
|
+
self, event_types: List[Type[BaseEvent]], func: MiddlewareFunction[MET, RT]
|
|
58
|
+
):
|
|
59
|
+
self.middleware.append((event_types, func))
|
|
60
|
+
|
|
61
|
+
def get_middleware_for_event(self, event: MET) -> List[MiddlewareFunction[MET, RT]]:
|
|
62
|
+
if self.parent_controller is not None:
|
|
63
|
+
_middleware_functions = self.parent_controller.get_middleware_for_event(
|
|
64
|
+
event
|
|
65
|
+
)
|
|
66
|
+
else:
|
|
67
|
+
_middleware_functions = list()
|
|
68
|
+
|
|
69
|
+
for event_types, func in self.middleware:
|
|
70
|
+
if any(isinstance(event, event_type) for event_type in event_types):
|
|
71
|
+
_middleware_functions.append(func)
|
|
72
|
+
|
|
73
|
+
return _middleware_functions
|
|
47
74
|
|
|
48
75
|
def add_task(self, task: AsyncLambdaTask):
|
|
49
76
|
"""
|
|
@@ -382,7 +409,7 @@ class AsyncLambdaController:
|
|
|
382
409
|
"""
|
|
383
410
|
Invoke an Async-Lambda task.
|
|
384
411
|
"""
|
|
385
|
-
self._async_invoke(
|
|
412
|
+
return self._async_invoke(
|
|
386
413
|
destination_task_id=task_id,
|
|
387
414
|
payload=payload,
|
|
388
415
|
delay=delay,
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from typing import Callable, Generic, List, Tuple, Type, TypeVar
|
|
2
|
+
|
|
3
|
+
from .models.events.base_event import BaseEvent
|
|
4
|
+
|
|
5
|
+
MET = TypeVar("MET", bound=BaseEvent)
|
|
6
|
+
RT = TypeVar("RT")
|
|
7
|
+
|
|
8
|
+
MiddlewareFunction = Callable[[MET, Callable[[MET], RT]], RT]
|
|
9
|
+
MiddlewareRegistration = Tuple[List[Type[MET]], MiddlewareFunction[MET, RT]]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MiddlewareStackExecutor(Generic[MET, RT]):
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
middleware: List[MiddlewareFunction],
|
|
16
|
+
final: Callable[[MET], RT],
|
|
17
|
+
):
|
|
18
|
+
self.middleware = middleware.copy()
|
|
19
|
+
self.final = final
|
|
20
|
+
self._ran_fns = list()
|
|
21
|
+
|
|
22
|
+
def call_next(self, event: MET) -> RT:
|
|
23
|
+
while True:
|
|
24
|
+
if len(self.middleware) == 0:
|
|
25
|
+
return self.final(event)
|
|
26
|
+
next_fn = self.middleware.pop(0)
|
|
27
|
+
if next_fn in self._ran_fns:
|
|
28
|
+
continue
|
|
29
|
+
self._ran_fns.append(next_fn)
|
|
30
|
+
return next_fn(event, self.call_next)
|
|
@@ -13,6 +13,7 @@ from ..config import config
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
14
|
from ..controller import AsyncLambdaController # pragma: not covered
|
|
15
15
|
|
|
16
|
+
from ..middleware import RT, MiddlewareStackExecutor
|
|
16
17
|
from .events.dynamodb_event import DynamoDBEvent
|
|
17
18
|
from .events.managed_sqs_event import ManagedSQSEvent
|
|
18
19
|
from .events.scheduled_event import ScheduledEvent
|
|
@@ -33,7 +34,7 @@ EventType = TypeVar(
|
|
|
33
34
|
)
|
|
34
35
|
|
|
35
36
|
|
|
36
|
-
class AsyncLambdaTask(Generic[EventType]):
|
|
37
|
+
class AsyncLambdaTask(Generic[EventType, RT]):
|
|
37
38
|
controller: "AsyncLambdaController"
|
|
38
39
|
task_id: str
|
|
39
40
|
trigger_type: TaskTriggerType
|
|
@@ -46,12 +47,12 @@ class AsyncLambdaTask(Generic[EventType]):
|
|
|
46
47
|
init_tasks: List[Union[Callable[[str], Any], Callable[[], Any]]]
|
|
47
48
|
_has_run_init_tasks: bool
|
|
48
49
|
|
|
49
|
-
executable: Callable[[EventType],
|
|
50
|
+
executable: Callable[[EventType], RT]
|
|
50
51
|
|
|
51
52
|
def __init__(
|
|
52
53
|
self,
|
|
53
54
|
controller: "AsyncLambdaController",
|
|
54
|
-
executable: Callable[[EventType],
|
|
55
|
+
executable: Callable[[EventType], RT],
|
|
55
56
|
task_id: str,
|
|
56
57
|
trigger_type: TaskTriggerType,
|
|
57
58
|
trigger_config: Optional[dict] = None,
|
|
@@ -481,9 +482,13 @@ class AsyncLambdaTask(Generic[EventType]):
|
|
|
481
482
|
return self.controller.get_task(self.trigger_config["dlq_task_id"])
|
|
482
483
|
return self.controller.get_dlq_task()
|
|
483
484
|
|
|
484
|
-
def execute(self, event: EventType) ->
|
|
485
|
+
def execute(self, event: EventType) -> RT:
|
|
485
486
|
"""
|
|
486
487
|
Executes the tasks function
|
|
487
488
|
"""
|
|
488
489
|
self._run_init_tasks()
|
|
489
|
-
|
|
490
|
+
middleware = self.controller.get_middleware_for_event(event)
|
|
491
|
+
middleware_stack_executor = MiddlewareStackExecutor[EventType, RT](
|
|
492
|
+
middleware=middleware, final=self.executable
|
|
493
|
+
)
|
|
494
|
+
return middleware_stack_executor.call_next(event)
|
{async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda_unstable.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: async-lambda-unstable
|
|
3
|
-
Version: 0.3
|
|
3
|
+
Version: 0.4.3
|
|
4
4
|
Summary: A framework for creating AWS Lambda Async Workflows. - Unstable Branch
|
|
5
5
|
Author-email: "Nuclei, Inc" <engineering@nuclei.ai>
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -186,8 +186,83 @@ def api_task(event: APIEvent):
|
|
|
186
186
|
event.headers # request headers
|
|
187
187
|
event.querystring_params # request querystring params
|
|
188
188
|
event.body # request body
|
|
189
|
+
event.headers # This is a case insensitive dict
|
|
189
190
|
```
|
|
190
191
|
|
|
192
|
+
# Middleware
|
|
193
|
+
|
|
194
|
+
Middleware functions can be registered with controllers which will wrap the execution of tasks.
|
|
195
|
+
These functions can be configured to trigger on specific types of tasks and can trigger
|
|
196
|
+
side effects and modify the `event` or `response` objects.
|
|
197
|
+
|
|
198
|
+
Middleware functions must have the signature `Callable[[BaseEvent, Callable[[BaseEvent], T]], T]`.
|
|
199
|
+
The first argument is the `event`, and the second argument (`call_next`) is a function which will propagate the
|
|
200
|
+
calls down the middleware/task stack. The `call_next` function must be called, and its result in most cases be returned.
|
|
201
|
+
If this is not done then tasks will not run as expected.
|
|
202
|
+
|
|
203
|
+
**Extreme care should be taken with middleware as a simple mistake can have catastrophic effects.**
|
|
204
|
+
|
|
205
|
+
- Middleware functions are run in the order which they were registered and parent controller middleware will be run first.
|
|
206
|
+
|
|
207
|
+
- Middleware functions which are registered more than once will only be run once.
|
|
208
|
+
|
|
209
|
+
Registration can be done when the `AsyncLambdaController` is initialized with the parameter `middleware` or by using the `add_middleware` method.
|
|
210
|
+
|
|
211
|
+
Middleware functions have three sections:
|
|
212
|
+
|
|
213
|
+
1. Pre task
|
|
214
|
+
2. Task execution
|
|
215
|
+
3. Post task
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
def async_lambda_middleware(event: BaseEvent, call_next):
|
|
219
|
+
# pre task
|
|
220
|
+
result = call_next(event) # task execution
|
|
221
|
+
# post task
|
|
222
|
+
return result
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
If there are multiple middleware functions then `call_next` will actually be calling the next middleware function in the stack.
|
|
226
|
+
|
|
227
|
+
For example if there is middleware functions `A` and `B` registered in that order.
|
|
228
|
+
Then the execution order would go:
|
|
229
|
+
|
|
230
|
+
`A(Pre)` -> `B(Pre)` -> `Task` -> `B(Post)` -> `A(Post)`
|
|
231
|
+
|
|
232
|
+
EX:
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
def async_task_only_middleware(event: ManagedSQSEvent, call_next):
|
|
236
|
+
print(f"Invocation Payload: {event}")
|
|
237
|
+
result = call_next(event)
|
|
238
|
+
print(f"Invocation Result: {result}")
|
|
239
|
+
return result
|
|
240
|
+
|
|
241
|
+
def all_task_types_middleware(event: BaseEvent, call_next):
|
|
242
|
+
print(f"This event is of the type {type(event)}")
|
|
243
|
+
result = call_next(event)
|
|
244
|
+
print(f"The result is of the type {type(result)}")
|
|
245
|
+
return event
|
|
246
|
+
|
|
247
|
+
controller = AsyncLambdaController(middleware=[([BaseEvent], all_task_types_middleware)])
|
|
248
|
+
|
|
249
|
+
controller.add_middleware([ManagedSQSEvent], async_task_only_middleware)
|
|
250
|
+
|
|
251
|
+
@controller.async_task("ATask")
|
|
252
|
+
def a_task(event: ManagedSQSEvent):
|
|
253
|
+
pass
|
|
254
|
+
|
|
255
|
+
@controller.api_task("BTask", "/test", "get")
|
|
256
|
+
def b_task(event: APIEvent):
|
|
257
|
+
return "hello world"
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
In this scenario when `ATask` is invoked first `all_task_types_middleware` will be run, then
|
|
261
|
+
`async_task_only_middleware` will be run and finally the `a_task` function will be executed.
|
|
262
|
+
|
|
263
|
+
When `BTask` is invoked first `all_task_types_middleware` will be run, and then the `b_task`
|
|
264
|
+
function will be executed
|
|
265
|
+
|
|
191
266
|
# `async-lambda` config
|
|
192
267
|
|
|
193
268
|
Configuration options can be set with the `.async_lambda/config.json` file.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/events/__init__.py
RENAMED
|
File without changes
|
{async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/events/api_event.py
RENAMED
|
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.3.12 → async-lambda-unstable-0.4.3}/async_lambda/models/mock/mock_event.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
|