[Chore]: Patch getLargestUid function

Now preventing uid-drift.
Also fixing the monstrocity that was statistics-store formatting
This commit is contained in:
ClaraCrazy 2026-01-06 19:46:45 +01:00
parent d8b19dcd26
commit dc79d52245
No known key found for this signature in database
GPG key ID: EBBC896ACB497011
2 changed files with 29 additions and 50 deletions

View file

@ -31,6 +31,22 @@ class MailProcessingService extends EventEmitter {
setInterval(() => { setInterval(() => {
this._deleteOldMails() this._deleteOldMails()
}, this.config.imap.refreshIntervalSeconds * 1000) }, this.config.imap.refreshIntervalSeconds * 1000)
// Periodically ground largestUid to IMAP state every 5 minutes
setInterval(async() => {
try {
if (this.statisticsStore && this.imapService) {
const realLargestUid = await this.imapService.getLargestUid();
if (realLargestUid && realLargestUid !== this.statisticsStore.largestUid) {
this.statisticsStore.largestUid = realLargestUid;
this.statisticsStore._saveToDatabase && this.statisticsStore._saveToDatabase();
debug(`Grounded statisticsStore.largestUid to IMAP: ${realLargestUid}`);
}
}
} catch (err) {
debug('Error grounding largestUid to IMAP:', err.message);
}
}, 60 * 1000); // 1 minute
} }
_initCache() { _initCache() {

View file

@ -405,9 +405,7 @@ class StatisticsStore {
recordDelete() { recordDelete() {
this.currentCount = Math.max(0, this.currentCount - 1) this.currentCount = Math.max(0, this.currentCount - 1)
this._addDataPoint('delete') this._addDataPoint('delete')
debug(` debug(`Email deleted. Current: ${this.currentCount}`)
Email deleted.Current: $ { this.currentCount }
`)
} }
/** /**
@ -415,8 +413,7 @@ class StatisticsStore {
*/ */
recordForward() { recordForward() {
this._addDataPoint('forward') this._addDataPoint('forward')
debug(` debug(`Email forwarded. Current: ${this.currentCount}`)
Email forwarded `)
} }
/** /**
@ -470,18 +467,12 @@ class StatisticsStore {
const now = Date.now() const now = Date.now()
if (this.enhancedStats && (now - this.lastEnhancedStatsTime) < this.enhancedStatsCacheDuration) { if (this.enhancedStats && (now - this.lastEnhancedStatsTime) < this.enhancedStatsCacheDuration) {
debug(` debug(`Using cached enhanced stats(age: ${Math.round((now - this.lastEnhancedStatsTime) / 1000)}s)`)
Using cached enhanced stats(age: $ { Math.round((now - this.lastEnhancedStatsTime) / 1000) }
s)
`)
return return
} }
debug(` debug(`Calculating enhanced statistics from ${allMails.length} emails `)
Calculating enhanced statistics from $ { allMails.length } // Track sender domains (privacy-friendly: domain only, not full address)
emails `)
// Track sender domains (privacy-friendly: domain only, not full address)
const senderDomains = new Map() const senderDomains = new Map()
const recipientDomains = new Map() const recipientDomains = new Map()
const hourlyActivity = Array(24).fill(0) const hourlyActivity = Array(24).fill(0)
@ -591,10 +582,7 @@ class StatisticsStore {
} }
this.lastEnhancedStatsTime = now this.lastEnhancedStatsTime = now
debug(` debug(`Enhanced stats calculated: ${this.enhancedStats.uniqueSenderDomains} unique sender domains, ${this.enhancedStats.busiestHours.length} busy hours `)
Enhanced stats calculated: $ { this.enhancedStats.uniqueSenderDomains }
unique sender domains, $ { this.enhancedStats.busiestHours.length }
busy hours `)
} }
/** /**
@ -610,18 +598,11 @@ class StatisticsStore {
// Check cache - if analysis was done recently, skip it // Check cache - if analysis was done recently, skip it
const now = Date.now() const now = Date.now()
if (this.historicalData && (now - this.lastAnalysisTime) < this.analysisCacheDuration) { if (this.historicalData && (now - this.lastAnalysisTime) < this.analysisCacheDuration) {
debug(` debug(`Using cached historical data(${this.historicalData.length} points, age: ${Math.round((now - this.lastAnalysisTime) / 1000)}s)`)
Using cached historical data($ { this.historicalData.length }
points, age: $ { Math.round((now - this.lastAnalysisTime) / 1000) }
s)
`)
return return
} }
debug(` debug(`Analyzing ${allMails.length} emails for historical statistics `)
Analyzing $ { allMails.length }
emails
for historical statistics `)
const startTime = Date.now() const startTime = Date.now()
// Group emails by minute // Group emails by minute
@ -651,10 +632,7 @@ class StatisticsStore {
this.lastAnalysisTime = now this.lastAnalysisTime = now
const elapsed = Date.now() - startTime const elapsed = Date.now() - startTime
debug(` debug(`Built historical data: ${this.historicalData.length} time buckets in ${elapsed} ms `)
Built historical data: $ { this.historicalData.length }
time buckets in $ { elapsed }
ms `)
} }
/** /**
@ -742,11 +720,7 @@ class StatisticsStore {
.map(([timestamp, receives]) => ({ timestamp, receives })) .map(([timestamp, receives]) => ({ timestamp, receives }))
.sort((a, b) => a.timestamp - b.timestamp) .sort((a, b) => a.timestamp - b.timestamp)
debug(` debug(`Historical timeline: ${intervalData.length} 15 - min interval points within ${config.email.purgeTime.time} ${config.email.purgeTime.unit} window `)
Historical timeline: $ { intervalData.length }
15 - min interval points within $ { config.email.purgeTime.time }
$ { config.email.purgeTime.unit }
window `)
return intervalData return intervalData
} }
@ -786,11 +760,7 @@ class StatisticsStore {
hourlyAverages.set(hour, avg) hourlyAverages.set(hour, avg)
}) })
debug(` debug(`Built hourly patterns for ${hourlyAverages.size} hours from ${this.historicalData.length} data points `)
Built hourly patterns
for $ { hourlyAverages.size }
hours from $ { this.historicalData.length }
data points `)
// Generate predictions for a reasonable future window // Generate predictions for a reasonable future window
// Limit to 20% of purge duration or 12 hours max to maintain chart balance // Limit to 20% of purge duration or 12 hours max to maintain chart balance
@ -826,9 +796,7 @@ class StatisticsStore {
}) })
} }
debug(` debug(`Generated ${predictions.length} prediction points based on hourly patterns `)
Generated $ { predictions.length }
prediction points based on hourly patterns `)
return predictions return predictions
} }
@ -881,12 +849,7 @@ class StatisticsStore {
if (beforeCount !== this.hourlyData.length) { if (beforeCount !== this.hourlyData.length) {
this._saveToDatabase() // Save after cleanup this._saveToDatabase() // Save after cleanup
debug(` debug(`Cleaned up ${beforeCount - this.hourlyData.length} old data points(keeping data for ${config.email.purgeTime.time} ${config.email.purgeTime.unit})`)
Cleaned up $ { beforeCount - this.hourlyData.length }
old data points(keeping data
for $ { config.email.purgeTime.time }
$ { config.email.purgeTime.unit })
`)
} }
this.lastCleanup = now this.lastCleanup = now