feat(spiders): The option to start sessions lazily
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
|
from asyncio import Lock
|
||||||
|
|
||||||
from scrapling.spiders.request import Request
|
from scrapling.spiders.request import Request
|
||||||
from scrapling.engines.static import _ASyncSessionLogic
|
from scrapling.engines.static import _ASyncSessionLogic
|
||||||
from scrapling.engines.toolbelt.convertor import Response
|
from scrapling.engines.toolbelt.convertor import Response
|
||||||
from scrapling.core._types import cast, SUPPORTED_HTTP_METHODS
|
from scrapling.core._types import Set, cast, SUPPORTED_HTTP_METHODS
|
||||||
from scrapling.fetchers import AsyncDynamicSession, AsyncStealthySession, FetcherSession
|
from scrapling.fetchers import AsyncDynamicSession, AsyncStealthySession, FetcherSession
|
||||||
|
|
||||||
Session = FetcherSession | AsyncDynamicSession | AsyncStealthySession
|
Session = FetcherSession | AsyncDynamicSession | AsyncStealthySession
|
||||||
@@ -14,13 +16,16 @@ class SessionManager:
|
|||||||
self._sessions: dict[str, Session] = {}
|
self._sessions: dict[str, Session] = {}
|
||||||
self._default_session_id: str | None = None
|
self._default_session_id: str | None = None
|
||||||
self._started: bool = False
|
self._started: bool = False
|
||||||
|
self._lazy_sessions: Set[str] = set()
|
||||||
|
self._lazy_lock = Lock()
|
||||||
|
|
||||||
def add(self, session_id: str, session: Session, *, default: bool = False) -> "SessionManager":
|
def add(self, session_id: str, session: Session, *, default: bool = False, lazy: bool = False) -> "SessionManager":
|
||||||
"""Register a session instance.
|
"""Register a session instance.
|
||||||
|
|
||||||
:param session_id: Name to reference this session in requests
|
:param session_id: Name to reference this session in requests
|
||||||
:param session: Your pre-configured session instance
|
:param session: Your pre-configured session instance
|
||||||
:param default: If True, this becomes the default session
|
:param default: If True, this becomes the default session
|
||||||
|
:param lazy: If True, the session will be started only when a request uses its ID.
|
||||||
"""
|
"""
|
||||||
if session_id in self._sessions:
|
if session_id in self._sessions:
|
||||||
raise ValueError(f"Session '{session_id}' already registered")
|
raise ValueError(f"Session '{session_id}' already registered")
|
||||||
@@ -30,6 +35,9 @@ class SessionManager:
|
|||||||
if default or self._default_session_id is None:
|
if default or self._default_session_id is None:
|
||||||
self._default_session_id = session_id
|
self._default_session_id = session_id
|
||||||
|
|
||||||
|
if lazy:
|
||||||
|
self._lazy_sessions.add(session_id)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def remove(self, session_id: str) -> None:
|
def remove(self, session_id: str) -> None:
|
||||||
@@ -48,6 +56,8 @@ class SessionManager:
|
|||||||
raise KeyError(f"Session '{session_id}' not found")
|
raise KeyError(f"Session '{session_id}' not found")
|
||||||
|
|
||||||
session = self._sessions.pop(session_id)
|
session = self._sessions.pop(session_id)
|
||||||
|
if session_id in self._lazy_sessions:
|
||||||
|
self._lazy_sessions.remove(session_id)
|
||||||
|
|
||||||
if session and self._default_session_id == session_id:
|
if session and self._default_session_id == session_id:
|
||||||
self._default_session_id = next(iter(self._sessions), None)
|
self._default_session_id = next(iter(self._sessions), None)
|
||||||
@@ -75,8 +85,8 @@ class SessionManager:
|
|||||||
if self._started:
|
if self._started:
|
||||||
return
|
return
|
||||||
|
|
||||||
for session in self._sessions.values():
|
for sid, session in self._sessions.items():
|
||||||
if not session._is_alive:
|
if sid not in self._lazy_sessions and not session._is_alive:
|
||||||
await session.__aenter__()
|
await session.__aenter__()
|
||||||
|
|
||||||
self._started = True
|
self._started = True
|
||||||
@@ -93,6 +103,11 @@ class SessionManager:
|
|||||||
session = self.get(sid)
|
session = self.get(sid)
|
||||||
|
|
||||||
if session:
|
if session:
|
||||||
|
if sid in self._lazy_sessions and not session._is_alive:
|
||||||
|
async with self._lazy_lock:
|
||||||
|
if not session._is_alive:
|
||||||
|
await session.__aenter__()
|
||||||
|
|
||||||
if isinstance(session, FetcherSession):
|
if isinstance(session, FetcherSession):
|
||||||
session = session._client
|
session = session._client
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user