fiuai-sdk-python 0.10.0__tar.gz → 0.11.0__tar.gz

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 (43) hide show
  1. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/PKG-INFO +1 -1
  2. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/pyproject.toml +1 -1
  3. fiuai_sdk_python-0.11.0/src/fiuai_sdk_python/pkg/scheduler/__init__.py +13 -0
  4. fiuai_sdk_python-0.11.0/src/fiuai_sdk_python/pkg/scheduler/runner.py +153 -0
  5. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/.gitignore +0 -0
  6. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/CHANGELOG.md +0 -0
  7. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/LICENSE +0 -0
  8. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/README.md +0 -0
  9. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/__init__.py +0 -0
  10. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/auth/__init__.py +0 -0
  11. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/auth/context_mgr.py +0 -0
  12. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/auth/header.py +0 -0
  13. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/auth/helper.py +0 -0
  14. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/auth/type.py +0 -0
  15. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/bank.py +0 -0
  16. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/client.py +0 -0
  17. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/company.py +0 -0
  18. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/config.py +0 -0
  19. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/const.py +0 -0
  20. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/context.py +0 -0
  21. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/datatype.py +0 -0
  22. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/doctype.py +0 -0
  23. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/error.py +0 -0
  24. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/examples/fastapi_integration.py +0 -0
  25. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/http/__init__.py +0 -0
  26. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/http/client.py +0 -0
  27. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/item.py +0 -0
  28. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/perm.py +0 -0
  29. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/__init__.py +0 -0
  30. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/cache_client.py +0 -0
  31. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/circuit_breaker.py +0 -0
  32. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/decorator.py +0 -0
  33. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/redis_manager.py +0 -0
  34. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/types.py +0 -0
  35. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/profile.py +0 -0
  36. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/resp.py +0 -0
  37. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/setup.py +0 -0
  38. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/type.py +0 -0
  39. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/util.py +0 -0
  40. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/utils/__init__.py +0 -0
  41. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/utils/ids.py +0 -0
  42. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/utils/logger.py +0 -0
  43. {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/utils/text.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fiuai_sdk_python
3
- Version: 0.10.0
3
+ Version: 0.11.0
4
4
  Summary: FiuAI Python SDK - 企业级AI服务集成开发工具包
5
5
  Project-URL: Homepage, https://github.com/fiuai/fiuai-sdk-python
6
6
  Project-URL: Documentation, https://github.com/fiuai/fiuai-sdk-python#readme
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fiuai_sdk_python"
3
- version = "0.10.0"
3
+ version = "0.11.0"
4
4
  description = "FiuAI Python SDK - 企业级AI服务集成开发工具包"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -0,0 +1,13 @@
1
+ # -- coding: utf-8 --
2
+ # Project: fiuai-sdk-python
3
+ # Created Date: 2026-04-10
4
+ # Author: liming
5
+ # Agent: Cursor
6
+ # Email: lmlala@aliyun.com
7
+ # Copyright (c) 2025 FiuAI
8
+
9
+ from .runner import PeriodicRunner
10
+
11
+ __all__ = [
12
+ "PeriodicRunner",
13
+ ]
@@ -0,0 +1,153 @@
1
+ # -- coding: utf-8 --
2
+ # Project: fiuai-sdk-python
3
+ # Created Date: 2026-04-10
4
+ # Author: liming
5
+ # Agent: Cursor
6
+ # Email: lmlala@aliyun.com
7
+ # Copyright (c) 2025 FiuAI
8
+
9
+ import asyncio
10
+ import random
11
+ from collections.abc import Awaitable, Callable
12
+ from datetime import datetime, timezone
13
+
14
+ from ...utils.logger import get_logger
15
+
16
+ logger = get_logger(__name__)
17
+
18
+
19
+ class PeriodicRunner:
20
+ """通用异步定时任务运行器
21
+
22
+ 支持两种运行方式:
23
+ - 嵌入 FastAPI: asyncio.create_task(runner.start())
24
+ - 独立进程: asyncio.run(runner.start())
25
+ """
26
+
27
+ def __init__(
28
+ self,
29
+ name: str,
30
+ task: Callable[[], Awaitable[None]],
31
+ interval_seconds: float,
32
+ *,
33
+ run_on_start: bool = True,
34
+ error_handler: Callable[[Exception], Awaitable[None]] | None = None,
35
+ jitter_seconds: float = 0,
36
+ ) -> None:
37
+ if not name:
38
+ raise ValueError("name must not be empty")
39
+ if not callable(task):
40
+ raise TypeError("task must be callable")
41
+ if interval_seconds <= 0:
42
+ raise ValueError("interval_seconds must be positive")
43
+ if jitter_seconds < 0:
44
+ raise ValueError("jitter_seconds must be non-negative")
45
+
46
+ self._name = name
47
+ self._task = task
48
+ self._interval_seconds = interval_seconds
49
+ self._run_on_start = run_on_start
50
+ self._error_handler = error_handler
51
+ self._jitter_seconds = jitter_seconds
52
+
53
+ self._running = False
54
+ self._stop_event: asyncio.Event | None = None
55
+ self._last_run_at: datetime | None = None
56
+ self._last_error: Exception | None = None
57
+ self._consecutive_failures = 0
58
+
59
+ # -- public API ----------------------------------------------------------
60
+
61
+ async def start(self) -> None:
62
+ """启动循环, 阻塞直到 stop() 被调用"""
63
+ self._running = True
64
+ self._stop_event = asyncio.Event()
65
+
66
+ logger.info(
67
+ "[PeriodicRunner:%s] started (interval=%ss, jitter=%ss)",
68
+ self._name,
69
+ self._interval_seconds,
70
+ self._jitter_seconds,
71
+ )
72
+
73
+ try:
74
+ if self._run_on_start:
75
+ await self._safe_execute()
76
+
77
+ while self._running:
78
+ sleep_time = self._interval_seconds
79
+ if self._jitter_seconds > 0:
80
+ sleep_time += random.uniform(0, self._jitter_seconds)
81
+
82
+ # 可中断 sleep: stop() 时 _stop_event 被 set, wait_for 立即返回
83
+ try:
84
+ await asyncio.wait_for(
85
+ self._stop_event.wait(), timeout=sleep_time
86
+ )
87
+ break
88
+ except asyncio.TimeoutError:
89
+ pass
90
+
91
+ if not self._running:
92
+ break
93
+
94
+ await self._safe_execute()
95
+ finally:
96
+ self._running = False
97
+ logger.info("[PeriodicRunner:%s] stopped", self._name)
98
+
99
+ def stop(self) -> None:
100
+ """请求停止 (当前周期结束后退出)"""
101
+ self._running = False
102
+ if self._stop_event is not None:
103
+ self._stop_event.set()
104
+
105
+ # -- properties -----------------------------------------------------------
106
+
107
+ @property
108
+ def name(self) -> str:
109
+ return self._name
110
+
111
+ @property
112
+ def is_running(self) -> bool:
113
+ return self._running
114
+
115
+ @property
116
+ def last_run_at(self) -> datetime | None:
117
+ return self._last_run_at
118
+
119
+ @property
120
+ def last_error(self) -> Exception | None:
121
+ return self._last_error
122
+
123
+ @property
124
+ def consecutive_failures(self) -> int:
125
+ return self._consecutive_failures
126
+
127
+ # -- internals ------------------------------------------------------------
128
+
129
+ async def _safe_execute(self) -> None:
130
+ try:
131
+ await self._task()
132
+ self._last_run_at = datetime.now(timezone.utc)
133
+ self._last_error = None
134
+ self._consecutive_failures = 0
135
+ except Exception as exc:
136
+ self._last_error = exc
137
+ self._consecutive_failures += 1
138
+ logger.error(
139
+ "[PeriodicRunner:%s] task failed (%d): %s",
140
+ self._name,
141
+ self._consecutive_failures,
142
+ exc,
143
+ exc_info=True,
144
+ )
145
+ if self._error_handler:
146
+ try:
147
+ await self._error_handler(exc)
148
+ except Exception as handler_exc:
149
+ logger.warning(
150
+ "[PeriodicRunner:%s] error_handler raised: %s",
151
+ self._name,
152
+ handler_exc,
153
+ )