Skip to content

Commit e8cda0a

Browse files
authored
fix: respect explicit zero custom_after_sleep in metamorph and reboot (#971)
## Description - `Actor.metamorph()` and `Actor.reboot()` used a falsy check on `custom_after_sleep`, so an explicit `timedelta(0)` was treated as unset and silently replaced with the 5-minute default (`Configuration.metamorph_after_sleep`). - Changed both checks to `is None`, so an explicit zero now skips the after-sleep entirely, while omitting the argument (or passing `None`) still uses the default. - Added unit tests covering both methods, asserting that no sleep happens for `timedelta(0)` and that the underlying API call is still made.
1 parent fe71bd7 commit e8cda0a

2 files changed

Lines changed: 38 additions & 1 deletion

File tree

src/apify/_actor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1164,7 +1164,7 @@ async def metamorph(
11641164
self.log.error('Actor.metamorph() is only supported when running on the Apify platform.')
11651165
return
11661166

1167-
if not custom_after_sleep:
1167+
if custom_after_sleep is None:
11681168
custom_after_sleep = self.configuration.metamorph_after_sleep
11691169

11701170
# If is_at_home() is True, configuration.actor_run_id is always set

tests/unit/actor/test_actor_helpers.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import logging
55
from datetime import UTC, datetime, timedelta
66
from typing import TYPE_CHECKING
7+
from unittest.mock import AsyncMock, patch
78

89
import pytest
910

@@ -422,6 +423,42 @@ async def hanging_listener(*_args: object) -> None:
422423
assert len(apify_client_async_patcher.calls['run']['reboot']) == 1
423424

424425

426+
async def test_metamorph_with_zero_custom_after_sleep_does_not_sleep(
427+
apify_client_async_patcher: ApifyClientAsyncPatcher,
428+
) -> None:
429+
"""Test that an explicit `custom_after_sleep=timedelta(0)` is not replaced by the default sleep duration."""
430+
apify_client_async_patcher.patch('run', 'metamorph', return_value=None)
431+
432+
async with Actor:
433+
Actor.configuration.is_at_home = True
434+
Actor.configuration.actor_run_id = 'some-run-id'
435+
436+
with patch('asyncio.sleep', new=AsyncMock()) as sleep_mock:
437+
await Actor.metamorph('target-actor-id', custom_after_sleep=timedelta(0))
438+
439+
sleep_mock.assert_not_awaited()
440+
441+
assert len(apify_client_async_patcher.calls['run']['metamorph']) == 1
442+
443+
444+
async def test_reboot_with_zero_custom_after_sleep_does_not_sleep(
445+
apify_client_async_patcher: ApifyClientAsyncPatcher,
446+
) -> None:
447+
"""Test that an explicit `custom_after_sleep=timedelta(0)` is not replaced by the default sleep duration."""
448+
apify_client_async_patcher.patch('run', 'reboot', return_value=None)
449+
450+
async with Actor:
451+
Actor.configuration.is_at_home = True
452+
Actor.configuration.actor_run_id = 'some-run-id'
453+
454+
with patch('asyncio.sleep', new=AsyncMock()) as sleep_mock:
455+
await Actor.reboot(custom_after_sleep=timedelta(0))
456+
457+
sleep_mock.assert_not_awaited()
458+
459+
assert len(apify_client_async_patcher.calls['run']['reboot']) == 1
460+
461+
425462
async def test_reboot_can_be_retried_after_failed_attempt(
426463
apify_client_async_patcher: ApifyClientAsyncPatcher,
427464
) -> None:

0 commit comments

Comments
 (0)