Initial web
This commit is contained in:
71
web/app/api/ingest/[combinator]/route.ts
Normal file
71
web/app/api/ingest/[combinator]/route.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import pool from '@/lib/db';
|
||||
import { withAuth } from '@/lib/apiHelpers';
|
||||
|
||||
interface CircuitNetwork {
|
||||
green: Record<string, number>;
|
||||
red: Record<string, number>;
|
||||
}
|
||||
|
||||
interface IngestBody {
|
||||
game_tick: number;
|
||||
circuit_network: CircuitNetwork;
|
||||
logistic_network: Record<string, number>;
|
||||
}
|
||||
|
||||
export const POST = withAuth(async (req: NextRequest, { params }) => {
|
||||
const { combinator } = await params;
|
||||
|
||||
const mtimeHeader = req.headers.get('x-file-mtime');
|
||||
const realTime = mtimeHeader ? new Date(parseInt(mtimeHeader, 10)) : new Date();
|
||||
|
||||
let body: IngestBody;
|
||||
try {
|
||||
body = await req.json();
|
||||
} catch {
|
||||
return NextResponse.json({ error: 'Invalid JSON' }, { status: 400 });
|
||||
}
|
||||
|
||||
const { game_tick, circuit_network, logistic_network } = body;
|
||||
if (typeof game_tick !== 'number') {
|
||||
return NextResponse.json({ error: 'Missing game_tick' }, { status: 400 });
|
||||
}
|
||||
|
||||
const green = circuit_network?.green ?? {};
|
||||
const red = circuit_network?.red ?? {};
|
||||
const logistic = logistic_network ?? {};
|
||||
const allKeys = new Set([...Object.keys(green), ...Object.keys(red), ...Object.keys(logistic)]);
|
||||
|
||||
if (allKeys.size === 0) return NextResponse.json({ ok: true, rows: 0 });
|
||||
|
||||
const client = await pool.connect();
|
||||
try {
|
||||
await client.query('BEGIN');
|
||||
|
||||
const values: unknown[] = [];
|
||||
const placeholders: string[] = [];
|
||||
let idx = 1;
|
||||
for (const key of allKeys) {
|
||||
placeholders.push(`($${idx++},$${idx++},$${idx++},$${idx++},$${idx++},$${idx++},$${idx++})`);
|
||||
values.push(realTime, game_tick, combinator, key, green[key] ?? 0, red[key] ?? 0, logistic[key] ?? null);
|
||||
}
|
||||
|
||||
await client.query(
|
||||
`INSERT INTO signals (real_time, game_tick, combinator, item_key, green, red, logistic)
|
||||
VALUES ${placeholders.join(', ')}`,
|
||||
values,
|
||||
);
|
||||
await client.query(
|
||||
`INSERT INTO tick_timing (real_time, game_tick, combinator) VALUES ($1,$2,$3)`,
|
||||
[realTime, game_tick, combinator],
|
||||
);
|
||||
|
||||
await client.query('COMMIT');
|
||||
return NextResponse.json({ ok: true, rows: allKeys.size });
|
||||
} catch (err) {
|
||||
await client.query('ROLLBACK');
|
||||
throw err; // re-throw — withAuth handler catches and returns 500
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user