@@ -1139,7 +1139,7 @@ async def test_named_start_gets_the_budget_left(apify_client_async_patcher: Apif
11391139 """A named start without a charge limit gets the part of the parent's budget it has not charged itself."""
11401140 async with Actor :
11411141 await Actor .charge ('some-event' , count = 3 )
1142- await Actor .start ('some-actor' , name = 'child' )
1142+ await Actor .start ('some-actor' , run_name = 'child' )
11431143
11441144 assert started_limits (apify_client_async_patcher ) == [Decimal (7 )]
11451145
@@ -1159,7 +1159,7 @@ async def test_named_start_charge_limit_is_capped_at_the_budget_left(
11591159) -> None :
11601160 """An explicit charge limit of a named start is kept within the budget left and lowered above it."""
11611161 async with Actor :
1162- await Actor .start ('some-actor' , name = 'child' , max_total_charge_usd = requested )
1162+ await Actor .start ('some-actor' , run_name = 'child' , max_total_charge_usd = requested )
11631163
11641164 assert started_limits (apify_client_async_patcher ) == [expected ]
11651165
@@ -1171,7 +1171,7 @@ async def test_unnamed_start_charge_limit_is_passed_through(
11711171 """A start without a name is not tracked, so its charge limit is neither capped nor reserved."""
11721172 async with Actor :
11731173 await Actor .start ('some-actor' , max_total_charge_usd = Decimal (20 ))
1174- await Actor .start ('some-actor' , name = 'child' )
1174+ await Actor .start ('some-actor' , run_name = 'child' )
11751175
11761176 assert started_limits (apify_client_async_patcher ) == [Decimal (20 ), Decimal (10 )]
11771177
@@ -1183,8 +1183,8 @@ async def test_named_start_charge_limit_is_passed_through_without_a_parent_budge
11831183 apify_client_async_patcher .patch ('actor' , 'start' , return_value = make_run ('new-run' , 'READY' ))
11841184
11851185 async with Actor :
1186- await Actor .start ('some-actor' , name = 'first' , max_total_charge_usd = Decimal (20 ))
1187- await Actor .start ('some-actor' , name = 'second' )
1186+ await Actor .start ('some-actor' , run_name = 'first' , max_total_charge_usd = Decimal (20 ))
1187+ await Actor .start ('some-actor' , run_name = 'second' )
11881188
11891189 assert started_limits (apify_client_async_patcher ) == [Decimal (20 ), None ]
11901190
@@ -1193,19 +1193,47 @@ async def test_named_start_charge_limit_is_passed_through_without_a_parent_budge
11931193async def test_running_child_run_reserves_its_charge_limit (apify_client_async_patcher : ApifyClientAsyncPatcher ) -> None :
11941194 """The limit of a running child run is reserved, both from later child runs and from the parent's own charges."""
11951195 async with Actor :
1196- await Actor .start ('some-actor' , name = 'first' , max_total_charge_usd = Decimal (6 ))
1196+ await Actor .start ('some-actor' , run_name = 'first' , max_total_charge_usd = Decimal (6 ))
11971197 charge_result = await Actor .charge ('some-event' , count = 3 )
1198- await Actor .start ('some-actor' , name = 'second' )
1198+ await Actor .start ('some-actor' , run_name = 'second' )
11991199
12001200 assert charge_result .charged_count == 3
12011201 assert started_limits (apify_client_async_patcher ) == [Decimal (6 ), Decimal (1 )]
12021202
12031203
1204+ @pytest .mark .usefixtures ('parent_budget' )
1205+ async def test_named_call_task_is_rejected_under_a_parent_budget (
1206+ apify_client_async_patcher : ApifyClientAsyncPatcher ,
1207+ ) -> None :
1208+ """A named task call that would start a run under a parent budget set by the user raises without starting it."""
1209+ apify_client_async_patcher .patch ('task' , 'start' , return_value = make_run ('task-run' , 'READY' ))
1210+
1211+ async with Actor :
1212+ with pytest .raises (RuntimeError , match = 'cannot be given a part of the budget' ):
1213+ await Actor .call_task ('some-task' , run_name = 'child' )
1214+
1215+ assert apify_client_async_patcher .calls ['task' ]['start' ] == []
1216+
1217+
1218+ async def test_named_call_task_starts_without_a_charge_limit (
1219+ apify_client_async_patcher : ApifyClientAsyncPatcher ,
1220+ ) -> None :
1221+ """Without a parent budget, a named task call starts the task with the options the task client accepts."""
1222+ apify_client_async_patcher .patch ('task' , 'start' , return_value = make_run ('task-run' , 'READY' ))
1223+ apify_client_async_patcher .patch ('run' , 'wait_for_finish' , return_value = make_run ('task-run' , 'SUCCEEDED' ))
1224+
1225+ async with Actor :
1226+ await Actor .call_task ('some-task' , run_name = 'child' )
1227+
1228+ [(_ , kwargs )] = apify_client_async_patcher .calls ['task' ]['start' ]
1229+ assert 'max_total_charge_usd' not in kwargs
1230+
1231+
12041232@pytest .mark .usefixtures ('parent_budget' )
12051233async def test_reserved_budget_limits_the_parent_charges () -> None :
12061234 """The parent charges only the part of its budget not reserved for child runs."""
12071235 async with Actor :
1208- await Actor .start ('some-actor' , name = 'child' , max_total_charge_usd = Decimal (6 ))
1236+ await Actor .start ('some-actor' , run_name = 'child' , max_total_charge_usd = Decimal (6 ))
12091237 charge_result = await Actor .charge ('some-event' , count = 10 )
12101238
12111239 assert charge_result .charged_count == 4
@@ -1215,17 +1243,17 @@ async def test_reserved_budget_limits_the_parent_charges() -> None:
12151243async def test_exhausted_budget_rejects_a_named_start () -> None :
12161244 """A named start raises when the whole parent budget is charged or reserved."""
12171245 async with Actor :
1218- await Actor .start ('some-actor' , name = 'first' )
1246+ await Actor .start ('some-actor' , run_name = 'first' )
12191247 with pytest .raises (RuntimeError , match = 'budget of this Actor run is spent or reserved' ):
1220- await Actor .start ('some-actor' , name = 'second' )
1248+ await Actor .start ('some-actor' , run_name = 'second' )
12211249
12221250
12231251@pytest .mark .usefixtures ('parent_budget' )
12241252async def test_concurrent_named_starts_share_the_budget () -> None :
12251253 """Concurrent named starts reserve their limits one at a time, so together they stay within the budget."""
12261254 async with Actor :
12271255 results = await asyncio .gather (
1228- * (Actor .start ('some-actor' , name = name , max_total_charge_usd = Decimal (6 )) for name in ('a' , 'b' )),
1256+ * (Actor .start ('some-actor' , run_name = name , max_total_charge_usd = Decimal (6 )) for name in ('a' , 'b' )),
12291257 return_exceptions = True ,
12301258 )
12311259 child_runs = await Actor .child_runs ()
@@ -1240,11 +1268,11 @@ async def test_finished_child_run_releases_its_unused_budget(
12401268 """A finished child run keeps only its charge reserved, and records it once it can no longer change."""
12411269 monkeypatch .setattr ('apify._child_runs._STATUS_MAX_AGE' , timedelta (0 ))
12421270 async with Actor :
1243- first = await Actor .start ('some-actor' , name = 'first' , max_total_charge_usd = Decimal (6 ))
1271+ first = await Actor .start ('some-actor' , run_name = 'first' , max_total_charge_usd = Decimal (6 ))
12441272 parent_budget [first .id ] = finish (parent_budget [first .id ], 'SUCCEEDED' , 2 )
1245- await Actor .start ('some-actor' , name = 'second' , max_total_charge_usd = Decimal (3 ))
1273+ await Actor .start ('some-actor' , run_name = 'second' , max_total_charge_usd = Decimal (3 ))
12461274 parent_budget ['run-2' ] = finish (parent_budget ['run-2' ], 'SUCCEEDED' , 1 , finished_ago = timedelta (minutes = 5 ))
1247- await Actor .start ('some-actor' , name = 'third' )
1275+ await Actor .start ('some-actor' , run_name = 'third' )
12481276 kvs = await Actor .open_key_value_store ()
12491277 stored = await kvs .get_value (CHILD_RUNS_KEY )
12501278
@@ -1293,7 +1321,7 @@ async def test_resurrection_reuses_the_reservation_of_its_run(
12931321 )
12941322
12951323 async with _ActorType () as actor :
1296- await actor .start ('some-actor' , name = 'child' )
1324+ await actor .start ('some-actor' , run_name = 'child' )
12971325
12981326 [(_ , kwargs )] = apify_client_async_patcher .calls ['run' ]['resurrect' ]
12991327 assert kwargs ['max_total_charge_usd' ] == Decimal (7 )
@@ -1309,7 +1337,7 @@ async def test_replaced_failed_run_keeps_its_charge_reserved(
13091337 await seed_budget_record ('child' , 'old-run' , maxTotalChargeUsd = '6' )
13101338
13111339 async with _ActorType () as actor :
1312- await actor .start ('some-actor' , name = 'child' )
1340+ await actor .start ('some-actor' , run_name = 'child' )
13131341 kvs = await actor .open_key_value_store ()
13141342 stored = await kvs .get_value (CHILD_RUNS_KEY )
13151343
@@ -1324,7 +1352,7 @@ async def test_failed_named_start_releases_its_reservation(apify_client_async_pa
13241352 async with Actor :
13251353 apify_client_async_patcher .patch ('actor' , 'start' , replacement_method = Mock (side_effect = RuntimeError ('boom' )))
13261354 with pytest .raises (RuntimeError , match = 'boom' ):
1327- await Actor .start ('some-actor' , name = 'child' )
1355+ await Actor .start ('some-actor' , run_name = 'child' )
13281356 charge_result = await Actor .charge ('some-event' , count = 10 )
13291357
13301358 assert charge_result .charged_count == 10
@@ -1346,7 +1374,7 @@ async def start(*_args: Any, **_kwargs: Any) -> Run:
13461374
13471375 async with Actor :
13481376 apify_client_async_patcher .patch ('actor' , 'start' , replacement_method = start )
1349- start_task = asyncio .create_task (Actor .start ('some-actor' , name = 'first' ))
1377+ start_task = asyncio .create_task (Actor .start ('some-actor' , run_name = 'first' ))
13501378 await started .wait ()
13511379 charge_result = await Actor .charge ('some-event' , count = 1 )
13521380 release .set ()
@@ -1358,7 +1386,7 @@ async def start(*_args: Any, **_kwargs: Any) -> Run:
13581386async def test_listing_child_runs_releases_the_unused_budget (parent_budget : dict [str , Run ]) -> None :
13591387 """Listing the child runs releases the unused limit of those that finished."""
13601388 async with Actor :
1361- run = await Actor .start ('some-actor' , name = 'child' , max_total_charge_usd = Decimal (6 ))
1389+ run = await Actor .start ('some-actor' , run_name = 'child' , max_total_charge_usd = Decimal (6 ))
13621390 parent_budget [run .id ] = finish (parent_budget [run .id ], 'SUCCEEDED' , 2 )
13631391 await Actor .child_runs ()
13641392 charge_result = await Actor .charge ('some-event' , count = 10 )
@@ -1377,7 +1405,7 @@ async def test_named_call_releases_the_unused_budget_when_the_run_finishes(
13771405 )
13781406
13791407 async with Actor :
1380- await Actor .call ('some-actor' , name = 'child' , max_total_charge_usd = Decimal (6 ), logger = None )
1408+ await Actor .call ('some-actor' , run_name = 'child' , max_total_charge_usd = Decimal (6 ), logger = None )
13811409 charge_result = await Actor .charge ('some-event' , count = 10 )
13821410
13831411 assert charge_result .charged_count == 8
@@ -1393,8 +1421,8 @@ async def test_platform_default_charge_limit_is_not_shared_with_child_runs(
13931421 )
13941422
13951423 async with Actor :
1396- await Actor .start ('some-actor' , name = 'first' )
1397- await Actor .start ('some-actor' , name = 'second' , max_total_charge_usd = Decimal (20 ))
1424+ await Actor .start ('some-actor' , run_name = 'first' )
1425+ await Actor .start ('some-actor' , run_name = 'second' , max_total_charge_usd = Decimal (20 ))
13981426 charge_result = await Actor .charge ('some-event' , count = 10 )
13991427
14001428 assert started_limits (apify_client_async_patcher ) == [None , Decimal (20 )]
@@ -1430,7 +1458,7 @@ def resurrect(run_client: Any, **_: Any) -> Run:
14301458 async with _ActorType () as actor :
14311459 list_task = asyncio .create_task (actor .child_runs ())
14321460 await listing .wait ()
1433- await actor .start ('some-actor' , name = 'child' )
1461+ await actor .start ('some-actor' , run_name = 'child' )
14341462 release .set ()
14351463 await list_task
14361464 charge_result = await actor .charge ('some-event' , count = 10 )
@@ -1457,7 +1485,7 @@ async def resurrect(run_client: Any, **_: Any) -> Run:
14571485 apify_client_async_patcher .patch ('run' , 'resurrect' , replacement_method = resurrect , is_async = True )
14581486
14591487 async with _ActorType () as actor :
1460- start_task = asyncio .create_task (actor .start ('some-actor' , name = 'child' , max_total_charge_usd = Decimal (4 )))
1488+ start_task = asyncio .create_task (actor .start ('some-actor' , run_name = 'child' , max_total_charge_usd = Decimal (4 )))
14611489 await started .wait ()
14621490 charge_result = await actor .charge ('some-event' , count = 10 )
14631491 release .set ()
@@ -1479,7 +1507,7 @@ async def test_failed_resurrection_leaves_the_charge_of_its_run_to_settle(
14791507
14801508 async with _ActorType () as actor :
14811509 with pytest .raises (RuntimeError , match = 'boom' ):
1482- await actor .start ('some-actor' , name = 'child' )
1510+ await actor .start ('some-actor' , run_name = 'child' )
14831511 monkeypatch .setattr ('apify._child_runs._CHARGE_SETTLE_TIME' , timedelta (0 ))
14841512 await actor .child_runs ()
14851513 kvs = await actor .open_key_value_store ()
0 commit comments