Skip to content

Commit bea1bde

Browse files
committed
Bumped deps
1 parent edd8006 commit bea1bde

File tree

9 files changed

+75
-76
lines changed

9 files changed

+75
-76
lines changed

data/google-crawlers.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"creationTime": "2025-08-27T14:46:10.000000",
2+
"creationTime": "2025-08-28T14:46:01.000000",
33
"prefixes": [
44
{
55
"ipv6Prefix": "2001:4860:4801:2008::/64"

lib/email-client/base-client.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,13 @@ const SMTP_POOL_CLEANUP_INTERVAL = 2 * 60 * 1000;
114114
let smtpPoolCleanupTimer = setInterval(() => {
115115
const now = Date.now();
116116
const idleKeys = [];
117-
117+
118118
for (const [poolKey, lastUsed] of SMTP_POOL_LAST_USED.entries()) {
119119
if (now - lastUsed > SMTP_POOL_MAX_IDLE) {
120120
idleKeys.push(poolKey);
121121
}
122122
}
123-
123+
124124
for (const poolKey of idleKeys) {
125125
const transporter = SMTP_POOLS.get(poolKey);
126126
if (transporter) {
@@ -131,7 +131,7 @@ let smtpPoolCleanupTimer = setInterval(() => {
131131
logger.trace({ msg: 'SMTP pool still has active connections, skipping cleanup', poolKey });
132132
continue;
133133
}
134-
134+
135135
logger.debug({ msg: 'Cleaning up idle SMTP pool connection', poolKey, idleTime: now - SMTP_POOL_LAST_USED.get(poolKey) });
136136
try {
137137
transporter.close();
@@ -142,7 +142,7 @@ let smtpPoolCleanupTimer = setInterval(() => {
142142
SMTP_POOLS.delete(poolKey);
143143
SMTP_POOL_LAST_USED.delete(poolKey);
144144
}
145-
145+
146146
if (idleKeys.length > 0) {
147147
logger.info({ msg: 'SMTP pool cleanup completed', cleaned: idleKeys.length, remaining: SMTP_POOLS.size });
148148
}

lib/metrics-collector.js

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ class MetricsCollector {
88
this.cacheInterval = options.cacheInterval || 15 * 1000; // Default 15 seconds
99
this.workerTimeout = options.workerTimeout || 500; // Default 500ms per worker
1010
this.delayBetweenWorkers = options.delayBetweenWorkers || 100; // Default 100ms between workers
11-
11+
1212
// State management
1313
this.cachedThreadsInfo = null;
1414
this.collectorTimer = null;
1515
this.isCollecting = false;
1616
this.lastCollectionTime = null;
17-
17+
1818
// Callbacks to get data from main server
1919
this.getWorkers = options.getWorkers || (() => new Map());
2020
this.callWorker = options.callWorker || (() => Promise.reject(new Error('callWorker not configured')));
@@ -28,18 +28,18 @@ class MetricsCollector {
2828
start() {
2929
// Stop any existing collector
3030
this.stop();
31-
32-
this.logger.info({
33-
msg: 'Starting background metrics collector',
31+
32+
this.logger.info({
33+
msg: 'Starting background metrics collector',
3434
interval: this.cacheInterval,
35-
delayBetweenWorkers: this.delayBetweenWorkers
35+
delayBetweenWorkers: this.delayBetweenWorkers
3636
});
37-
37+
3838
// Collect metrics immediately on start
3939
this.collectInBackground().catch(err => {
4040
this.logger.error({ msg: 'Initial metrics collection failed', err });
4141
});
42-
42+
4343
// Schedule next collection
4444
this.scheduleNextCollection();
4545
}
@@ -64,17 +64,17 @@ class MetricsCollector {
6464
if (this.collectorTimer) {
6565
clearTimeout(this.collectorTimer);
6666
}
67-
67+
6868
this.collectorTimer = setTimeout(async () => {
6969
// Prevent overlapping runs
7070
if (this.isCollecting) {
7171
this.logger.debug({ msg: 'Metrics collection still running, rescheduling' });
7272
this.scheduleNextCollection();
7373
return;
7474
}
75-
75+
7676
this.isCollecting = true;
77-
77+
7878
try {
7979
await this.collectInBackground();
8080
} catch (err) {
@@ -92,23 +92,23 @@ class MetricsCollector {
9292
*/
9393
async collectInBackground() {
9494
const startTime = Date.now();
95-
95+
9696
// Start with main thread info
9797
let threadsInfo = [
9898
Object.assign(
99-
{
100-
type: 'main',
101-
isMain: true,
102-
threadId: 0,
103-
online: this.startTime
104-
},
99+
{
100+
type: 'main',
101+
isMain: true,
102+
threadId: 0,
103+
online: this.startTime
104+
},
105105
threadStats.usage()
106106
)
107107
];
108-
108+
109109
// Get all workers from the main server
110110
const workers = this.getWorkers();
111-
111+
112112
// Collect info from all worker threads SEQUENTIALLY to avoid CPU spikes
113113
for (let [type, workerSet] of workers) {
114114
if (workerSet && workerSet.size) {
@@ -119,10 +119,10 @@ class MetricsCollector {
119119
cmd: 'resource-usage',
120120
timeout: this.workerTimeout
121121
});
122-
122+
123123
// Get additional metadata for this worker
124124
const metadata = this.getWorkerMetadata(worker);
125-
125+
126126
let threadData = Object.assign(
127127
{
128128
type,
@@ -132,17 +132,17 @@ class MetricsCollector {
132132
resourceUsage,
133133
metadata
134134
);
135-
135+
136136
threadsInfo.push(threadData);
137-
137+
138138
// Small delay between workers to spread CPU load
139139
if (this.delayBetweenWorkers > 0) {
140140
await new Promise(resolve => setTimeout(resolve, this.delayBetweenWorkers));
141141
}
142142
} catch (err) {
143143
// Handle errors gracefully - still include the worker in results
144144
const metadata = this.getWorkerMetadata(worker);
145-
145+
146146
threadsInfo.push({
147147
type,
148148
threadId: worker.threadId,
@@ -158,19 +158,19 @@ class MetricsCollector {
158158
}
159159
}
160160
}
161-
161+
162162
// Update the cache atomically
163163
this.cachedThreadsInfo = threadsInfo;
164164
this.lastCollectionTime = Date.now();
165-
165+
166166
const duration = Date.now() - startTime;
167-
this.logger.debug({
168-
msg: 'Background metrics collection completed',
169-
duration,
167+
this.logger.debug({
168+
msg: 'Background metrics collection completed',
169+
duration,
170170
workers: threadsInfo.length,
171171
cacheAge: 0
172172
});
173-
173+
174174
return threadsInfo;
175175
}
176176

@@ -183,17 +183,17 @@ class MetricsCollector {
183183
// If we have cached data and don't need to force refresh, return it
184184
if (!forceRefresh && this.cachedThreadsInfo) {
185185
const cacheAge = this.lastCollectionTime ? Date.now() - this.lastCollectionTime : null;
186-
this.logger.debug({
187-
msg: 'Returning cached metrics',
186+
this.logger.debug({
187+
msg: 'Returning cached metrics',
188188
workers: this.cachedThreadsInfo.length,
189-
cacheAge
189+
cacheAge
190190
});
191191
return this.cachedThreadsInfo;
192192
}
193-
193+
194194
// No cache available or forced refresh - collect synchronously
195195
this.logger.debug({ msg: 'No cached metrics available or forced refresh, collecting synchronously' });
196-
196+
197197
// For synchronous collection, we still do it sequentially to be safe
198198
// but we could optionally do parallel collection here if needed for first-time speed
199199
return await this.collectInBackground();
@@ -214,4 +214,4 @@ class MetricsCollector {
214214
}
215215
}
216216

217-
module.exports = MetricsCollector;
217+
module.exports = MetricsCollector;

package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sbom.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

server.js

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -666,21 +666,21 @@ async function getThreadsInfo() {
666666
// Use metrics collector if available
667667
if (metricsCollector) {
668668
let threadsInfo = await metricsCollector.getThreadsInfo();
669-
669+
670670
// Add human-readable descriptions and configuration info
671671
threadsInfo.forEach(threadInfo => {
672672
threadInfo.description = THREAD_NAMES[threadInfo.type];
673673
if (THREAD_CONFIG_VALUES[threadInfo.type]) {
674674
threadInfo.config = THREAD_CONFIG_VALUES[threadInfo.type];
675675
}
676676
});
677-
677+
678678
return threadsInfo;
679679
}
680-
680+
681681
// Fallback to original implementation if collector not initialized
682682
// This should only happen during startup or if collector fails
683-
683+
684684
// Start with main thread info
685685
let threadsInfo = [Object.assign({ type: 'main', isMain: true, threadId: 0, online: NOW }, threadStats.usage())];
686686

@@ -1117,20 +1117,20 @@ let spawnWorker = async type => {
11171117
exitCode,
11181118
availableWorkers: availableIMAPWorkers.size
11191119
});
1120-
1120+
11211121
// Check if all workers have exited (Redis reconnection scenario)
11221122
if (availableIMAPWorkers.size === 0) {
11231123
logger.info({
11241124
msg: 'All IMAP workers exited, reloading accounts from Redis for reassignment'
11251125
});
1126-
1126+
11271127
// Reload all accounts from Redis since we lost track
11281128
try {
11291129
let accounts = await redis.smembers(`${REDIS_PREFIX}ia:accounts`);
11301130
unassigned = new Set(accounts);
11311131
assigned.clear();
11321132
workerAssigned = new WeakMap();
1133-
1133+
11341134
logger.info({
11351135
msg: 'Reloaded accounts from Redis',
11361136
accountCount: accounts.length
@@ -1442,7 +1442,7 @@ let spawnWorker = async type => {
14421442
workerHealthStatus.set(worker, 'healthy');
14431443

14441444
resolve(worker.threadId);
1445-
1445+
14461446
logger.info({
14471447
msg: 'IMAP worker ready',
14481448
threadId: worker.threadId,
@@ -1608,7 +1608,6 @@ async function call(worker, message, transferList) {
16081608
});
16091609
}
16101610

1611-
16121611
/**
16131612
* Assign unassigned accounts to available IMAP workers
16141613
* Uses load-aware distribution with round-robin for initial assignment
@@ -3105,52 +3104,52 @@ const startApplication = async () => {
31053104
if (await settings.get('imapProxyServerEnabled')) {
31063105
await spawnWorker('imapProxy');
31073106
}
3108-
3107+
31093108
// Initialize and start the metrics collector after all workers are ready
31103109
metricsCollector = new MetricsCollector({
31113110
logger,
31123111
cacheInterval: 10 * 1000, // 10 seconds
31133112
workerTimeout: 500, // 500ms timeout per worker
31143113
delayBetweenWorkers: 50, // 50ms delay between worker queries
31153114
startTime: NOW,
3116-
3115+
31173116
// Provide callbacks to access server state
31183117
getWorkers: () => workers,
31193118
callWorker: (worker, message) => call(worker, message),
3120-
getWorkerMetadata: (worker) => {
3119+
getWorkerMetadata: worker => {
31213120
const metadata = {};
3122-
3121+
31233122
// Add account count for IMAP workers
31243123
if (workerAssigned.has(worker)) {
31253124
metadata.accounts = workerAssigned.get(worker).size;
31263125
}
3127-
3126+
31283127
// Add health status
31293128
metadata.healthStatus = workerHealthStatus.get(worker) || 'unknown';
31303129
const lastHeartbeat = workerHeartbeats.get(worker);
31313130
if (lastHeartbeat) {
31323131
metadata.lastHeartbeat = lastHeartbeat;
31333132
metadata.timeSinceHeartbeat = Date.now() - lastHeartbeat;
31343133
}
3135-
3134+
31363135
// Add circuit breaker status
31373136
const circuit = getCircuitBreaker(worker);
31383137
metadata.circuitState = circuit.state;
31393138
metadata.circuitFailures = circuit.failures;
3140-
3139+
31413140
// Add worker metadata
31423141
let workerMeta = workersMeta.has(worker) ? workersMeta.get(worker) : {};
31433142
for (let key of Object.keys(workerMeta)) {
31443143
metadata[key] = workerMeta[key];
31453144
}
3146-
3145+
31473146
return metadata;
31483147
}
31493148
});
3150-
3149+
31513150
// Start the background collection
31523151
metricsCollector.start();
3153-
3152+
31543153
logger.info({ msg: 'Background metrics collector initialized and started' });
31553154
};
31563155

0 commit comments

Comments
 (0)