dsfsdf
All checks were successful
Deploy / deploy-staging (push) Successful in 5s
Deploy / deploy-production (push) Has been skipped

This commit is contained in:
2026-05-02 01:38:39 +02:00
parent 7ad4b45d22
commit f920991015

View File

@@ -19,6 +19,10 @@ use PDO;
final class Router
{
private const BOOTSTRAP_MEASUREMENT_LIMIT = 150;
private const BOOTSTRAP_SNAPSHOT_LIMIT = 40;
private const LONG_REQUEST_BUDGET_SECONDS = 8.0;
private string $moduleBasePath;
private ModuleConfig $config;
private ?PDO $pdo = null;
@@ -61,6 +65,7 @@ final class Router
public function handle(string $relativePath): never
{
try {
$this->configureRuntimeGuards();
$this->releaseSessionLock();
$method = strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET'));
$path = trim($relativePath, '/');
@@ -315,10 +320,10 @@ final class Router
'purchased_miners' => [],
'measurement_rates' => [],
]);
$measurements = $this->safeRead(fn () => $this->measurements($projectKey, $settings, false), []);
$measurements = $this->safeRead(fn () => $this->bootstrapMeasurements($projectKey, $settings), []);
$targets = $this->safeRead(fn () => $this->targets($projectKey), []);
$dashboards = $this->safeRead(fn () => $this->dashboards($projectKey), []);
$fxSnapshots = $this->safeRead(fn () => $this->measurementFxSnapshots($measurements), []);
$fxSnapshots = $this->safeRead(fn () => $this->measurementFxSnapshots($measurements, self::BOOTSTRAP_SNAPSHOT_LIMIT), []);
$summary = $this->safeRead(fn () => $this->analytics()->buildSummary($measurements, $settings, $targets), [
'latest_measurement' => $measurements !== [] ? $measurements[array_key_last($measurements)] : null,
'baseline' => $settings,
@@ -326,6 +331,7 @@ final class Router
'payouts' => [],
'miner_offers' => [],
]);
$measurementCount = is_array($measurements) ? count($measurements) : 0;
return [
'project' => $this->repository()->getProject($projectKey),
@@ -336,7 +342,10 @@ final class Router
'fx_snapshots' => $fxSnapshots,
'summary' => $summary,
'bootstrap_meta' => [
'degraded' => false,
'degraded' => $measurementCount >= self::BOOTSTRAP_MEASUREMENT_LIMIT,
'measurement_limit' => self::BOOTSTRAP_MEASUREMENT_LIMIT,
'snapshot_limit' => self::BOOTSTRAP_SNAPSHOT_LIMIT,
'measurement_count' => $measurementCount,
'duration_ms' => round((microtime(true) - $startedAt) * 1000, 2),
],
];
@@ -773,6 +782,7 @@ final class Router
throw new ApiException('Das Modul fx-rates ist nicht verfuegbar.', 422);
}
$startedAt = microtime(true);
module_fn('fx-rates', 'ensure_schema');
$legacyRows = $this->repository()->listAllFxRates();
$legacyFetches = $this->groupLegacyFxFetches($legacyRows);
@@ -784,6 +794,7 @@ final class Router
$migratedRates = 0;
foreach ($legacyFetches as $legacyFetchId => $legacyFetch) {
$this->assertRequestWithinBudget($startedAt, 'Legacy-FX-Migration dauert zu lange.');
$existing = $this->findExistingFxFetchForLegacy($fxRepository, $legacyFetch);
if (is_array($existing) && !empty($existing['id'])) {
$fetchIdMap[$legacyFetchId] = (int) $existing['id'];
@@ -817,6 +828,7 @@ final class Router
$unresolvedMeasurements = 0;
foreach ($measurements as $measurement) {
$this->assertRequestWithinBudget($startedAt, 'Legacy-FX-Migration dauert zu lange.');
$measurementId = is_numeric($measurement['id'] ?? null) ? (int) $measurement['id'] : 0;
if ($measurementId <= 0) {
continue;
@@ -1133,6 +1145,12 @@ final class Router
return $this->analytics()->enrichMeasurements($rows, $settings);
}
private function bootstrapMeasurements(string $projectKey, array $settings): array
{
$rows = $this->repository()->listMeasurements($projectKey, self::BOOTSTRAP_MEASUREMENT_LIMIT);
return $this->analytics()->enrichMeasurements($rows, $settings);
}
private function createMeasurement(string $projectKey, array $input): array
{
$projectTimezone = $this->projectTimezone($projectKey);
@@ -1981,10 +1999,15 @@ final class Router
return $resolved;
}
private function measurementFxSnapshots(array $measurements): array
private function measurementFxSnapshots(array $measurements, ?int $limit = null): array
{
$snapshots = [];
foreach ($measurements as $measurement) {
$measurementPool = $measurements;
if ($limit !== null && $limit > 0 && count($measurementPool) > $limit) {
$measurementPool = array_slice($measurementPool, -$limit);
}
foreach ($measurementPool as $measurement) {
$fetchId = is_numeric($measurement['fx_fetch_id'] ?? null) ? (int) $measurement['fx_fetch_id'] : 0;
if ($fetchId <= 0 || isset($snapshots[$fetchId])) {
continue;
@@ -2114,6 +2137,16 @@ final class Router
Http::json($payload, $statusCode);
}
private function configureRuntimeGuards(): void
{
if (function_exists('ignore_user_abort')) {
@ignore_user_abort(false);
}
if (function_exists('set_time_limit')) {
@set_time_limit(15);
}
}
private function releaseSessionLock(): void
{
if (PHP_SAPI === 'cli') {
@@ -2125,6 +2158,13 @@ final class Router
}
}
private function assertRequestWithinBudget(float $startedAt, string $message): void
{
if ((microtime(true) - $startedAt) > self::LONG_REQUEST_BUDGET_SECONDS) {
throw new ApiException($message, 503, ['timeout' => true]);
}
}
private function debugLatest(): array
{
$filePath = DebugState::latestFilePath();