Skip to content

Commit b2355cf

Browse files
authored
fix: Fix detection of whether any instance is initialized (#675)
Closes: #674
1 parent 34e1e23 commit b2355cf

File tree

3 files changed

+60
-71
lines changed

3 files changed

+60
-71
lines changed

src/apify/_actor.py

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,8 @@
3434
from apify._utils import docs_group, docs_name, get_system_info, is_running_in_ipython
3535
from apify.events import ApifyEventManager, EventManager, LocalEventManager
3636
from apify.log import _configure_logging, logger
37-
from apify.storage_clients import ApifyStorageClient
37+
from apify.storage_clients import ApifyStorageClient, SmartApifyStorageClient
3838
from apify.storage_clients._file_system import ApifyFileSystemStorageClient
39-
from apify.storage_clients._smart_apify._storage_client import SmartApifyStorageClient
4039
from apify.storages import Dataset, KeyValueStore, RequestQueue
4140

4241
if TYPE_CHECKING:
@@ -95,12 +94,6 @@ async def main() -> None:
9594
```
9695
"""
9796

98-
_is_rebooting = False
99-
"""Whether the Actor is currently rebooting."""
100-
101-
_is_any_instance_initialized = False
102-
"""Whether any Actor instance was initialized."""
103-
10497
def __init__(
10598
self,
10699
configuration: Configuration | None = None,
@@ -139,8 +132,14 @@ def __init__(
139132

140133
self._apify_client: ApifyClientAsync | None = None
141134

142-
self._is_exiting = False
143135
self._is_initialized = False
136+
"""Whether any Actor instance is currently initialized."""
137+
138+
self._is_rebooting = False
139+
"""Whether the Actor is currently rebooting."""
140+
141+
self._is_exiting = False
142+
"""Whether the Actor is currently exiting."""
144143

145144
async def __aenter__(self) -> Self:
146145
"""Enter the Actor context.
@@ -169,15 +168,11 @@ async def __aenter__(self) -> Self:
169168
# Configure logging based on the configuration, any logs before this point are lost.
170169
if self._configure_logging:
171170
_configure_logging()
172-
self.log.debug('Logging configured')
171+
self.log.debug('Logging configured')
173172

174173
self.log.info('Initializing Actor', extra=get_system_info())
175174
self.log.debug('Configuration initialized')
176175

177-
# Warn about non-standard usage patterns.
178-
if _ActorType._is_any_instance_initialized:
179-
self.log.warning('Repeated Actor initialization detected - this is non-standard usage, proceed with care.')
180-
181176
# Update the global Actor proxy to refer to this instance.
182177
cast('Proxy', Actor).__wrapped__ = self
183178
self._is_exiting = False
@@ -197,7 +192,6 @@ async def __aenter__(self) -> Self:
197192

198193
# Mark initialization as complete and update global state.
199194
self._is_initialized = True
200-
_ActorType._is_any_instance_initialized = True
201195
return self
202196

203197
async def __aexit__(
@@ -1113,11 +1107,11 @@ async def reboot(
11131107
self.log.error('Actor.reboot() is only supported when running on the Apify platform.')
11141108
return
11151109

1116-
if _ActorType._is_rebooting:
1110+
if self._is_rebooting:
11171111
self.log.debug('Actor is already rebooting, skipping the additional reboot call.')
11181112
return
11191113

1120-
_ActorType._is_rebooting = True
1114+
self._is_rebooting = True
11211115

11221116
if not custom_after_sleep:
11231117
custom_after_sleep = self.configuration.metamorph_after_sleep

tests/unit/actor/test_actor_log.py

Lines changed: 48 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -36,72 +36,67 @@ async def test_actor_logs_messages_correctly(caplog: pytest.LogCaptureFixture) -
3636
# Test that exception in Actor.main is logged with the traceback
3737
raise RuntimeError('Dummy RuntimeError')
3838

39-
# We skip the first entry, as it is related to the initialization of `lazy_object_proxy.Proxy` for `Actor`.
40-
records = caplog.records[1:]
39+
records = caplog.records
4140

42-
# Updated expected number of log records (additional debug messages added)
43-
assert len(records) == 14
41+
# Expected number of log records
42+
assert len(records) == 13
4443

45-
# Record 0: Logging configured
46-
assert records[0].levelno == logging.DEBUG
47-
assert records[0].message == 'Logging configured'
44+
# Record 0: Initializing Actor
45+
assert records[0].levelno == logging.INFO
46+
assert records[0].message == 'Initializing Actor'
4847

49-
# Record 1: Initializing Actor
50-
assert records[1].levelno == logging.INFO
51-
assert records[1].message == 'Initializing Actor'
48+
# Record 1: Configuration initialized
49+
assert records[1].levelno == logging.DEBUG
50+
assert records[1].message == 'Configuration initialized'
5251

53-
# Record 2: Configuration initialized
52+
# Record 2: Storage client initialized
5453
assert records[2].levelno == logging.DEBUG
55-
assert records[2].message == 'Configuration initialized'
54+
assert records[2].message == 'Storage client initialized'
5655

57-
# Record 3: Storage client initialized
56+
# Record 3: Event manager initialized
5857
assert records[3].levelno == logging.DEBUG
59-
assert records[3].message == 'Storage client initialized'
58+
assert records[3].message == 'Event manager initialized'
6059

61-
# Record 4: Event manager initialized
60+
# Record 4: Charging manager initialized
6261
assert records[4].levelno == logging.DEBUG
63-
assert records[4].message == 'Event manager initialized'
62+
assert records[4].message == 'Charging manager initialized'
6463

65-
# Record 5: Charging manager initialized
64+
# Record 5: Debug message
6665
assert records[5].levelno == logging.DEBUG
67-
assert records[5].message == 'Charging manager initialized'
66+
assert records[5].message == 'Debug message'
6867

69-
# Record 6: Debug message
70-
assert records[6].levelno == logging.DEBUG
71-
assert records[6].message == 'Debug message'
68+
# Record 6: Info message
69+
assert records[6].levelno == logging.INFO
70+
assert records[6].message == 'Info message'
7271

73-
# Record 7: Info message
74-
assert records[7].levelno == logging.INFO
75-
assert records[7].message == 'Info message'
72+
# Record 7: Warning message
73+
assert records[7].levelno == logging.WARNING
74+
assert records[7].message == 'Warning message'
7675

77-
# Record 8: Warning message
78-
assert records[8].levelno == logging.WARNING
79-
assert records[8].message == 'Warning message'
76+
# Record 8: Error message
77+
assert records[8].levelno == logging.ERROR
78+
assert records[8].message == 'Error message'
8079

81-
# Record 9: Error message
80+
# Record 9: Exception message with traceback (ValueError)
8281
assert records[9].levelno == logging.ERROR
83-
assert records[9].message == 'Error message'
84-
85-
# Record 10: Exception message with traceback (ValueError)
86-
assert records[10].levelno == logging.ERROR
87-
assert records[10].message == 'Exception message'
88-
assert records[10].exc_info is not None
89-
assert records[10].exc_info[0] is ValueError
90-
assert isinstance(records[10].exc_info[1], ValueError)
91-
assert str(records[10].exc_info[1]) == 'Dummy ValueError'
92-
93-
# Record 11: Multiline log message
94-
assert records[11].levelno == logging.INFO
95-
assert records[11].message == 'Multi\nline\nlog\nmessage'
96-
97-
# Record 12: Actor failed with an exception (RuntimeError)
98-
assert records[12].levelno == logging.ERROR
99-
assert records[12].message == 'Actor failed with an exception'
100-
assert records[12].exc_info is not None
101-
assert records[12].exc_info[0] is RuntimeError
102-
assert isinstance(records[12].exc_info[1], RuntimeError)
103-
assert str(records[12].exc_info[1]) == 'Dummy RuntimeError'
104-
105-
# Record 13: Exiting Actor
106-
assert records[13].levelno == logging.INFO
107-
assert records[13].message == 'Exiting Actor'
82+
assert records[9].message == 'Exception message'
83+
assert records[9].exc_info is not None
84+
assert records[9].exc_info[0] is ValueError
85+
assert isinstance(records[9].exc_info[1], ValueError)
86+
assert str(records[9].exc_info[1]) == 'Dummy ValueError'
87+
88+
# Record 10: Multiline log message
89+
assert records[10].levelno == logging.INFO
90+
assert records[10].message == 'Multi\nline\nlog\nmessage'
91+
92+
# Record 11: Actor failed with an exception (RuntimeError)
93+
assert records[11].levelno == logging.ERROR
94+
assert records[11].message == 'Actor failed with an exception'
95+
assert records[11].exc_info is not None
96+
assert records[11].exc_info[0] is RuntimeError
97+
assert isinstance(records[11].exc_info[1], RuntimeError)
98+
assert str(records[11].exc_info[1]) == 'Dummy RuntimeError'
99+
100+
# Record 12: Exiting Actor
101+
assert records[12].levelno == logging.INFO
102+
assert records[12].message == 'Exiting Actor'

tests/unit/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def prepare_test_env(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> Callabl
6262
def _prepare_test_env() -> None:
6363
if hasattr(apify._actor.Actor, '__wrapped__'):
6464
delattr(apify._actor.Actor, '__wrapped__')
65-
apify._actor._ActorType._is_any_instance_initialized = False
65+
apify._actor.Actor._is_initialized = False
6666

6767
# Set the environment variable for the local storage directory to the temporary path.
6868
monkeypatch.setenv(ApifyEnvVars.LOCAL_STORAGE_DIR, str(tmp_path))

0 commit comments

Comments
 (0)