apify / apify-client-python

Apify API client for Python
https://docs.apify.com/api/client/python/
Apache License 2.0
42 stars 10 forks source link

Getting storages of last run does not work #231

Closed vdusek closed 5 days ago

vdusek commented 1 month ago

After the recent fix to abort the last runs - fix: aborting of last Actor/task run, a new issue has emerged: retrieving the storages of the last run no longer works.

How to reproduce:

import logging

from apify_client import ApifyClient

TOKEN = '...'
ACTOR_ID = '...'

logging.basicConfig(level=logging.DEBUG)

def actor_run_abort(apify_client: ApifyClient, actor_id: str) -> None:
    actor_client = apify_client.actor(actor_id)
    last_run = actor_client.last_run()
    last_run_kvs_client = last_run.key_value_store()
    output = last_run_kvs_client.get_record('OUTPUT')
    print(f'output: {output}')

if __name__ == '__main__':
    apify_client = ApifyClient(TOKEN)
    actor_run_abort(apify_client, ACTOR_ID)

This issue also occurs with the last task run and their async versions.

Once a fix is implemented, we should release a beta version and use it in the SDK to run integration tests there, as the current test coverage of the client is very limited.

vdusek commented 1 month ago

Some investigation...

The expected endpoint (docs):

/v2/actor-runs/{runId}/key-value-store

This one is called instead:

/v2/acts/{actorId}/runs/{runId}/key-value-store

resulting in:

ApifyApiError: We have bad news: there is no API endpoint at this URL. Did you specify it correctly?
vdusek commented 1 month ago

Solution: Platform team will provide us a new API endpoint for aborting the last runs (https://github.com/apify/apify-core/issues/16225), we will then revert "hacks" in https://github.com/apify/apify-client-python/pull/192.

honzajavorek commented 1 week ago

I think I'm affected by this. Until upgrade the following code worked OK:

def fetch_data(
    actor_name: str,
    token: str | None = None,
    raise_if_missing: bool = True,
) -> list[dict]:
    client = ApifyClient(token=token or APIFY_API_KEY)

    logger.debug(f"Getting last successful run of {actor_name}")
    actor = client.actor(actor_name)
    last_run = actor.last_run(status=ActorJobStatus.SUCCEEDED)
    run_info = last_run.get()
    if run_info is None:
        if raise_if_missing:
            raise RuntimeError(f"No successful runs of {actor_name!r} found")
        logger.error(f"No successful runs of {actor_name!r} found")
        return []

    run_url = (
        f"https://console.apify.com/actors/{run_info['actId']}/runs/{run_info['id']}"
    )
    logger.debug(
        f"Last successful run of {actor_name}: {run_url}, "
        f"finished {run_info['finishedAt']}, "
        f"took {run_info['stats']['runTimeSecs']}s"
    )
    dataset = last_run.dataset()
    return list(dataset.iterate_items())

Now it crashes:

  File "/Users/honza/Projects/juniorguru/jg/coop/sync/courses_up.py", line 16, in main
    for course in (item for item in apify.fetch_data("honzajavorek/courses-up")):
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/honza/Projects/juniorguru/.venv/lib/python3.11/site-packages/diskcache/core.py", line 1875, in wrapper
    result = func(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/honza/Projects/juniorguru/jg/coop/lib/apify.py", line 44, in fetch_data
    return list(dataset.iterate_items())
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/honza/Projects/juniorguru/.venv/lib/python3.11/site-packages/apify_client/clients/resource_clients/dataset.py", line 196, in iterate_items
    current_items_page = self.list_items(
                         ^^^^^^^^^^^^^^^^
  File "/Users/honza/Projects/juniorguru/.venv/lib/python3.11/site-packages/apify_client/_logging.py", line 82, in wrapper
    return fun(resource_client, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/honza/Projects/juniorguru/.venv/lib/python3.11/site-packages/apify_client/clients/resource_clients/dataset.py", line 120, in list_items
    response = self.http_client.call(
               ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/honza/Projects/juniorguru/.venv/lib/python3.11/site-packages/apify_client/_http_client.py", line 193, in call
    return retry_with_exp_backoff(
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/honza/Projects/juniorguru/.venv/lib/python3.11/site-packages/apify_client/_utils.py", line 64, in retry_with_exp_backoff
    return func(stop_retrying, attempt)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/honza/Projects/juniorguru/.venv/lib/python3.11/site-packages/apify_client/_http_client.py", line 191, in _make_request
    raise ApifyApiError(response, attempt)
apify_client._errors.ApifyApiError: We have bad news: there is no API endpoint at this URL. Did you specify it correctly?
vdusek commented 5 days ago

Thanks @honzajavorek, I'll provide a patch version soon.

honzajavorek commented 5 hours ago

I can confirm 1.7.1 fixes the issue, thanks!