mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: add worker threads, persistent Python sidecar, graceful shutdown, and architectural improvements
- Graceful shutdown: SIGTERM/SIGINT handlers drain HTTP, stop workers, close DB - Thumbnail caching: disk-cached thumbnails with immutable Cache-Control headers - Worker thread pool: Piscina offloads Sharp processing off the main event loop - Persistent Python dispatcher: pre-imports ML libraries, eliminates cold-start latency - Tool page registry: declarative tool-to-component mapping replaces 750-line switch - File store cleanup: remove dead derived fields, stable files array reference - Job persistence: progress written to SQLite jobs table, stale jobs recovered on startup
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Worker pool for offloading CPU-bound image processing from the main event loop.
|
||||
*
|
||||
* Uses Piscina (backed by worker_threads) so Sharp operations don't block
|
||||
* HTTP request handling, SSE streams, or health checks.
|
||||
*/
|
||||
import { availableParallelism } from "node:os";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import Piscina from "piscina";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
// Size the pool: leave 1 thread for the event loop, min 1 worker
|
||||
const maxThreads = Math.max(1, Math.min(availableParallelism() - 1, 4));
|
||||
|
||||
let pool: Piscina | null = null;
|
||||
|
||||
export function getWorkerPool(): Piscina {
|
||||
if (!pool) {
|
||||
pool = new Piscina({
|
||||
filename: resolve(__dirname, "image-worker.ts"),
|
||||
// Inherit tsx loader flags from the main process so .ts files work in workers
|
||||
execArgv: [...process.execArgv],
|
||||
maxThreads,
|
||||
idleTimeout: 30000,
|
||||
});
|
||||
}
|
||||
return pool;
|
||||
}
|
||||
|
||||
export async function shutdownWorkerPool(): Promise<void> {
|
||||
if (pool) {
|
||||
await pool.destroy();
|
||||
pool = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user