This commit is contained in:
Your Name
2026-07-27 15:20:15 +08:00
parent 4970d8f8d3
commit 8ba13a8ff9
10 changed files with 424 additions and 39 deletions
+16 -6
View File
@@ -87,20 +87,29 @@ class AccountReplyQueue:
details: Optional[dict[str, Any]] = None,
merge_key: str = "",
merge_keys: Optional[Iterable[str]] = None,
immediate_if_idle: bool = False,
) -> int:
"""Append one reply job and return its current 1-based queue position."""
"""Append one reply job and return its current 1-based queue position.
When ``immediate_if_idle`` is enabled, the first job in a completely
idle account queue reserves a zero-second slot. Jobs arriving behind
it still reserve the configured interval, so the normal per-account
pacing resumes from the second job onward.
"""
interval = max(0.0, float(delay_seconds or 0))
loop = asyncio.get_running_loop()
async with self._state_lock:
if not self._running or not self._task or self._task.done():
raise RuntimeError("reply queue is not running")
due_at = max(loop.time(), self._tail_due_at) + interval
queue_is_idle = self.pending_count == 0
slot_seconds = 0.0 if immediate_if_idle and queue_is_idle else interval
due_at = max(loop.time(), self._tail_due_at) + slot_seconds
self._tail_due_at = due_at
self._waiting.append(
_QueueItem(
job_id=uuid.uuid4().hex,
due_at=due_at,
slot_seconds=interval,
slot_seconds=slot_seconds,
callback=callback,
description=description,
queued_at=time.time(),
@@ -256,9 +265,10 @@ class AccountReplyQueue:
item = self._waiting.pop(selected_index)
shift_seconds = max(0.0, item.slot_seconds)
shifted_count = 0
for later in self._waiting[selected_index:]:
later.due_at -= shift_seconds
shifted_count += 1
if shift_seconds > 0:
for later in self._waiting[selected_index:]:
later.due_at -= shift_seconds
shifted_count += 1
item.due_at = asyncio.get_running_loop().time()
item.expedited = True
+16 -3
View File
@@ -578,19 +578,32 @@ class DouyinImService:
"replies": list(replies),
},
merge_keys=queue_merge_keys,
immediate_if_idle=True,
)
scheduled_wait = 0 if position == 1 else delay_seconds
logger.info(
"Queued reply to %s for account %s: position=%s interval=%ss",
"Queued reply to %s for account %s: position=%s wait=%ss interval=%ss",
sender,
self.account_id,
position,
scheduled_wait,
delay_seconds,
)
if position == 1:
queue_detail = (
f"{sender} 是当前账号队列的首条任务,等待时间为 0 秒;"
f"后续任务仍按 {delay_seconds} 秒间隔排队。"
)
else:
queue_detail = (
f"{sender} 当前排在第 {position} 位;账号生效间隔为 {delay_seconds} 秒,"
"后续任务继续依次排队。"
)
system_logger.record(
"自动回复已进入账号队列",
detail=(
f"{sender} 当前排在第 {position} 位;账号生效间隔为 {delay_seconds} 秒,"
"账号内计时与排位独立;到点后再进入全局带宽队列逐条投递。"
f"{queue_detail} 账号内计时与排位独立;"
"发送时仍进入全局带宽队列逐条投递。"
),
level="info",
category="send",