dsfsdf
This commit is contained in:
@@ -19,6 +19,10 @@ use PDO;
|
|||||||
|
|
||||||
final class Router
|
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 string $moduleBasePath;
|
||||||
private ModuleConfig $config;
|
private ModuleConfig $config;
|
||||||
private ?PDO $pdo = null;
|
private ?PDO $pdo = null;
|
||||||
@@ -61,6 +65,7 @@ final class Router
|
|||||||
public function handle(string $relativePath): never
|
public function handle(string $relativePath): never
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->configureRuntimeGuards();
|
||||||
$this->releaseSessionLock();
|
$this->releaseSessionLock();
|
||||||
$method = strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET'));
|
$method = strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET'));
|
||||||
$path = trim($relativePath, '/');
|
$path = trim($relativePath, '/');
|
||||||
@@ -315,10 +320,10 @@ final class Router
|
|||||||
'purchased_miners' => [],
|
'purchased_miners' => [],
|
||||||
'measurement_rates' => [],
|
'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), []);
|
$targets = $this->safeRead(fn () => $this->targets($projectKey), []);
|
||||||
$dashboards = $this->safeRead(fn () => $this->dashboards($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), [
|
$summary = $this->safeRead(fn () => $this->analytics()->buildSummary($measurements, $settings, $targets), [
|
||||||
'latest_measurement' => $measurements !== [] ? $measurements[array_key_last($measurements)] : null,
|
'latest_measurement' => $measurements !== [] ? $measurements[array_key_last($measurements)] : null,
|
||||||
'baseline' => $settings,
|
'baseline' => $settings,
|
||||||
@@ -326,6 +331,7 @@ final class Router
|
|||||||
'payouts' => [],
|
'payouts' => [],
|
||||||
'miner_offers' => [],
|
'miner_offers' => [],
|
||||||
]);
|
]);
|
||||||
|
$measurementCount = is_array($measurements) ? count($measurements) : 0;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'project' => $this->repository()->getProject($projectKey),
|
'project' => $this->repository()->getProject($projectKey),
|
||||||
@@ -336,7 +342,10 @@ final class Router
|
|||||||
'fx_snapshots' => $fxSnapshots,
|
'fx_snapshots' => $fxSnapshots,
|
||||||
'summary' => $summary,
|
'summary' => $summary,
|
||||||
'bootstrap_meta' => [
|
'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),
|
'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);
|
throw new ApiException('Das Modul fx-rates ist nicht verfuegbar.', 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$startedAt = microtime(true);
|
||||||
module_fn('fx-rates', 'ensure_schema');
|
module_fn('fx-rates', 'ensure_schema');
|
||||||
$legacyRows = $this->repository()->listAllFxRates();
|
$legacyRows = $this->repository()->listAllFxRates();
|
||||||
$legacyFetches = $this->groupLegacyFxFetches($legacyRows);
|
$legacyFetches = $this->groupLegacyFxFetches($legacyRows);
|
||||||
@@ -784,6 +794,7 @@ final class Router
|
|||||||
$migratedRates = 0;
|
$migratedRates = 0;
|
||||||
|
|
||||||
foreach ($legacyFetches as $legacyFetchId => $legacyFetch) {
|
foreach ($legacyFetches as $legacyFetchId => $legacyFetch) {
|
||||||
|
$this->assertRequestWithinBudget($startedAt, 'Legacy-FX-Migration dauert zu lange.');
|
||||||
$existing = $this->findExistingFxFetchForLegacy($fxRepository, $legacyFetch);
|
$existing = $this->findExistingFxFetchForLegacy($fxRepository, $legacyFetch);
|
||||||
if (is_array($existing) && !empty($existing['id'])) {
|
if (is_array($existing) && !empty($existing['id'])) {
|
||||||
$fetchIdMap[$legacyFetchId] = (int) $existing['id'];
|
$fetchIdMap[$legacyFetchId] = (int) $existing['id'];
|
||||||
@@ -817,6 +828,7 @@ final class Router
|
|||||||
$unresolvedMeasurements = 0;
|
$unresolvedMeasurements = 0;
|
||||||
|
|
||||||
foreach ($measurements as $measurement) {
|
foreach ($measurements as $measurement) {
|
||||||
|
$this->assertRequestWithinBudget($startedAt, 'Legacy-FX-Migration dauert zu lange.');
|
||||||
$measurementId = is_numeric($measurement['id'] ?? null) ? (int) $measurement['id'] : 0;
|
$measurementId = is_numeric($measurement['id'] ?? null) ? (int) $measurement['id'] : 0;
|
||||||
if ($measurementId <= 0) {
|
if ($measurementId <= 0) {
|
||||||
continue;
|
continue;
|
||||||
@@ -1133,6 +1145,12 @@ final class Router
|
|||||||
return $this->analytics()->enrichMeasurements($rows, $settings);
|
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
|
private function createMeasurement(string $projectKey, array $input): array
|
||||||
{
|
{
|
||||||
$projectTimezone = $this->projectTimezone($projectKey);
|
$projectTimezone = $this->projectTimezone($projectKey);
|
||||||
@@ -1981,10 +1999,15 @@ final class Router
|
|||||||
return $resolved;
|
return $resolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function measurementFxSnapshots(array $measurements): array
|
private function measurementFxSnapshots(array $measurements, ?int $limit = null): array
|
||||||
{
|
{
|
||||||
$snapshots = [];
|
$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;
|
$fetchId = is_numeric($measurement['fx_fetch_id'] ?? null) ? (int) $measurement['fx_fetch_id'] : 0;
|
||||||
if ($fetchId <= 0 || isset($snapshots[$fetchId])) {
|
if ($fetchId <= 0 || isset($snapshots[$fetchId])) {
|
||||||
continue;
|
continue;
|
||||||
@@ -2114,6 +2137,16 @@ final class Router
|
|||||||
Http::json($payload, $statusCode);
|
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
|
private function releaseSessionLock(): void
|
||||||
{
|
{
|
||||||
if (PHP_SAPI === 'cli') {
|
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
|
private function debugLatest(): array
|
||||||
{
|
{
|
||||||
$filePath = DebugState::latestFilePath();
|
$filePath = DebugState::latestFilePath();
|
||||||
|
|||||||
Reference in New Issue
Block a user