33import traceback
44from datetime import datetime
55from functools import wraps
6- from time import sleep
76from typing import Any , Callable , MutableMapping , Optional , Tuple , Type , Union
87
98from .boto3_proxy import SessionProxy , _get_boto_session
10- from .callback import report_progress
119from .exceptions import InternalFailure , InvalidRequest , _HandlerError
1210from .interface import (
1311 Action ,
1816)
1917from .log_delivery import ProviderLogHandler
2018from .metrics import MetricsPublisherProxy
21- from .scheduler import cleanup_cloudwatch_events , reschedule_after_minutes
2219from .utils import (
2320 BaseModel ,
2421 Credentials ,
3229LOG = logging .getLogger (__name__ )
3330
3431MUTATING_ACTIONS = (Action .CREATE , Action .UPDATE , Action .DELETE )
35- INVOCATION_TIMEOUT_MS = 60000
3632
3733HandlerSignature = Callable [
3834 [Optional [SessionProxy ], Any , MutableMapping [str , Any ]], ProgressEvent
@@ -72,38 +68,6 @@ def _add_handler(f: HandlerSignature) -> HandlerSignature:
7268
7369 return _add_handler
7470
75- @staticmethod
76- def schedule_reinvocation (
77- handler_request : HandlerRequest ,
78- handler_response : ProgressEvent ,
79- context : LambdaContext ,
80- session : SessionProxy ,
81- ) -> bool :
82- if handler_response .status != OperationStatus .IN_PROGRESS :
83- return False
84- # modify requestContext dict in-place, so that invoke count is bumped on local
85- # reinvoke too
86- reinvoke_context = handler_request .requestContext
87- reinvoke_context ["invocation" ] = reinvoke_context .get ("invocation" , 0 ) + 1
88- callback_delay_s = handler_response .callbackDelaySeconds
89- remaining_ms = context .get_remaining_time_in_millis ()
90-
91- # when a handler requests a sub-minute callback delay, and if the lambda
92- # invocation has enough runtime (with 20% buffer), we can re-run the handler
93- # locally otherwise we re-invoke through CloudWatchEvents
94- needed_ms_remaining = callback_delay_s * 1200 + INVOCATION_TIMEOUT_MS
95- if callback_delay_s < 60 and remaining_ms > needed_ms_remaining :
96- sleep (callback_delay_s )
97- return True
98- callback_delay_min = int (callback_delay_s / 60 )
99- reschedule_after_minutes (
100- session ,
101- function_arn = context .invoked_function_arn ,
102- minutes_from_now = callback_delay_min ,
103- handler_request = handler_request ,
104- )
105- return False
106-
10771 def _invoke_handler (
10872 self ,
10973 session : Optional [SessionProxy ],
@@ -169,26 +133,23 @@ def test_entrypoint(
169133 def _parse_request (
170134 event_data : MutableMapping [str , Any ]
171135 ) -> Tuple [
172- Tuple [Optional [SessionProxy ], Optional [SessionProxy ], SessionProxy ],
136+ Tuple [Optional [SessionProxy ], Optional [SessionProxy ]],
173137 Action ,
174138 MutableMapping [str , Any ],
175139 HandlerRequest ,
176140 ]:
177141 try :
178142 event = HandlerRequest .deserialize (event_data )
179- platform_sess = _get_boto_session (event .requestData .platformCredentials )
180143 caller_sess = _get_boto_session (event .requestData .callerCredentials )
181144 provider_sess = _get_boto_session (event .requestData .providerCredentials )
182145 # credentials are used when rescheduling, so can't zero them out (for now)
183- if platform_sess is None :
184- raise ValueError ("No platform credentials" )
185146 action = Action [event .action ]
186- callback_context = event .requestContext . get ( " callbackContext" , {})
147+ callback_context = event .callbackContext or {}
187148 except Exception as e : # pylint: disable=broad-except
188149 LOG .exception ("Invalid request" )
189150 raise InvalidRequest (f"{ e } ({ type (e ).__name__ } )" ) from e
190151 return (
191- (caller_sess , provider_sess , platform_sess ),
152+ (caller_sess , provider_sess ),
192153 action ,
193154 callback_context ,
194155 event ,
@@ -224,66 +185,28 @@ def print_or_log(message: str) -> None:
224185
225186 try :
226187 sessions , action , callback , event = self ._parse_request (event_data )
227- caller_sess , provider_sess , platform_sess = sessions
188+ caller_sess , provider_sess = sessions
228189 ProviderLogHandler .setup (event , provider_sess )
229190 logs_setup = True
230191
231192 request = self ._cast_resource_request (event )
232193
233194 metrics = MetricsPublisherProxy (event .awsAccountId , event .resourceType )
234- metrics .add_metrics_publisher (platform_sess )
235195 metrics .add_metrics_publisher (provider_sess )
236- # Acknowledge the task for first time invocation
237- if not event .requestContext :
238- report_progress (
239- platform_sess ,
240- event .bearerToken ,
241- None ,
242- OperationStatus .IN_PROGRESS ,
243- OperationStatus .PENDING ,
244- None ,
245- "" ,
246- )
247- else :
248- # If this invocation was triggered by a 're-invoke' CloudWatch Event,
249- # clean it up
250- cleanup_cloudwatch_events (
251- platform_sess ,
252- event .requestContext .get ("cloudWatchEventsRuleName" , "" ),
253- event .requestContext .get ("cloudWatchEventsTargetId" , "" ),
254- )
255- invoke = True
256- while invoke :
257- metrics .publish_invocation_metric (datetime .utcnow (), action )
258- start_time = datetime .utcnow ()
259- error = None
260- try :
261- progress = self ._invoke_handler (
262- caller_sess , request , action , callback
263- )
264- except Exception as e : # pylint: disable=broad-except
265- error = e
266- m_secs = (datetime .utcnow () - start_time ).total_seconds () * 1000.0
267- metrics .publish_duration_metric (datetime .utcnow (), action , m_secs )
268- if error :
269- metrics .publish_exception_metric (datetime .utcnow (), action , error )
270- raise error
271- if progress .callbackContext :
272- callback = progress .callbackContext
273- event .requestContext ["callbackContext" ] = callback
274- if event .action in MUTATING_ACTIONS :
275- report_progress (
276- platform_sess ,
277- event .bearerToken ,
278- progress .errorCode ,
279- progress .status ,
280- OperationStatus .IN_PROGRESS ,
281- progress .resourceModel ,
282- progress .message ,
283- )
284- invoke = self .schedule_reinvocation (
285- event , progress , context , platform_sess
286- )
196+
197+ metrics .publish_invocation_metric (datetime .utcnow (), action )
198+ start_time = datetime .utcnow ()
199+ error = None
200+
201+ try :
202+ progress = self ._invoke_handler (caller_sess , request , action , callback )
203+ except Exception as e : # pylint: disable=broad-except
204+ error = e
205+ m_secs = (datetime .utcnow () - start_time ).total_seconds () * 1000.0
206+ metrics .publish_duration_metric (datetime .utcnow (), action , m_secs )
207+ if error :
208+ metrics .publish_exception_metric (datetime .utcnow (), action , error )
209+ raise error
287210 except _HandlerError as e :
288211 print_or_log ("Handler error" )
289212 progress = e .to_progress_event ()
@@ -296,6 +219,4 @@ def print_or_log(message: str) -> None:
296219
297220 # use the raw event_data as a last-ditch attempt to call back if the
298221 # request is invalid
299- return progress ._serialize ( # pylint: disable=protected-access
300- to_response = True , bearer_token = event_data .get ("bearerToken" )
301- )
222+ return progress ._serialize () # pylint: disable=protected-access
0 commit comments