X-Git-Url: https://git.giacomolli.uk/onechat/blobdiff_plain/0da50dc187c8b4aa23ac1ddd0418c0da779389d9..add3cf6416e33c24331fd1e90e99284f44d2aae2:/whatsapp_inbox.go?ds=inline diff --git a/whatsapp_inbox.go b/whatsapp_inbox.go index 5121976..9d2183e 100644 --- a/whatsapp_inbox.go +++ b/whatsapp_inbox.go @@ -16,12 +16,20 @@ import ( ) const ( + // whatsappContactLookupTimeout is the longest time of a read of names + // in the session. + whatsappContactLookupTimeout = 10 * time.Second + + // 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 @@ -29,16 +37,13 @@ const ( // holds shared images, and logger gets image failures. func newWhatsAppInbox(state *WhatsAppState, clock func() time.Time, groups *WhatsAppGroups, images *ImageStore, logger *slog.Logger) *WhatsAppInbox { return &WhatsAppInbox{ - state: state, - clock: clock, - groups: groups, - images: images, - logger: logger, - lookupTime: whatsappLookupTime, - imageTime: whatsappImageTime, - catchupLimit: whatsappCatchupLimit, - wake: make(chan struct{}, 1), - failures: make(chan error, 1), + state: state, + clock: clock, + groups: groups, + images: images, + logger: logger, + wake: make(chan struct{}, 1), + failures: make(chan error, 1), } } @@ -48,16 +53,16 @@ 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 -// catchupLimit 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 catch-up -// in the same way. The event handler acknowledges a message only after the -// state file holds it, so the servers send again a message that a crash lost. A -// batch leaves the state file only after its work message is durable in the log -// or agent queue. A crash between the two can repeat an unrouted batch once. A -// routed batch enters the durable agent queue, which prevents a second log -// entry and wakes only the child. A missing child uses the root. +// 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 +// catch-up in the same way. The event handler acknowledges a message only after +// the state file holds it, so the servers send again a message that a crash +// lost. A batch leaves the state file only after its work message is durable in +// the log or agent queue. A crash between the two can repeat an unrouted batch +// once. A routed batch enters the durable agent queue, which prevents a second +// log entry and wakes only the child. A missing child uses the root. // // The state file is the one of WhatsApp, which keeps the send records in it // too. groups gives the names of the groups. The mutex protects the state of @@ -65,16 +70,13 @@ func newWhatsAppInbox(state *WhatsAppState, clock func() time.Time, groups *What // goroutines. wake tells Run that a batch can be due or that a catch-up ended, // and failures gives Run the error of a write of the state file. type WhatsAppInbox struct { - state *WhatsAppState - clock func() time.Time - groups *WhatsAppGroups - images *ImageStore - logger *slog.Logger - lookupTime time.Duration - imageTime time.Duration - catchupLimit time.Duration - wake chan struct{} - failures chan error + state *WhatsAppState + clock func() time.Time + groups *WhatsAppGroups + images *ImageStore + logger *slog.Logger + wake chan struct{} + failures chan error mutex sync.Mutex catchingUp bool @@ -206,7 +208,7 @@ func (i *WhatsAppInbox) waitForCatchup() { } // startCatchup starts the catch-up of a new connection, which ends at -// endCatchup or after catchupLimit. +// endCatchup or after whatsappCatchupTimeout. func (i *WhatsAppInbox) startCatchup() { i.mutex.Lock() defer i.mutex.Unlock() @@ -218,7 +220,7 @@ func (i *WhatsAppInbox) startCatchup() { i.catchupTimer.Stop() } - i.catchupTimer = time.AfterFunc(i.catchupLimit, func() { + i.catchupTimer = time.AfterFunc(whatsappCatchupTimeout, func() { i.caughtUpBy(catchups) }) } @@ -228,17 +230,17 @@ func (i *WhatsAppInbox) startCatchup() { // message, so that the library does not acknowledge it, and Run stops the // 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(link WhatsAppLink, event *events.Message) bool { - ctx, cancel := context.WithTimeout(context.Background(), i.lookupTime) +func (i *WhatsAppInbox) receive(ctx context.Context, link WhatsAppLink, event *events.Message) bool { + lookupCtx, cancel := context.WithTimeout(ctx, whatsappContactLookupTimeout) defer cancel() - chat, message, found := whatsappMessage(ctx, link.device, link.own, event) + chat, message, found := whatsappMessage(lookupCtx, link.device, link.own, event) if !found { return true } if event.Message.GetImageMessage() != nil { - ctx, cancel := context.WithTimeout(context.Background(), i.imageTime) + ctx, cancel := context.WithTimeout(ctx, whatsappImageDownloadTimeout) defer cancel() message.Text = i.imageText(ctx, link, event, message.Text)