mirror of
https://github.com/warmbly/warmbly.git
synced 2026-09-06 08:01:24 +00:00
* feat: let a warmup recipient answer the mailbox that just wrote to it, so a thread reads as a conversation rather than two mailboxes monologuing on their own ramps: warmup_tasks.target_account_id was written as nil and never read by anything, so a reply only happened when the recipient's own ramp fired AND the draw happened to land on that partner; a verified receipt now sometimes re-points the recipient's pending warmup task at the sender 25 minutes to 5 hours later inside its own warmup hours, which is a re-pointing rather than new work because only one warmup task may be pending per mailbox, it can never delay a send the mailbox had planned sooner, and it stops before the thread cap so replies cannot answer replies forever; the clock parser also moves into models.ClockMinutes so a second copy of the HH:MM parsing that silently disabled every sending window cannot drift back in * feat: stop the reply-back drawing the reply rate twice, and stop its jitter escaping a short warmup window: the scheduler drew the recipient's reply rate to decide whether to answer at all, then the task handler drew it again to decide reply-versus-new, so a 30 percent reply rate produced a 9 percent answer rate and a directed task could send a fresh message to the mailbox it was meant to be answering; a directed task now IS the reply, and the opening-time jitter is capped to the window width so a mailbox warming 09:00 to 09:20 is not scheduled past its own close
34 lines
808 B
Go
34 lines
808 B
Go
package models
|
|
|
|
import "testing"
|
|
|
|
func TestClockMinutes(t *testing.T) {
|
|
tests := []struct {
|
|
in string
|
|
want int
|
|
}{
|
|
{"09:00", 9 * 60},
|
|
{"09:00:00", 9 * 60},
|
|
// What pgx hands back for a `time` column. Rejecting this silently
|
|
// disabled every campaign sending window and every warmup window.
|
|
{"09:00:00.000000", 9 * 60},
|
|
{"17:30:00.000000", 17*60 + 30},
|
|
{"23:59:59.999999", 23*60 + 59},
|
|
{"00:00:00.000000", 0},
|
|
{" 08:15 ", 8*60 + 15},
|
|
{"", -1},
|
|
{"nonsense", -1},
|
|
{"25:00", -1},
|
|
{"12:60", -1},
|
|
{"12", -1},
|
|
{"-1:00", -1},
|
|
}
|
|
for _, tt := range tests {
|
|
// A distinctive fallback, so "parsed as zero" and "fell back" are
|
|
// distinguishable.
|
|
if got := ClockMinutes(tt.in, -1); got != tt.want {
|
|
t.Errorf("ClockMinutes(%q) = %d, want %d", tt.in, got, tt.want)
|
|
}
|
|
}
|
|
}
|