191 lines
8.1 KiB
PHP
191 lines
8.1 KiB
PHP
<?php
|
|
// Cache warm-up script.
|
|
// Run via CLI: php warm_cache.php
|
|
// Run via cron: every 30 min: php /path/to/warm_cache.php
|
|
// Run via HTTP: http://localhost:8000/public/userarea/warm_cache.php (requires auth)
|
|
|
|
$startTime = microtime(true);
|
|
$isCli = (php_sapi_name() === 'cli');
|
|
$isStream = (!$isCli && isset($_GET['stream']));
|
|
|
|
// Analisi incluse? Default SÌ (il cron non passa il parametro → fa tutto).
|
|
// Solo una richiesta HTTP con analisi=0 le salta.
|
|
$includeAnalisi = !(!$isCli && isset($_GET['analisi']) && $_GET['analisi'] === '0');
|
|
|
|
if (!$isCli) {
|
|
// When called via HTTP, require auth
|
|
include('include/headscript.php');
|
|
if (!Auth::check()) {
|
|
http_response_code(403);
|
|
echo json_encode(['error' => 'Unauthorized']);
|
|
exit;
|
|
}
|
|
|
|
if ($isStream) {
|
|
// Streaming mode: send progress line-by-line (Server-Sent Events)
|
|
set_time_limit(0);
|
|
header('Content-Type: text/event-stream');
|
|
header('Cache-Control: no-cache');
|
|
header('X-Accel-Buffering: no'); // disable nginx buffering
|
|
while (ob_get_level() > 0) ob_end_flush();
|
|
} else {
|
|
header('Content-Type: application/json');
|
|
}
|
|
}
|
|
|
|
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
|
require_once __DIR__ . '/class/VisualLimsApiClient.class.php';
|
|
require_once __DIR__ . '/class/db-functions.php';
|
|
|
|
$cacheDir = __DIR__ . '/cache';
|
|
if (!is_dir($cacheDir)) mkdir($cacheDir, 0755, true);
|
|
|
|
$log = [];
|
|
|
|
// Prevent two runs at the same time (e.g. cron + manual click)
|
|
$lockHandle = fopen($cacheDir . '/.warm.lock', 'w');
|
|
if ($lockHandle === false || !flock($lockHandle, LOCK_EX | LOCK_NB)) {
|
|
$busyMsg = 'Un aggiornamento è già in corso in questo momento. Riprova tra poco.';
|
|
if ($isCli) {
|
|
echo $busyMsg . PHP_EOL;
|
|
} elseif ($isStream) {
|
|
header('Content-Type: text/event-stream');
|
|
echo "event: busy\ndata: " . $busyMsg . "\n\n";
|
|
@flush();
|
|
} else {
|
|
echo json_encode(['success' => false, 'busy' => true, 'message' => $busyMsg]);
|
|
}
|
|
exit;
|
|
}
|
|
|
|
function warmLog(string $msg, bool $isCli)
|
|
{
|
|
global $log, $isStream;
|
|
$line = date('H:i:s') . " $msg";
|
|
$log[] = $line;
|
|
if ($isCli) {
|
|
echo $line . PHP_EOL;
|
|
} elseif (!empty($isStream)) {
|
|
echo "data: " . str_replace("\n", ' ', $line) . "\n\n";
|
|
@ob_flush();
|
|
@flush();
|
|
}
|
|
}
|
|
|
|
try {
|
|
$api = VisualLimsApiClient::getInstance();
|
|
$pdo = DBHandlerSelect::getInstance()->getConnection();
|
|
|
|
// 1. Clients
|
|
warmLog('[clients] Fetching...', $isCli);
|
|
$params = ['$select' => 'IdCliente,Nominativo,CodiceCliente,Inattivo', '$orderby' => 'Nominativo asc'];
|
|
$clientData = $api->get("Cliente?" . http_build_query($params));
|
|
file_put_contents($cacheDir . '/clienti.json', json_encode($clientData));
|
|
$clientCount = count($clientData['value'] ?? []);
|
|
warmLog("[clients] Cached $clientCount clients", $isCli);
|
|
|
|
// 2. Fixed fields: MoltiplicatorePrezzo, AnagraficaCertestObject, AnagraficaCertestService
|
|
$fixedFields = [
|
|
'MoltiplicatorePrezzo' => ['endpoint' => 'MoltiplicatorePrezzi', 'file' => 'moltiplicatori_prezzo.json'],
|
|
'AnagraficaCertestObject' => ['endpoint' => 'AnagraficaCertestObject', 'file' => 'anagrafica_certest_object.json'],
|
|
'AnagraficaCertestService' => ['endpoint' => 'AnagraficaCertestService', 'file' => 'anagrafica_certest_service.json'],
|
|
];
|
|
|
|
foreach ($fixedFields as $name => $cfg) {
|
|
warmLog("[$name] Fetching...", $isCli);
|
|
$data = $api->get($cfg['endpoint']);
|
|
file_put_contents($cacheDir . '/' . $cfg['file'], json_encode($data, JSON_PRETTY_PRINT));
|
|
$count = count($data['value'] ?? $data ?? []);
|
|
warmLog("[$name] Cached $count items", $isCli);
|
|
}
|
|
|
|
// 3. ClienteResponsabile — for each unique client in datadb
|
|
$stmt = $pdo->query("SELECT DISTINCT idclient FROM datadb WHERE idclient IS NOT NULL AND idclient > 0 ORDER BY idclient ASC");
|
|
$clientIds = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
|
warmLog("[ClienteResponsabile] Fetching for " . count($clientIds) . " clients...", $isCli);
|
|
|
|
foreach ($clientIds as $cid) {
|
|
$cid = (int)$cid;
|
|
$endpoint = "Cliente($cid)?\$expand=Responsabili";
|
|
$cacheFile = $cacheDir . '/cliente_responsabili_' . $cid . '.json';
|
|
try {
|
|
$data = $api->get($endpoint);
|
|
file_put_contents($cacheFile, json_encode($data, JSON_PRETTY_PRINT));
|
|
$count = count($data['Responsabili'] ?? []);
|
|
warmLog("[ClienteResponsabile] Client $cid: $count responsabili", $isCli);
|
|
} catch (Exception $e) {
|
|
warmLog("[ClienteResponsabile] Client $cid: ERROR " . $e->getMessage(), $isCli);
|
|
}
|
|
}
|
|
|
|
// 4. CustomField values — all SceltaMultipla field_ids from template_mapping
|
|
$stmt = $pdo->query("SELECT DISTINCT field_id FROM template_mapping WHERE data_type = 'SceltaMultipla' AND is_visible_import = 1 AND field_id IS NOT NULL ORDER BY field_id");
|
|
$fieldIds = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
|
warmLog("[CustomFields] Fetching " . count($fieldIds) . " fields...", $isCli);
|
|
|
|
foreach ($fieldIds as $fid) {
|
|
$fid = (int)$fid;
|
|
$cacheFile = $cacheDir . '/customfield_' . $fid . '.json';
|
|
try {
|
|
$endpoint = "CustomField($fid)?\$expand=CustomFieldsValues";
|
|
$data = $api->get($endpoint);
|
|
$values = $data['CustomFieldsValues'] ?? [];
|
|
file_put_contents($cacheFile, json_encode($values));
|
|
warmLog("[CustomField $fid] Cached " . count($values) . " values", $isCli);
|
|
} catch (Exception $e) {
|
|
warmLog("[CustomField $fid] ERROR " . $e->getMessage(), $isCli);
|
|
}
|
|
}
|
|
|
|
// 5. Matrici (from LIMS API)
|
|
warmLog('[matrici] Fetching from API...', $isCli);
|
|
$matriciData = $api->get('Matrice');
|
|
$matrici = [];
|
|
foreach (($matriciData['value'] ?? []) as $item) {
|
|
$nome = $item['NomeMatrice'] ?? '';
|
|
if ($nome !== '' && substr($nome, 0, 1) !== '*') {
|
|
$matrici[] = ['IdMatrice' => $item['IdMatrice'], 'NomeMatrice' => $nome, 'MacroMatrice' => $item['MacroMatrice'] ?? null];
|
|
}
|
|
}
|
|
usort($matrici, fn($a, $b) => strcasecmp($a['NomeMatrice'], $b['NomeMatrice']));
|
|
file_put_contents($cacheDir . '/matrici.json', json_encode(['success' => true, 'value' => $matrici]));
|
|
warmLog("[matrici] Cached " . count($matrici) . " items", $isCli);
|
|
|
|
// 6. Analisi — only for matrici actually used by parts (warming all ~2500 matrici
|
|
// would mean one API call each; the used set is a few dozen).
|
|
if (!$includeAnalisi) {
|
|
warmLog('[analisi] Saltate su richiesta.', $isCli);
|
|
} else {
|
|
$stmt = $pdo->query("SELECT DISTINCT idmatrice FROM identification_parts WHERE idmatrice IS NOT NULL AND idmatrice > 0 ORDER BY idmatrice ASC");
|
|
$matriceIds = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
|
warmLog("[analisi] Fetching for " . count($matriceIds) . " matrici in use...", $isCli);
|
|
|
|
foreach ($matriceIds as $mid) {
|
|
$mid = (int)$mid;
|
|
// Same query as get_analisi_matrice_filter.php with web_only=1 (what the analysis modal requests)
|
|
$filter = rawurlencode("Matrice/IdMatrice eq $mid and SelezionabileSuWeb eq true");
|
|
try {
|
|
$data = $api->get("Analisi?\$filter={$filter}");
|
|
$values = $data['value'] ?? [];
|
|
file_put_contents($cacheDir . '/analisi_matrice_' . $mid . '.json', json_encode(['value' => $values]));
|
|
warmLog("[analisi] Matrice $mid: " . count($values) . " analisi", $isCli);
|
|
} catch (Exception $e) {
|
|
warmLog("[analisi] Matrice $mid: ERROR " . $e->getMessage(), $isCli);
|
|
}
|
|
}
|
|
} // fine if includeAnalisi
|
|
|
|
$elapsed = round(microtime(true) - $startTime, 1);
|
|
warmLog("Aggiornamento completato in {$elapsed}s", $isCli);
|
|
} catch (Exception $e) {
|
|
$elapsed = round(microtime(true) - $startTime, 1);
|
|
warmLog("ERRORE: " . $e->getMessage(), $isCli);
|
|
}
|
|
|
|
if ($isStream) {
|
|
echo "event: done\ndata: " . json_encode(['elapsed' => $elapsed ?? 0]) . "\n\n";
|
|
@flush();
|
|
} elseif (!$isCli) {
|
|
echo json_encode(['success' => true, 'log' => $log]);
|
|
}
|