mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
e453618463
Introduce BookDockWorkQueue to serialize metadata extraction and auto-finalize jobs. Files process newest-first with a 250 ms drain window and 500-1000 ms inter-job spacing to avoid hammering metadata providers. Watched-folder rescans now requeue files stuck in extracting or fetching status after a server restart rather than silently dropping them. Replace the global ThrottlerGuard with SensitiveEndpointThrottlerGuard, which only activates on endpoints that carry explicit @Throttle() metadata. This eliminates all @SkipThrottle() decorators from non-auth controllers and adds missing throttle coverage for oidcGenerateLinkState and oidcGeneratePreviewState. Update the login page to match the simplified 429 error message. Fix countsByStatus to aggregate extracting and fetching rows into the pending bucket so the UI counter stays accurate mid-pipeline. Add a secondary id sort to findAll for deterministic pagination ordering. Auto-detect the container memory limit via cgroup v1/v2 in entrypoint.sh and compute --max-old-space-size proportionally (50-75 % of limit) instead of defaulting to a fixed 2048 MB that OOMs small containers. Closes #441
BookOrbit - Server
NestJS 11 backend running on Fastify.
Running
From the repo root: pnpm dev (starts both server and client).
Server only: pnpm start:dev (from this directory).
The server loads environment variables from .env in this directory. See .env.example for all available options.
Module structure
Each feature is a self-contained NestJS module under src/modules/:
src/modules/
├── auth/ Authentication (JWT, OIDC, password reset)
├── book/ Book CRUD, cover images, file serving
├── library/ Library management
├── scanner/ File system scanning, metadata extraction
├── collection/ User book collections
├── smart-scope/ Saved search/filter views
├── user/ User management
├── role/ Roles and permissions (RBAC)
├── metadata/ Book metadata providers
├── kobo/ Kobo device sync
├── annotation/ Highlights and annotations
├── bookmark/ Reading position bookmarks
├── reader-preferences/ Per-user reader settings
├── cbz/ CBZ archive handling
├── path/ File path utilities
├── seed/ Database seeding
└── app-settings/ Global application settings
Database
Schema files live in src/db/schema/, one per domain. Migrations are generated by Drizzle Kit.
pnpm db:generate add_some_column # generate migration from schema diff
pnpm db:migrate # apply pending migrations
pnpm db:studio # open Drizzle Studio (DB browser)
Testing
pnpm test # unit tests
pnpm test:watch # unit tests in watch mode
pnpm e2e:run # app-smoke end-to-end test from server package
pnpm test:cov # unit tests with coverage
For suite-based e2e runs, run from the repository root:
pnpm run e2e:list
pnpm run e2e:all
pnpm run e2e:run -- scanner-scenarios
Quality
pnpm type-check # TypeScript checks (no emit)
pnpm lint:check # Non-mutating lint checks
pnpm lint:fix # Auto-fix lint issues
pnpm format:check # Prettier check
pnpm format # Prettier write
Key conventions
- Constructor injection with
@Inject(DB)for the Drizzle instance. - Config via
@nestjs/confignamed configs (appConfig,dbConfig,authConfig,storageConfig,mailerConfig). Never readprocess.envdirectly in services. - DTOs use
class-validatordecorators. GlobalValidationPiperejects unknown fields. - Throw NestJS
HttpExceptionsubclasses (NotFoundException,ForbiddenException, etc.) - never rawError. - All user-owned data is scoped by
userId. Service methods check ownership.