unrealon 1.0.9__py3-none-any.whl → 1.1.0__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.0.dist-info/METADATA +164 -0
- unrealon-1.1.0.dist-info/RECORD +82 -0
- {unrealon-1.0.9.dist-info → unrealon-1.1.0.dist-info}/WHEEL +1 -1
- unrealon-1.1.0.dist-info/entry_points.txt +9 -0
- {unrealon-1.0.9.dist-info → unrealon-1.1.0.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
|
@@ -1,549 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Enterprise Event System for UnrealOn SDK v1.0
|
|
3
|
-
|
|
4
|
-
Layer 2: Enterprise Services - Type-safe event handling with:
|
|
5
|
-
- Pydantic v2 validation for all events
|
|
6
|
-
- Event correlation and tracking
|
|
7
|
-
- Performance monitoring and metrics
|
|
8
|
-
- Event replay and audit capabilities
|
|
9
|
-
- Real-time event streaming via WebSocket
|
|
10
|
-
- Circuit breaker and error recovery
|
|
11
|
-
|
|
12
|
-
Enterprise Features:
|
|
13
|
-
- Type-safe event dispatching with Pydantic validation
|
|
14
|
-
- Event correlation tracking across requests
|
|
15
|
-
- Performance metrics and analytics
|
|
16
|
-
- Audit trails and compliance logging
|
|
17
|
-
- Real-time subscription management
|
|
18
|
-
- Circuit breaker for fault tolerance
|
|
19
|
-
- Event replay for debugging and analytics
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
import asyncio
|
|
23
|
-
import logging
|
|
24
|
-
from datetime import datetime, timezone
|
|
25
|
-
from typing import Dict, List, Optional, Callable, Any, Union, Awaitable
|
|
26
|
-
from collections import defaultdict, deque
|
|
27
|
-
|
|
28
|
-
# Pydantic v2 for all data models
|
|
29
|
-
from pydantic import BaseModel, Field, ConfigDict
|
|
30
|
-
|
|
31
|
-
# Auto-generated models - use these for WebSocket communication
|
|
32
|
-
from unrealon_sdk.src.clients.python_websocket.events import SocketEvent, EventType
|
|
33
|
-
from unrealon_sdk.src.clients.python_websocket.types import LogEntryMessage
|
|
34
|
-
|
|
35
|
-
# DTO models for type-safe data structures
|
|
36
|
-
from unrealon_sdk.src.dto.events import (
|
|
37
|
-
EventPriority,
|
|
38
|
-
EventDeliveryStatus,
|
|
39
|
-
EventSubscriptionFilter,
|
|
40
|
-
EventMetadata,
|
|
41
|
-
EventDeliveryResult,
|
|
42
|
-
EventStatistics,
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
# Core SDK components
|
|
46
|
-
from unrealon_sdk.src.core.config import AdapterConfig
|
|
47
|
-
from unrealon_sdk.src.core.exceptions import ConnectionError # Use existing exception type
|
|
48
|
-
from unrealon_sdk.src.utils import generate_correlation_id
|
|
49
|
-
|
|
50
|
-
# Development logging
|
|
51
|
-
from typing import TYPE_CHECKING
|
|
52
|
-
|
|
53
|
-
if TYPE_CHECKING:
|
|
54
|
-
from .logging.development import DevelopmentLogger
|
|
55
|
-
|
|
56
|
-
logger = logging.getLogger(__name__)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
# EventPriority and EventDeliveryStatus moved to unrealon_sdk.dto.events
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
# EventSubscriptionFilter and EventMetadata moved to unrealon_sdk.dto.events
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
class EnterpriseEvent(BaseModel):
|
|
66
|
-
"""
|
|
67
|
-
Enterprise-grade event model with full type safety.
|
|
68
|
-
|
|
69
|
-
Wraps auto-generated events with enterprise features while
|
|
70
|
-
maintaining compatibility with WebSocket communication.
|
|
71
|
-
"""
|
|
72
|
-
|
|
73
|
-
model_config = ConfigDict(validate_assignment=True, extra="forbid")
|
|
74
|
-
|
|
75
|
-
event_type: SocketEvent = Field(..., description="Socket event type")
|
|
76
|
-
data: Dict[str, Any] = Field(..., description="Event payload data")
|
|
77
|
-
metadata: EventMetadata = Field(..., description="Event metadata")
|
|
78
|
-
|
|
79
|
-
def to_websocket_message(self) -> LogEntryMessage:
|
|
80
|
-
"""Convert to WebSocket message format for transmission."""
|
|
81
|
-
return LogEntryMessage(
|
|
82
|
-
type="event",
|
|
83
|
-
session_id=self.metadata.correlation_id,
|
|
84
|
-
entry={
|
|
85
|
-
"event_type": self.event_type.value,
|
|
86
|
-
"data": self.data,
|
|
87
|
-
"metadata": self.metadata.model_dump(),
|
|
88
|
-
"timestamp": self.metadata.timestamp.isoformat(),
|
|
89
|
-
},
|
|
90
|
-
timestamp=self.metadata.timestamp.isoformat(),
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
class EventSubscription(BaseModel):
|
|
95
|
-
"""Type-safe event subscription configuration."""
|
|
96
|
-
|
|
97
|
-
model_config = ConfigDict(validate_assignment=True, extra="forbid")
|
|
98
|
-
|
|
99
|
-
subscription_id: str = Field(..., description="Unique subscription identifier")
|
|
100
|
-
subscriber_id: str = Field(..., description="Subscriber identifier")
|
|
101
|
-
event_types: List[SocketEvent] = Field(..., description="Subscribed event types")
|
|
102
|
-
filters: Optional[EventSubscriptionFilter] = Field(None, description="Event filters")
|
|
103
|
-
priority: EventPriority = Field(default=EventPriority.NORMAL)
|
|
104
|
-
active: bool = Field(default=True, description="Subscription status")
|
|
105
|
-
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
|
|
106
|
-
last_event_received: Optional[datetime] = Field(None, description="Last event timestamp")
|
|
107
|
-
events_received: int = Field(default=0, description="Total events received")
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
# EventDeliveryResult and EventStatistics moved to unrealon_sdk.dto.events
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
class EventHandler:
|
|
114
|
-
"""Type-safe event handler wrapper."""
|
|
115
|
-
|
|
116
|
-
def __init__(
|
|
117
|
-
self,
|
|
118
|
-
handler: Callable[[EnterpriseEvent], Union[None, Awaitable[None]]],
|
|
119
|
-
subscription: EventSubscription,
|
|
120
|
-
):
|
|
121
|
-
self.handler = handler
|
|
122
|
-
self.subscription = subscription
|
|
123
|
-
self.call_count = 0
|
|
124
|
-
self.last_called: Optional[datetime] = None
|
|
125
|
-
self.errors: List[str] = []
|
|
126
|
-
|
|
127
|
-
async def __call__(self, event: EnterpriseEvent) -> bool:
|
|
128
|
-
"""Execute handler with error handling and tracking."""
|
|
129
|
-
try:
|
|
130
|
-
self.call_count += 1
|
|
131
|
-
self.last_called = datetime.now(timezone.utc)
|
|
132
|
-
|
|
133
|
-
result = self.handler(event)
|
|
134
|
-
if asyncio.iscoroutine(result):
|
|
135
|
-
await result
|
|
136
|
-
|
|
137
|
-
return True
|
|
138
|
-
|
|
139
|
-
except Exception as e:
|
|
140
|
-
error_msg = f"Handler error: {e}"
|
|
141
|
-
self.errors.append(error_msg)
|
|
142
|
-
logger.error(f"Event handler failed: {error_msg}")
|
|
143
|
-
return False
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
class EnterpriseEventSystem:
|
|
147
|
-
"""
|
|
148
|
-
Enterprise-grade event system for UnrealOn SDK.
|
|
149
|
-
|
|
150
|
-
Features:
|
|
151
|
-
- Type-safe event handling with Pydantic validation
|
|
152
|
-
- Event correlation and tracking
|
|
153
|
-
- Performance monitoring and metrics
|
|
154
|
-
- Event replay and audit capabilities
|
|
155
|
-
- Real-time subscription management
|
|
156
|
-
- Circuit breaker pattern for fault tolerance
|
|
157
|
-
"""
|
|
158
|
-
|
|
159
|
-
def __init__(self, config: AdapterConfig):
|
|
160
|
-
"""
|
|
161
|
-
Initialize Enterprise Event System.
|
|
162
|
-
|
|
163
|
-
Args:
|
|
164
|
-
config: Adapter configuration
|
|
165
|
-
"""
|
|
166
|
-
self.config = config
|
|
167
|
-
self.logger = logger
|
|
168
|
-
|
|
169
|
-
# Event management
|
|
170
|
-
self._subscriptions: Dict[str, EventSubscription] = {}
|
|
171
|
-
self._handlers: Dict[str, List[EventHandler]] = defaultdict(list)
|
|
172
|
-
self._event_history: deque[EnterpriseEvent] = deque(maxlen=1000)
|
|
173
|
-
self._delivery_results: deque[EventDeliveryResult] = deque(maxlen=500)
|
|
174
|
-
|
|
175
|
-
# Performance tracking
|
|
176
|
-
self._statistics = EventStatistics()
|
|
177
|
-
self._delivery_times: deque[float] = deque(maxlen=100)
|
|
178
|
-
|
|
179
|
-
# Circuit breaker
|
|
180
|
-
self._circuit_open = False
|
|
181
|
-
self._circuit_failures = 0
|
|
182
|
-
self._circuit_reset_time: Optional[datetime] = None
|
|
183
|
-
self._max_failures = 5
|
|
184
|
-
self._circuit_timeout = 60 # seconds
|
|
185
|
-
|
|
186
|
-
# Background tasks
|
|
187
|
-
self._background_tasks: List[asyncio.Task[Any]] = []
|
|
188
|
-
self._shutdown_event = asyncio.Event()
|
|
189
|
-
|
|
190
|
-
self.logger.info("Enterprise Event System initialized")
|
|
191
|
-
|
|
192
|
-
async def subscribe(
|
|
193
|
-
self,
|
|
194
|
-
subscriber_id: str,
|
|
195
|
-
event_types: List[SocketEvent],
|
|
196
|
-
handler: Callable[[EnterpriseEvent], Union[None, Awaitable[None]]],
|
|
197
|
-
filters: Optional[EventSubscriptionFilter] = None,
|
|
198
|
-
priority: EventPriority = EventPriority.NORMAL,
|
|
199
|
-
) -> str:
|
|
200
|
-
"""
|
|
201
|
-
Subscribe to events with type-safe handler.
|
|
202
|
-
|
|
203
|
-
Args:
|
|
204
|
-
subscriber_id: Unique subscriber identifier
|
|
205
|
-
event_types: List of event types to subscribe to
|
|
206
|
-
handler: Event handler function (sync or async)
|
|
207
|
-
filters: Optional event filters
|
|
208
|
-
priority: Subscription priority
|
|
209
|
-
|
|
210
|
-
Returns:
|
|
211
|
-
Subscription ID
|
|
212
|
-
"""
|
|
213
|
-
subscription_id = generate_correlation_id()
|
|
214
|
-
|
|
215
|
-
subscription = EventSubscription(
|
|
216
|
-
subscription_id=subscription_id,
|
|
217
|
-
subscriber_id=subscriber_id,
|
|
218
|
-
event_types=event_types,
|
|
219
|
-
filters=filters,
|
|
220
|
-
priority=priority,
|
|
221
|
-
last_event_received=None,
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
self._subscriptions[subscription_id] = subscription
|
|
225
|
-
|
|
226
|
-
# Create handler wrapper
|
|
227
|
-
event_handler = EventHandler(handler, subscription)
|
|
228
|
-
|
|
229
|
-
# Register handler for each event type
|
|
230
|
-
for event_type in event_types:
|
|
231
|
-
self._handlers[event_type.value].append(event_handler)
|
|
232
|
-
|
|
233
|
-
self._statistics.active_subscriptions = len(self._subscriptions)
|
|
234
|
-
|
|
235
|
-
self.logger.info(
|
|
236
|
-
f"Subscription created: {subscription_id} for {subscriber_id}, "
|
|
237
|
-
f"events: {[e.value for e in event_types]}"
|
|
238
|
-
)
|
|
239
|
-
|
|
240
|
-
return subscription_id
|
|
241
|
-
|
|
242
|
-
async def unsubscribe(self, subscription_id: str) -> bool:
|
|
243
|
-
"""
|
|
244
|
-
Unsubscribe from events.
|
|
245
|
-
|
|
246
|
-
Args:
|
|
247
|
-
subscription_id: Subscription to remove
|
|
248
|
-
|
|
249
|
-
Returns:
|
|
250
|
-
True if unsubscribed successfully
|
|
251
|
-
"""
|
|
252
|
-
if subscription_id not in self._subscriptions:
|
|
253
|
-
return False
|
|
254
|
-
|
|
255
|
-
subscription = self._subscriptions[subscription_id]
|
|
256
|
-
|
|
257
|
-
# Remove handlers
|
|
258
|
-
for event_type in subscription.event_types:
|
|
259
|
-
handlers = self._handlers[event_type.value]
|
|
260
|
-
self._handlers[event_type.value] = [
|
|
261
|
-
h for h in handlers if h.subscription.subscription_id != subscription_id
|
|
262
|
-
]
|
|
263
|
-
|
|
264
|
-
# Remove subscription
|
|
265
|
-
del self._subscriptions[subscription_id]
|
|
266
|
-
self._statistics.active_subscriptions = len(self._subscriptions)
|
|
267
|
-
|
|
268
|
-
self.logger.info(f"Subscription removed: {subscription_id}")
|
|
269
|
-
return True
|
|
270
|
-
|
|
271
|
-
async def publish(
|
|
272
|
-
self,
|
|
273
|
-
event_type: SocketEvent,
|
|
274
|
-
data: Dict[str, Any],
|
|
275
|
-
source: str,
|
|
276
|
-
priority: EventPriority = EventPriority.NORMAL,
|
|
277
|
-
correlation_id: Optional[str] = None,
|
|
278
|
-
tags: Optional[List[str]] = None,
|
|
279
|
-
) -> str:
|
|
280
|
-
"""
|
|
281
|
-
Publish event to all matching subscribers.
|
|
282
|
-
|
|
283
|
-
Args:
|
|
284
|
-
event_type: Type of event to publish
|
|
285
|
-
data: Event payload data
|
|
286
|
-
source: Event source identifier
|
|
287
|
-
priority: Event priority level
|
|
288
|
-
correlation_id: Optional correlation ID
|
|
289
|
-
tags: Optional event tags
|
|
290
|
-
|
|
291
|
-
Returns:
|
|
292
|
-
Event ID
|
|
293
|
-
"""
|
|
294
|
-
if self._circuit_open:
|
|
295
|
-
if self._circuit_reset_time and datetime.now(timezone.utc) < self._circuit_reset_time:
|
|
296
|
-
self.logger.warning("Circuit breaker open - event publishing suspended")
|
|
297
|
-
raise ConnectionError("Event system circuit breaker is open")
|
|
298
|
-
else:
|
|
299
|
-
self._circuit_open = False
|
|
300
|
-
self._circuit_failures = 0
|
|
301
|
-
self.logger.info("Circuit breaker reset")
|
|
302
|
-
|
|
303
|
-
# Create event metadata
|
|
304
|
-
metadata = EventMetadata(
|
|
305
|
-
event_id=generate_correlation_id(),
|
|
306
|
-
correlation_id=correlation_id or generate_correlation_id(),
|
|
307
|
-
source=source,
|
|
308
|
-
priority=priority,
|
|
309
|
-
tags=tags or [],
|
|
310
|
-
expires_at=None,
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
# Create enterprise event
|
|
314
|
-
event = EnterpriseEvent(event_type=event_type, data=data, metadata=metadata)
|
|
315
|
-
|
|
316
|
-
# Add to history
|
|
317
|
-
self._event_history.append(event)
|
|
318
|
-
|
|
319
|
-
# Update statistics
|
|
320
|
-
self._statistics.total_events_published += 1
|
|
321
|
-
self._statistics.events_by_type[event_type.value] = (
|
|
322
|
-
self._statistics.events_by_type.get(event_type.value, 0) + 1
|
|
323
|
-
)
|
|
324
|
-
self._statistics.events_by_priority[priority.value] = (
|
|
325
|
-
self._statistics.events_by_priority.get(priority.value, 0) + 1
|
|
326
|
-
)
|
|
327
|
-
|
|
328
|
-
# Route event to subscribers
|
|
329
|
-
await self._route_event(event)
|
|
330
|
-
|
|
331
|
-
self.logger.debug(
|
|
332
|
-
f"Event published: {event.metadata.event_id}, "
|
|
333
|
-
f"type: {event_type.value}, source: {source}"
|
|
334
|
-
)
|
|
335
|
-
|
|
336
|
-
return event.metadata.event_id
|
|
337
|
-
|
|
338
|
-
async def _route_event(self, event: EnterpriseEvent) -> None:
|
|
339
|
-
"""Route event to matching subscribers with error handling."""
|
|
340
|
-
handlers = self._handlers.get(event.event_type.value, [])
|
|
341
|
-
|
|
342
|
-
if not handlers:
|
|
343
|
-
return
|
|
344
|
-
|
|
345
|
-
delivery_tasks = []
|
|
346
|
-
|
|
347
|
-
for handler in handlers:
|
|
348
|
-
# Check if subscription matches filters
|
|
349
|
-
if self._matches_filters(event, handler.subscription.filters):
|
|
350
|
-
task = asyncio.create_task(self._deliver_event(event, handler))
|
|
351
|
-
delivery_tasks.append(task)
|
|
352
|
-
|
|
353
|
-
# Wait for all deliveries
|
|
354
|
-
if delivery_tasks:
|
|
355
|
-
results = await asyncio.gather(*delivery_tasks, return_exceptions=True)
|
|
356
|
-
|
|
357
|
-
# Process results
|
|
358
|
-
for result in results:
|
|
359
|
-
if isinstance(result, Exception):
|
|
360
|
-
self._handle_circuit_breaker_failure()
|
|
361
|
-
self.logger.error(f"Event delivery failed: {result}")
|
|
362
|
-
|
|
363
|
-
def _matches_filters(
|
|
364
|
-
self, event: EnterpriseEvent, filters: Optional[EventSubscriptionFilter]
|
|
365
|
-
) -> bool:
|
|
366
|
-
"""Check if event matches subscription filters."""
|
|
367
|
-
if not filters:
|
|
368
|
-
return True
|
|
369
|
-
|
|
370
|
-
# Check event types
|
|
371
|
-
if filters.event_types and event.event_type not in filters.event_types:
|
|
372
|
-
return False
|
|
373
|
-
|
|
374
|
-
# Check source pattern
|
|
375
|
-
if filters.source_pattern and filters.source_pattern not in event.metadata.source:
|
|
376
|
-
return False
|
|
377
|
-
|
|
378
|
-
# Check priority minimum
|
|
379
|
-
if filters.priority_min:
|
|
380
|
-
priority_order = {
|
|
381
|
-
EventPriority.LOW: 0,
|
|
382
|
-
EventPriority.NORMAL: 1,
|
|
383
|
-
EventPriority.HIGH: 2,
|
|
384
|
-
EventPriority.CRITICAL: 3,
|
|
385
|
-
}
|
|
386
|
-
if priority_order[event.metadata.priority] < priority_order[filters.priority_min]:
|
|
387
|
-
return False
|
|
388
|
-
|
|
389
|
-
# Check correlation ID
|
|
390
|
-
if filters.correlation_id and event.metadata.correlation_id != filters.correlation_id:
|
|
391
|
-
return False
|
|
392
|
-
|
|
393
|
-
# Check tags
|
|
394
|
-
if filters.tags:
|
|
395
|
-
if not any(tag in event.metadata.tags for tag in filters.tags):
|
|
396
|
-
return False
|
|
397
|
-
|
|
398
|
-
return True
|
|
399
|
-
|
|
400
|
-
async def _deliver_event(self, event: EnterpriseEvent, handler: EventHandler) -> bool:
|
|
401
|
-
"""Deliver event to specific handler with tracking."""
|
|
402
|
-
start_time = datetime.now(timezone.utc)
|
|
403
|
-
delivery_id = generate_correlation_id()
|
|
404
|
-
|
|
405
|
-
try:
|
|
406
|
-
success = await handler(event)
|
|
407
|
-
|
|
408
|
-
delivery_time = (datetime.now(timezone.utc) - start_time).total_seconds() * 1000
|
|
409
|
-
self._delivery_times.append(delivery_time)
|
|
410
|
-
|
|
411
|
-
# Update statistics
|
|
412
|
-
if success:
|
|
413
|
-
self._statistics.total_events_delivered += 1
|
|
414
|
-
handler.subscription.events_received += 1
|
|
415
|
-
handler.subscription.last_event_received = datetime.now(timezone.utc)
|
|
416
|
-
else:
|
|
417
|
-
self._statistics.total_delivery_failures += 1
|
|
418
|
-
self._handle_circuit_breaker_failure()
|
|
419
|
-
|
|
420
|
-
# Record delivery result
|
|
421
|
-
result = EventDeliveryResult(
|
|
422
|
-
delivery_id=delivery_id,
|
|
423
|
-
event_id=event.metadata.event_id,
|
|
424
|
-
subscription_id=handler.subscription.subscription_id,
|
|
425
|
-
status=EventDeliveryStatus.DELIVERED if success else EventDeliveryStatus.FAILED,
|
|
426
|
-
delivery_time_ms=delivery_time,
|
|
427
|
-
error_message=None if success else "Handler returned False",
|
|
428
|
-
)
|
|
429
|
-
|
|
430
|
-
self._delivery_results.append(result)
|
|
431
|
-
|
|
432
|
-
# Update average delivery time
|
|
433
|
-
if self._delivery_times:
|
|
434
|
-
self._statistics.average_delivery_time_ms = sum(self._delivery_times) / len(
|
|
435
|
-
self._delivery_times
|
|
436
|
-
)
|
|
437
|
-
|
|
438
|
-
return success
|
|
439
|
-
|
|
440
|
-
except Exception as e:
|
|
441
|
-
self._statistics.total_delivery_failures += 1
|
|
442
|
-
self._handle_circuit_breaker_failure()
|
|
443
|
-
|
|
444
|
-
# Record failed delivery
|
|
445
|
-
result = EventDeliveryResult(
|
|
446
|
-
delivery_id=delivery_id,
|
|
447
|
-
event_id=event.metadata.event_id,
|
|
448
|
-
subscription_id=handler.subscription.subscription_id,
|
|
449
|
-
status=EventDeliveryStatus.FAILED,
|
|
450
|
-
error_message=str(e),
|
|
451
|
-
delivery_time_ms=None,
|
|
452
|
-
)
|
|
453
|
-
|
|
454
|
-
self._delivery_results.append(result)
|
|
455
|
-
|
|
456
|
-
self.logger.error(f"Event delivery failed: {e}")
|
|
457
|
-
return False
|
|
458
|
-
|
|
459
|
-
def _handle_circuit_breaker_failure(self) -> None:
|
|
460
|
-
"""Handle circuit breaker logic for failure tracking."""
|
|
461
|
-
self._circuit_failures += 1
|
|
462
|
-
|
|
463
|
-
if self._circuit_failures >= self._max_failures:
|
|
464
|
-
self._circuit_open = True
|
|
465
|
-
self._circuit_reset_time = datetime.now(timezone.utc).replace(
|
|
466
|
-
second=datetime.now(timezone.utc).second + self._circuit_timeout
|
|
467
|
-
)
|
|
468
|
-
self.logger.warning(
|
|
469
|
-
f"Circuit breaker opened after {self._circuit_failures} failures. "
|
|
470
|
-
f"Reset in {self._circuit_timeout} seconds."
|
|
471
|
-
)
|
|
472
|
-
|
|
473
|
-
def get_statistics(self) -> EventStatistics:
|
|
474
|
-
"""Get current event system statistics."""
|
|
475
|
-
return self._statistics
|
|
476
|
-
|
|
477
|
-
def get_subscription(self, subscription_id: str) -> Optional[EventSubscription]:
|
|
478
|
-
"""Get subscription by ID."""
|
|
479
|
-
return self._subscriptions.get(subscription_id)
|
|
480
|
-
|
|
481
|
-
def list_subscriptions(self, subscriber_id: Optional[str] = None) -> List[EventSubscription]:
|
|
482
|
-
"""List all subscriptions or filter by subscriber."""
|
|
483
|
-
if subscriber_id:
|
|
484
|
-
return [
|
|
485
|
-
sub for sub in self._subscriptions.values() if sub.subscriber_id == subscriber_id
|
|
486
|
-
]
|
|
487
|
-
return list(self._subscriptions.values())
|
|
488
|
-
|
|
489
|
-
def get_event_history(
|
|
490
|
-
self, event_types: Optional[List[SocketEvent]] = None, limit: int = 100
|
|
491
|
-
) -> List[EnterpriseEvent]:
|
|
492
|
-
"""Get recent event history with optional filtering."""
|
|
493
|
-
events = list(self._event_history)
|
|
494
|
-
|
|
495
|
-
if event_types:
|
|
496
|
-
events = [e for e in events if e.event_type in event_types]
|
|
497
|
-
|
|
498
|
-
return events[-limit:]
|
|
499
|
-
|
|
500
|
-
async def shutdown(self) -> None:
|
|
501
|
-
"""Shutdown event system gracefully."""
|
|
502
|
-
self.logger.info("Shutting down Enterprise Event System...")
|
|
503
|
-
|
|
504
|
-
# Signal shutdown
|
|
505
|
-
self._shutdown_event.set()
|
|
506
|
-
|
|
507
|
-
# Cancel background tasks
|
|
508
|
-
for task in self._background_tasks:
|
|
509
|
-
task.cancel()
|
|
510
|
-
|
|
511
|
-
# Wait for tasks to complete
|
|
512
|
-
if self._background_tasks:
|
|
513
|
-
await asyncio.gather(*self._background_tasks, return_exceptions=True)
|
|
514
|
-
|
|
515
|
-
self.logger.info("Enterprise Event System shutdown complete")
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
# Convenience function for creating event system
|
|
519
|
-
def create_event_system(config: AdapterConfig) -> EnterpriseEventSystem:
|
|
520
|
-
"""
|
|
521
|
-
Create and configure Enterprise Event System.
|
|
522
|
-
|
|
523
|
-
Args:
|
|
524
|
-
config: Adapter configuration
|
|
525
|
-
|
|
526
|
-
Returns:
|
|
527
|
-
Configured event system instance
|
|
528
|
-
"""
|
|
529
|
-
return EnterpriseEventSystem(config)
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
# Export all public components
|
|
533
|
-
__all__ = [
|
|
534
|
-
# Core system
|
|
535
|
-
"EnterpriseEventSystem",
|
|
536
|
-
"create_event_system",
|
|
537
|
-
# Models
|
|
538
|
-
"EnterpriseEvent",
|
|
539
|
-
"EventMetadata",
|
|
540
|
-
"EventSubscription",
|
|
541
|
-
"EventSubscriptionFilter",
|
|
542
|
-
"EventDeliveryResult",
|
|
543
|
-
"EventStatistics",
|
|
544
|
-
# Enums
|
|
545
|
-
"EventPriority",
|
|
546
|
-
"EventDeliveryStatus",
|
|
547
|
-
# Handler
|
|
548
|
-
"EventHandler",
|
|
549
|
-
]
|