feat: ATM10-Statistikportal
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>
This commit is contained in:
1 parent
56d2078e6a
commit
e66f89f49e
214 files changed
+27077
No files matched your search
@@ -0,0 +1,36 @@
|
||||
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' }]);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user