Add intake worker
Subsystem to monitor IMAP mailbox for new messages. Introduces: - intake: worker that uses IDLE or polling to detect new emails. - imap: client wrapper for connection management and IMAP commands. - filter: logic for IMAP search and sender allow-list. - tracker: concurrency control to prevent processing the same UID twice. - backoff: for handling connection retries with jitter.
This commit is contained in:
43
internal/tracker/tracker.go
Normal file
43
internal/tracker/tracker.go
Normal file
@@ -0,0 +1,43 @@
|
||||
// Package tracker prevents duplicate processing of IMAP messages by
|
||||
// maintaining a transient set of active, in-flight UIDs.
|
||||
package tracker
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/emersion/go-imap/v2"
|
||||
)
|
||||
|
||||
// Tracker ensures unique concurrent processing of messages.
|
||||
// This prevents race conditions where a message might be fetched
|
||||
// again before its initial processing completes.
|
||||
type Tracker struct {
|
||||
mu sync.Mutex
|
||||
ids map[imap.UID]struct{}
|
||||
}
|
||||
|
||||
// New returns a ready-to-use Tracker.
|
||||
func New() *Tracker {
|
||||
return &Tracker{
|
||||
ids: make(map[imap.UID]struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// TryAcquire attempts to claim exclusive processing rights for a UID.
|
||||
// It returns true only if the UID is not currently being tracked.
|
||||
func (t *Tracker) TryAcquire(uid imap.UID) bool {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if _, exists := t.ids[uid]; exists {
|
||||
return false
|
||||
}
|
||||
t.ids[uid] = struct{}{}
|
||||
return true
|
||||
}
|
||||
|
||||
// Release relinquishes processing rights for a UID, allowing it to be acquired again.
|
||||
func (t *Tracker) Release(uid imap.UID) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
delete(t.ids, uid)
|
||||
}
|
||||
Reference in New Issue
Block a user