|
5 | 5 | from logging import getLogger |
6 | 6 | from typing import TYPE_CHECKING, ClassVar, Literal, overload |
7 | 7 |
|
| 8 | +from propcache import cached_property |
| 9 | + |
8 | 10 | from apify_client import ApifyClientAsync |
9 | 11 |
|
10 | 12 | from ._utils import hash_api_base_url_and_token |
@@ -136,11 +138,9 @@ def __init__( |
136 | 138 | alias: str, |
137 | 139 | configuration: Configuration, |
138 | 140 | ) -> None: |
| 141 | + self._storage_type = storage_type |
139 | 142 | self._alias = alias |
140 | 143 | self._configuration = configuration |
141 | | - self._storage_key = self.get_storage_key( |
142 | | - storage_type=storage_type, alias=alias, additional_cache_key=hash_api_base_url_and_token(configuration) |
143 | | - ) |
144 | 144 |
|
145 | 145 | async def __aenter__(self) -> AliasResolver: |
146 | 146 | """Context manager to prevent race condition in alias creation.""" |
@@ -194,6 +194,18 @@ async def resolve_id(self) -> str | None: |
194 | 194 | Returns: |
195 | 195 | Storage id if it exists, None otherwise. |
196 | 196 | """ |
| 197 | + # First try to find the alias in the configuration mapping to avoid any API calls. |
| 198 | + # This mapping is maintained by the Apify platform and does not have to be maintained in the default KVS. |
| 199 | + if self._configuration.actor_storages and self._alias != 'default': |
| 200 | + storage_maps = { |
| 201 | + 'Dataset': self._configuration.actor_storages.datasets, |
| 202 | + 'KeyValueStore': self._configuration.actor_storages.key_value_stores, |
| 203 | + 'RequestQueue': self._configuration.actor_storages.request_queues, |
| 204 | + } |
| 205 | + if storage_id := storage_maps.get(self._storage_type, {}).get(self._alias): |
| 206 | + return storage_id |
| 207 | + |
| 208 | + # Fallback to the mapping saved in the default KVS |
197 | 209 | return (await self._get_alias_map(self._configuration)).get(self._storage_key, None) |
198 | 210 |
|
199 | 211 | async def store_mapping(self, storage_id: str) -> None: |
@@ -237,60 +249,12 @@ async def _get_default_kvs_client(configuration: Configuration) -> KeyValueStore |
237 | 249 |
|
238 | 250 | return apify_client_async.key_value_store(key_value_store_id=configuration.default_key_value_store_id) |
239 | 251 |
|
240 | | - @classmethod |
241 | | - def get_storage_key( |
242 | | - cls, storage_type: Literal['Dataset', 'KeyValueStore', 'RequestQueue'], alias: str, additional_cache_key: str |
243 | | - ) -> str: |
244 | | - return cls._ALIAS_STORAGE_KEY_SEPARATOR.join( |
| 252 | + @cached_property |
| 253 | + def _storage_key(self) -> str: |
| 254 | + return self._ALIAS_STORAGE_KEY_SEPARATOR.join( |
245 | 255 | [ |
246 | | - storage_type, |
247 | | - alias, |
248 | | - additional_cache_key, |
| 256 | + self._storage_type, |
| 257 | + self._alias, |
| 258 | + hash_api_base_url_and_token(self._configuration), |
249 | 259 | ] |
250 | 260 | ) |
251 | | - |
252 | | - @classmethod |
253 | | - async def register_aliases(cls, configuration: Configuration) -> None: |
254 | | - """Load alias mapping from configuration to the default kvs.""" |
255 | | - async with await cls._get_alias_init_lock(): |
256 | | - # Skip if no mapping or just default storages |
257 | | - if configuration.actor_storages is None or set( |
258 | | - configuration.actor_storages.datasets.keys() |
259 | | - | configuration.actor_storages.key_value_stores.keys() |
260 | | - | configuration.actor_storages.request_queues.keys() |
261 | | - ) == {'default'}: |
262 | | - return |
263 | | - |
264 | | - configuration_mapping = {} |
265 | | - |
266 | | - if configuration.default_dataset_id != configuration.actor_storages.datasets.get('default'): |
267 | | - logger.warning( |
268 | | - f'Conflicting default dataset ids: {configuration.default_dataset_id=},' |
269 | | - f" {configuration.actor_storages.datasets.get('default')=}" |
270 | | - ) |
271 | | - additional_cache_key = hash_api_base_url_and_token(configuration) |
272 | | - |
273 | | - for mapping, storage_type in ( |
274 | | - (configuration.actor_storages.key_value_stores, 'KeyValueStore'), |
275 | | - (configuration.actor_storages.datasets, 'Dataset'), |
276 | | - (configuration.actor_storages.request_queues, 'RequestQueue'), |
277 | | - ): |
278 | | - for storage_alias, storage_id in mapping.items(): |
279 | | - configuration_mapping[ |
280 | | - cls.get_storage_key( |
281 | | - storage_type, |
282 | | - '__default__' if storage_alias == 'default' else storage_alias, |
283 | | - additional_cache_key, |
284 | | - ) |
285 | | - ] = storage_id |
286 | | - |
287 | | - # Bulk update the mapping in the default KVS with the configuration mapping. |
288 | | - client = await cls._get_default_kvs_client(configuration=configuration) |
289 | | - record = await client.get_record(cls._ALIAS_MAPPING_KEY) |
290 | | - existing_mapping = record.get('value', {}) if record else {} |
291 | | - |
292 | | - # Update the existing mapping with the configuration mapping. |
293 | | - existing_mapping.update(configuration_mapping) |
294 | | - # Store the updated mapping back in the KVS and in memory. |
295 | | - await client.set_record(cls._ALIAS_MAPPING_KEY, existing_mapping) |
296 | | - cls._alias_map.update(existing_mapping) |
0 commit comments