修复节日福利过期补发
This commit is contained in:
@@ -124,6 +124,9 @@ class TriggerHolidayEventJob implements ShouldQueue
|
||||
|
||||
$now = now();
|
||||
$scheduledFor = $this->manual ? $now->copy() : $event->send_at;
|
||||
$expiresAt = $this->manual
|
||||
? $now->copy()->addMinutes($event->expire_minutes)
|
||||
: $scheduledFor?->copy()->addMinutes($event->expire_minutes);
|
||||
|
||||
if (! $this->manual) {
|
||||
// 定时触发只允许处理真正到期且仍处于 pending 的模板。
|
||||
@@ -131,12 +134,23 @@ class TriggerHolidayEventJob implements ShouldQueue
|
||||
return null;
|
||||
}
|
||||
|
||||
$validScheduledFor = $scheduleService->skipExpiredOccurrences($event, $now);
|
||||
if ($validScheduledFor === null || ! $validScheduledFor->equalTo($scheduledFor)) {
|
||||
// 漏跑且已过期的批次只推进模板,不生成领取批次和聊天室公告。
|
||||
$event->update([
|
||||
'send_at' => $validScheduledFor,
|
||||
'status' => $validScheduledFor ? 'pending' : 'completed',
|
||||
]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$nextSendAt = $scheduleService->advanceAfterTrigger($event);
|
||||
$event->update([
|
||||
'send_at' => $nextSendAt,
|
||||
'status' => $nextSendAt ? 'pending' : 'completed',
|
||||
'triggered_at' => $now,
|
||||
'expires_at' => $now->copy()->addMinutes($event->expire_minutes),
|
||||
'expires_at' => $expiresAt,
|
||||
'claimed_count' => 0,
|
||||
'claimed_amount' => 0,
|
||||
]);
|
||||
@@ -163,7 +177,7 @@ class TriggerHolidayEventJob implements ShouldQueue
|
||||
'repeat_type' => $event->repeat_type,
|
||||
'scheduled_for' => $scheduledFor,
|
||||
'triggered_at' => $now,
|
||||
'expires_at' => $now->copy()->addMinutes($event->expire_minutes),
|
||||
'expires_at' => $expiresAt,
|
||||
'status' => 'active',
|
||||
'audience_count' => 0,
|
||||
'claimed_count' => 0,
|
||||
|
||||
@@ -45,6 +45,39 @@ class HolidayEventScheduleService
|
||||
|
||||
$currentSendAt = CarbonImmutable::instance($event->send_at);
|
||||
|
||||
return $this->nextOccurrenceAfter($event, $currentSendAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳过已经超过领取窗口的历史计划点。
|
||||
*/
|
||||
public function skipExpiredOccurrences(HolidayEvent $event, CarbonInterface $reference): ?CarbonImmutable
|
||||
{
|
||||
if ($event->send_at === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$candidate = CarbonImmutable::instance($event->send_at);
|
||||
$referenceTime = CarbonImmutable::instance($reference);
|
||||
$expireMinutes = max(0, (int) $event->expire_minutes);
|
||||
|
||||
while ($candidate->addMinutes($expireMinutes)->lessThanOrEqualTo($referenceTime)) {
|
||||
// 历史批次的领取窗口已经结束,只推进调度指针,不能补发金币。
|
||||
$candidate = $this->nextOccurrenceAfter($event, $candidate);
|
||||
|
||||
if ($candidate === null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return $candidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算指定计划点之后的下一次触发时间。
|
||||
*/
|
||||
private function nextOccurrenceAfter(HolidayEvent $event, CarbonImmutable $currentSendAt): ?CarbonImmutable
|
||||
{
|
||||
return match ($event->repeat_type) {
|
||||
'daily' => $currentSendAt->addDay(),
|
||||
'weekly' => $currentSendAt->addWeek(),
|
||||
|
||||
Reference in New Issue
Block a user