apify-sdk-python icon indicating copy to clipboard operation
apify-sdk-python copied to clipboard

Make Actor consistently reusable without raising `ServiceConflictError`

Open vdusek opened this issue 4 months ago • 0 comments

Description

The following patterns should all be equivalent and valid:

1) Actor + Actor - works ✔️

async with Actor:
    Actor.exit_process = False
    print('Hello world')

async with Actor:
    print('Hello world')

2) Actor() + Actor - works ✔️

async with Actor(exit_process=False) as actor:
    print('Hello world')

async with Actor:
    print('Hello world')

3) Actor + Actor() - ServiceConflictError

async with Actor:
    Actor.exit_process = False
    print('Hello world')

async with Actor() as actor:
    print('Hello world')

4) Actor() + Actor() - ServiceConflictError

async with Actor(exit_process=False) as actor:
    print('Hello world')

async with Actor() as actor:
    print('Hello world')

We have real use cases for this (e.g., in the example-code-runner-py Actor).

However, some of these code paths currently raise a ServiceConflictError:

crawlee.errors.ServiceConflictError: Service EventManager is already in use. Existing value: <crawlee.events._local_event_manager.LocalEventManager object at 0x7f84b5460ad0>, attempted new value: <crawlee.events._local_event_manager.LocalEventManager object at 0x7f84b7483d90>.

This means the Actor context manager is not fully isolated between runs.

Possible solution

Apply the same service-locator cleanup/isolation logic that we already use in conftest.py:

# Reset the services in the service locator.
service_locator._configuration = None
service_locator._event_manager = None
service_locator._storage_client = None
service_locator.storage_instance_manager.clear_cache()

This should allow all async with Actor usages to behave consistently and avoid cross-run conflicts.

vdusek avatar Nov 13 '25 12:11 vdusek