scan public groups one-by-one with random delay, fill chatCache
()
| 158 | /* ignore rename failure; overwrite below */ |
| 159 | } |
| 160 | this.chatCache.clear(); |
| 161 | this.cacheDb = await JSONFilePreset<FbiCache>(cp, { cache: {} }); |
| 162 | await this.cacheDb.write(); |
| 163 | console.warn("[fbi] cache reset to empty after corruption recovery"); |
| 164 | } |
| 165 | |
| 166 | this.cacheReady = true; |
| 167 | |
| 168 | // cold sweep every 24h — prune expired messages in silent groups |
| 169 | this.coldSweepTimer = setInterval(() => { |
| 170 | if (!this.cacheReady) return; |
| 171 | let anyPruned = false; |
| 172 | for (const chat of this.chatCache.values()) |
| 173 | if (this.pruneExpired(chat)) anyPruned = true; |
| 174 | if (anyPruned) this.schedulePersistCache(); |
| 175 | }, 24 * 60 * 60 * 1000); |
| 176 | this.ready = true; |
| 177 | } |
| 178 | |
| 179 | private async persistDb() { |
| 180 | this.configDb.data.surveillance = Object.fromEntries(this.sv); |
| 181 | await this.configDb.write(); |
| 182 | } |
| 183 | |
| 184 | /** Cleanup timers on plugin unload to prevent leaks across reloads */ |
| 185 | cleanup(): void { |
| 186 | // flush pending cache before clearing timers |
| 187 | if (this.cacheDirty && this.cachePath) { |
| 188 | try { |
| 189 | this.cacheDb.data.cache = Object.fromEntries(this.chatCache); |
| 190 | fs.writeFileSync(this.cachePath, JSON.stringify(this.cacheDb.data)); |
| 191 | } catch (e) { |
| 192 | console.error("[fbi] cleanup sync flush failed", e); |
| 193 | } |
| 194 | } |
| 195 | if (this.coldSweepTimer) { |
| 196 | clearInterval(this.coldSweepTimer); |
| 197 | this.coldSweepTimer = null; |
| 198 | } |
| 199 | if (this.cachePersistTimer) { |
| 200 | clearTimeout(this.cachePersistTimer); |
| 201 | this.cachePersistTimer = null; |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | /** debounced cache persist — at most once every 10s */ |
| 206 | private schedulePersistCache() { |
| 207 | this.cacheDirty = true; |
| 208 | if (this.cachePersistTimer) return; // already queued |
| 209 | this.cachePersistTimer = setTimeout(async () => { |
| 210 | this.cachePersistTimer = null; |
| 211 | if (!this.cacheDirty) return; |
| 212 | this.cacheDirty = false; |
| 213 | this.cacheDb.data.cache = Object.fromEntries(this.chatCache); |
| 214 | await this.cacheDb.write(); |
| 215 | }, 10_000); |
| 216 | } |
| 217 |