From: Anderson A. Giacomolli Date: Tue, 10 Nov 2026 18:09:23 +0000 (-0300) Subject: Name timeouts for the operations they limit X-Git-Url: https://git.giacomolli.uk/onechat/commitdiff_plain/add3cf6416e33c24331fd1e90e99284f44d2aae2 Name timeouts for the operations they limit Each operation limit ends in Timeout and names its operation. Telegram file lookup, image download, and typing have separate names from message sends. All wait values stay the same, including the server wait for updates and the memory build wait. --- diff --git a/build_run.go b/build_run.go index 9c27ff2..cc12cf2 100644 --- a/build_run.go +++ b/build_run.go @@ -19,6 +19,9 @@ import ( // buildLineBytes is the most bytes of one line in a build input or usage log. const buildLineBytes = 1 << 20 +// buildWaitTimeout is the longest wait for pending memory builds. +const buildWaitTimeout = time.Second + // buildQuotaLimit is the largest increase in used quota points of a run. const buildQuotaLimit = 15.0 @@ -113,7 +116,7 @@ func (r *BuildRun) check() string { // waitBuilds waits up to one second without leaving a child context open. func (r *BuildRun) waitBuilds(ctx context.Context) error { - ctx, cancel := context.WithTimeout(ctx, time.Second) + ctx, cancel := context.WithTimeout(ctx, buildWaitTimeout) defer cancel() return r.memory.Wait(ctx) diff --git a/schedule.go b/schedule.go index a1eba1c..28a5a76 100644 --- a/schedule.go +++ b/schedule.go @@ -33,10 +33,10 @@ const ( // scheduleSource is the source of the work events of the runs. scheduleSource = "schedule" - // scheduleCheck is the longest wait of Run before it looks at the times - // again, so that it sees a suspend of the machine or a change of the - // clock. - scheduleCheck = time.Minute + // scheduleClockWaitTimeout is the longest wait of Run before it looks + // at the times again, so that it sees a suspend of the machine or a + // change of the clock. + scheduleClockWaitTimeout = time.Minute // scheduleLate is how long after its time a run is late. scheduleLate = time.Minute @@ -124,9 +124,10 @@ type Schedules struct { } // Run starts the runs of the due schedules in l until ctx ends. It waits until -// the first due time, at most scheduleCheck at a time, and also wakes at a set -// or a remove. So a schedule that came due while the daemon was stopped runs at -// the start. It returns the error of a write of the log or of the file. +// the first due time, at most scheduleClockWaitTimeout at a time, and also +// wakes at a set or a remove. So a schedule that came due while the daemon was +// stopped runs at the start. It returns the error of a write of the log or of +// the file. func (s *Schedules) Run(ctx context.Context, l *TurnLoop) error { for { err := s.deliver(ctx, l) @@ -141,7 +142,7 @@ func (s *Schedules) Run(ctx context.Context, l *TurnLoop) error { wait, found := s.Wait(s.clock()) if found { - timer = time.NewTimer(min(wait, scheduleCheck)) + timer = time.NewTimer(min(wait, scheduleClockWaitTimeout)) timeout = timer.C } diff --git a/schedule_test.go b/schedule_test.go index 5743a22..cb839d5 100644 --- a/schedule_test.go +++ b/schedule_test.go @@ -336,7 +336,7 @@ func TestSchedulesCheckTheClockAfterItsWaitLimit(t *testing.T) { synctest.Wait() require.Zero(t, loop.memory.Len()) clock.Set(clock.Now().Add(5 * time.Minute)) - time.Sleep(scheduleCheck) + time.Sleep(scheduleClockWaitTimeout) synctest.Wait() require.Equal(t, 1, loop.memory.Len()) require.Contains(t, events.Last("work"), "Check the clock.") diff --git a/telegram_api.go b/telegram_api.go index a04b2fa..8f78387 100644 --- a/telegram_api.go +++ b/telegram_api.go @@ -15,25 +15,33 @@ import ( ) const ( - // telegramPollSeconds is how long one getUpdates call waits for an - // update. - telegramPollSeconds = 50 + // telegramUpdateWaitTimeout is how long one getUpdates call waits for + // an update. + telegramUpdateWaitTimeout = 50 * time.Second - // telegramPollSlack is how much longer than telegramPollSeconds a + // telegramPollSlack is how much longer than telegramUpdateWaitTimeout a // getUpdates call can take before the bot gives it up. telegramPollSlack = 20 * time.Second // telegramPollTimeout is how long one getUpdates call can take. - telegramPollTimeout = telegramPollSeconds*time.Second + telegramPollSlack - - // telegramSendTimeout is how long a sendMessage, sendRichMessage, or - // sendChatAction call can take. A connection that stops without a - // close, such as after a network change, then fails the call, and the - // sender tries again, instead of a wait until TCP gives up. The client - // has no timeout of its own, because the long poll of getUpdates needs - // a longer limit. + telegramPollTimeout = telegramUpdateWaitTimeout + telegramPollSlack + + // telegramSendTimeout is how long a sendMessage or sendRichMessage call + // can take. A connection that stops without a close, such as after a + // network change, then fails the call, and the sender tries again, + // instead of a wait until TCP gives up. The client has no timeout of + // its own, because the long poll of getUpdates needs a longer limit. telegramSendTimeout = 30 * time.Second + // telegramFileLookupTimeout is the longest wait for image file details. + telegramFileLookupTimeout = 30 * time.Second + + // telegramImageDownloadTimeout is the longest wait for image bytes. + telegramImageDownloadTimeout = 30 * time.Second + + // telegramTypingTimeout is the longest wait to show the typing action. + telegramTypingTimeout = 30 * time.Second + // telegramAnswerBytes is the most bytes of one answer of the Bot API. telegramAnswerBytes = 16 << 20 ) @@ -84,15 +92,15 @@ type TelegramAPI struct { http *http.Client } -// GetUpdates waits for the updates from offset on, up to telegramPollSeconds, -// and returns them. Telegram forgets each update before offset. Only new -// messages are asked for. +// GetUpdates waits for the updates from offset on, up to +// telegramUpdateWaitTimeout, and returns them. Telegram forgets each update +// before offset. Only new messages are asked for. func (b *TelegramAPI) GetUpdates(ctx context.Context, offset int64) ([]TelegramUpdate, error) { var updates []TelegramUpdate err := b.call(ctx, telegramPollTimeout, "getUpdates", map[string]any{ "offset": offset, - "timeout": telegramPollSeconds, + "timeout": int(telegramUpdateWaitTimeout / time.Second), "allowed_updates": []string{"message"}, }, &updates) @@ -107,7 +115,7 @@ func (b *TelegramAPI) GetImage(ctx context.Context, id string) (data []byte, err Size int64 `json:"file_size"` } - err = b.call(ctx, telegramSendTimeout, "getFile", map[string]any{"file_id": id}, &file) + err = b.call(ctx, telegramFileLookupTimeout, "getFile", map[string]any{"file_id": id}, &file) if err != nil { return nil, fmt.Errorf("get image file: %w", err) } @@ -120,7 +128,7 @@ func (b *TelegramAPI) GetImage(ctx context.Context, id string) (data []byte, err return nil, errors.New("invalid image file path") } - ctx, cancel := context.WithTimeout(ctx, telegramSendTimeout) + ctx, cancel := context.WithTimeout(ctx, telegramImageDownloadTimeout) defer cancel() request, err := http.NewRequestWithContext(ctx, http.MethodGet, b.base+"/file/bot"+b.token+"/"+file.Path, nil) @@ -130,13 +138,13 @@ func (b *TelegramAPI) GetImage(ctx context.Context, id string) (data []byte, err response, err := b.http.Do(request) if err != nil { - return nil, b.networkError("image download failed", err, telegramSendTimeout) + return nil, b.networkError("image download failed", err, telegramImageDownloadTimeout) } defer func() { closeErr := response.Body.Close() if closeErr != nil { - err = errors.Join(err, b.networkError("close image download", closeErr, telegramSendTimeout)) + err = errors.Join(err, b.networkError("close image download", closeErr, telegramImageDownloadTimeout)) } }() @@ -149,7 +157,7 @@ func (b *TelegramAPI) GetImage(ctx context.Context, id string) (data []byte, err data, err = io.ReadAll(io.LimitReader(response.Body, imageMaxBytes+1)) if err != nil { - return nil, b.networkError("image cut off", err, telegramSendTimeout) + return nil, b.networkError("image cut off", err, telegramImageDownloadTimeout) } if len(data) > imageMaxBytes { @@ -189,9 +197,10 @@ func (b *TelegramAPI) SendRichMessage(ctx context.Context, chat int64, markdown } // SendTyping shows the typing action in chat for about five seconds. A call -// that takes longer than telegramSendTimeout fails with a TelegramNetworkError. +// that takes longer than telegramTypingTimeout fails with a +// TelegramNetworkError. func (b *TelegramAPI) SendTyping(ctx context.Context, chat int64) error { - return b.call(ctx, telegramSendTimeout, "sendChatAction", map[string]any{ + return b.call(ctx, telegramTypingTimeout, "sendChatAction", map[string]any{ "chat_id": chat, "action": "typing", }, nil) diff --git a/telegram_api_test.go b/telegram_api_test.go index 6fa4cba..ca11274 100644 --- a/telegram_api_test.go +++ b/telegram_api_test.go @@ -29,7 +29,7 @@ func TestGetUpdatesAsksForMessagesFromTheOffset(t *testing.T) { require.Equal(t, "getUpdates", call.method) require.Equal(t, map[string]any{ "offset": float64(7), - "timeout": float64(telegramPollSeconds), + "timeout": float64(telegramUpdateWaitTimeout / time.Second), "allowed_updates": []any{"message"}, }, call.params) } diff --git a/tools.go b/tools.go index 96cbb97..bbd34cf 100644 --- a/tools.go +++ b/tools.go @@ -27,9 +27,9 @@ const ( // output, enough for toolClipCharacters/2 characters of 4 bytes. toolClipBytes = 4 * toolClipCharacters / 2 - // toolShellWaitDelay is how long a command can keep its output open + // toolShellOutputTimeout is how long a command can keep its output open // after it ends or after its kill. - toolShellWaitDelay = 2 * time.Second + toolShellOutputTimeout = 2 * time.Second ) // ToolLog is the log that the tools write their calls and results to. @@ -379,7 +379,7 @@ func (b *Toolbox) shell(ctx context.Context, command string) string { cmd.Cancel = func() error { return syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) } - cmd.WaitDelay = toolShellWaitDelay + cmd.WaitDelay = toolShellOutputTimeout output := &ToolHeadTail{} cmd.Stdout = output diff --git a/whatsapp.go b/whatsapp.go index 9365173..97b1e85 100644 --- a/whatsapp.go +++ b/whatsapp.go @@ -54,17 +54,17 @@ const ( // whatsappTimeLayout is the layout of the times in the answers. whatsappTimeLayout = "2006-01-02 15:04" - // whatsappPairTime is the longest time of a pairing. The library closes - // the pairing connection after about 160 seconds. - whatsappPairTime = 3 * time.Minute + // whatsappPairTimeout is the longest time of a pairing. The library + // closes the pairing connection after about 160 seconds. + whatsappPairTimeout = 3 * time.Minute - // whatsappLogoutTime is the longest time of the logout call of an + // whatsappLogoutTimeout is the longest time of the logout call of an // unlink. - whatsappLogoutTime = 30 * time.Second + whatsappLogoutTimeout = 30 * time.Second - // whatsappNoticeDelay is how long a disconnection lasts before the user - // gets a notice. - whatsappNoticeDelay = 10 * time.Minute + // whatsappOutageNoticeDelay is the delay from a disconnection to its + // notice to the user. + whatsappOutageNoticeDelay = 10 * time.Minute // whatsappRetryDelay is the first wait after a failed starting // connection. @@ -309,7 +309,7 @@ func (w *WhatsApp) Run(ctx context.Context, l *TurnLoop, notify func(Event)) err case w.isLinked(): request.answer("WhatsApp is linked already. Run /whatsapp unlink first.") default: - pairCtx, cancelPair := context.WithTimeout(ctx, whatsappPairTime) + pairCtx, cancelPair := context.WithTimeout(ctx, whatsappPairTimeout) cancel = cancelPair pairing.Go(func() { defer cancelPair() @@ -569,7 +569,7 @@ func (w *WhatsApp) startOutage() bool { w.disconnectedAt = w.clock() w.disconnections++ disconnections := w.disconnections - w.timer = time.AfterFunc(whatsappNoticeDelay, func() { + w.timer = time.AfterFunc(whatsappOutageNoticeDelay, func() { w.disconnectedLong(disconnections) }) } @@ -654,7 +654,7 @@ func (w *WhatsApp) unlink(ctx context.Context, l *TurnLoop, answer func(text str var logoutErr error if client != nil { - ctx, cancel := context.WithTimeout(ctx, whatsappLogoutTime) + ctx, cancel := context.WithTimeout(ctx, whatsappLogoutTimeout) defer cancel() logoutErr = client.Logout(ctx) @@ -890,8 +890,8 @@ func (w *WhatsApp) linkedBy(client WhatsAppClient) { // handle takes one event of the library and tells if it was handled. A message // goes to the inbox. The names of the groups follow the events of the groups. A // connection starts a catch-up of the inbox, which ends at OfflineSyncCompleted -// or after whatsappCatchupLimit. A disconnection keeps the time of its start -// while Run or the library tries again. After whatsappNoticeDelay of a +// or after whatsappCatchupTimeout. A disconnection keeps the time of its start +// while Run or the library tries again. After whatsappOutageNoticeDelay of a // disconnection, all clients get one notice, and they get one more when the // connection comes back. A disconnection that the library does not try again // gives a notice at once. diff --git a/whatsapp_groups.go b/whatsapp_groups.go index 4d6c7e5..6e9bed3 100644 --- a/whatsapp_groups.go +++ b/whatsapp_groups.go @@ -9,9 +9,9 @@ import ( ) const ( - // whatsappGroupsLookupTime is the longest time of a read of group + // whatsappGroupLookupTimeout is the longest time of a read of group // names. - whatsappGroupsLookupTime = 10 * time.Second + whatsappGroupLookupTimeout = 10 * time.Second // whatsappGroupsRefresh is the shortest time between two reads of the // groups from WhatsApp for a group with no name. @@ -81,7 +81,7 @@ func (g *WhatsAppGroups) read(ctx context.Context, link WhatsAppLink) bool { return false } - ctx, cancel := context.WithTimeout(ctx, whatsappGroupsLookupTime) + ctx, cancel := context.WithTimeout(ctx, whatsappGroupLookupTimeout) defer cancel() groups, err := link.client.GetJoinedGroups(ctx) diff --git a/whatsapp_image_test.go b/whatsapp_image_test.go index 91af70a..75a95dc 100644 --- a/whatsapp_image_test.go +++ b/whatsapp_image_test.go @@ -83,7 +83,7 @@ func TestWhatsAppImageDownloadCanOutlastNameLookup(t *testing.T) { synctest.Test(t, func(t *testing.T) { whatsapp, fake := whatsappStartTestLinked(t) whatsapp.client = fake - fake.downloadWait = whatsappLookupTime + time.Second + fake.downloadWait = whatsappContactLookupTimeout + time.Second data := imageTestPNG(t, 3, 2) fake.downloadData = data diff --git a/whatsapp_inbox.go b/whatsapp_inbox.go index 392593f..9d2183e 100644 --- a/whatsapp_inbox.go +++ b/whatsapp_inbox.go @@ -16,19 +16,20 @@ import ( ) const ( - // whatsappLookupTime is the longest time of a read of names in the - // session. - whatsappLookupTime = 10 * time.Second + // whatsappContactLookupTimeout is the longest time of a read of names + // in the session. + whatsappContactLookupTimeout = 10 * time.Second - // whatsappImageTime is the longest time of an image download. - whatsappImageTime = 2 * time.Minute + // whatsappImageDownloadTimeout is the longest time of an image + // download. + whatsappImageDownloadTimeout = 2 * time.Minute // whatsappSource is the source of the work events of the batches. whatsappSource = "whatsapp" - // whatsappCatchupLimit is the longest wait for the end of the catch-up - // after a connection. - whatsappCatchupLimit = time.Minute + // whatsappCatchupTimeout is the longest wait for the end of the + // catch-up after a connection. + whatsappCatchupTimeout = time.Minute ) // newWhatsAppInbox returns the inbox of the batches in state, with clock for @@ -52,7 +53,7 @@ func newWhatsAppInbox(state *WhatsAppState, clock func() time.Time, groups *What // // After each connection, the servers send the messages that came while the // daemon was away, and then OfflineSyncCompleted. Until then, or until -// whatsappCatchupLimit passes, the closed batches wait in the state file. At +// whatsappCatchupTimeout passes, the closed batches wait in the state file. At // the end of the catch-up, deliver closes all batches and logs them. It wakes // the root once for its batches, so their catch-up gives one turn, not one for // each chat. The batches of the state file at the start wait for the first @@ -207,7 +208,7 @@ func (i *WhatsAppInbox) waitForCatchup() { } // startCatchup starts the catch-up of a new connection, which ends at -// endCatchup or after whatsappCatchupLimit. +// endCatchup or after whatsappCatchupTimeout. func (i *WhatsAppInbox) startCatchup() { i.mutex.Lock() defer i.mutex.Unlock() @@ -219,7 +220,7 @@ func (i *WhatsAppInbox) startCatchup() { i.catchupTimer.Stop() } - i.catchupTimer = time.AfterFunc(whatsappCatchupLimit, func() { + i.catchupTimer = time.AfterFunc(whatsappCatchupTimeout, func() { i.caughtUpBy(catchups) }) } @@ -230,7 +231,7 @@ func (i *WhatsAppInbox) startCatchup() { // daemon. An image that cannot be downloaded or stored gets a text marker. A // message that the batches do not take is handled with nothing to do. func (i *WhatsAppInbox) receive(ctx context.Context, link WhatsAppLink, event *events.Message) bool { - lookupCtx, cancel := context.WithTimeout(ctx, whatsappLookupTime) + lookupCtx, cancel := context.WithTimeout(ctx, whatsappContactLookupTimeout) defer cancel() chat, message, found := whatsappMessage(lookupCtx, link.device, link.own, event) @@ -239,7 +240,7 @@ func (i *WhatsAppInbox) receive(ctx context.Context, link WhatsAppLink, event *e } if event.Message.GetImageMessage() != nil { - ctx, cancel := context.WithTimeout(ctx, whatsappImageTime) + ctx, cancel := context.WithTimeout(ctx, whatsappImageDownloadTimeout) defer cancel() message.Text = i.imageText(ctx, link, event, message.Text) diff --git a/whatsapp_inbox_test.go b/whatsapp_inbox_test.go index a0a0f9d..1ce9a72 100644 --- a/whatsapp_inbox_test.go +++ b/whatsapp_inbox_test.go @@ -147,7 +147,7 @@ func TestWhatsAppRunClosesABatchAfterQuietTime(t *testing.T) { synctest.Wait() require.True(t, test.fake.Emit(whatsappTestMessage(whatsappTestAna, whatsappTestOwn, "m1", "On my way.", time.Now()))) synctest.Wait() - time.Sleep(whatsappBatchQuiet - time.Nanosecond) + time.Sleep(whatsappBatchIdleTimeout - time.Nanosecond) synctest.Wait() require.Zero(t, test.loop.memory.Len()) @@ -268,7 +268,7 @@ func TestWhatsAppCatchupEndsAfterItsLimit(t *testing.T) { require.NoError(t, test.whatsapp.inbox.deliver(t.Context(), test.loop, test.whatsapp.link(), false)) require.Zero(t, test.loop.memory.Len()) - time.Sleep(whatsappCatchupLimit) + time.Sleep(whatsappCatchupTimeout) synctest.Wait() require.NoError(t, test.whatsapp.inbox.deliver(t.Context(), test.loop, test.whatsapp.link(), false)) require.Equal(t, 1, test.loop.memory.Len()) diff --git a/whatsapp_send.go b/whatsapp_send.go index ce3f70b..d5995df 100644 --- a/whatsapp_send.go +++ b/whatsapp_send.go @@ -16,8 +16,8 @@ import ( ) const ( - // whatsappSendTime is the longest time of a send. - whatsappSendTime = 30 * time.Second + // whatsappSendTimeout is the longest time of a send. + whatsappSendTimeout = 30 * time.Second // whatsappSendBytes is the most bytes of the text of a send. whatsappSendBytes = 65536 @@ -77,7 +77,7 @@ func whatsappSend(ctx context.Context, link WhatsAppLink, groups *WhatsAppGroups return "", err } - sendCtx, cancel := context.WithTimeout(ctx, whatsappSendTime) + sendCtx, cancel := context.WithTimeout(ctx, whatsappSendTimeout) defer cancel() response, err := link.client.SendMessage(sendCtx, jid, &waE2E.Message{ diff --git a/whatsapp_state.go b/whatsapp_state.go index 41bd2f0..b1b5935 100644 --- a/whatsapp_state.go +++ b/whatsapp_state.go @@ -16,12 +16,12 @@ const ( // the batches that are not in the log yet and the records of the sends. whatsappStateFileName = "state.json" - // whatsappBatchQuiet is how long a chat is quiet before its batch + // whatsappBatchIdleTimeout is how long a chat is quiet before its batch // closes. - whatsappBatchQuiet = 20 * time.Second + whatsappBatchIdleTimeout = 20 * time.Second - // whatsappBatchWindow is the longest time of a batch. - whatsappBatchWindow = 2 * time.Minute + // whatsappBatchTimeout is the longest time of a batch. + whatsappBatchTimeout = 2 * time.Minute // whatsappBatchMessages is the most messages of a batch. whatsappBatchMessages = 50 @@ -32,8 +32,9 @@ const ( ) // openWhatsAppState reads the batches and the send records of the state file at -// path. A missing file holds none. A batch closes after whatsappBatchQuiet with -// no message, or after whatsappBatchWindow at the latest. +// path. A missing file holds none. A batch closes after +// whatsappBatchIdleTimeout with no message, or after whatsappBatchTimeout at +// the latest. func openWhatsAppState(path string) (*WhatsAppState, error) { s := &WhatsAppState{ path: path, @@ -59,12 +60,13 @@ func openWhatsAppState(path string) (*WhatsAppState, error) { // WhatsAppState holds the state file: the send records, and the batches of the // WhatsApp messages that are not in the log yet, open and closed, in the order // of their first message. The messages of one chat form one batch while the -// times of the messages are at most whatsappBatchQuiet apart, at most -// whatsappBatchWindow after the first, and the batch has fewer than +// times of the messages are at most whatsappBatchIdleTimeout apart, at most +// whatsappBatchTimeout after the first, and the batch has fewer than // whatsappBatchMessages messages. The times are the WhatsApp times, so a // catch-up after a stop gives the same batches as live messages. A batch also -// closes when whatsappBatchQuiet passes after the arrival of its last message, -// or whatsappBatchWindow after the arrival of its first message, in real time. +// closes when whatsappBatchIdleTimeout passes after the arrival of its last +// message, or whatsappBatchTimeout after the arrival of its first message, in +// real time. // // A send record keeps the result of a send by its ID, so that a repeated call // of the send tool does not send again. The state file keeps the last @@ -99,7 +101,7 @@ func (s *WhatsAppState) Add(chat WhatsAppChat, message WhatsAppMessage, arrival return false, nil } - if message.Time.Sub(batch.Messages[len(batch.Messages)-1].Time) > whatsappBatchQuiet || message.Time.Sub(batch.Messages[0].Time) > whatsappBatchWindow { + if message.Time.Sub(batch.Messages[len(batch.Messages)-1].Time) > whatsappBatchIdleTimeout || message.Time.Sub(batch.Messages[0].Time) > whatsappBatchTimeout { batch.Closed = true closed = true index = -1 @@ -258,8 +260,8 @@ func (s *WhatsAppState) open(chat string) int { // deadline returns when batch closes in real time. func (s *WhatsAppState) deadline(batch WhatsAppBatch) time.Time { - quiet := batch.Last.Add(whatsappBatchQuiet) - window := batch.First.Add(whatsappBatchWindow) + quiet := batch.Last.Add(whatsappBatchIdleTimeout) + window := batch.First.Add(whatsappBatchTimeout) if window.Before(quiet) { return window } diff --git a/whatsapp_test.go b/whatsapp_test.go index f098c90..c1471e9 100644 --- a/whatsapp_test.go +++ b/whatsapp_test.go @@ -249,12 +249,12 @@ func TestWhatsAppLongFirstConnectionOutageGivesOneNotice(t *testing.T) { since := time.Now().Format(whatsappTimeLayout) - time.Sleep(whatsappNoticeDelay) + time.Sleep(whatsappOutageNoticeDelay) synctest.Wait() require.Equal(t, 1, test.events.Count("notice")) require.Equal(t, "WhatsApp is disconnected since "+since+". OneChat tries again.", test.events.Last("notice")) - time.Sleep(whatsappNoticeDelay) + time.Sleep(whatsappOutageNoticeDelay) synctest.Wait() require.Equal(t, 1, test.events.Count("notice")) test.fake.mutex.Lock() @@ -613,18 +613,18 @@ func TestWhatsAppLongDisconnectionGivesOneNotice(t *testing.T) { require.True(t, test.fake.Emit(&events.Connected{})) require.True(t, test.fake.Emit(&events.Disconnected{})) require.True(t, test.fake.Emit(&events.Connected{})) - time.Sleep(whatsappNoticeDelay + time.Second) + time.Sleep(whatsappOutageNoticeDelay + time.Second) synctest.Wait() require.Zero(t, test.events.Count("notice")) require.True(t, test.fake.Emit(&events.Disconnected{})) require.True(t, test.fake.Emit(&events.Disconnected{})) - time.Sleep(whatsappNoticeDelay) + time.Sleep(whatsappOutageNoticeDelay) synctest.Wait() require.Equal(t, 1, test.events.Count("notice")) require.Contains(t, test.events.Last("notice"), "OneChat tries again.") require.True(t, test.fake.Emit(&events.Disconnected{})) - time.Sleep(whatsappNoticeDelay) + time.Sleep(whatsappOutageNoticeDelay) synctest.Wait() require.Equal(t, 1, test.events.Count("notice"))