Files
usenet-indexer/start/routes.ts
T
Daan MeijerandClaude Fable 5.1 1f6e3316ec
Test and deploy / test (push) Successful in 55s
Test and deploy / edge (push) Successful in 2m9s
Test and deploy / deploy (push) Successful in 1m16s
The window worker: group leases, the stream serving the corpus, the snapshot through the API (design 1 and 5)
A worker thread leases a group and takes its ranges in article order through
one carried window; the coordinator keeps one cursor a group (group_leases,
migration 6500) and hands out the next range, the rules and nothing about
where the chunks are: the range stream serves a stored range's chunks from the
corpus file and a live one's from the spool. The window's snapshot (bincode:
the frontier, the open files, releases and albums, the upload numbers, the
batch-counter table) goes to the coordinator every EDGE_SNAPSHOT_MINUTES and
when the group is given back, and the next holder restores it; a takeover
after LEASE_TTL_SECONDS plans the ranges from the snapshot's article again.
The prefetcher runs ahead of held groups' cursors and skips chunks the corpus
has. LEASE_MIN_PRIORITY..LEASE_MAX_PRIORITY bound what is leased. edge-node
holds groups by default; --ranges keeps the old per-range path.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-26 18:22:18 +01:00

86 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
|--------------------------------------------------------------------------
| Routes file
|--------------------------------------------------------------------------
|
| The routes file is used for defining the HTTP routes.
|
*/
import { middleware } from '#start/kernel'
import router from '@adonisjs/core/services/router'
import { controllers } from '#generated/controllers'
import env from '#start/env'
/**
* Which routes this process serves (HTTP_ROUTES): `node`, the edge workers'
* API only (its own service: hour-long streams and batches of up to 256 MB
* parsed in-process don't hold up the web interface; LOG.md 2026-10-11 (3));
* `public`, everything else; `all` (the default, for development and tests).
*/
const routes = env.get('HTTP_ROUTES', 'all')
const publicRoutes = routes !== 'node'
const nodeRoutes = routes !== 'public'
router.get('/health', () => ({ ok: true, routes }))
if (publicRoutes) {
// The web interface is public/index.html (static middleware).
// Newznab API for Prowlarr, Sonarr, Radarr (from voyager 1).
router.get('/api', [controllers.Newznab, 'handle'])
}
router
.group(() => {
if (publicRoutes) {
router
.group(() => {
router.post('signup', [controllers.NewAccount, 'store'])
router.post('login', [controllers.AccessTokens, 'store'])
})
.prefix('auth')
.as('auth')
router
.group(() => {
router.get('profile', [controllers.Profile, 'show'])
router.post('logout', [controllers.AccessTokens, 'destroy'])
})
.prefix('account')
.as('profile')
.use(middleware.auth())
// The catalog (REBUILD.md, part 9): open, as voyager 1's (the web interface uses it); Newznab has its key.
router.get('releases', [controllers.Releases, 'index'])
router.get('releases/:id', [controllers.Releases, 'show']).where('id', router.matchers.number())
router.get('releases/:id/nzb', [controllers.Releases, 'nzb']).where('id', router.matchers.number())
router.get('stats', [controllers.Releases, 'stats'])
}
if (nodeRoutes) {
// Edge workers (REBUILD.md, parts 1–2).
router
.group(() => {
router.post('lease', [controllers.Node, 'lease'])
// Group leases (REBUILD.md, "Voyager 3: window indexing", 1 and 5): the window worker's.
router.post('groups/lease', [controllers.Node, 'leaseGroup'])
router.post('groups/:id/next', [controllers.Node, 'nextRange'])
router.post('groups/:id/heartbeat', [controllers.Node, 'groupHeartbeat'])
router.post('groups/:id/release', [controllers.Node, 'releaseGroup'])
router.put('groups/:id/snapshot', [controllers.Node, 'putSnapshot'])
router.get('groups/:id/snapshot', [controllers.Node, 'getSnapshot'])
router.get('ranges/:id/stream', [controllers.Node, 'stream'])
router.post('ranges/:id/batches', [controllers.Node, 'batch'])
router.post('ranges/:id/heartbeat', [controllers.Node, 'heartbeat'])
router.post('ranges/:id/finish', [controllers.Node, 'finish'])
router.post('ranges/:id/release', [controllers.Node, 'release'])
router.post('ranges/:id/corrupt', [controllers.Node, 'corrupt'])
})
.prefix('node')
.as('node')
.use(middleware.auth({ guards: ['node'] }))
}
})
.prefix('/api/v1')