@@ -164,12 +164,16 @@ async function mapPool(items, concurrency, fn) {
164164 await Promise . all ( Array . from ( { length : Math . max ( 1 , Math . min ( concurrency , items . length ) ) } , worker ) ) ;
165165}
166166
167- /** Sweep targets: allowlist ∪ already-verified relays (stalest first), capped. */
167+ /** Sweep targets: allowlist ∪ relays we already track (stalest first), capped.
168+ * Membership = `lastChecked` exists (we've probed it before) — decoupled from
169+ * the uptime counters so those can be reset without losing the rotation, and
170+ * so offline-but-known relays stay in rotation (and can recover). Brand-new
171+ * harvested candidates (never probed) are excluded. */
168172async function sweepTargets ( db , cfg ) {
169- const verified = await db . collection ( RELAY_DIRECTORY )
170- . find ( { checksOnline : { $gte : 1 } } , { projection : { relay : 1 , _id : 0 } } )
173+ const tracked = await db . collection ( RELAY_DIRECTORY )
174+ . find ( { lastChecked : { $exists : true } } , { projection : { relay : 1 , _id : 0 } } )
171175 . sort ( { lastChecked : 1 } ) . limit ( cfg . cap ) . toArray ( ) ;
172- return selectTargets ( proberRelays ( ) , verified . map ( ( d ) => d . relay ) , cfg . cap ) ;
176+ return selectTargets ( proberRelays ( ) , tracked . map ( ( d ) => d . relay ) , cfg . cap ) ;
173177}
174178
175179/** One sweep over the allowlist + verified candidates (never new harvest). */
0 commit comments