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.
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/PKG-INFO +1 -1
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/pyproject.toml +1 -1
- fiuai_sdk_python-0.11.0/src/fiuai_sdk_python/pkg/scheduler/__init__.py +13 -0
- fiuai_sdk_python-0.11.0/src/fiuai_sdk_python/pkg/scheduler/runner.py +153 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/.gitignore +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/CHANGELOG.md +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/LICENSE +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/README.md +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/__init__.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/auth/__init__.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/auth/context_mgr.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/auth/header.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/auth/helper.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/auth/type.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/bank.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/client.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/company.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/config.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/const.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/context.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/datatype.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/doctype.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/error.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/examples/fastapi_integration.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/http/__init__.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/http/client.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/item.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/perm.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/__init__.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/cache_client.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/circuit_breaker.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/decorator.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/redis_manager.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/types.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/profile.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/resp.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/setup.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/type.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/util.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/utils/__init__.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/utils/ids.py +0 -0
- {fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/utils/logger.py +0 -0
- {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.
|
|
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
|
|
@@ -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
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/auth/context_mgr.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/__init__.py
RENAMED
|
File without changes
|
{fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/cache_client.py
RENAMED
|
File without changes
|
|
File without changes
|
{fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/decorator.py
RENAMED
|
File without changes
|
{fiuai_sdk_python-0.10.0 → fiuai_sdk_python-0.11.0}/src/fiuai_sdk_python/pkg/cache/redis_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|