Rebuild: the fragment merger
Files cut by a range's edge are put together once the ranges around them are done (coordinator:run, every minute): a complete file is judged by the rules and written as a release chunk with probe candidates; one still missing parts while both neighbouring ranges are done is dropped and counted (incomplete/edge). A neighbour not planned yet counts as not done, except before the group's oldest article. BatchStore.writeReleases is the shared write path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2c14315f94
commit
b862201991
7 files changed
+365
-65
No files matched your search
@@ -3,14 +3,17 @@ import type { CommandOptions } from '@adonisjs/core/types/ace'
|
||||
import { setTimeout as sleep } from 'node:timers/promises'
|
||||
import { Prefetcher } from '#services/prefetcher'
|
||||
import Planner from '#services/planner'
|
||||
import FragmentMerger from '#services/fragment_merger'
|
||||
import NntpPool from '#services/nntp_pool'
|
||||
|
||||
const TICK_MS = 2000
|
||||
const PLAN_EVERY_MS = 60 * 60 * 1000
|
||||
const MERGE_EVERY_MS = 60 * 1000
|
||||
|
||||
/**
|
||||
* The coordinator's background work (REBUILD.md, part 1): the prefetcher,
|
||||
* and planning ranges for new articles every hour. The API (leases, stream,
|
||||
* merging fragments of finished ranges every minute, and planning ranges
|
||||
* for new articles every hour. The API (leases, stream,
|
||||
* batches) runs in the web server.
|
||||
*/
|
||||
export default class CoordinatorRun extends BaseCommand {
|
||||
@@ -30,6 +33,7 @@ export default class CoordinatorRun extends BaseCommand {
|
||||
await done
|
||||
})
|
||||
let plannedAt = 0
|
||||
let mergedAt = 0
|
||||
this.logger.info('Coordinator started.')
|
||||
while (!stopping) {
|
||||
try {
|
||||
@@ -38,6 +42,11 @@ export default class CoordinatorRun extends BaseCommand {
|
||||
const { groups, ranges } = await Planner.planAll()
|
||||
if (ranges > 0) this.logger.info(`Planned ${ranges} ranges over ${groups} groups.`)
|
||||
}
|
||||
if (Date.now() - mergedAt >= MERGE_EVERY_MS) {
|
||||
mergedAt = Date.now()
|
||||
const merged = await FragmentMerger.run()
|
||||
if (merged.completed || merged.incomplete) this.logger.info(`Fragments: ${merged.completed} files completed, ${merged.incomplete} incomplete, ${merged.waiting} waiting.`)
|
||||
}
|
||||
await prefetcher.tick()
|
||||
} catch (error: any) {
|
||||
this.logger.error(`Coordinator round failed: ${error.message}`)
|
||||
|
||||
Reference in new issue
Block a user