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.
Files changed (302) hide show
  1. unrealon/__init__.py +23 -21
  2. unrealon-1.1.1.dist-info/METADATA +722 -0
  3. unrealon-1.1.1.dist-info/RECORD +82 -0
  4. {unrealon-1.0.9.dist-info → unrealon-1.1.1.dist-info}/WHEEL +1 -1
  5. unrealon-1.1.1.dist-info/entry_points.txt +9 -0
  6. {unrealon-1.0.9.dist-info → unrealon-1.1.1.dist-info/licenses}/LICENSE +1 -1
  7. unrealon_bridge/__init__.py +114 -0
  8. unrealon_bridge/cli.py +316 -0
  9. unrealon_bridge/client/__init__.py +93 -0
  10. unrealon_bridge/client/base.py +78 -0
  11. unrealon_bridge/client/commands.py +89 -0
  12. unrealon_bridge/client/connection.py +90 -0
  13. unrealon_bridge/client/events.py +65 -0
  14. unrealon_bridge/client/health.py +38 -0
  15. unrealon_bridge/client/html_parser.py +146 -0
  16. unrealon_bridge/client/logging.py +139 -0
  17. unrealon_bridge/client/proxy.py +70 -0
  18. unrealon_bridge/client/scheduler.py +450 -0
  19. unrealon_bridge/client/session.py +70 -0
  20. unrealon_bridge/configs/__init__.py +14 -0
  21. unrealon_bridge/configs/bridge_config.py +212 -0
  22. unrealon_bridge/configs/bridge_config.yaml +39 -0
  23. unrealon_bridge/models/__init__.py +138 -0
  24. unrealon_bridge/models/base.py +28 -0
  25. unrealon_bridge/models/command.py +41 -0
  26. unrealon_bridge/models/events.py +40 -0
  27. unrealon_bridge/models/html_parser.py +79 -0
  28. unrealon_bridge/models/logging.py +55 -0
  29. unrealon_bridge/models/parser.py +63 -0
  30. unrealon_bridge/models/proxy.py +41 -0
  31. unrealon_bridge/models/requests.py +95 -0
  32. unrealon_bridge/models/responses.py +88 -0
  33. unrealon_bridge/models/scheduler.py +592 -0
  34. unrealon_bridge/models/session.py +28 -0
  35. unrealon_bridge/server/__init__.py +91 -0
  36. unrealon_bridge/server/base.py +171 -0
  37. unrealon_bridge/server/handlers/__init__.py +23 -0
  38. unrealon_bridge/server/handlers/command.py +110 -0
  39. unrealon_bridge/server/handlers/html_parser.py +139 -0
  40. unrealon_bridge/server/handlers/logging.py +95 -0
  41. unrealon_bridge/server/handlers/parser.py +95 -0
  42. unrealon_bridge/server/handlers/proxy.py +75 -0
  43. unrealon_bridge/server/handlers/scheduler.py +545 -0
  44. unrealon_bridge/server/handlers/session.py +66 -0
  45. unrealon_browser/__init__.py +61 -18
  46. unrealon_browser/{src/cli → cli}/browser_cli.py +6 -13
  47. unrealon_browser/{src/cli → cli}/cookies_cli.py +5 -1
  48. unrealon_browser/{src/core → core}/browser_manager.py +2 -2
  49. unrealon_browser/{src/managers → managers}/captcha.py +1 -1
  50. unrealon_browser/{src/managers → managers}/cookies.py +1 -1
  51. unrealon_browser/managers/logger_bridge.py +231 -0
  52. unrealon_browser/{src/managers → managers}/profile.py +1 -1
  53. unrealon_driver/__init__.py +73 -19
  54. unrealon_driver/browser/__init__.py +8 -0
  55. unrealon_driver/browser/config.py +74 -0
  56. unrealon_driver/browser/manager.py +416 -0
  57. unrealon_driver/exceptions.py +28 -0
  58. unrealon_driver/parser/__init__.py +55 -0
  59. unrealon_driver/parser/cli_manager.py +141 -0
  60. unrealon_driver/parser/daemon_manager.py +227 -0
  61. unrealon_driver/parser/managers/__init__.py +46 -0
  62. unrealon_driver/parser/managers/browser.py +51 -0
  63. unrealon_driver/parser/managers/config.py +281 -0
  64. unrealon_driver/parser/managers/error.py +412 -0
  65. unrealon_driver/parser/managers/html.py +732 -0
  66. unrealon_driver/parser/managers/logging.py +609 -0
  67. unrealon_driver/parser/managers/result.py +321 -0
  68. unrealon_driver/parser/parser_manager.py +628 -0
  69. unrealon/sdk_config.py +0 -88
  70. unrealon-1.0.9.dist-info/METADATA +0 -810
  71. unrealon-1.0.9.dist-info/RECORD +0 -246
  72. unrealon_browser/pyproject.toml +0 -182
  73. unrealon_browser/src/__init__.py +0 -62
  74. unrealon_browser/src/managers/logger_bridge.py +0 -395
  75. unrealon_driver/README.md +0 -204
  76. unrealon_driver/pyproject.toml +0 -187
  77. unrealon_driver/src/__init__.py +0 -90
  78. unrealon_driver/src/cli/__init__.py +0 -10
  79. unrealon_driver/src/cli/main.py +0 -66
  80. unrealon_driver/src/cli/simple.py +0 -510
  81. unrealon_driver/src/config/__init__.py +0 -11
  82. unrealon_driver/src/config/auto_config.py +0 -478
  83. unrealon_driver/src/core/__init__.py +0 -18
  84. unrealon_driver/src/core/exceptions.py +0 -289
  85. unrealon_driver/src/core/parser.py +0 -638
  86. unrealon_driver/src/dto/__init__.py +0 -66
  87. unrealon_driver/src/dto/cli.py +0 -119
  88. unrealon_driver/src/dto/config.py +0 -18
  89. unrealon_driver/src/dto/events.py +0 -237
  90. unrealon_driver/src/dto/execution.py +0 -313
  91. unrealon_driver/src/dto/services.py +0 -311
  92. unrealon_driver/src/execution/__init__.py +0 -23
  93. unrealon_driver/src/execution/daemon_mode.py +0 -317
  94. unrealon_driver/src/execution/interactive_mode.py +0 -88
  95. unrealon_driver/src/execution/modes.py +0 -45
  96. unrealon_driver/src/execution/scheduled_mode.py +0 -209
  97. unrealon_driver/src/execution/test_mode.py +0 -250
  98. unrealon_driver/src/logging/__init__.py +0 -24
  99. unrealon_driver/src/logging/driver_logger.py +0 -512
  100. unrealon_driver/src/services/__init__.py +0 -24
  101. unrealon_driver/src/services/browser_service.py +0 -726
  102. unrealon_driver/src/services/llm/__init__.py +0 -15
  103. unrealon_driver/src/services/llm/browser_llm_service.py +0 -363
  104. unrealon_driver/src/services/llm/llm.py +0 -195
  105. unrealon_driver/src/services/logger_service.py +0 -232
  106. unrealon_driver/src/services/metrics_service.py +0 -185
  107. unrealon_driver/src/services/scheduler_service.py +0 -489
  108. unrealon_driver/src/services/websocket_service.py +0 -362
  109. unrealon_driver/src/utils/__init__.py +0 -16
  110. unrealon_driver/src/utils/service_factory.py +0 -317
  111. unrealon_driver/src/utils/time_formatter.py +0 -338
  112. unrealon_llm/README.md +0 -44
  113. unrealon_llm/__init__.py +0 -26
  114. unrealon_llm/pyproject.toml +0 -154
  115. unrealon_llm/src/__init__.py +0 -228
  116. unrealon_llm/src/cli/__init__.py +0 -0
  117. unrealon_llm/src/core/__init__.py +0 -11
  118. unrealon_llm/src/core/smart_client.py +0 -438
  119. unrealon_llm/src/dto/__init__.py +0 -155
  120. unrealon_llm/src/dto/models/__init__.py +0 -0
  121. unrealon_llm/src/dto/models/config.py +0 -343
  122. unrealon_llm/src/dto/models/core.py +0 -328
  123. unrealon_llm/src/dto/models/enums.py +0 -123
  124. unrealon_llm/src/dto/models/html_analysis.py +0 -345
  125. unrealon_llm/src/dto/models/statistics.py +0 -473
  126. unrealon_llm/src/dto/models/translation.py +0 -383
  127. unrealon_llm/src/dto/models/type_conversion.py +0 -462
  128. unrealon_llm/src/dto/schemas/__init__.py +0 -0
  129. unrealon_llm/src/exceptions.py +0 -392
  130. unrealon_llm/src/llm_config/__init__.py +0 -20
  131. unrealon_llm/src/llm_config/logging_config.py +0 -178
  132. unrealon_llm/src/llm_logging/__init__.py +0 -42
  133. unrealon_llm/src/llm_logging/llm_events.py +0 -107
  134. unrealon_llm/src/llm_logging/llm_logger.py +0 -466
  135. unrealon_llm/src/managers/__init__.py +0 -15
  136. unrealon_llm/src/managers/cache_manager.py +0 -67
  137. unrealon_llm/src/managers/cost_manager.py +0 -107
  138. unrealon_llm/src/managers/request_manager.py +0 -298
  139. unrealon_llm/src/modules/__init__.py +0 -0
  140. unrealon_llm/src/modules/html_processor/__init__.py +0 -25
  141. unrealon_llm/src/modules/html_processor/base_processor.py +0 -415
  142. unrealon_llm/src/modules/html_processor/details_processor.py +0 -85
  143. unrealon_llm/src/modules/html_processor/listing_processor.py +0 -91
  144. unrealon_llm/src/modules/html_processor/models/__init__.py +0 -20
  145. unrealon_llm/src/modules/html_processor/models/processing_models.py +0 -40
  146. unrealon_llm/src/modules/html_processor/models/universal_model.py +0 -56
  147. unrealon_llm/src/modules/html_processor/processor.py +0 -102
  148. unrealon_llm/src/modules/llm/__init__.py +0 -0
  149. unrealon_llm/src/modules/translator/__init__.py +0 -0
  150. unrealon_llm/src/provider.py +0 -116
  151. unrealon_llm/src/utils/__init__.py +0 -95
  152. unrealon_llm/src/utils/common.py +0 -64
  153. unrealon_llm/src/utils/data_extractor.py +0 -188
  154. unrealon_llm/src/utils/html_cleaner.py +0 -767
  155. unrealon_llm/src/utils/language_detector.py +0 -308
  156. unrealon_llm/src/utils/models_cache.py +0 -592
  157. unrealon_llm/src/utils/smart_counter.py +0 -229
  158. unrealon_llm/src/utils/token_counter.py +0 -189
  159. unrealon_sdk/README.md +0 -25
  160. unrealon_sdk/__init__.py +0 -30
  161. unrealon_sdk/pyproject.toml +0 -231
  162. unrealon_sdk/src/__init__.py +0 -150
  163. unrealon_sdk/src/cli/__init__.py +0 -12
  164. unrealon_sdk/src/cli/commands/__init__.py +0 -22
  165. unrealon_sdk/src/cli/commands/benchmark.py +0 -42
  166. unrealon_sdk/src/cli/commands/diagnostics.py +0 -573
  167. unrealon_sdk/src/cli/commands/health.py +0 -46
  168. unrealon_sdk/src/cli/commands/integration.py +0 -498
  169. unrealon_sdk/src/cli/commands/reports.py +0 -43
  170. unrealon_sdk/src/cli/commands/security.py +0 -36
  171. unrealon_sdk/src/cli/commands/server.py +0 -483
  172. unrealon_sdk/src/cli/commands/servers.py +0 -56
  173. unrealon_sdk/src/cli/commands/tests.py +0 -55
  174. unrealon_sdk/src/cli/main.py +0 -126
  175. unrealon_sdk/src/cli/utils/reporter.py +0 -519
  176. unrealon_sdk/src/clients/openapi.yaml +0 -3347
  177. unrealon_sdk/src/clients/python_http/__init__.py +0 -3
  178. unrealon_sdk/src/clients/python_http/api_config.py +0 -228
  179. unrealon_sdk/src/clients/python_http/models/BaseModel.py +0 -12
  180. unrealon_sdk/src/clients/python_http/models/BroadcastDeliveryStats.py +0 -33
  181. unrealon_sdk/src/clients/python_http/models/BroadcastMessage.py +0 -17
  182. unrealon_sdk/src/clients/python_http/models/BroadcastMessageRequest.py +0 -35
  183. unrealon_sdk/src/clients/python_http/models/BroadcastPriority.py +0 -10
  184. unrealon_sdk/src/clients/python_http/models/BroadcastResponse.py +0 -21
  185. unrealon_sdk/src/clients/python_http/models/BroadcastResultResponse.py +0 -33
  186. unrealon_sdk/src/clients/python_http/models/BroadcastTarget.py +0 -11
  187. unrealon_sdk/src/clients/python_http/models/ConnectionStats.py +0 -27
  188. unrealon_sdk/src/clients/python_http/models/ConnectionsResponse.py +0 -21
  189. unrealon_sdk/src/clients/python_http/models/DeveloperMessageResponse.py +0 -23
  190. unrealon_sdk/src/clients/python_http/models/ErrorResponse.py +0 -25
  191. unrealon_sdk/src/clients/python_http/models/HTTPValidationError.py +0 -16
  192. unrealon_sdk/src/clients/python_http/models/HealthResponse.py +0 -23
  193. unrealon_sdk/src/clients/python_http/models/HealthStatus.py +0 -33
  194. unrealon_sdk/src/clients/python_http/models/LogLevel.py +0 -10
  195. unrealon_sdk/src/clients/python_http/models/LoggingRequest.py +0 -27
  196. unrealon_sdk/src/clients/python_http/models/LoggingResponse.py +0 -23
  197. unrealon_sdk/src/clients/python_http/models/MaintenanceMode.py +0 -9
  198. unrealon_sdk/src/clients/python_http/models/MaintenanceModeRequest.py +0 -33
  199. unrealon_sdk/src/clients/python_http/models/MaintenanceStatusResponse.py +0 -39
  200. unrealon_sdk/src/clients/python_http/models/ParserCommandRequest.py +0 -25
  201. unrealon_sdk/src/clients/python_http/models/ParserMessageResponse.py +0 -21
  202. unrealon_sdk/src/clients/python_http/models/ParserRegistrationRequest.py +0 -28
  203. unrealon_sdk/src/clients/python_http/models/ParserRegistrationResponse.py +0 -25
  204. unrealon_sdk/src/clients/python_http/models/ParserType.py +0 -10
  205. unrealon_sdk/src/clients/python_http/models/ProxyBlockRequest.py +0 -19
  206. unrealon_sdk/src/clients/python_http/models/ProxyEndpointResponse.py +0 -20
  207. unrealon_sdk/src/clients/python_http/models/ProxyListResponse.py +0 -19
  208. unrealon_sdk/src/clients/python_http/models/ProxyProvider.py +0 -10
  209. unrealon_sdk/src/clients/python_http/models/ProxyPurchaseRequest.py +0 -25
  210. unrealon_sdk/src/clients/python_http/models/ProxyResponse.py +0 -47
  211. unrealon_sdk/src/clients/python_http/models/ProxyRotationRequest.py +0 -23
  212. unrealon_sdk/src/clients/python_http/models/ProxyStatus.py +0 -10
  213. unrealon_sdk/src/clients/python_http/models/ProxyUsageRequest.py +0 -19
  214. unrealon_sdk/src/clients/python_http/models/ProxyUsageStatsResponse.py +0 -26
  215. unrealon_sdk/src/clients/python_http/models/ServiceRegistrationDto.py +0 -23
  216. unrealon_sdk/src/clients/python_http/models/ServiceStatsResponse.py +0 -31
  217. unrealon_sdk/src/clients/python_http/models/SessionStartRequest.py +0 -23
  218. unrealon_sdk/src/clients/python_http/models/SuccessResponse.py +0 -25
  219. unrealon_sdk/src/clients/python_http/models/SystemNotificationResponse.py +0 -23
  220. unrealon_sdk/src/clients/python_http/models/ValidationError.py +0 -18
  221. unrealon_sdk/src/clients/python_http/models/ValidationErrorResponse.py +0 -21
  222. unrealon_sdk/src/clients/python_http/models/WebSocketMetrics.py +0 -21
  223. unrealon_sdk/src/clients/python_http/models/__init__.py +0 -44
  224. unrealon_sdk/src/clients/python_http/services/None_service.py +0 -35
  225. unrealon_sdk/src/clients/python_http/services/ParserManagement_service.py +0 -190
  226. unrealon_sdk/src/clients/python_http/services/ProxyManagement_service.py +0 -289
  227. unrealon_sdk/src/clients/python_http/services/SocketLogging_service.py +0 -187
  228. unrealon_sdk/src/clients/python_http/services/SystemHealth_service.py +0 -119
  229. unrealon_sdk/src/clients/python_http/services/WebSocketAPI_service.py +0 -198
  230. unrealon_sdk/src/clients/python_http/services/__init__.py +0 -0
  231. unrealon_sdk/src/clients/python_http/services/admin_service.py +0 -125
  232. unrealon_sdk/src/clients/python_http/services/async_None_service.py +0 -35
  233. unrealon_sdk/src/clients/python_http/services/async_ParserManagement_service.py +0 -190
  234. unrealon_sdk/src/clients/python_http/services/async_ProxyManagement_service.py +0 -289
  235. unrealon_sdk/src/clients/python_http/services/async_SocketLogging_service.py +0 -189
  236. unrealon_sdk/src/clients/python_http/services/async_SystemHealth_service.py +0 -123
  237. unrealon_sdk/src/clients/python_http/services/async_WebSocketAPI_service.py +0 -200
  238. unrealon_sdk/src/clients/python_http/services/async_admin_service.py +0 -125
  239. unrealon_sdk/src/clients/python_websocket/__init__.py +0 -28
  240. unrealon_sdk/src/clients/python_websocket/client.py +0 -490
  241. unrealon_sdk/src/clients/python_websocket/events.py +0 -732
  242. unrealon_sdk/src/clients/python_websocket/example.py +0 -136
  243. unrealon_sdk/src/clients/python_websocket/types.py +0 -871
  244. unrealon_sdk/src/core/__init__.py +0 -64
  245. unrealon_sdk/src/core/client.py +0 -556
  246. unrealon_sdk/src/core/config.py +0 -465
  247. unrealon_sdk/src/core/exceptions.py +0 -239
  248. unrealon_sdk/src/core/metadata.py +0 -191
  249. unrealon_sdk/src/core/models.py +0 -142
  250. unrealon_sdk/src/core/types.py +0 -68
  251. unrealon_sdk/src/dto/__init__.py +0 -268
  252. unrealon_sdk/src/dto/authentication.py +0 -108
  253. unrealon_sdk/src/dto/cache.py +0 -208
  254. unrealon_sdk/src/dto/common.py +0 -19
  255. unrealon_sdk/src/dto/concurrency.py +0 -393
  256. unrealon_sdk/src/dto/events.py +0 -108
  257. unrealon_sdk/src/dto/health.py +0 -339
  258. unrealon_sdk/src/dto/load_balancing.py +0 -336
  259. unrealon_sdk/src/dto/logging.py +0 -230
  260. unrealon_sdk/src/dto/performance.py +0 -165
  261. unrealon_sdk/src/dto/rate_limiting.py +0 -295
  262. unrealon_sdk/src/dto/resource_pooling.py +0 -128
  263. unrealon_sdk/src/dto/structured_logging.py +0 -112
  264. unrealon_sdk/src/dto/task_scheduling.py +0 -121
  265. unrealon_sdk/src/dto/websocket.py +0 -55
  266. unrealon_sdk/src/enterprise/__init__.py +0 -59
  267. unrealon_sdk/src/enterprise/authentication.py +0 -401
  268. unrealon_sdk/src/enterprise/cache_manager.py +0 -578
  269. unrealon_sdk/src/enterprise/error_recovery.py +0 -494
  270. unrealon_sdk/src/enterprise/event_system.py +0 -549
  271. unrealon_sdk/src/enterprise/health_monitor.py +0 -747
  272. unrealon_sdk/src/enterprise/load_balancer.py +0 -964
  273. unrealon_sdk/src/enterprise/logging/__init__.py +0 -68
  274. unrealon_sdk/src/enterprise/logging/cleanup.py +0 -156
  275. unrealon_sdk/src/enterprise/logging/development.py +0 -744
  276. unrealon_sdk/src/enterprise/logging/service.py +0 -410
  277. unrealon_sdk/src/enterprise/multithreading_manager.py +0 -853
  278. unrealon_sdk/src/enterprise/performance_monitor.py +0 -539
  279. unrealon_sdk/src/enterprise/proxy_manager.py +0 -696
  280. unrealon_sdk/src/enterprise/rate_limiter.py +0 -652
  281. unrealon_sdk/src/enterprise/resource_pool.py +0 -763
  282. unrealon_sdk/src/enterprise/task_scheduler.py +0 -709
  283. unrealon_sdk/src/internal/__init__.py +0 -10
  284. unrealon_sdk/src/internal/command_router.py +0 -497
  285. unrealon_sdk/src/internal/connection_manager.py +0 -397
  286. unrealon_sdk/src/internal/http_client.py +0 -446
  287. unrealon_sdk/src/internal/websocket_client.py +0 -420
  288. unrealon_sdk/src/provider.py +0 -471
  289. unrealon_sdk/src/utils.py +0 -234
  290. /unrealon_browser/{src/cli → cli}/__init__.py +0 -0
  291. /unrealon_browser/{src/cli → cli}/interactive_mode.py +0 -0
  292. /unrealon_browser/{src/cli → cli}/main.py +0 -0
  293. /unrealon_browser/{src/core → core}/__init__.py +0 -0
  294. /unrealon_browser/{src/dto → dto}/__init__.py +0 -0
  295. /unrealon_browser/{src/dto → dto}/models/config.py +0 -0
  296. /unrealon_browser/{src/dto → dto}/models/core.py +0 -0
  297. /unrealon_browser/{src/dto → dto}/models/dataclasses.py +0 -0
  298. /unrealon_browser/{src/dto → dto}/models/detection.py +0 -0
  299. /unrealon_browser/{src/dto → dto}/models/enums.py +0 -0
  300. /unrealon_browser/{src/dto → dto}/models/statistics.py +0 -0
  301. /unrealon_browser/{src/managers → managers}/__init__.py +0 -0
  302. /unrealon_browser/{src/managers → managers}/stealth.py +0 -0
@@ -1,578 +0,0 @@
1
- """
2
- Cache Manager - Layer 3 Infrastructure Service
3
-
4
- Intelligent caching system with TTL (Time To Live), size management,
5
- and automatic eviction policies. Provides high-performance caching
6
- for UnrealOn SDK components with comprehensive cache analytics.
7
-
8
- Features:
9
- - TTL-based cache expiration with automatic cleanup
10
- - Size-based eviction using LRU (Least Recently Used) policy
11
- - Multi-level cache hierarchy (memory, persistent)
12
- - Cache hit/miss statistics and performance metrics
13
- - Automatic cache warming and preloading
14
- - Cache invalidation patterns and dependencies
15
- - Compression support for large cached objects
16
- - Thread-safe operations for concurrent access
17
- """
18
-
19
- import asyncio
20
- import logging
21
- import time
22
- import threading
23
- import hashlib
24
- import pickle
25
- import gzip
26
- from typing import Dict, List, Optional, Any, Union, Callable, TypeVar, Generic
27
- from datetime import datetime, timezone, timedelta
28
- from enum import Enum
29
- from dataclasses import dataclass, field
30
- from collections import OrderedDict
31
- import weakref
32
-
33
- # Pydantic v2 for all data models
34
- from pydantic import BaseModel, Field, ConfigDict
35
-
36
- # Core SDK components
37
- from unrealon_sdk.src.core.config import AdapterConfig
38
- from unrealon_sdk.src.utils import generate_correlation_id
39
-
40
- # DTO models
41
- from unrealon_sdk.src.dto.logging import SDKEventType, SDKSeverity
42
- from unrealon_sdk.src.dto.cache import (
43
- CachePolicy,
44
- CacheLevel,
45
- CacheEventType,
46
- CacheEntry,
47
- CacheStatistics,
48
- CacheConfig,
49
- CacheOperation,
50
- CacheMetrics,
51
- )
52
-
53
- # Development logging
54
- from typing import TYPE_CHECKING
55
-
56
- if TYPE_CHECKING:
57
- from unrealon_sdk.src.enterprise.logging import DevelopmentLogger
58
-
59
- logger = logging.getLogger(__name__)
60
-
61
- T = TypeVar("T")
62
-
63
-
64
- # All cache models are now imported from DTO layer
65
-
66
-
67
- class CacheManager:
68
- """
69
- Enterprise-grade intelligent cache manager.
70
-
71
- Provides high-performance caching with TTL, size management,
72
- and comprehensive analytics for UnrealOn SDK components.
73
- """
74
-
75
- def __init__(
76
- self,
77
- config: AdapterConfig,
78
- cache_config: Optional[CacheConfig] = None,
79
- dev_logger: Optional["DevelopmentLogger"] = None,
80
- ):
81
- """Initialize cache manager."""
82
- self.config = config
83
- self.cache_config = cache_config or CacheConfig()
84
- self.dev_logger = dev_logger
85
-
86
- # Cache storage
87
- self._cache: OrderedDict[str, CacheEntry[Any]] = OrderedDict()
88
- self._lock = threading.RLock()
89
-
90
- # Statistics
91
- self.statistics = CacheStatistics(max_size=self.cache_config.max_entries)
92
-
93
- # Background tasks
94
- self._cleanup_task: Optional[asyncio.Task[None]] = None
95
- self._shutdown = False
96
-
97
- # Performance tracking
98
- self._access_times: List[float] = []
99
-
100
- # Cache warming callbacks
101
- self._warm_callbacks: List[Callable[[], None]] = []
102
-
103
- self._log_info("Cache manager initialized")
104
-
105
- async def start(self) -> None:
106
- """Start cache manager background tasks."""
107
- if self._cleanup_task is None:
108
- self._cleanup_task = asyncio.create_task(self._cleanup_loop())
109
-
110
- # Warm cache if enabled
111
- if self.cache_config.warm_cache_on_startup:
112
- await self._warm_cache()
113
-
114
- self._log_info("Cache manager started")
115
-
116
- async def stop(self) -> None:
117
- """Stop cache manager and cleanup."""
118
- self._shutdown = True
119
-
120
- if self._cleanup_task:
121
- self._cleanup_task.cancel()
122
- try:
123
- await self._cleanup_task
124
- except asyncio.CancelledError:
125
- pass
126
-
127
- self._log_info("Cache manager stopped")
128
-
129
- def get(self, key: str, default: Optional[T] = None) -> Optional[T]:
130
- """Get value from cache."""
131
- start_time = time.time()
132
-
133
- with self._lock:
134
- self.statistics.total_requests += 1
135
-
136
- if key in self._cache:
137
- entry = self._cache[key]
138
-
139
- # Check if expired
140
- if entry.is_expired():
141
- self._remove_entry(key, CacheEventType.CACHE_EXPIRE)
142
- self.statistics.cache_misses += 1
143
- self._log_cache_event(CacheEventType.CACHE_MISS, key, "expired")
144
- return default
145
-
146
- # Update access info
147
- entry.touch()
148
-
149
- # Move to end for LRU
150
- if self.cache_config.eviction_policy == CachePolicy.LRU:
151
- self._cache.move_to_end(key)
152
-
153
- self.statistics.cache_hits += 1
154
- self._log_cache_event(CacheEventType.CACHE_HIT, key)
155
-
156
- # Track access time
157
- access_time = (time.time() - start_time) * 1000
158
- self._track_access_time(access_time)
159
-
160
- return entry.value
161
- else:
162
- self.statistics.cache_misses += 1
163
- self._log_cache_event(CacheEventType.CACHE_MISS, key, "not found")
164
- return default
165
-
166
- def set(
167
- self,
168
- key: str,
169
- value: T,
170
- ttl_seconds: Optional[float] = None,
171
- compress: bool = False,
172
- ) -> bool:
173
- """Set value in cache."""
174
- try:
175
- # Use default TTL if not specified
176
- if ttl_seconds is None:
177
- ttl_seconds = self.cache_config.default_ttl_seconds
178
-
179
- # Clamp TTL to maximum
180
- if ttl_seconds > self.cache_config.max_ttl_seconds:
181
- ttl_seconds = self.cache_config.max_ttl_seconds
182
-
183
- # Calculate size
184
- size_bytes = self._calculate_size(value)
185
-
186
- # Compress if needed
187
- if compress or (
188
- self.cache_config.compression_enabled
189
- and size_bytes > self.cache_config.compression_threshold_bytes
190
- ):
191
- value = self._compress_value(value)
192
- compress = True
193
-
194
- with self._lock:
195
- # Check if we need to evict entries (sync version for set method)
196
- self._ensure_capacity_sync()
197
-
198
- # Create cache entry
199
- entry = CacheEntry(
200
- key=key,
201
- value=value,
202
- created_at=datetime.now(timezone.utc),
203
- last_accessed=datetime.now(timezone.utc),
204
- ttl_seconds=ttl_seconds,
205
- compressed=compress,
206
- size_bytes=size_bytes,
207
- )
208
-
209
- # Add to cache
210
- if key in self._cache:
211
- # Update existing entry
212
- old_entry = self._cache[key]
213
- self.statistics.memory_usage_bytes -= old_entry.size_bytes
214
-
215
- self._cache[key] = entry
216
- self.statistics.current_size = len(self._cache)
217
- self.statistics.memory_usage_bytes += size_bytes
218
- self.statistics.total_sets += 1
219
-
220
- self._log_cache_event(CacheEventType.CACHE_SET, key)
221
- return True
222
-
223
- except Exception as e:
224
- logger.error(f"Error setting cache key {key}: {e}")
225
- return False
226
-
227
- def delete(self, key: str) -> bool:
228
- """Delete key from cache."""
229
- with self._lock:
230
- if key in self._cache:
231
- self._remove_entry(key, CacheEventType.CACHE_DELETE)
232
- return True
233
- return False
234
-
235
- def clear(self) -> None:
236
- """Clear all cache entries."""
237
- with self._lock:
238
- count = len(self._cache)
239
- self._cache.clear()
240
- self.statistics.current_size = 0
241
- self.statistics.memory_usage_bytes = 0
242
-
243
- self._log_cache_event(CacheEventType.CACHE_CLEAR, f"cleared {count} entries")
244
-
245
- def exists(self, key: str) -> bool:
246
- """Check if key exists in cache (without accessing it)."""
247
- with self._lock:
248
- if key in self._cache:
249
- entry = self._cache[key]
250
- return not entry.is_expired()
251
- return False
252
-
253
- def get_keys(self, pattern: Optional[str] = None) -> List[str]:
254
- """Get all cache keys, optionally filtered by pattern."""
255
- with self._lock:
256
- keys = list(self._cache.keys())
257
-
258
- if pattern:
259
- import fnmatch
260
-
261
- keys = [k for k in keys if fnmatch.fnmatch(k, pattern)]
262
-
263
- return keys
264
-
265
- def get_statistics(self) -> CacheStatistics:
266
- """Get cache statistics."""
267
- with self._lock:
268
- # Update calculated stats
269
- total_requests = self.statistics.cache_hits + self.statistics.cache_misses
270
- if total_requests > 0:
271
- self.statistics.hit_rate_percent = (
272
- self.statistics.cache_hits / total_requests
273
- ) * 100
274
-
275
- if self._access_times:
276
- self.statistics.avg_access_time_ms = sum(self._access_times) / len(
277
- self._access_times
278
- )
279
-
280
- return self.statistics.model_copy()
281
-
282
- def reset_statistics(self) -> None:
283
- """Reset cache statistics."""
284
- with self._lock:
285
- self.statistics = CacheStatistics(
286
- max_size=self.cache_config.max_entries,
287
- current_size=len(self._cache),
288
- memory_usage_bytes=self.statistics.memory_usage_bytes,
289
- )
290
- self._access_times.clear()
291
-
292
- self._log_info("Cache statistics reset")
293
-
294
- def _ensure_capacity_sync(self) -> None:
295
- """Ensure cache doesn't exceed capacity limits (synchronous version)."""
296
- # Check entry count
297
- max_entries = self.cache_config.max_entries
298
- if len(self._cache) >= max_entries:
299
- self._evict_entries_sync(int(max_entries * (1 - self.cache_config.eviction_threshold)))
300
-
301
- # Check memory usage
302
- max_memory_bytes = self.cache_config.max_memory_mb * 1024 * 1024
303
- if self.statistics.memory_usage_bytes >= max_memory_bytes:
304
- self._evict_by_memory_sync()
305
-
306
- async def _ensure_capacity(self) -> None:
307
- """Ensure cache doesn't exceed capacity limits (async version)."""
308
- # Check entry count
309
- max_entries = self.cache_config.max_entries
310
- if len(self._cache) >= max_entries:
311
- await self._evict_entries(int(max_entries * (1 - self.cache_config.eviction_threshold)))
312
-
313
- # Check memory usage
314
- max_memory_bytes = self.cache_config.max_memory_mb * 1024 * 1024
315
- if self.statistics.memory_usage_bytes >= max_memory_bytes:
316
- await self._evict_by_memory()
317
-
318
- async def _evict_entries(self, target_count: int) -> None:
319
- """Evict entries based on eviction policy."""
320
- if len(self._cache) <= target_count:
321
- return
322
-
323
- evict_count = len(self._cache) - target_count
324
- policy = self.cache_config.eviction_policy
325
-
326
- if policy == CachePolicy.LRU:
327
- # Remove least recently used (from front of OrderedDict)
328
- for _ in range(evict_count):
329
- if self._cache:
330
- key = next(iter(self._cache))
331
- self._remove_entry(key, CacheEventType.CACHE_EVICT)
332
-
333
- elif policy == CachePolicy.LFU:
334
- # Remove least frequently used
335
- entries = list(self._cache.items())
336
- entries.sort(key=lambda x: x[1].access_count)
337
- for key, _ in entries[:evict_count]:
338
- self._remove_entry(key, CacheEventType.CACHE_EVICT)
339
-
340
- elif policy == CachePolicy.FIFO:
341
- # Remove oldest entries
342
- entries = list(self._cache.items())
343
- entries.sort(key=lambda x: x[1].created_at)
344
- for key, _ in entries[:evict_count]:
345
- self._remove_entry(key, CacheEventType.CACHE_EVICT)
346
-
347
- self._log_info(f"Evicted {evict_count} entries using {policy.value} policy")
348
-
349
- def _evict_entries_sync(self, target_count: int) -> None:
350
- """Evict entries based on eviction policy (synchronous version)."""
351
- if len(self._cache) <= target_count:
352
- return
353
-
354
- evict_count = len(self._cache) - target_count
355
- policy = self.cache_config.eviction_policy
356
-
357
- if policy == CachePolicy.LRU:
358
- # Remove least recently used (from front of OrderedDict)
359
- for _ in range(evict_count):
360
- if self._cache:
361
- key = next(iter(self._cache))
362
- self._remove_entry(key, CacheEventType.CACHE_EVICT)
363
-
364
- elif policy == CachePolicy.LFU:
365
- # Remove least frequently used
366
- entries = list(self._cache.items())
367
- entries.sort(key=lambda x: x[1].access_count)
368
- for key, _ in entries[:evict_count]:
369
- self._remove_entry(key, CacheEventType.CACHE_EVICT)
370
-
371
- elif policy == CachePolicy.FIFO:
372
- # Remove oldest entries
373
- entries = list(self._cache.items())
374
- entries.sort(key=lambda x: x[1].created_at)
375
- for key, _ in entries[:evict_count]:
376
- self._remove_entry(key, CacheEventType.CACHE_EVICT)
377
-
378
- self._log_info(f"Evicted {evict_count} entries using {policy.value} policy (sync)")
379
-
380
- async def _evict_by_memory(self) -> None:
381
- """Evict entries to reduce memory usage."""
382
- target_memory = (
383
- self.cache_config.max_memory_mb * 1024 * 1024 * self.cache_config.eviction_threshold
384
- )
385
-
386
- # Sort by size (largest first) and remove until under target
387
- entries = list(self._cache.items())
388
- entries.sort(key=lambda x: x[1].size_bytes, reverse=True)
389
-
390
- for key, entry in entries:
391
- if self.statistics.memory_usage_bytes <= target_memory:
392
- break
393
- self._remove_entry(key, CacheEventType.CACHE_EVICT)
394
-
395
- self._log_info(
396
- f"Memory-based eviction completed, usage: {self.statistics.memory_usage_bytes} bytes"
397
- )
398
-
399
- def _evict_by_memory_sync(self) -> None:
400
- """Evict entries to reduce memory usage (synchronous version)."""
401
- target_memory = (
402
- self.cache_config.max_memory_mb * 1024 * 1024 * self.cache_config.eviction_threshold
403
- )
404
-
405
- # Sort by size (largest first) and remove until under target
406
- entries = list(self._cache.items())
407
- entries.sort(key=lambda x: x[1].size_bytes, reverse=True)
408
-
409
- for key, entry in entries:
410
- if self.statistics.memory_usage_bytes <= target_memory:
411
- break
412
- self._remove_entry(key, CacheEventType.CACHE_EVICT)
413
-
414
- self._log_info(
415
- f"Memory-based eviction completed (sync), usage: {self.statistics.memory_usage_bytes} bytes"
416
- )
417
-
418
- def _remove_entry(self, key: str, event_type: CacheEventType) -> None:
419
- """Remove entry from cache and update statistics."""
420
- if key in self._cache:
421
- entry = self._cache[key]
422
- del self._cache[key]
423
-
424
- self.statistics.current_size = len(self._cache)
425
- self.statistics.memory_usage_bytes -= entry.size_bytes
426
-
427
- if event_type == CacheEventType.CACHE_EVICT:
428
- self.statistics.total_evictions += 1
429
- elif event_type == CacheEventType.CACHE_EXPIRE:
430
- self.statistics.total_expirations += 1
431
- elif event_type == CacheEventType.CACHE_DELETE:
432
- self.statistics.total_deletes += 1
433
-
434
- async def _cleanup_loop(self) -> None:
435
- """Background task for cleaning up expired entries."""
436
- while not self._shutdown:
437
- try:
438
- await asyncio.sleep(self.cache_config.cleanup_interval_seconds)
439
- await self._cleanup_expired()
440
- except asyncio.CancelledError:
441
- break
442
- except Exception as e:
443
- logger.error(f"Error in cache cleanup: {e}")
444
-
445
- async def _cleanup_expired(self) -> None:
446
- """Remove expired cache entries."""
447
- expired_keys = []
448
-
449
- with self._lock:
450
- for key, entry in self._cache.items():
451
- if entry.is_expired():
452
- expired_keys.append(key)
453
-
454
- for key in expired_keys:
455
- with self._lock:
456
- self._remove_entry(key, CacheEventType.CACHE_EXPIRE)
457
-
458
- if expired_keys:
459
- self._log_info(f"Cleaned up {len(expired_keys)} expired cache entries")
460
-
461
- async def _warm_cache(self) -> None:
462
- """Warm cache using registered callbacks."""
463
- for callback in self._warm_callbacks:
464
- try:
465
- callback()
466
- except Exception as e:
467
- logger.error(f"Error in cache warming callback: {e}")
468
-
469
- self._log_cache_event(
470
- CacheEventType.CACHE_WARM, f"warmed with {len(self._warm_callbacks)} callbacks"
471
- )
472
-
473
- def add_warm_callback(self, callback: Callable[[], None]) -> None:
474
- """Add callback for cache warming."""
475
- self._warm_callbacks.append(callback)
476
-
477
- def _calculate_size(self, value: Any) -> int:
478
- """Calculate approximate size of value in bytes."""
479
- try:
480
- return len(pickle.dumps(value))
481
- except Exception:
482
- # Fallback estimation
483
- return len(str(value).encode("utf-8"))
484
-
485
- def _compress_value(self, value: Any) -> bytes:
486
- """Compress value using gzip."""
487
- try:
488
- pickled = pickle.dumps(value)
489
- return gzip.compress(pickled)
490
- except Exception as e:
491
- logger.error(f"Error compressing value: {e}")
492
- return value
493
-
494
- def _decompress_value(self, compressed_data: bytes) -> Any:
495
- """Decompress value from gzip."""
496
- try:
497
- decompressed = gzip.decompress(compressed_data)
498
- return pickle.loads(decompressed)
499
- except Exception as e:
500
- logger.error(f"Error decompressing value: {e}")
501
- return compressed_data
502
-
503
- def _track_access_time(self, access_time_ms: float) -> None:
504
- """Track cache access time for statistics."""
505
- self._access_times.append(access_time_ms)
506
-
507
- # Keep only recent access times
508
- if len(self._access_times) > 1000:
509
- self._access_times = self._access_times[-500:]
510
-
511
- def _log_cache_event(self, event_type: CacheEventType, key: str, details: str = "") -> None:
512
- """Log cache event."""
513
- message = f"Cache {event_type.value}: {key}"
514
- if details:
515
- message += f" ({details})"
516
-
517
- if self.dev_logger:
518
- self.dev_logger.log_debug(
519
- SDKEventType.DEBUG_CHECKPOINT,
520
- message,
521
- details={"cache_event": event_type.value, "key": key, "details": details},
522
- )
523
- else:
524
- logger.debug(message)
525
-
526
- def _log_info(self, message: str, **kwargs: Any) -> None:
527
- """Log info message."""
528
- if self.dev_logger:
529
- self.dev_logger.log_info(
530
- SDKEventType.PERFORMANCE_OPTIMIZATION_APPLIED, message, **kwargs
531
- )
532
- else:
533
- logger.info(message)
534
-
535
-
536
- # Context manager for cache operations
537
- class CacheContext:
538
- """Context manager for automatic cache operations."""
539
-
540
- def __init__(
541
- self,
542
- cache_manager: CacheManager,
543
- key_generator: Callable[..., str],
544
- ttl_seconds: Optional[float] = None,
545
- ):
546
- self.cache_manager = cache_manager
547
- self.key_generator = key_generator
548
- self.ttl_seconds = ttl_seconds
549
-
550
- def __call__(self, func: Callable[..., T]) -> Callable[..., T]:
551
- """Decorator for automatic caching."""
552
-
553
- def wrapper(*args, **kwargs) -> T:
554
- # Generate cache key
555
- cache_key = self.key_generator(*args, **kwargs)
556
-
557
- # Try to get from cache
558
- cached_result = self.cache_manager.get(cache_key)
559
- if cached_result is not None:
560
- return cached_result
561
-
562
- # Execute function and cache result
563
- result = func(*args, **kwargs)
564
- self.cache_manager.set(cache_key, result, self.ttl_seconds)
565
-
566
- return result
567
-
568
- return wrapper
569
-
570
-
571
- __all__ = [
572
- # Main business logic class
573
- "CacheManager",
574
- # Utilities
575
- "CacheContext",
576
- # Note: Cache models (CacheConfig, CacheEntry, CacheStatistics, etc.)
577
- # are available via DTO imports: from unrealon_sdk.src.dto.cache import ...
578
- ]