✨ feat(scheduler): 为多目标定时任务添加固定间隔串行执行选项

This commit is contained in:
webjoin111
2025-10-29 18:38:07 +08:00
parent 6815caf805
commit 9bba83cfe6
8 changed files with 76 additions and 11 deletions
+35 -7
View File
@@ -412,16 +412,44 @@ async def _execute_job(
if isinstance(schedule.execution_options, dict)
else {}
)
spread_seconds = spread_config.get("spread", 1.0)
interval_seconds = spread_config.get("interval")
async def worker(target_id: str | None):
await asyncio.sleep(random.uniform(0.1, spread_seconds))
async with semaphore:
if interval_seconds is not None and interval_seconds > 0:
logger.debug(
f"任务 {schedule.id}: 使用串行模式执行 {len(resolved_targets)} "
f"个目标,固定间隔 {interval_seconds} 秒。"
)
for i, target_id in enumerate(resolved_targets):
if i > 0:
logger.debug(
f"任务 {schedule.id} 目标 [{target_id or '全局'}]: "
f"等待 {interval_seconds} 秒后执行。"
)
await asyncio.sleep(interval_seconds)
await _execute_single_job_instance(schedule, bot, group_id=target_id)
else:
spread_seconds = spread_config.get("spread", 1.0)
tasks_to_run = [worker(target_id) for target_id in resolved_targets]
if tasks_to_run:
await asyncio.gather(*tasks_to_run, return_exceptions=True)
logger.debug(
f"任务 {schedule.id}: 将在 {spread_seconds:.2f} 秒内分散执行 "
f"{len(resolved_targets)} 个目标。"
)
async def worker(target_id: str | None):
delay = random.uniform(0.1, spread_seconds)
logger.debug(
f"任务 {schedule.id} 目标 [{target_id or '全局'}]: "
f"随机延迟 {delay:.2f} 秒后执行。"
)
await asyncio.sleep(delay)
async with semaphore:
await _execute_single_job_instance(
schedule, bot, group_id=target_id
)
tasks_to_run = [worker(target_id) for target_id in resolved_targets]
if tasks_to_run:
await asyncio.gather(*tasks_to_run, return_exceptions=True)
schedule.last_run_at = datetime.now()
schedule.last_run_status = "SUCCESS"
+4
View File
@@ -109,6 +109,7 @@ class SchedulerManager:
policy: ExecutionPolicy | None = None,
default_jitter: int | None = None,
default_spread: int | None = None,
default_interval: int | None = None,
):
"""
声明式定时任务的统一装饰器。
@@ -140,6 +141,7 @@ class SchedulerManager:
"model": params_model,
"default_jitter": default_jitter,
"default_spread": default_spread,
"default_interval": default_interval,
}
job_kwargs = model_dump(default_params) if default_params else {}
@@ -205,6 +207,7 @@ class SchedulerManager:
default_permission: int = 5,
default_jitter: int | None = None,
default_spread: int | None = None,
default_interval: int | None = None,
) -> Callable:
"""
注册可调度的任务函数
@@ -220,6 +223,7 @@ class SchedulerManager:
"default_permission": default_permission,
"default_jitter": default_jitter,
"default_spread": default_spread,
"default_interval": default_interval,
}
model_name = params_model.__name__ if params_model else "无"
logger.debug(
+6 -1
View File
@@ -83,7 +83,12 @@ class ExecutionOptions(BaseModel):
"""
jitter: int | None = Field(None, description="触发时间抖动(秒)")
spread: int | None = Field(None, description="多目标执行的分散延迟(秒)")
spread: int | None = Field(
None, description="(并发模式)多目标执行的最大分散延迟(秒)"
)
interval: int | None = Field(
None, description="多目标执行的固定间隔(秒),设置后将强制串行执行"
)
concurrency_policy: Literal["ALLOW", "SKIP", "QUEUE"] = Field(
"ALLOW", description="并发策略"
)