-
Notifications
You must be signed in to change notification settings - Fork 421
/
Copy pathdecorators.py
253 lines (210 loc) · 7.72 KB
/
decorators.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
from __future__ import annotations
from typing import Any, Awaitable, Callable, Dict, List
from aws_lambda_powertools.middleware_factory import lambda_handler_decorator
from aws_lambda_powertools.utilities.batch import (
AsyncBatchProcessor,
BasePartialBatchProcessor,
BatchProcessor,
EventType,
)
from aws_lambda_powertools.utilities.batch.types import PartialItemFailureResponse
from aws_lambda_powertools.utilities.typing import LambdaContext
@lambda_handler_decorator
def async_batch_processor(
handler: Callable,
event: Dict,
context: LambdaContext,
record_handler: Callable[..., Awaitable[Any]],
processor: AsyncBatchProcessor,
):
"""
Middleware to handle batch event processing
Notes
-----
Consider using async_process_partial_response function for an easier experience.
Parameters
----------
handler: Callable
Lambda's handler
event: Dict
Lambda's Event
context: LambdaContext
Lambda's Context
record_handler: Callable[..., Awaitable[Any]]
Callable to process each record from the batch
processor: AsyncBatchProcessor
Batch Processor to handle partial failure cases
Examples
--------
**Processes Lambda's event with a BasePartialProcessor**
>>> from aws_lambda_powertools.utilities.batch import async_batch_processor, AsyncBatchProcessor
>>> from aws_lambda_powertools.utilities.data_classes.sqs_event import SQSRecord
>>>
>>> processor = AsyncBatchProcessor(event_type=EventType.SQS)
>>>
>>> async def async_record_handler(record: SQSRecord):
>>> payload: str = record.body
>>> return payload
>>>
>>> @async_batch_processor(record_handler=async_record_handler, processor=processor)
>>> def lambda_handler(event, context):
>>> return processor.response()
Limitations
-----------
* Sync batch processors. Use `batch_processor` instead.
"""
records = event["Records"]
with processor(records, record_handler, lambda_context=context):
processor.async_process()
return handler(event, context)
@lambda_handler_decorator
def batch_processor(
handler: Callable,
event: Dict,
context: LambdaContext,
record_handler: Callable,
processor: BatchProcessor,
):
"""
Middleware to handle batch event processing
Notes
-----
Consider using process_partial_response function for an easier experience.
Parameters
----------
handler: Callable
Lambda's handler
event: Dict
Lambda's Event
context: LambdaContext
Lambda's Context
record_handler: Callable
Callable or corutine to process each record from the batch
processor: BatchProcessor
Batch Processor to handle partial failure cases
Examples
--------
**Processes Lambda's event with a BatchProcessor**
>>> from aws_lambda_powertools.utilities.batch import batch_processor, BatchProcessor, EventType
>>> from aws_lambda_powertools.utilities.data_classes.sqs_event import SQSRecord
>>>
>>> processor = BatchProcessor(EventType.SQS)
>>>
>>> def record_handler(record):
>>> return record["body"]
>>>
>>> @batch_processor(record_handler=record_handler, processor=BatchProcessor())
>>> def handler(event, context):
>>> return processor.response()
Limitations
-----------
* Async batch processors. Use `async_batch_processor` instead.
"""
records = event["Records"]
with processor(records, record_handler, lambda_context=context):
processor.process()
return handler(event, context)
def process_partial_response(
event: Dict,
record_handler: Callable,
processor: BasePartialBatchProcessor,
context: LambdaContext | None = None,
) -> PartialItemFailureResponse:
"""
Higher level function to handle batch event processing.
Parameters
----------
event: Dict
Lambda's original event
record_handler: Callable
Callable to process each record from the batch
processor: BasePartialBatchProcessor
Batch Processor to handle partial failure cases
context: LambdaContext
Lambda's context, used to optionally inject in record handler
Returns
-------
result: PartialItemFailureResponse
Lambda Partial Batch Response
Examples
--------
**Processes Lambda's SQS event**
```python
from aws_lambda_powertools.utilities.batch import BatchProcessor, EventType, process_partial_response
from aws_lambda_powertools.utilities.data_classes.sqs_event import SQSRecord
processor = BatchProcessor(EventType.SQS)
def record_handler(record: SQSRecord):
return record.body
def handler(event, context):
return process_partial_response(
event=event, record_handler=record_handler, processor=processor, context=context
)
```
Limitations
-----------
* Async batch processors. Use `async_process_partial_response` instead.
"""
try:
records: List[Dict] = event.get("Records", [])
except AttributeError:
event_types = ", ".join(list(EventType.__members__))
docs = "https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/#processing-messages-from-sqs" # noqa: E501 # long-line
raise ValueError(
f"Invalid event format. Please ensure batch event is a valid {processor.event_type.value} event. \n"
f"See sample events in our documentation for either {event_types}: \n {docs}",
)
with processor(records, record_handler, context):
processor.process()
return processor.response()
def async_process_partial_response(
event: Dict,
record_handler: Callable,
processor: AsyncBatchProcessor,
context: LambdaContext | None = None,
) -> PartialItemFailureResponse:
"""
Higher level function to handle batch event processing asynchronously.
Parameters
----------
event: Dict
Lambda's original event
record_handler: Callable
Callable to process each record from the batch
processor: AsyncBatchProcessor
Batch Processor to handle partial failure cases
context: LambdaContext
Lambda's context, used to optionally inject in record handler
Returns
-------
result: PartialItemFailureResponse
Lambda Partial Batch Response
Examples
--------
**Processes Lambda's SQS event**
```python
from aws_lambda_powertools.utilities.batch import AsyncBatchProcessor, EventType, process_partial_response
from aws_lambda_powertools.utilities.data_classes.sqs_event import SQSRecord
processor = BatchProcessor(EventType.SQS)
async def record_handler(record: SQSRecord):
return record.body
def handler(event, context):
return async_process_partial_response(
event=event, record_handler=record_handler, processor=processor, context=context
)
```
Limitations
-----------
* Sync batch processors. Use `process_partial_response` instead.
"""
try:
records: List[Dict] = event.get("Records", [])
except AttributeError:
event_types = ", ".join(list(EventType.__members__))
docs = "https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/#processing-messages-from-sqs" # noqa: E501 # long-line
raise ValueError(
f"Invalid event format. Please ensure batch event is a valid {processor.event_type.value} event. \n"
f"See sample events in our documentation for either {event_types}: \n {docs}",
)
with processor(records, record_handler, context):
processor.async_process()
return processor.response()