44 lines
1.0 KiB
Go
44 lines
1.0 KiB
Go
|
|
// 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)
|
||
|
|
}
|