Skip to content

Commit 186afe7

Browse files
authored
fix: aborting of last Actor/task run (#192)
## Problem description ### Aborting the last Actor run does not work - Resulting in: ``` apify_client._errors.ApifyApiError: We have bad news: there is no API endpoint at this URL. Did you specify it correctly? ``` - Code to reproduce it: ```python # sync version from apify_client import ApifyClient TOKEN = '...' ACTOR_ID = '...' def actor_run_abort(apify_client: ApifyClient, actor_id: str) -> None: actor_client = apify_client.actor(actor_id) actor_client.call(wait_secs=1) last_run = actor_client.last_run(status='RUNNING', origin='API') aborted_info = last_run.abort() print(f'aborted_info: {aborted_info}') if __name__ == '__main__': apify_client = ApifyClient(TOKEN) actor_run_abort(apify_client, ACTOR_ID) ``` ```python # async version import asyncio from apify_client import ApifyClientAsync TOKEN = '...' ACTOR_ID = '...' async def actor_run_abort_async(apify_client: ApifyClientAsync, actor_id: str) -> None: actor_client = apify_client.actor(actor_id) await actor_client.call(wait_secs=1) last_run = await actor_client.last_run(status='RUNNING', origin='API') aborted_info = await last_run.abort() print(f'aborted_info: {aborted_info}') if __name__ == '__main__': apify_client = ApifyClientAsync(TOKEN) asyncio.run(actor_run_abort_async(apify_client, ACTOR_ID)) ``` ### Aborting of the last task run does not work - Resulting in: ``` apify_client._errors.ApifyApiError: We have bad news: there is no API endpoint at this URL. Did you specify it correctly? ``` - Code to reproduce it: ```python # sync version from apify_client import ApifyClient TOKEN = '...' TASK_ID = '...' def task_run_abort(apify_client: ApifyClient, task_id: str) -> None: task_client = apify_client.task(task_id) task_client.call(wait_secs=1) last_run = task_client.last_run(status='RUNNING', origin='API') aborted_info = last_run.abort() print(f'aborted_info: {aborted_info}') if __name__ == '__main__': apify_client = ApifyClient(TOKEN) task_run_abort(apify_client, TASK_ID) ``` ```python # async version import asyncio from apify_client import ApifyClientAsync TOKEN = '...' TASK_ID = '...' async def task_run_abort_async(apify_client: ApifyClientAsync, task_id: str) -> None: task_client = apify_client.task(task_id) await task_client.call(wait_secs=1) last_run = await task_client.last_run(status='RUNNING', origin='API') aborted_info = await last_run.abort() print(f'aborted_info: {aborted_info}') if __name__ == '__main__': apify_client = ApifyClientAsync(TOKEN) asyncio.run(task_run_abort_async(apify_client, TASK_ID)) ``` ### Related issues - The aborting of the last task run was reported in #190. The aborting of the last Actor run does not work as well as was described above. ### Solution - Using additional API call to be able to call `https://api.apify.com/v2/acts/{actorId}/runs/{runId}/abort` in both cases. - In the async version it results in `last_run` method being `async` (should not be released as patch version). - Copied from source code (Actor run): ```python # Note: # The API does not provide a direct endpoint for aborting the last Actor run using a URL like: # https://api.apify.com/v2/acts/{actor_id}/runs/last/abort # To achieve this, we need to implement a workaround using the following URL format: # https://api.apify.com/v2/acts/{actorId}/runs/{runId}/abort ``` - Copied from source code (task run): ```python # Note: # The API does not provide a direct endpoint for aborting the last task run using a URL like: # https://api.apify.com/v2/actor-tasks/{task_id}/runs/last/abort # To achieve this, we need to implement a workaround using the following URL format: # https://api.apify.com/v2/acts/{actorId}/runs/{runId}/abort ``` ### Testing - As we do not have a proper testing framework here, it was tested just manually with the code examples provided at the beginning.
1 parent 87b64bf commit 186afe7

File tree

4 files changed

+96
-9
lines changed

4 files changed

+96
-9
lines changed

CHANGELOG.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
# Changelog
22

3-
## [1.6.5](../../releases/tag/v1.6.5) - Not released yet
3+
## [1.7.0](../../releases/tag/v1.7.0) - Not released yet
44

5-
...
5+
### Fixed
6+
7+
- fix abort of last task run
8+
- fix abort of last Actor run
69

710
## [1.6.4](../../releases/tag/v1.6.4) - 2024-02-27
811

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "apify_client"
3-
version = "1.6.5"
3+
version = "1.7.0"
44
description = "Apify API client for Python"
55
readme = "README.md"
66
license = { text = "Apache Software License" }

src/apify_client/clients/resource_clients/actor.py

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,13 @@ def last_run(
344344
Returns:
345345
RunClient: The resource client for the last run of this actor.
346346
"""
347-
return RunClient(
347+
# Note:
348+
# The API does not provide a direct endpoint for aborting the last Actor run using a URL like:
349+
# https://api.apify.com/v2/acts/{actor_id}/runs/last/abort
350+
# To achieve this, we need to implement a workaround using the following URL format:
351+
# https://api.apify.com/v2/acts/{actorId}/runs/{runId}/abort
352+
353+
last_run_client = RunClient(
348354
**self._sub_resource_init_options(
349355
resource_id='last',
350356
resource_path='runs',
@@ -355,6 +361,21 @@ def last_run(
355361
)
356362
)
357363

364+
last_run_client_info = last_run_client.get()
365+
actor_id = last_run_client_info['actId'] # type: ignore
366+
actor_run_id = last_run_client_info['id'] # type: ignore
367+
368+
return RunClient(
369+
**self._sub_resource_init_options(
370+
base_url='https://api.apify.com/v2',
371+
resource_path=f'acts/{actor_id}/runs/{actor_run_id}',
372+
params=self._params(
373+
status=maybe_extract_enum_member_value(status),
374+
origin=maybe_extract_enum_member_value(origin),
375+
),
376+
)
377+
)
378+
358379
def versions(self: ActorClient) -> ActorVersionCollectionClient:
359380
"""Retrieve a client for the versions of this actor."""
360381
return ActorVersionCollectionClient(**self._sub_resource_init_options())
@@ -634,7 +655,7 @@ def runs(self: ActorClientAsync) -> RunCollectionClientAsync:
634655
"""Retrieve a client for the runs of this actor."""
635656
return RunCollectionClientAsync(**self._sub_resource_init_options(resource_path='runs'))
636657

637-
def last_run(self: ActorClientAsync, *, status: ActorJobStatus | None = None, origin: MetaOrigin | None = None) -> RunClientAsync:
658+
async def last_run(self: ActorClientAsync, *, status: ActorJobStatus | None = None, origin: MetaOrigin | None = None) -> RunClientAsync:
638659
"""Retrieve the client for the last run of this actor.
639660
640661
Last run is retrieved based on the start time of the runs.
@@ -646,7 +667,13 @@ def last_run(self: ActorClientAsync, *, status: ActorJobStatus | None = None, or
646667
Returns:
647668
RunClientAsync: The resource client for the last run of this actor.
648669
"""
649-
return RunClientAsync(
670+
# Note:
671+
# The API does not provide a direct endpoint for aborting the last Actor run using a URL like:
672+
# https://api.apify.com/v2/acts/{actor_id}/runs/last/abort
673+
# To achieve this, we need to implement a workaround using the following URL format:
674+
# https://api.apify.com/v2/acts/{actorId}/runs/{runId}/abort
675+
676+
last_run_client = RunClientAsync(
650677
**self._sub_resource_init_options(
651678
resource_id='last',
652679
resource_path='runs',
@@ -657,6 +684,21 @@ def last_run(self: ActorClientAsync, *, status: ActorJobStatus | None = None, or
657684
)
658685
)
659686

687+
last_run_client_info = await last_run_client.get()
688+
actor_id = last_run_client_info['actId'] # type: ignore
689+
actor_run_id = last_run_client_info['id'] # type: ignore
690+
691+
return RunClientAsync(
692+
**self._sub_resource_init_options(
693+
base_url='https://api.apify.com/v2',
694+
resource_path=f'acts/{actor_id}/runs/{actor_run_id}',
695+
params=self._params(
696+
status=maybe_extract_enum_member_value(status),
697+
origin=maybe_extract_enum_member_value(origin),
698+
),
699+
)
700+
)
701+
660702
def versions(self: ActorClientAsync) -> ActorVersionCollectionClientAsync:
661703
"""Retrieve a client for the versions of this actor."""
662704
return ActorVersionCollectionClientAsync(**self._sub_resource_init_options())

src/apify_client/clients/resource_clients/task.py

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,13 @@ def last_run(self: TaskClient, *, status: ActorJobStatus | None = None, origin:
266266
Returns:
267267
RunClient: The resource client for the last run of this task.
268268
"""
269-
return RunClient(
269+
# Note:
270+
# The API does not provide a direct endpoint for aborting the last task run using a URL like:
271+
# https://api.apify.com/v2/actor-tasks/{task_id}/runs/last/abort
272+
# To achieve this, we need to implement a workaround using the following URL format:
273+
# https://api.apify.com/v2/acts/{actorId}/runs/{runId}/abort
274+
275+
last_run_client = RunClient(
270276
**self._sub_resource_init_options(
271277
resource_id='last',
272278
resource_path='runs',
@@ -277,6 +283,21 @@ def last_run(self: TaskClient, *, status: ActorJobStatus | None = None, origin:
277283
)
278284
)
279285

286+
last_run_client_info = last_run_client.get()
287+
actor_id = last_run_client_info['actId'] # type: ignore
288+
actor_run_id = last_run_client_info['id'] # type: ignore
289+
290+
return RunClient(
291+
**self._sub_resource_init_options(
292+
base_url='https://api.apify.com/v2',
293+
resource_path=f'acts/{actor_id}/runs/{actor_run_id}',
294+
params=self._params(
295+
status=maybe_extract_enum_member_value(status),
296+
origin=maybe_extract_enum_member_value(origin),
297+
),
298+
)
299+
)
300+
280301
def webhooks(self: TaskClient) -> WebhookCollectionClient:
281302
"""Retrieve a client for webhooks associated with this task."""
282303
return WebhookCollectionClient(**self._sub_resource_init_options())
@@ -491,7 +512,7 @@ def runs(self: TaskClientAsync) -> RunCollectionClientAsync:
491512
"""Retrieve a client for the runs of this task."""
492513
return RunCollectionClientAsync(**self._sub_resource_init_options(resource_path='runs'))
493514

494-
def last_run(self: TaskClientAsync, *, status: ActorJobStatus | None = None, origin: MetaOrigin | None = None) -> RunClientAsync:
515+
async def last_run(self: TaskClientAsync, *, status: ActorJobStatus | None = None, origin: MetaOrigin | None = None) -> RunClientAsync:
495516
"""Retrieve the client for the last run of this task.
496517
497518
Last run is retrieved based on the start time of the runs.
@@ -503,7 +524,13 @@ def last_run(self: TaskClientAsync, *, status: ActorJobStatus | None = None, ori
503524
Returns:
504525
RunClientAsync: The resource client for the last run of this task.
505526
"""
506-
return RunClientAsync(
527+
# Note:
528+
# The API does not provide a direct endpoint for aborting the last task run using a URL like:
529+
# https://api.apify.com/v2/actor-tasks/{task_id}/runs/last/abort
530+
# To achieve this, we need to implement a workaround using the following URL format:
531+
# https://api.apify.com/v2/acts/{actorId}/runs/{runId}/abort
532+
533+
last_run_client = RunClientAsync(
507534
**self._sub_resource_init_options(
508535
resource_id='last',
509536
resource_path='runs',
@@ -514,6 +541,21 @@ def last_run(self: TaskClientAsync, *, status: ActorJobStatus | None = None, ori
514541
)
515542
)
516543

544+
last_run_client_info = await last_run_client.get()
545+
actor_id = last_run_client_info['actId'] # type: ignore
546+
actor_run_id = last_run_client_info['id'] # type: ignore
547+
548+
return RunClientAsync(
549+
**self._sub_resource_init_options(
550+
base_url='https://api.apify.com/v2',
551+
resource_path=f'acts/{actor_id}/runs/{actor_run_id}',
552+
params=self._params(
553+
status=maybe_extract_enum_member_value(status),
554+
origin=maybe_extract_enum_member_value(origin),
555+
),
556+
)
557+
)
558+
517559
def webhooks(self: TaskClientAsync) -> WebhookCollectionClientAsync:
518560
"""Retrieve a client for webhooks associated with this task."""
519561
return WebhookCollectionClientAsync(**self._sub_resource_init_options())

0 commit comments

Comments
 (0)