@@ -177,8 +177,7 @@ async def native_activity(context, payload):
177177 store .upload_async .assert_awaited_once ()
178178
179179
180- @pytest .mark .asyncio
181- async def test_sync_activity_awaits_storage_and_offloads_user_code (monkeypatch , payload_store_factory ):
180+ def test_sync_activity_uses_sync_storage_on_the_calling_thread (monkeypatch , payload_store_factory ):
182181 store = payload_store_factory ()
183182 monkeypatch .setattr (payloads , "_payload_store" , store )
184183 value = {"large" : "x" * 200 }
@@ -187,11 +186,11 @@ async def test_sync_activity_awaits_storage_and_offloads_user_code(monkeypatch,
187186 original_download = store .download
188187 original_upload = store .upload
189188
190- async def download (reference ):
189+ def download (reference ):
191190 thread_ids .append (threading .get_ident ())
192191 return original_download (reference )
193192
194- async def upload (data , * , instance_id = None ):
193+ def upload (data , * , instance_id = None ):
195194 thread_ids .append (threading .get_ident ())
196195 return original_upload (data , instance_id = instance_id )
197196
@@ -200,18 +199,22 @@ def activity(payload):
200199 assert payload == value
201200 return payload
202201
203- monkeypatch .setattr (store , "download_async " , download )
204- monkeypatch .setattr (store , "upload_async " , upload )
205- monkeypatch .setattr (store , "download " , Mock (side_effect = AssertionError ("sync download" )))
206- monkeypatch .setattr (store , "upload " , Mock (side_effect = AssertionError ("sync upload" )))
202+ monkeypatch .setattr (store , "download " , Mock ( side_effect = download ) )
203+ monkeypatch .setattr (store , "upload " , Mock ( side_effect = upload ) )
204+ monkeypatch .setattr (store , "download_async " , AsyncMock (side_effect = AssertionError ("async download" )))
205+ monkeypatch .setattr (store , "upload_async " , AsyncMock (side_effect = AssertionError ("async upload" )))
207206 wrapper = wrap_activity_payloads (activity , "payload" )
208- assert inspect .iscoroutinefunction (wrapper )
207+ assert not inspect .iscoroutinefunction (wrapper )
209208 decoded = ActivityTriggerConverter .decode (
210209 meta .Datum (type = "string" , value = token ), trigger_metadata = None )
211- await wrapper (decoded )
212- assert len (thread_ids ) == 3
213- assert thread_ids [0 ] == thread_ids [2 ] == threading .get_ident ()
214- assert thread_ids [1 ] != threading .get_ident ()
210+ result = wrapper (decoded )
211+ encoded = ActivityTriggerConverter .encode (result , expected_type = None )
212+ assert json .loads (original_download (json .loads (encoded .value ))) == value
213+ assert thread_ids == [threading .get_ident ()] * 3
214+ store .download .assert_called_once_with (token )
215+ store .upload .assert_called_once ()
216+ store .download_async .assert_not_called ()
217+ store .upload_async .assert_not_called ()
215218
216219
217220@pytest .mark .asyncio
@@ -223,8 +226,8 @@ async def test_activity_storage_errors_propagate_without_retry(
223226 monkeypatch .setattr (payloads , "_payload_store" , store )
224227 token = store .upload (json .dumps ("x" * 200 ).encode ())
225228 error = OSError ("payload storage unavailable" )
226- failure = AsyncMock (side_effect = error )
227- monkeypatch .setattr (store , operation + "_async" , failure )
229+ failure = AsyncMock (side_effect = error ) if use_async else Mock ( side_effect = error )
230+ monkeypatch .setattr (store , operation + ( "_async" if use_async else "" ) , failure )
228231 called = []
229232
230233 def activity (payload ):
@@ -238,10 +241,16 @@ async def async_activity(payload):
238241 decoded = ActivityTriggerConverter .decode (
239242 meta .Datum (type = "string" , value = token ), trigger_metadata = None )
240243 with pytest .raises (OSError ) as raised :
241- await wrapper (decoded )
244+ if use_async :
245+ await wrapper (decoded )
246+ else :
247+ wrapper (decoded )
242248 assert raised .value is error
243249 assert called == ([True ] if operation == "upload" else [])
244- failure .assert_awaited_once ()
250+ if use_async :
251+ failure .assert_awaited_once ()
252+ else :
253+ failure .assert_called_once ()
245254
246255
247256@pytest .mark .parametrize ("setting, expected" , [(None , None ), ("2" , 2 ), ("invalid" , None ), ("0" , None )])
@@ -289,42 +298,3 @@ async def handle(payload):
289298 assert await loop .run_in_executor (executor , host_invocation_id .get ) is None
290299 assert await loop .run_in_executor (executor , getattr , storage , "invocation_id" ) == "previous"
291300 assert invocation ._invocation_context .get () is None
292-
293-
294- async def test_storage_downloads_do_not_wait_for_execution_thread (monkeypatch , payload_store_factory ):
295- store = payload_store_factory ()
296- monkeypatch .setattr (payloads , "_payload_store" , store )
297- token = store .upload (b'"input"' )
298- loop = asyncio .get_running_loop ()
299- executing = asyncio .Event ()
300- downloaded = asyncio .Event ()
301- release = threading .Event ()
302- downloads = []
303-
304- async def download (reference ):
305- downloads .append (reference )
306- if len (downloads ) == 2 :
307- downloaded .set ()
308- return store ._blobs [reference ]
309-
310- def activity (payload ):
311- loop .call_soon_threadsafe (executing .set )
312- assert release .wait (timeout = 5 )
313- return payload
314-
315- monkeypatch .setattr (store , "download_async" , download )
316- monkeypatch .setattr (store , "download" , Mock (side_effect = AssertionError ("sync download" )))
317- wrapper = wrap_activity_payloads (activity , "payload" )
318- with ThreadPoolExecutor (max_workers = 1 ) as executor :
319- monkeypatch .setattr (invocation , "_executor" , lambda : executor )
320- first = asyncio .create_task (wrapper (payloads .ActivityPayload (token )))
321- second = None
322- try :
323- await asyncio .wait_for (executing .wait (), timeout = 5 )
324- second = asyncio .create_task (wrapper (payloads .ActivityPayload (token )))
325- await asyncio .wait_for (downloaded .wait (), timeout = 5 )
326- assert not first .done ()
327- assert not second .done ()
328- finally :
329- release .set ()
330- await asyncio .gather (first , * ([second ] if second is not None else []))
0 commit comments