async-lambda-unstable 0.3.12__tar.gz → 0.4.1__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.
Files changed (32) hide show
  1. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/PKG-INFO +43 -1
  2. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/README.md +42 -0
  3. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/__init__.py +2 -1
  4. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/controller.py +30 -1
  5. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/models/task.py +1 -0
  6. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda_unstable.egg-info/PKG-INFO +43 -1
  7. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/build_config.py +0 -0
  8. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/cli.py +0 -0
  9. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/client.py +0 -0
  10. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/config.py +0 -0
  11. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/defer.py +0 -0
  12. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/env.py +0 -0
  13. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/models/__init__.py +0 -0
  14. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/models/case_insensitive_dict.py +0 -0
  15. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/models/events/__init__.py +0 -0
  16. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/models/events/api_event.py +0 -0
  17. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/models/events/base_event.py +0 -0
  18. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/models/events/dynamodb_event.py +0 -0
  19. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/models/events/managed_sqs_event.py +0 -0
  20. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/models/events/scheduled_event.py +0 -0
  21. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/models/events/unmanaged_sqs_event.py +0 -0
  22. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/models/mock/mock_context.py +0 -0
  23. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/models/mock/mock_event.py +0 -0
  24. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/py.typed +0 -0
  25. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda/util.py +0 -0
  26. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda_unstable.egg-info/SOURCES.txt +0 -0
  27. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda_unstable.egg-info/dependency_links.txt +0 -0
  28. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda_unstable.egg-info/entry_points.txt +0 -0
  29. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda_unstable.egg-info/requires.txt +0 -0
  30. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/async_lambda_unstable.egg-info/top_level.txt +0 -0
  31. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/pyproject.toml +0 -0
  32. {async-lambda-unstable-0.3.12 → async-lambda-unstable-0.4.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: async-lambda-unstable
3
- Version: 0.3.12
3
+ Version: 0.4.1
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,50 @@ 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 execute before the task code is run.
195
+ These functions can be configured to trigger on specific types of tasks and can modify the `event`.
196
+
197
+ Middleware functions must have the signature `Callable[[BaseEvent], BaseEvent]`.
198
+ Middleware functions are run in the order which they were registered and parent controller middleware will be run first.
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
+ EX:
204
+
205
+ ```python
206
+ def async_task_only_middleware(event: ManagedSQSEvent):
207
+ print(f"Invocation Payload: {event}")
208
+ return event
209
+
210
+ def all_task_types_middleware(event: BaseEvent):
211
+ print(f"This task is of the type {type(event)}")
212
+ return event
213
+
214
+ controller = AsyncLambdaController(middleware=[([BaseEvent], all_task_types_middleware)])
215
+
216
+ controller.add_middleware([ManagedSQSEvent], async_task_only_middleware)
217
+
218
+ @controller.async_task("ATask")
219
+ def a_task(event: ManagedSQSEvent):
220
+ pass
221
+
222
+ @controller.api_task("BTask", "/test", "get")
223
+ def b_task(event: APIEvent):
224
+ return "hello world"
225
+ ```
226
+
227
+ In this scenario when `ATask` is invoked first `all_task_types_middleware` will be run, then
228
+ `async_task_only_middleware` will be run and finally the `a_task` function will be executed.
229
+
230
+ When `BTask` is invoked first `all_task_types_middleware` will be run, and then the `b_task`
231
+ function will be executed
232
+
191
233
  # `async-lambda` config
192
234
 
193
235
  Configuration options can be set with the `.async_lambda/config.json` file.
@@ -178,8 +178,50 @@ 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 execute before the task code is run.
187
+ These functions can be configured to trigger on specific types of tasks and can modify the `event`.
188
+
189
+ Middleware functions must have the signature `Callable[[BaseEvent], BaseEvent]`.
190
+ Middleware functions are run in the order which they were registered and parent controller middleware will be run first.
191
+ Middleware functions which are registered more than once will only be run once.
192
+
193
+ Registration can be done when the `AsyncLambdaController` is initialized with the parameter `middleware` or by using the `add_middleware` method.
194
+
195
+ EX:
196
+
197
+ ```python
198
+ def async_task_only_middleware(event: ManagedSQSEvent):
199
+ print(f"Invocation Payload: {event}")
200
+ return event
201
+
202
+ def all_task_types_middleware(event: BaseEvent):
203
+ print(f"This task is of the type {type(event)}")
204
+ return event
205
+
206
+ controller = AsyncLambdaController(middleware=[([BaseEvent], all_task_types_middleware)])
207
+
208
+ controller.add_middleware([ManagedSQSEvent], async_task_only_middleware)
209
+
210
+ @controller.async_task("ATask")
211
+ def a_task(event: ManagedSQSEvent):
212
+ pass
213
+
214
+ @controller.api_task("BTask", "/test", "get")
215
+ def b_task(event: APIEvent):
216
+ return "hello world"
217
+ ```
218
+
219
+ In this scenario when `ATask` is invoked first `all_task_types_middleware` will be run, then
220
+ `async_task_only_middleware` will be run and finally the `a_task` function will be executed.
221
+
222
+ When `BTask` is invoked first `all_task_types_middleware` will be run, and then the `b_task`
223
+ function will be executed
224
+
183
225
  # `async-lambda` config
184
226
 
185
227
  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.12"
16
+ __version__ = "0.4.1"
@@ -4,13 +4,14 @@ 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, TypeVar
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
13
  from .models.events.api_event import APIEvent
14
+ from .models.events.base_event import BaseEvent
14
15
  from .models.events.dynamodb_event import DynamoDBEvent
15
16
  from .models.events.managed_sqs_event import ManagedSQSEvent
16
17
  from .models.events.scheduled_event import ScheduledEvent
@@ -22,6 +23,11 @@ from .util import make_cf_tags
22
23
 
23
24
  logger = logging.getLogger(__name__)
24
25
 
26
+ MET = TypeVar("MET", bound=BaseEvent)
27
+
28
+ MiddlewareFunction = Callable[[MET], MET]
29
+ MiddlewareRegistration = Tuple[List[Type[MET]], MiddlewareFunction[MET]]
30
+
25
31
 
26
32
  class AsyncLambdaController:
27
33
  is_sub: bool
@@ -32,6 +38,7 @@ class AsyncLambdaController:
32
38
  current_lane: Optional[int] = None
33
39
  current_invocation_id: Optional[str] = None
34
40
  parent_controller: Optional["AsyncLambdaController"] = None
41
+ middleware: List[MiddlewareRegistration]
35
42
  dlq_task_id: Optional[str] = None
36
43
 
37
44
  def __init__(
@@ -39,11 +46,33 @@ class AsyncLambdaController:
39
46
  is_sub: bool = False,
40
47
  lane_count: Optional[int] = None,
41
48
  propagate_lane_assignment: Optional[bool] = None,
49
+ middleware: Optional[List[MiddlewareRegistration]] = None,
42
50
  ):
43
51
  self.tasks = dict()
44
52
  self.is_sub = is_sub
45
53
  self.lane_count = lane_count
46
54
  self.propagate_lane_assignment = propagate_lane_assignment
55
+ self.middleware = middleware or list()
56
+
57
+ def add_middleware(
58
+ self, event_types: List[Type[BaseEvent]], func: MiddlewareFunction[MET]
59
+ ):
60
+ self.middleware.append((event_types, func))
61
+
62
+ def execute_middleware(
63
+ self, event: MET, _ran_fns: Optional[List[Callable]] = None
64
+ ) -> Tuple[MET, List[Callable]]:
65
+ if _ran_fns is None:
66
+ _ran_fns = list()
67
+ if self.parent_controller is not None:
68
+ event, _ran_fns = self.parent_controller.execute_middleware(event, _ran_fns)
69
+ for event_types, func in self.middleware:
70
+ if func in _ran_fns:
71
+ continue
72
+ if any(isinstance(event, event_type) for event_type in event_types):
73
+ event = func(event)
74
+ _ran_fns.append(func)
75
+ return event, _ran_fns
47
76
 
48
77
  def add_task(self, task: AsyncLambdaTask):
49
78
  """
@@ -486,4 +486,5 @@ class AsyncLambdaTask(Generic[EventType]):
486
486
  Executes the tasks function
487
487
  """
488
488
  self._run_init_tasks()
489
+ self.controller.execute_middleware(event)
489
490
  return self.executable(event)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: async-lambda-unstable
3
- Version: 0.3.12
3
+ Version: 0.4.1
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,50 @@ 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 execute before the task code is run.
195
+ These functions can be configured to trigger on specific types of tasks and can modify the `event`.
196
+
197
+ Middleware functions must have the signature `Callable[[BaseEvent], BaseEvent]`.
198
+ Middleware functions are run in the order which they were registered and parent controller middleware will be run first.
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
+ EX:
204
+
205
+ ```python
206
+ def async_task_only_middleware(event: ManagedSQSEvent):
207
+ print(f"Invocation Payload: {event}")
208
+ return event
209
+
210
+ def all_task_types_middleware(event: BaseEvent):
211
+ print(f"This task is of the type {type(event)}")
212
+ return event
213
+
214
+ controller = AsyncLambdaController(middleware=[([BaseEvent], all_task_types_middleware)])
215
+
216
+ controller.add_middleware([ManagedSQSEvent], async_task_only_middleware)
217
+
218
+ @controller.async_task("ATask")
219
+ def a_task(event: ManagedSQSEvent):
220
+ pass
221
+
222
+ @controller.api_task("BTask", "/test", "get")
223
+ def b_task(event: APIEvent):
224
+ return "hello world"
225
+ ```
226
+
227
+ In this scenario when `ATask` is invoked first `all_task_types_middleware` will be run, then
228
+ `async_task_only_middleware` will be run and finally the `a_task` function will be executed.
229
+
230
+ When `BTask` is invoked first `all_task_types_middleware` will be run, and then the `b_task`
231
+ function will be executed
232
+
191
233
  # `async-lambda` config
192
234
 
193
235
  Configuration options can be set with the `.async_lambda/config.json` file.