@@ -117,3 +117,44 @@ async def main() -> None:
117117
118118 assert run_result .exit_code == 91
119119 assert run_result .status == 'FAILED'
120+
121+
122+ async def test_actor_with_crawler_reboot (make_actor : MakeActorFunction , run_actor : RunActorFunction ) -> None :
123+ """Test that crawler in actor works as expected after reboot.
124+
125+ Handle two requests. Reboot in between the two requests."""
126+
127+ async def main () -> None :
128+ from crawlee ._types import BasicCrawlingContext , ConcurrencySettings
129+ from crawlee .crawlers import BasicCrawler
130+
131+ from apify import Actor
132+
133+ async with Actor :
134+ crawler = BasicCrawler (concurrency_settings = ConcurrencySettings (max_concurrency = 1 ))
135+ requests = ['https://example.com/1' , 'https://example.com/2' ]
136+
137+ run = await Actor .apify_client .run (Actor .configuration .actor_run_id or '' ).get ()
138+ assert run
139+ first_run = run .get ('stats' , {}).get ('rebootCount' , 0 ) == 0
140+
141+ @crawler .router .default_handler
142+ async def default_handler (context : BasicCrawlingContext ) -> None :
143+ context .log .info (f'Processing { context .request .url } ...' )
144+
145+ # Simulate migration through reboot
146+ if context .request .url == requests [1 ] and first_run :
147+ context .log .info (f'Reclaiming { context .request .url } ...' )
148+ rq = await crawler .get_request_manager ()
149+ await rq .reclaim_request (context .request )
150+ await Actor .reboot ()
151+
152+ await crawler .run (requests )
153+
154+ # Each time one request is finished.
155+ assert crawler .statistics .state .requests_finished == 1
156+
157+ actor = await make_actor (label = 'migration' , main_func = main )
158+ run_result = await run_actor (actor )
159+
160+ assert run_result .status == 'SUCCEEDED'
0 commit comments