unrealon 1.0.9__py3-none-any.whl → 1.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- unrealon/__init__.py +23 -21
- unrealon-1.1.1.dist-info/METADATA +722 -0
- unrealon-1.1.1.dist-info/RECORD +82 -0
- {unrealon-1.0.9.dist-info → unrealon-1.1.1.dist-info}/WHEEL +1 -1
- unrealon-1.1.1.dist-info/entry_points.txt +9 -0
- {unrealon-1.0.9.dist-info → unrealon-1.1.1.dist-info/licenses}/LICENSE +1 -1
- unrealon_bridge/__init__.py +114 -0
- unrealon_bridge/cli.py +316 -0
- unrealon_bridge/client/__init__.py +93 -0
- unrealon_bridge/client/base.py +78 -0
- unrealon_bridge/client/commands.py +89 -0
- unrealon_bridge/client/connection.py +90 -0
- unrealon_bridge/client/events.py +65 -0
- unrealon_bridge/client/health.py +38 -0
- unrealon_bridge/client/html_parser.py +146 -0
- unrealon_bridge/client/logging.py +139 -0
- unrealon_bridge/client/proxy.py +70 -0
- unrealon_bridge/client/scheduler.py +450 -0
- unrealon_bridge/client/session.py +70 -0
- unrealon_bridge/configs/__init__.py +14 -0
- unrealon_bridge/configs/bridge_config.py +212 -0
- unrealon_bridge/configs/bridge_config.yaml +39 -0
- unrealon_bridge/models/__init__.py +138 -0
- unrealon_bridge/models/base.py +28 -0
- unrealon_bridge/models/command.py +41 -0
- unrealon_bridge/models/events.py +40 -0
- unrealon_bridge/models/html_parser.py +79 -0
- unrealon_bridge/models/logging.py +55 -0
- unrealon_bridge/models/parser.py +63 -0
- unrealon_bridge/models/proxy.py +41 -0
- unrealon_bridge/models/requests.py +95 -0
- unrealon_bridge/models/responses.py +88 -0
- unrealon_bridge/models/scheduler.py +592 -0
- unrealon_bridge/models/session.py +28 -0
- unrealon_bridge/server/__init__.py +91 -0
- unrealon_bridge/server/base.py +171 -0
- unrealon_bridge/server/handlers/__init__.py +23 -0
- unrealon_bridge/server/handlers/command.py +110 -0
- unrealon_bridge/server/handlers/html_parser.py +139 -0
- unrealon_bridge/server/handlers/logging.py +95 -0
- unrealon_bridge/server/handlers/parser.py +95 -0
- unrealon_bridge/server/handlers/proxy.py +75 -0
- unrealon_bridge/server/handlers/scheduler.py +545 -0
- unrealon_bridge/server/handlers/session.py +66 -0
- unrealon_browser/__init__.py +61 -18
- unrealon_browser/{src/cli → cli}/browser_cli.py +6 -13
- unrealon_browser/{src/cli → cli}/cookies_cli.py +5 -1
- unrealon_browser/{src/core → core}/browser_manager.py +2 -2
- unrealon_browser/{src/managers → managers}/captcha.py +1 -1
- unrealon_browser/{src/managers → managers}/cookies.py +1 -1
- unrealon_browser/managers/logger_bridge.py +231 -0
- unrealon_browser/{src/managers → managers}/profile.py +1 -1
- unrealon_driver/__init__.py +73 -19
- unrealon_driver/browser/__init__.py +8 -0
- unrealon_driver/browser/config.py +74 -0
- unrealon_driver/browser/manager.py +416 -0
- unrealon_driver/exceptions.py +28 -0
- unrealon_driver/parser/__init__.py +55 -0
- unrealon_driver/parser/cli_manager.py +141 -0
- unrealon_driver/parser/daemon_manager.py +227 -0
- unrealon_driver/parser/managers/__init__.py +46 -0
- unrealon_driver/parser/managers/browser.py +51 -0
- unrealon_driver/parser/managers/config.py +281 -0
- unrealon_driver/parser/managers/error.py +412 -0
- unrealon_driver/parser/managers/html.py +732 -0
- unrealon_driver/parser/managers/logging.py +609 -0
- unrealon_driver/parser/managers/result.py +321 -0
- unrealon_driver/parser/parser_manager.py +628 -0
- unrealon/sdk_config.py +0 -88
- unrealon-1.0.9.dist-info/METADATA +0 -810
- unrealon-1.0.9.dist-info/RECORD +0 -246
- unrealon_browser/pyproject.toml +0 -182
- unrealon_browser/src/__init__.py +0 -62
- unrealon_browser/src/managers/logger_bridge.py +0 -395
- unrealon_driver/README.md +0 -204
- unrealon_driver/pyproject.toml +0 -187
- unrealon_driver/src/__init__.py +0 -90
- unrealon_driver/src/cli/__init__.py +0 -10
- unrealon_driver/src/cli/main.py +0 -66
- unrealon_driver/src/cli/simple.py +0 -510
- unrealon_driver/src/config/__init__.py +0 -11
- unrealon_driver/src/config/auto_config.py +0 -478
- unrealon_driver/src/core/__init__.py +0 -18
- unrealon_driver/src/core/exceptions.py +0 -289
- unrealon_driver/src/core/parser.py +0 -638
- unrealon_driver/src/dto/__init__.py +0 -66
- unrealon_driver/src/dto/cli.py +0 -119
- unrealon_driver/src/dto/config.py +0 -18
- unrealon_driver/src/dto/events.py +0 -237
- unrealon_driver/src/dto/execution.py +0 -313
- unrealon_driver/src/dto/services.py +0 -311
- unrealon_driver/src/execution/__init__.py +0 -23
- unrealon_driver/src/execution/daemon_mode.py +0 -317
- unrealon_driver/src/execution/interactive_mode.py +0 -88
- unrealon_driver/src/execution/modes.py +0 -45
- unrealon_driver/src/execution/scheduled_mode.py +0 -209
- unrealon_driver/src/execution/test_mode.py +0 -250
- unrealon_driver/src/logging/__init__.py +0 -24
- unrealon_driver/src/logging/driver_logger.py +0 -512
- unrealon_driver/src/services/__init__.py +0 -24
- unrealon_driver/src/services/browser_service.py +0 -726
- unrealon_driver/src/services/llm/__init__.py +0 -15
- unrealon_driver/src/services/llm/browser_llm_service.py +0 -363
- unrealon_driver/src/services/llm/llm.py +0 -195
- unrealon_driver/src/services/logger_service.py +0 -232
- unrealon_driver/src/services/metrics_service.py +0 -185
- unrealon_driver/src/services/scheduler_service.py +0 -489
- unrealon_driver/src/services/websocket_service.py +0 -362
- unrealon_driver/src/utils/__init__.py +0 -16
- unrealon_driver/src/utils/service_factory.py +0 -317
- unrealon_driver/src/utils/time_formatter.py +0 -338
- unrealon_llm/README.md +0 -44
- unrealon_llm/__init__.py +0 -26
- unrealon_llm/pyproject.toml +0 -154
- unrealon_llm/src/__init__.py +0 -228
- unrealon_llm/src/cli/__init__.py +0 -0
- unrealon_llm/src/core/__init__.py +0 -11
- unrealon_llm/src/core/smart_client.py +0 -438
- unrealon_llm/src/dto/__init__.py +0 -155
- unrealon_llm/src/dto/models/__init__.py +0 -0
- unrealon_llm/src/dto/models/config.py +0 -343
- unrealon_llm/src/dto/models/core.py +0 -328
- unrealon_llm/src/dto/models/enums.py +0 -123
- unrealon_llm/src/dto/models/html_analysis.py +0 -345
- unrealon_llm/src/dto/models/statistics.py +0 -473
- unrealon_llm/src/dto/models/translation.py +0 -383
- unrealon_llm/src/dto/models/type_conversion.py +0 -462
- unrealon_llm/src/dto/schemas/__init__.py +0 -0
- unrealon_llm/src/exceptions.py +0 -392
- unrealon_llm/src/llm_config/__init__.py +0 -20
- unrealon_llm/src/llm_config/logging_config.py +0 -178
- unrealon_llm/src/llm_logging/__init__.py +0 -42
- unrealon_llm/src/llm_logging/llm_events.py +0 -107
- unrealon_llm/src/llm_logging/llm_logger.py +0 -466
- unrealon_llm/src/managers/__init__.py +0 -15
- unrealon_llm/src/managers/cache_manager.py +0 -67
- unrealon_llm/src/managers/cost_manager.py +0 -107
- unrealon_llm/src/managers/request_manager.py +0 -298
- unrealon_llm/src/modules/__init__.py +0 -0
- unrealon_llm/src/modules/html_processor/__init__.py +0 -25
- unrealon_llm/src/modules/html_processor/base_processor.py +0 -415
- unrealon_llm/src/modules/html_processor/details_processor.py +0 -85
- unrealon_llm/src/modules/html_processor/listing_processor.py +0 -91
- unrealon_llm/src/modules/html_processor/models/__init__.py +0 -20
- unrealon_llm/src/modules/html_processor/models/processing_models.py +0 -40
- unrealon_llm/src/modules/html_processor/models/universal_model.py +0 -56
- unrealon_llm/src/modules/html_processor/processor.py +0 -102
- unrealon_llm/src/modules/llm/__init__.py +0 -0
- unrealon_llm/src/modules/translator/__init__.py +0 -0
- unrealon_llm/src/provider.py +0 -116
- unrealon_llm/src/utils/__init__.py +0 -95
- unrealon_llm/src/utils/common.py +0 -64
- unrealon_llm/src/utils/data_extractor.py +0 -188
- unrealon_llm/src/utils/html_cleaner.py +0 -767
- unrealon_llm/src/utils/language_detector.py +0 -308
- unrealon_llm/src/utils/models_cache.py +0 -592
- unrealon_llm/src/utils/smart_counter.py +0 -229
- unrealon_llm/src/utils/token_counter.py +0 -189
- unrealon_sdk/README.md +0 -25
- unrealon_sdk/__init__.py +0 -30
- unrealon_sdk/pyproject.toml +0 -231
- unrealon_sdk/src/__init__.py +0 -150
- unrealon_sdk/src/cli/__init__.py +0 -12
- unrealon_sdk/src/cli/commands/__init__.py +0 -22
- unrealon_sdk/src/cli/commands/benchmark.py +0 -42
- unrealon_sdk/src/cli/commands/diagnostics.py +0 -573
- unrealon_sdk/src/cli/commands/health.py +0 -46
- unrealon_sdk/src/cli/commands/integration.py +0 -498
- unrealon_sdk/src/cli/commands/reports.py +0 -43
- unrealon_sdk/src/cli/commands/security.py +0 -36
- unrealon_sdk/src/cli/commands/server.py +0 -483
- unrealon_sdk/src/cli/commands/servers.py +0 -56
- unrealon_sdk/src/cli/commands/tests.py +0 -55
- unrealon_sdk/src/cli/main.py +0 -126
- unrealon_sdk/src/cli/utils/reporter.py +0 -519
- unrealon_sdk/src/clients/openapi.yaml +0 -3347
- unrealon_sdk/src/clients/python_http/__init__.py +0 -3
- unrealon_sdk/src/clients/python_http/api_config.py +0 -228
- unrealon_sdk/src/clients/python_http/models/BaseModel.py +0 -12
- unrealon_sdk/src/clients/python_http/models/BroadcastDeliveryStats.py +0 -33
- unrealon_sdk/src/clients/python_http/models/BroadcastMessage.py +0 -17
- unrealon_sdk/src/clients/python_http/models/BroadcastMessageRequest.py +0 -35
- unrealon_sdk/src/clients/python_http/models/BroadcastPriority.py +0 -10
- unrealon_sdk/src/clients/python_http/models/BroadcastResponse.py +0 -21
- unrealon_sdk/src/clients/python_http/models/BroadcastResultResponse.py +0 -33
- unrealon_sdk/src/clients/python_http/models/BroadcastTarget.py +0 -11
- unrealon_sdk/src/clients/python_http/models/ConnectionStats.py +0 -27
- unrealon_sdk/src/clients/python_http/models/ConnectionsResponse.py +0 -21
- unrealon_sdk/src/clients/python_http/models/DeveloperMessageResponse.py +0 -23
- unrealon_sdk/src/clients/python_http/models/ErrorResponse.py +0 -25
- unrealon_sdk/src/clients/python_http/models/HTTPValidationError.py +0 -16
- unrealon_sdk/src/clients/python_http/models/HealthResponse.py +0 -23
- unrealon_sdk/src/clients/python_http/models/HealthStatus.py +0 -33
- unrealon_sdk/src/clients/python_http/models/LogLevel.py +0 -10
- unrealon_sdk/src/clients/python_http/models/LoggingRequest.py +0 -27
- unrealon_sdk/src/clients/python_http/models/LoggingResponse.py +0 -23
- unrealon_sdk/src/clients/python_http/models/MaintenanceMode.py +0 -9
- unrealon_sdk/src/clients/python_http/models/MaintenanceModeRequest.py +0 -33
- unrealon_sdk/src/clients/python_http/models/MaintenanceStatusResponse.py +0 -39
- unrealon_sdk/src/clients/python_http/models/ParserCommandRequest.py +0 -25
- unrealon_sdk/src/clients/python_http/models/ParserMessageResponse.py +0 -21
- unrealon_sdk/src/clients/python_http/models/ParserRegistrationRequest.py +0 -28
- unrealon_sdk/src/clients/python_http/models/ParserRegistrationResponse.py +0 -25
- unrealon_sdk/src/clients/python_http/models/ParserType.py +0 -10
- unrealon_sdk/src/clients/python_http/models/ProxyBlockRequest.py +0 -19
- unrealon_sdk/src/clients/python_http/models/ProxyEndpointResponse.py +0 -20
- unrealon_sdk/src/clients/python_http/models/ProxyListResponse.py +0 -19
- unrealon_sdk/src/clients/python_http/models/ProxyProvider.py +0 -10
- unrealon_sdk/src/clients/python_http/models/ProxyPurchaseRequest.py +0 -25
- unrealon_sdk/src/clients/python_http/models/ProxyResponse.py +0 -47
- unrealon_sdk/src/clients/python_http/models/ProxyRotationRequest.py +0 -23
- unrealon_sdk/src/clients/python_http/models/ProxyStatus.py +0 -10
- unrealon_sdk/src/clients/python_http/models/ProxyUsageRequest.py +0 -19
- unrealon_sdk/src/clients/python_http/models/ProxyUsageStatsResponse.py +0 -26
- unrealon_sdk/src/clients/python_http/models/ServiceRegistrationDto.py +0 -23
- unrealon_sdk/src/clients/python_http/models/ServiceStatsResponse.py +0 -31
- unrealon_sdk/src/clients/python_http/models/SessionStartRequest.py +0 -23
- unrealon_sdk/src/clients/python_http/models/SuccessResponse.py +0 -25
- unrealon_sdk/src/clients/python_http/models/SystemNotificationResponse.py +0 -23
- unrealon_sdk/src/clients/python_http/models/ValidationError.py +0 -18
- unrealon_sdk/src/clients/python_http/models/ValidationErrorResponse.py +0 -21
- unrealon_sdk/src/clients/python_http/models/WebSocketMetrics.py +0 -21
- unrealon_sdk/src/clients/python_http/models/__init__.py +0 -44
- unrealon_sdk/src/clients/python_http/services/None_service.py +0 -35
- unrealon_sdk/src/clients/python_http/services/ParserManagement_service.py +0 -190
- unrealon_sdk/src/clients/python_http/services/ProxyManagement_service.py +0 -289
- unrealon_sdk/src/clients/python_http/services/SocketLogging_service.py +0 -187
- unrealon_sdk/src/clients/python_http/services/SystemHealth_service.py +0 -119
- unrealon_sdk/src/clients/python_http/services/WebSocketAPI_service.py +0 -198
- unrealon_sdk/src/clients/python_http/services/__init__.py +0 -0
- unrealon_sdk/src/clients/python_http/services/admin_service.py +0 -125
- unrealon_sdk/src/clients/python_http/services/async_None_service.py +0 -35
- unrealon_sdk/src/clients/python_http/services/async_ParserManagement_service.py +0 -190
- unrealon_sdk/src/clients/python_http/services/async_ProxyManagement_service.py +0 -289
- unrealon_sdk/src/clients/python_http/services/async_SocketLogging_service.py +0 -189
- unrealon_sdk/src/clients/python_http/services/async_SystemHealth_service.py +0 -123
- unrealon_sdk/src/clients/python_http/services/async_WebSocketAPI_service.py +0 -200
- unrealon_sdk/src/clients/python_http/services/async_admin_service.py +0 -125
- unrealon_sdk/src/clients/python_websocket/__init__.py +0 -28
- unrealon_sdk/src/clients/python_websocket/client.py +0 -490
- unrealon_sdk/src/clients/python_websocket/events.py +0 -732
- unrealon_sdk/src/clients/python_websocket/example.py +0 -136
- unrealon_sdk/src/clients/python_websocket/types.py +0 -871
- unrealon_sdk/src/core/__init__.py +0 -64
- unrealon_sdk/src/core/client.py +0 -556
- unrealon_sdk/src/core/config.py +0 -465
- unrealon_sdk/src/core/exceptions.py +0 -239
- unrealon_sdk/src/core/metadata.py +0 -191
- unrealon_sdk/src/core/models.py +0 -142
- unrealon_sdk/src/core/types.py +0 -68
- unrealon_sdk/src/dto/__init__.py +0 -268
- unrealon_sdk/src/dto/authentication.py +0 -108
- unrealon_sdk/src/dto/cache.py +0 -208
- unrealon_sdk/src/dto/common.py +0 -19
- unrealon_sdk/src/dto/concurrency.py +0 -393
- unrealon_sdk/src/dto/events.py +0 -108
- unrealon_sdk/src/dto/health.py +0 -339
- unrealon_sdk/src/dto/load_balancing.py +0 -336
- unrealon_sdk/src/dto/logging.py +0 -230
- unrealon_sdk/src/dto/performance.py +0 -165
- unrealon_sdk/src/dto/rate_limiting.py +0 -295
- unrealon_sdk/src/dto/resource_pooling.py +0 -128
- unrealon_sdk/src/dto/structured_logging.py +0 -112
- unrealon_sdk/src/dto/task_scheduling.py +0 -121
- unrealon_sdk/src/dto/websocket.py +0 -55
- unrealon_sdk/src/enterprise/__init__.py +0 -59
- unrealon_sdk/src/enterprise/authentication.py +0 -401
- unrealon_sdk/src/enterprise/cache_manager.py +0 -578
- unrealon_sdk/src/enterprise/error_recovery.py +0 -494
- unrealon_sdk/src/enterprise/event_system.py +0 -549
- unrealon_sdk/src/enterprise/health_monitor.py +0 -747
- unrealon_sdk/src/enterprise/load_balancer.py +0 -964
- unrealon_sdk/src/enterprise/logging/__init__.py +0 -68
- unrealon_sdk/src/enterprise/logging/cleanup.py +0 -156
- unrealon_sdk/src/enterprise/logging/development.py +0 -744
- unrealon_sdk/src/enterprise/logging/service.py +0 -410
- unrealon_sdk/src/enterprise/multithreading_manager.py +0 -853
- unrealon_sdk/src/enterprise/performance_monitor.py +0 -539
- unrealon_sdk/src/enterprise/proxy_manager.py +0 -696
- unrealon_sdk/src/enterprise/rate_limiter.py +0 -652
- unrealon_sdk/src/enterprise/resource_pool.py +0 -763
- unrealon_sdk/src/enterprise/task_scheduler.py +0 -709
- unrealon_sdk/src/internal/__init__.py +0 -10
- unrealon_sdk/src/internal/command_router.py +0 -497
- unrealon_sdk/src/internal/connection_manager.py +0 -397
- unrealon_sdk/src/internal/http_client.py +0 -446
- unrealon_sdk/src/internal/websocket_client.py +0 -420
- unrealon_sdk/src/provider.py +0 -471
- unrealon_sdk/src/utils.py +0 -234
- /unrealon_browser/{src/cli → cli}/__init__.py +0 -0
- /unrealon_browser/{src/cli → cli}/interactive_mode.py +0 -0
- /unrealon_browser/{src/cli → cli}/main.py +0 -0
- /unrealon_browser/{src/core → core}/__init__.py +0 -0
- /unrealon_browser/{src/dto → dto}/__init__.py +0 -0
- /unrealon_browser/{src/dto → dto}/models/config.py +0 -0
- /unrealon_browser/{src/dto → dto}/models/core.py +0 -0
- /unrealon_browser/{src/dto → dto}/models/dataclasses.py +0 -0
- /unrealon_browser/{src/dto → dto}/models/detection.py +0 -0
- /unrealon_browser/{src/dto → dto}/models/enums.py +0 -0
- /unrealon_browser/{src/dto → dto}/models/statistics.py +0 -0
- /unrealon_browser/{src/managers → managers}/__init__.py +0 -0
- /unrealon_browser/{src/managers → managers}/stealth.py +0 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Proxy management for Parser Bridge Client.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from unrealon_rpc.logging import get_logger
|
|
7
|
+
|
|
8
|
+
from ..models import (
|
|
9
|
+
ProxyInfo, ProxyAllocateRequest, ProxyAllocateResponse,
|
|
10
|
+
ProxyReleaseRequest, ProxyReleaseResponse
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
logger = get_logger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ProxyMixin:
|
|
17
|
+
"""Mixin for proxy management functionality."""
|
|
18
|
+
|
|
19
|
+
async def request_proxy(self, proxy_type: str = "http", location: Optional[str] = None) -> ProxyInfo:
|
|
20
|
+
"""
|
|
21
|
+
Request proxy allocation.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
proxy_type: Type of proxy needed
|
|
25
|
+
location: Preferred proxy location
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
Allocated proxy information
|
|
29
|
+
"""
|
|
30
|
+
self._ensure_registered()
|
|
31
|
+
|
|
32
|
+
request = ProxyAllocateRequest(
|
|
33
|
+
parser_id=self.parser_id,
|
|
34
|
+
proxy_type=proxy_type,
|
|
35
|
+
location=location
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
result = await self.bridge_client.call_rpc(
|
|
39
|
+
method="proxy.allocate",
|
|
40
|
+
params=request.model_dump()
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
response = ProxyAllocateResponse.model_validate(result)
|
|
44
|
+
|
|
45
|
+
if response.success and response.proxy:
|
|
46
|
+
logger.info(f"Proxy allocated: {response.proxy.proxy_id} for {self.parser_id}")
|
|
47
|
+
return response.proxy
|
|
48
|
+
else:
|
|
49
|
+
raise RuntimeError(f"Proxy allocation failed: {response.error}")
|
|
50
|
+
|
|
51
|
+
async def release_proxy(self, proxy_id: str) -> None:
|
|
52
|
+
"""
|
|
53
|
+
Release proxy allocation.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
proxy_id: Proxy ID to release
|
|
57
|
+
"""
|
|
58
|
+
request = ProxyReleaseRequest(proxy_id=proxy_id)
|
|
59
|
+
|
|
60
|
+
result = await self.bridge_client.call_rpc(
|
|
61
|
+
method="proxy.release",
|
|
62
|
+
params=request.model_dump()
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
response = ProxyReleaseResponse.model_validate(result)
|
|
66
|
+
|
|
67
|
+
if response.success:
|
|
68
|
+
logger.info(f"Proxy released: {proxy_id}")
|
|
69
|
+
else:
|
|
70
|
+
logger.error(f"Proxy release failed: {response.error}")
|
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Scheduler client mixin for Parser Bridge Client.
|
|
3
|
+
|
|
4
|
+
Provides scheduler-related functionality for parsers.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Dict, Any, List, Optional
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
|
|
10
|
+
from unrealon_rpc.logging import get_logger
|
|
11
|
+
from unrealon_bridge.models.scheduler import (
|
|
12
|
+
ScheduledTask,
|
|
13
|
+
TaskParameters,
|
|
14
|
+
CronExpression,
|
|
15
|
+
TaskRetryConfig,
|
|
16
|
+
TaskExecutionResult,
|
|
17
|
+
ParserStatus,
|
|
18
|
+
SchedulerError,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
logger = get_logger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class SchedulerMixin:
|
|
25
|
+
"""Scheduler functionality mixin for Parser Bridge Client."""
|
|
26
|
+
|
|
27
|
+
async def create_scheduled_task(
|
|
28
|
+
self,
|
|
29
|
+
task_type: str,
|
|
30
|
+
parameters: TaskParameters,
|
|
31
|
+
cron_expression: Optional[str] = None,
|
|
32
|
+
scheduled_at: Optional[datetime] = None,
|
|
33
|
+
retry_config: Optional[TaskRetryConfig] = None,
|
|
34
|
+
priority: int = 5,
|
|
35
|
+
timeout_seconds: int = 300
|
|
36
|
+
) -> Dict[str, Any]:
|
|
37
|
+
"""
|
|
38
|
+
Create a new scheduled task.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
task_type: Type of task (command, scrape, parse, etc.)
|
|
42
|
+
parameters: Task parameters
|
|
43
|
+
cron_expression: Optional cron expression for recurring tasks
|
|
44
|
+
scheduled_at: Optional specific execution time
|
|
45
|
+
retry_config: Optional retry configuration
|
|
46
|
+
priority: Task priority (1-10, higher = more important)
|
|
47
|
+
timeout_seconds: Task timeout in seconds
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Task creation response with task_id and scheduling info
|
|
51
|
+
"""
|
|
52
|
+
try:
|
|
53
|
+
request_data = {
|
|
54
|
+
"parser_id": self.parser_id,
|
|
55
|
+
"task_type": task_type,
|
|
56
|
+
"parameters": parameters.model_dump(),
|
|
57
|
+
"priority": priority,
|
|
58
|
+
"timeout_seconds": timeout_seconds
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if cron_expression:
|
|
62
|
+
request_data["cron_expression"] = cron_expression
|
|
63
|
+
|
|
64
|
+
if scheduled_at:
|
|
65
|
+
request_data["scheduled_at"] = scheduled_at.isoformat()
|
|
66
|
+
|
|
67
|
+
if retry_config:
|
|
68
|
+
request_data["retry_config"] = retry_config.model_dump()
|
|
69
|
+
|
|
70
|
+
response = await self.bridge_client.call_rpc(
|
|
71
|
+
method="scheduler.create_task",
|
|
72
|
+
params=request_data,
|
|
73
|
+
timeout=30
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
logger.info(
|
|
77
|
+
f"Created scheduled task: {task_type}",
|
|
78
|
+
component="scheduler_client",
|
|
79
|
+
operation="create_task",
|
|
80
|
+
parser_id=self.parser_id,
|
|
81
|
+
task_type=task_type,
|
|
82
|
+
cron_expression=cron_expression
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
return response
|
|
86
|
+
|
|
87
|
+
except Exception as e:
|
|
88
|
+
logger.error(
|
|
89
|
+
f"Failed to create scheduled task: {e}",
|
|
90
|
+
component="scheduler_client",
|
|
91
|
+
operation="create_task",
|
|
92
|
+
error=e
|
|
93
|
+
)
|
|
94
|
+
raise SchedulerError(f"Failed to create scheduled task: {e}")
|
|
95
|
+
|
|
96
|
+
async def list_scheduled_tasks(
|
|
97
|
+
self,
|
|
98
|
+
task_type: Optional[str] = None,
|
|
99
|
+
status: Optional[str] = None,
|
|
100
|
+
limit: int = 100,
|
|
101
|
+
offset: int = 0
|
|
102
|
+
) -> Dict[str, Any]:
|
|
103
|
+
"""
|
|
104
|
+
List scheduled tasks for this parser.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
task_type: Optional filter by task type
|
|
108
|
+
status: Optional filter by status
|
|
109
|
+
limit: Maximum number of tasks to return
|
|
110
|
+
offset: Offset for pagination
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
List of scheduled tasks
|
|
114
|
+
"""
|
|
115
|
+
try:
|
|
116
|
+
request_data = {
|
|
117
|
+
"parser_id": self.parser_id,
|
|
118
|
+
"limit": limit,
|
|
119
|
+
"offset": offset
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if task_type:
|
|
123
|
+
request_data["task_type"] = task_type
|
|
124
|
+
|
|
125
|
+
if status:
|
|
126
|
+
request_data["status"] = status
|
|
127
|
+
|
|
128
|
+
response = await self.bridge_client.call_rpc(
|
|
129
|
+
method="scheduler.list_tasks",
|
|
130
|
+
params=request_data,
|
|
131
|
+
timeout=30
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
logger.info(
|
|
135
|
+
f"Listed scheduled tasks: {response.get('total_count', 0)} total",
|
|
136
|
+
component="scheduler_client",
|
|
137
|
+
operation="list_tasks",
|
|
138
|
+
parser_id=self.parser_id,
|
|
139
|
+
task_type=task_type,
|
|
140
|
+
status=status
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
return response
|
|
144
|
+
|
|
145
|
+
except Exception as e:
|
|
146
|
+
logger.error(
|
|
147
|
+
f"Failed to list scheduled tasks: {e}",
|
|
148
|
+
component="scheduler_client",
|
|
149
|
+
operation="list_tasks",
|
|
150
|
+
error=e
|
|
151
|
+
)
|
|
152
|
+
raise SchedulerError(f"Failed to list scheduled tasks: {e}")
|
|
153
|
+
|
|
154
|
+
async def get_task_status(self, task_id: str) -> Dict[str, Any]:
|
|
155
|
+
"""
|
|
156
|
+
Get task status and execution history.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
task_id: Task ID to query
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
Task status and execution history
|
|
163
|
+
"""
|
|
164
|
+
try:
|
|
165
|
+
response = await self.bridge_client.call_rpc(
|
|
166
|
+
method="scheduler.get_task",
|
|
167
|
+
params={"task_id": task_id},
|
|
168
|
+
timeout=30
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
logger.info(
|
|
172
|
+
f"Retrieved task status: {task_id}",
|
|
173
|
+
component="scheduler_client",
|
|
174
|
+
operation="get_task",
|
|
175
|
+
task_id=task_id
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
return response
|
|
179
|
+
|
|
180
|
+
except Exception as e:
|
|
181
|
+
logger.error(
|
|
182
|
+
f"Failed to get task status: {e}",
|
|
183
|
+
component="scheduler_client",
|
|
184
|
+
operation="get_task",
|
|
185
|
+
error=e
|
|
186
|
+
)
|
|
187
|
+
raise SchedulerError(f"Failed to get task status: {e}")
|
|
188
|
+
|
|
189
|
+
async def cancel_scheduled_task(self, task_id: str) -> Dict[str, Any]:
|
|
190
|
+
"""
|
|
191
|
+
Cancel a scheduled task.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
task_id: Task ID to cancel
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
Cancellation response
|
|
198
|
+
"""
|
|
199
|
+
try:
|
|
200
|
+
response = await self.bridge_client.call_rpc(
|
|
201
|
+
method="scheduler.cancel_task",
|
|
202
|
+
params={"task_id": task_id},
|
|
203
|
+
timeout=30
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
logger.info(
|
|
207
|
+
f"Cancelled scheduled task: {task_id}",
|
|
208
|
+
component="scheduler_client",
|
|
209
|
+
operation="cancel_task",
|
|
210
|
+
task_id=task_id
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
return response
|
|
214
|
+
|
|
215
|
+
except Exception as e:
|
|
216
|
+
logger.error(
|
|
217
|
+
f"Failed to cancel scheduled task: {e}",
|
|
218
|
+
component="scheduler_client",
|
|
219
|
+
operation="cancel_task",
|
|
220
|
+
error=e
|
|
221
|
+
)
|
|
222
|
+
raise SchedulerError(f"Failed to cancel scheduled task: {e}")
|
|
223
|
+
|
|
224
|
+
async def update_parser_status_for_scheduler(
|
|
225
|
+
self,
|
|
226
|
+
status: str,
|
|
227
|
+
current_task_id: Optional[str] = None,
|
|
228
|
+
capabilities: Optional[List[str]] = None
|
|
229
|
+
) -> Dict[str, Any]:
|
|
230
|
+
"""
|
|
231
|
+
Update parser status for scheduler.
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
status: Parser status (online, offline, busy, error)
|
|
235
|
+
current_task_id: Currently executing task ID
|
|
236
|
+
capabilities: Parser capabilities
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Status update response
|
|
240
|
+
"""
|
|
241
|
+
try:
|
|
242
|
+
request_data = {
|
|
243
|
+
"parser_id": self.parser_id,
|
|
244
|
+
"status": status,
|
|
245
|
+
"last_seen": datetime.utcnow().isoformat()
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if current_task_id:
|
|
249
|
+
request_data["current_task_id"] = current_task_id
|
|
250
|
+
|
|
251
|
+
if capabilities:
|
|
252
|
+
request_data["capabilities"] = capabilities
|
|
253
|
+
|
|
254
|
+
response = await self.bridge_client.call_rpc(
|
|
255
|
+
method="scheduler.update_parser_status",
|
|
256
|
+
params=request_data,
|
|
257
|
+
timeout=30
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
logger.info(
|
|
261
|
+
f"Updated parser status for scheduler: {status}",
|
|
262
|
+
component="scheduler_client",
|
|
263
|
+
operation="update_parser_status",
|
|
264
|
+
parser_id=self.parser_id,
|
|
265
|
+
status=status
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
return response
|
|
269
|
+
|
|
270
|
+
except Exception as e:
|
|
271
|
+
logger.error(
|
|
272
|
+
f"Failed to update parser status: {e}",
|
|
273
|
+
component="scheduler_client",
|
|
274
|
+
operation="update_parser_status",
|
|
275
|
+
error=e
|
|
276
|
+
)
|
|
277
|
+
raise SchedulerError(f"Failed to update parser status: {e}")
|
|
278
|
+
|
|
279
|
+
async def get_parser_scheduler_status(self) -> Dict[str, Any]:
|
|
280
|
+
"""
|
|
281
|
+
Get parser status and active tasks from scheduler.
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
Parser status and active tasks
|
|
285
|
+
"""
|
|
286
|
+
try:
|
|
287
|
+
response = await self.bridge_client.call_rpc(
|
|
288
|
+
method="scheduler.get_parser_status",
|
|
289
|
+
params={"parser_id": self.parser_id},
|
|
290
|
+
timeout=30
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
logger.info(
|
|
294
|
+
f"Retrieved parser scheduler status",
|
|
295
|
+
component="scheduler_client",
|
|
296
|
+
operation="get_parser_status",
|
|
297
|
+
parser_id=self.parser_id
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
return response
|
|
301
|
+
|
|
302
|
+
except Exception as e:
|
|
303
|
+
logger.error(
|
|
304
|
+
f"Failed to get parser scheduler status: {e}",
|
|
305
|
+
component="scheduler_client",
|
|
306
|
+
operation="get_parser_status",
|
|
307
|
+
error=e
|
|
308
|
+
)
|
|
309
|
+
raise SchedulerError(f"Failed to get parser scheduler status: {e}")
|
|
310
|
+
|
|
311
|
+
async def get_scheduler_stats(self) -> Dict[str, Any]:
|
|
312
|
+
"""
|
|
313
|
+
Get scheduler statistics.
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
Scheduler statistics
|
|
317
|
+
"""
|
|
318
|
+
try:
|
|
319
|
+
response = await self.bridge_client.call_rpc(
|
|
320
|
+
method="scheduler.get_stats",
|
|
321
|
+
params={},
|
|
322
|
+
timeout=30
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
logger.info(
|
|
326
|
+
"Retrieved scheduler statistics",
|
|
327
|
+
component="scheduler_client",
|
|
328
|
+
operation="get_stats"
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
return response
|
|
332
|
+
|
|
333
|
+
except Exception as e:
|
|
334
|
+
logger.error(
|
|
335
|
+
f"Failed to get scheduler stats: {e}",
|
|
336
|
+
component="scheduler_client",
|
|
337
|
+
operation="get_stats",
|
|
338
|
+
error=e
|
|
339
|
+
)
|
|
340
|
+
raise SchedulerError(f"Failed to get scheduler stats: {e}")
|
|
341
|
+
|
|
342
|
+
# Convenience methods for common task types
|
|
343
|
+
|
|
344
|
+
async def schedule_scraping_task(
|
|
345
|
+
self,
|
|
346
|
+
target_url: str,
|
|
347
|
+
scraping_config: Dict[str, Any],
|
|
348
|
+
cron_expression: Optional[str] = None,
|
|
349
|
+
scheduled_at: Optional[datetime] = None,
|
|
350
|
+
priority: int = 5
|
|
351
|
+
) -> Dict[str, Any]:
|
|
352
|
+
"""
|
|
353
|
+
Schedule a scraping task.
|
|
354
|
+
|
|
355
|
+
Args:
|
|
356
|
+
target_url: URL to scrape
|
|
357
|
+
scraping_config: Scraping configuration
|
|
358
|
+
cron_expression: Optional cron expression for recurring scraping
|
|
359
|
+
scheduled_at: Optional specific execution time
|
|
360
|
+
priority: Task priority
|
|
361
|
+
|
|
362
|
+
Returns:
|
|
363
|
+
Task creation response
|
|
364
|
+
"""
|
|
365
|
+
parameters = TaskParameters(
|
|
366
|
+
command_type="scrape",
|
|
367
|
+
parameters={
|
|
368
|
+
"target_url": target_url,
|
|
369
|
+
**{k: str(v) for k, v in scraping_config.items()}
|
|
370
|
+
}
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
return await self.create_scheduled_task(
|
|
374
|
+
task_type="scrape",
|
|
375
|
+
parameters=parameters,
|
|
376
|
+
cron_expression=cron_expression,
|
|
377
|
+
scheduled_at=scheduled_at,
|
|
378
|
+
priority=priority
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
async def schedule_parsing_task(
|
|
382
|
+
self,
|
|
383
|
+
input_data: str,
|
|
384
|
+
parsing_config: Dict[str, Any],
|
|
385
|
+
cron_expression: Optional[str] = None,
|
|
386
|
+
scheduled_at: Optional[datetime] = None,
|
|
387
|
+
priority: int = 5
|
|
388
|
+
) -> Dict[str, Any]:
|
|
389
|
+
"""
|
|
390
|
+
Schedule a parsing task.
|
|
391
|
+
|
|
392
|
+
Args:
|
|
393
|
+
input_data: Data to parse
|
|
394
|
+
parsing_config: Parsing configuration
|
|
395
|
+
cron_expression: Optional cron expression for recurring parsing
|
|
396
|
+
scheduled_at: Optional specific execution time
|
|
397
|
+
priority: Task priority
|
|
398
|
+
|
|
399
|
+
Returns:
|
|
400
|
+
Task creation response
|
|
401
|
+
"""
|
|
402
|
+
parameters = TaskParameters(
|
|
403
|
+
command_type="parse",
|
|
404
|
+
parameters={
|
|
405
|
+
"input_data": input_data,
|
|
406
|
+
**{k: str(v) for k, v in parsing_config.items()}
|
|
407
|
+
}
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
return await self.create_scheduled_task(
|
|
411
|
+
task_type="parse",
|
|
412
|
+
parameters=parameters,
|
|
413
|
+
cron_expression=cron_expression,
|
|
414
|
+
scheduled_at=scheduled_at,
|
|
415
|
+
priority=priority
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
async def schedule_command_task(
|
|
419
|
+
self,
|
|
420
|
+
command_type: str,
|
|
421
|
+
command_params: Dict[str, Any],
|
|
422
|
+
cron_expression: Optional[str] = None,
|
|
423
|
+
scheduled_at: Optional[datetime] = None,
|
|
424
|
+
priority: int = 5
|
|
425
|
+
) -> Dict[str, Any]:
|
|
426
|
+
"""
|
|
427
|
+
Schedule a command execution task.
|
|
428
|
+
|
|
429
|
+
Args:
|
|
430
|
+
command_type: Type of command to execute
|
|
431
|
+
command_params: Command parameters
|
|
432
|
+
cron_expression: Optional cron expression for recurring commands
|
|
433
|
+
scheduled_at: Optional specific execution time
|
|
434
|
+
priority: Task priority
|
|
435
|
+
|
|
436
|
+
Returns:
|
|
437
|
+
Task creation response
|
|
438
|
+
"""
|
|
439
|
+
parameters = TaskParameters(
|
|
440
|
+
command_type=command_type,
|
|
441
|
+
parameters={k: str(v) for k, v in command_params.items()}
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
return await self.create_scheduled_task(
|
|
445
|
+
task_type="command",
|
|
446
|
+
parameters=parameters,
|
|
447
|
+
cron_expression=cron_expression,
|
|
448
|
+
scheduled_at=scheduled_at,
|
|
449
|
+
priority=priority
|
|
450
|
+
)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Session management for Parser Bridge Client.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from unrealon_rpc.logging import get_logger
|
|
7
|
+
|
|
8
|
+
from ..models import (
|
|
9
|
+
SessionStartRequest, SessionStartResponse,
|
|
10
|
+
SessionEndRequest, SessionEndResponse
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
logger = get_logger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SessionMixin:
|
|
17
|
+
"""Mixin for session management functionality."""
|
|
18
|
+
|
|
19
|
+
async def start_session(self, session_type: str = "default", metadata: Optional[dict[str, str]] = None) -> str:
|
|
20
|
+
"""
|
|
21
|
+
Start a new parser session.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
session_type: Type of session
|
|
25
|
+
metadata: Session metadata
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
Session ID
|
|
29
|
+
"""
|
|
30
|
+
self._ensure_registered()
|
|
31
|
+
|
|
32
|
+
request = SessionStartRequest(
|
|
33
|
+
parser_id=self.parser_id,
|
|
34
|
+
session_type=session_type,
|
|
35
|
+
metadata=metadata
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
result = await self.bridge_client.call_rpc(
|
|
39
|
+
method="parser.start_session",
|
|
40
|
+
params=request.model_dump()
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
response = SessionStartResponse.model_validate(result)
|
|
44
|
+
|
|
45
|
+
if response.success and response.session:
|
|
46
|
+
self.session_id = response.session.session_id
|
|
47
|
+
logger.info(f"Session started: {self.session_id}")
|
|
48
|
+
return self.session_id
|
|
49
|
+
else:
|
|
50
|
+
raise RuntimeError(f"Session start failed: {response.error}")
|
|
51
|
+
|
|
52
|
+
async def end_session(self) -> None:
|
|
53
|
+
"""End current parser session."""
|
|
54
|
+
if not self.session_id:
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
request = SessionEndRequest(session_id=self.session_id)
|
|
58
|
+
|
|
59
|
+
result = await self.bridge_client.call_rpc(
|
|
60
|
+
method="parser.end_session",
|
|
61
|
+
params=request.model_dump()
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
response = SessionEndResponse.model_validate(result)
|
|
65
|
+
|
|
66
|
+
if response.success:
|
|
67
|
+
logger.info(f"Session ended: {self.session_id}")
|
|
68
|
+
self.session_id = None
|
|
69
|
+
else:
|
|
70
|
+
logger.error(f"Session end failed: {response.error}")
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Bridge configuration module.
|
|
3
|
+
|
|
4
|
+
Provides Pydantic2 configuration management for the bridge server.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .bridge_config import BridgeConfig, load_bridge_config, save_bridge_config, create_sample_config
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"BridgeConfig",
|
|
11
|
+
"load_bridge_config",
|
|
12
|
+
"save_bridge_config",
|
|
13
|
+
"create_sample_config"
|
|
14
|
+
]
|