mirror of
https://github.com/warmbly/warmbly.git
synced 2026-10-31 00:12:37 +00:00
feat: keep spread warmup reply-backs and deferred warmup sends inside short warmup windows and date an overdue next-warmup label in the mailbox list
This commit is contained in:
@@ -49,8 +49,12 @@ func (s *JobsService) scheduleWarmupReplyBack(ctx context.Context, token *models
|
||||
time.Duration(uint64(binary.BigEndian.Uint32(token.Token[4:8]))%uint64(replyBackMaxDelay-replyBackMinDelay)))
|
||||
// A reply at 04:00 from a mailbox that never sends then is worse than none.
|
||||
if rolled := withinWarmupHours(at, recipient); !rolled.Equal(at) {
|
||||
// Spread replies rolled to the opening over its first hour, so the pool does not answer on the stroke of it.
|
||||
at = rolled.Add(time.Duration(binary.BigEndian.Uint32(token.Token[8:12])%3600) * time.Second)
|
||||
// Spread replies rolled to the opening over its first hour (or the whole window when shorter), so the pool does not answer on the stroke of it.
|
||||
spread := uint32(3600)
|
||||
if span := models.ClockMinutes(recipient.WarmupEndTime, 20*60) - models.ClockMinutes(recipient.WarmupStartTime, 8*60); span > 0 && span*60 < int(spread) {
|
||||
spread = uint32(span * 60)
|
||||
}
|
||||
at = rolled.Add(time.Duration(binary.BigEndian.Uint32(token.Token[8:12])%spread) * time.Second)
|
||||
}
|
||||
|
||||
moved, err := lineage.BindWarmupSuccessor(ctx, token.TaskID, recipientAccountID, receivedIDs[0], at)
|
||||
|
||||
@@ -245,8 +245,11 @@ func (s *tasksService) HandleEmailTask(task *proto.ProcessTask) *errx.Error {
|
||||
return errx.InternalError()
|
||||
}
|
||||
if at.After(time.Now()) {
|
||||
// The gate answers with the window's opening; spread deferred sends past it rather than firing on the stroke.
|
||||
at = at.Add(time.Duration(1+rand.Intn(20*60)) * time.Second)
|
||||
// The gate answers with the window's opening; spread deferred sends past it, unless that would leave a short window.
|
||||
jittered := at.Add(time.Duration(1+rand.Intn(20*60)) * time.Second)
|
||||
if again, gerr := gate.WarmupDispatchNotBefore(ctx, account.ID, jittered); gerr == nil && !again.After(jittered) {
|
||||
at = jittered
|
||||
}
|
||||
if err := lineage.RescheduleWarmupTask(ctx, taskID, at); err != nil {
|
||||
return errx.InternalError()
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// A queued send time as a short label: "10:08" today, "tomorrow 09:12", or "Mon 09:12" later in the week.
|
||||
// A queued send time as a short label: "10:08" today, "tomorrow 09:12", "Mon 09:12" later in the week, and a dated label otherwise (an overdue slot included).
|
||||
export function nextSlotLabel(at: Date | string, now: Date = new Date()): string {
|
||||
const d = new Date(at);
|
||||
const time = d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
||||
const day = (x: Date) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();
|
||||
const days = Math.round((day(d) - day(now)) / 86_400_000);
|
||||
if (days <= 0) return time;
|
||||
if (days === 0) return time;
|
||||
if (days < 0) return `${d.toLocaleDateString([], { month: "short", day: "numeric" })} ${time}`;
|
||||
if (days === 1) return `tomorrow ${time}`;
|
||||
if (days < 7) return `${d.toLocaleDateString([], { weekday: "short" })} ${time}`;
|
||||
return `${d.toLocaleDateString([], { month: "short", day: "numeric" })} ${time}`;
|
||||
|
||||
Reference in New Issue
Block a user