Statistikportal für den All-the-Mods-10-Server (Minecraft 1.21.1, NeoForge 21.1): - mod/: serverseitige NeoForge-Mod atmstats – Ereignisse, Live-Zähler, Servergesundheit, FTB-Dateien; Outbox auf der Festplatte, signierter gzip-Versand per HTTPS mit Backoff - backend/: Fastify + PostgreSQL – idempotenter Ingest, Projektionen, Parser für SNBT, FTB Quests/Teams, world/stats, world/advancements und latest.log; Ranglisten, Snapshots, Retention, öffentliche API, SSE-Live-Updates, Admin mit argon2/CSRF, SFTP-Worker - web/: Next.js-Dashboard – Übersicht, Ranglisten, Spielerprofile, ATM10, Server, Datenquellen, Verwaltung - shared/: Protokoll v1 und API-Typen; tools/: Simulator, Log-Anonymisierer, RCON-Client - deploy/: Docker Compose hinter Traefik, Backup; docs/: Architektur, Datenquellen, Betrieb Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
37 lines
1.2 KiB
TypeScript
37 lines
1.2 KiB
TypeScript
import type { Pool } from 'pg';
|
|
import { afterAll, beforeEach, describe, expect, it } from 'vitest';
|
|
import { runJob } from '../src/worker/scheduler.ts';
|
|
import { closeTestPool, getTestPool, resetDb } from './helpers/db.ts';
|
|
|
|
let pool: Pool;
|
|
beforeEach(async () => {
|
|
pool = await getTestPool();
|
|
await resetDb(pool);
|
|
});
|
|
afterAll(closeTestPool);
|
|
|
|
describe('runJob', () => {
|
|
it('never runs the same job twice concurrently', async () => {
|
|
let running = 0;
|
|
let maxRunning = 0;
|
|
const job = async () => {
|
|
running++;
|
|
maxRunning = Math.max(maxRunning, running);
|
|
await new Promise((r) => setTimeout(r, 200));
|
|
running--;
|
|
};
|
|
const results = await Promise.all([runJob(pool, 'x', 900_001, job), runJob(pool, 'x', 900_001, job)]);
|
|
expect(maxRunning).toBe(1);
|
|
expect(results.sort()).toEqual(['locked', 'ok']);
|
|
});
|
|
|
|
it('records failures in app_errors', async () => {
|
|
const r = await runJob(pool, 'sftp', 900_002, async () => {
|
|
throw new Error('connection refused');
|
|
});
|
|
expect(r).toBe('error');
|
|
const { rows } = await pool.query('SELECT source, message FROM app_errors');
|
|
expect(rows).toEqual([{ source: 'sftp', message: 'connection refused' }]);
|
|
});
|
|
});
|