Refactor auto ChronoTrack sync script to enhance logging and error handling. Remove local heartbeat logging and update cron execution feedback. Improve admin interface with clearer instructions and a new button for manual sync diagnostics. Implement auto-sync diagnostics to provide detailed status and logs for events, facilitating better monitoring and troubleshooting of synchronization processes.
This commit is contained in:
@ -2,10 +2,10 @@
|
|||||||
/**
|
/**
|
||||||
* MSIN-4328 — Cron sync auto ChronoTrack (différentiel).
|
* MSIN-4328 — Cron sync auto ChronoTrack (différentiel).
|
||||||
*
|
*
|
||||||
* Cron recommandé (toutes les minutes) — IMPORTANT : -k si certificat preprod invalide :
|
* Même pattern que auto_liste_attente.php :
|
||||||
* /usr/bin/curl -sk https://VOTRE-DOMAINE/auto_chronotrack_sync.php > /dev/null 2>&1
|
* /usr/bin/curl -s https://VOTRE-DOMAINE/auto_chronotrack_sync.php > /dev/null 2>&1
|
||||||
*
|
*
|
||||||
* Preuve d’exécution : fichier log/chronotrack_cron_last.txt (mtime = dernier appel).
|
* Minute=* Hour=* … → le script décide selon fréquence/fin de chaque event.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ini_set('display_errors', 0);
|
ini_set('display_errors', 0);
|
||||||
@ -14,33 +14,12 @@ ini_set('error_log', __DIR__ . '/log/php_log.txt');
|
|||||||
|
|
||||||
@set_time_limit(300);
|
@set_time_limit(300);
|
||||||
|
|
||||||
$strLogDir = __DIR__ . '/log';
|
|
||||||
if (!is_dir($strLogDir)) {
|
|
||||||
@mkdir($strLogDir, 0755, true);
|
|
||||||
}
|
|
||||||
$strHeartbeat = $strLogDir . '/chronotrack_cron_last.txt';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Écrit une preuve locale que le script a été appelé (cron ou navigateur).
|
|
||||||
*/
|
|
||||||
function fxChronotrackCronHeartbeat($strHeartbeat, $strLine) {
|
|
||||||
$strPayload = $strLine . "\n"
|
|
||||||
. 'host=' . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '') . "\n"
|
|
||||||
. 'remote=' . (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '') . "\n"
|
|
||||||
. 'ua=' . (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '') . "\n";
|
|
||||||
@file_put_contents($strHeartbeat, $strPayload, LOCK_EX);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Preuve immédiate (même si lock / erreur après)
|
|
||||||
fxChronotrackCronHeartbeat($strHeartbeat, 'HIT ' . date('Y-m-d H:i:s'));
|
|
||||||
|
|
||||||
$strLockPath = rtrim(sys_get_temp_dir(), '/\\') . DIRECTORY_SEPARATOR . 'ms1_chronotrack_auto_sync.lock';
|
$strLockPath = rtrim(sys_get_temp_dir(), '/\\') . DIRECTORY_SEPARATOR . 'ms1_chronotrack_auto_sync.lock';
|
||||||
$fpLock = @fopen($strLockPath, 'c');
|
$fpLock = @fopen($strLockPath, 'c');
|
||||||
if ($fpLock === false || !flock($fpLock, LOCK_EX | LOCK_NB)) {
|
if ($fpLock === false || !flock($fpLock, LOCK_EX | LOCK_NB)) {
|
||||||
if (is_resource($fpLock)) {
|
if (is_resource($fpLock)) {
|
||||||
fclose($fpLock);
|
fclose($fpLock);
|
||||||
}
|
}
|
||||||
fxChronotrackCronHeartbeat($strHeartbeat, 'BUSY ' . date('Y-m-d H:i:s'));
|
|
||||||
header('Content-Type: text/plain; charset=utf-8');
|
header('Content-Type: text/plain; charset=utf-8');
|
||||||
echo 'busy';
|
echo 'busy';
|
||||||
exit;
|
exit;
|
||||||
@ -55,15 +34,14 @@ try {
|
|||||||
$arrResult = fxChronotrackApiSyncRunAutoCron();
|
$arrResult = fxChronotrackApiSyncRunAutoCron();
|
||||||
$strLine = 'auto_chronotrack_sync [' . date('Y-m-d H:i:s') . '] '
|
$strLine = 'auto_chronotrack_sync [' . date('Y-m-d H:i:s') . '] '
|
||||||
. ($arrResult['message'] ?? 'done');
|
. ($arrResult['message'] ?? 'done');
|
||||||
|
// Même style que liste d’attente : une ligne dans log/php_log.txt
|
||||||
error_log($strLine);
|
error_log($strLine);
|
||||||
fxChronotrackCronHeartbeat($strHeartbeat, 'OK ' . $strLine);
|
|
||||||
|
|
||||||
header('Content-Type: text/plain; charset=utf-8');
|
header('Content-Type: text/plain; charset=utf-8');
|
||||||
echo $strLine . "\n";
|
echo $strLine . "\n";
|
||||||
} catch (Throwable $ex) {
|
} catch (Throwable $ex) {
|
||||||
$strErr = 'ERROR ' . date('Y-m-d H:i:s') . ' ' . $ex->getMessage();
|
$strErr = 'auto_chronotrack_sync ERROR [' . date('Y-m-d H:i:s') . '] ' . $ex->getMessage();
|
||||||
error_log('auto_chronotrack_sync ' . $strErr);
|
error_log($strErr);
|
||||||
fxChronotrackCronHeartbeat($strHeartbeat, $strErr);
|
|
||||||
header('Content-Type: text/plain; charset=utf-8');
|
header('Content-Type: text/plain; charset=utf-8');
|
||||||
echo $strErr . "\n";
|
echo $strErr . "\n";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -298,14 +298,23 @@ function fxChronotrackApiAdminRenderPushPanel($intEveId, $blnClosed = false, $ar
|
|||||||
echo '</div>';
|
echo '</div>';
|
||||||
echo '<p class="small text-muted mb-0 mt-2" id="ct_api_auto_hint">';
|
echo '<p class="small text-muted mb-0 mt-2" id="ct_api_auto_hint">';
|
||||||
if ($blnAutoOn && $strUntilRaw !== '') {
|
if ($blnAutoOn && $strUntilRaw !== '') {
|
||||||
echo 'Config enregistrée — cron <code>auto_chronotrack_sync.php</code> (toutes les minutes). Arrêt : '
|
echo 'Config enregistrée — cron <code>auto_chronotrack_sync.php</code> (comme liste d’attente). Arrêt : '
|
||||||
. fxChronotrackApiAdminEsc($strUntilRaw) . '.';
|
. fxChronotrackApiAdminEsc($strUntilRaw) . '.';
|
||||||
} else {
|
} else {
|
||||||
echo 'Cochez, choisissez fréquence + date/heure de fin, puis Enregistrer. '
|
echo 'Cochez, choisissez fréquence + date/heure de fin, puis Enregistrer.';
|
||||||
. 'Le cron serveur doit appeler <code>auto_chronotrack_sync.php</code> chaque minute.';
|
}
|
||||||
|
echo '</p>';
|
||||||
|
$strLastAuto = trim((string)($arrConfig['last_auto_run_at'] ?? ''));
|
||||||
|
echo '<p class="small mb-0 mt-1" id="ct_api_auto_last">';
|
||||||
|
echo '<strong>Dernier passage auto :</strong> ';
|
||||||
|
if ($strLastAuto !== '' && $strLastAuto !== '0000-00-00 00:00:00') {
|
||||||
|
echo fxChronotrackApiAdminEsc($strLastAuto);
|
||||||
|
} else {
|
||||||
|
echo '<span class="text-warning">jamais (le cron n’a pas encore poussé cet event)</span>';
|
||||||
}
|
}
|
||||||
echo '</p>';
|
echo '</p>';
|
||||||
echo '<div id="ct_api_auto_msg" class="small mt-1"></div>';
|
echo '<div id="ct_api_auto_msg" class="small mt-1"></div>';
|
||||||
|
echo '<div id="ct_api_auto_diag" class="small mt-2 text-muted"></div>';
|
||||||
echo '</div>';
|
echo '</div>';
|
||||||
|
|
||||||
// Zone employé : statut clair + actions
|
// Zone employé : statut clair + actions
|
||||||
@ -320,13 +329,13 @@ function fxChronotrackApiAdminRenderPushPanel($intEveId, $blnClosed = false, $ar
|
|||||||
echo '<i class="fa fa-cloud-upload" aria-hidden="true"></i> Envoyer vers ChronoTrack</button> ';
|
echo '<i class="fa fa-cloud-upload" aria-hidden="true"></i> Envoyer vers ChronoTrack</button> ';
|
||||||
echo '<button type="button" class="btn btn-outline-dark btn-sm" id="ct_api_btn_logs">';
|
echo '<button type="button" class="btn btn-outline-dark btn-sm" id="ct_api_btn_logs">';
|
||||||
echo '<i class="fa fa-list" aria-hidden="true"></i> Voir les logs</button> ';
|
echo '<i class="fa fa-list" aria-hidden="true"></i> Voir les logs</button> ';
|
||||||
echo '<button type="button" class="btn btn-outline-secondary btn-sm" id="ct_api_btn_cron_ping" title="Appelle le script cron maintenant (test)">';
|
echo '<button type="button" class="btn btn-outline-secondary btn-sm" id="ct_api_btn_auto_diag">'
|
||||||
echo 'Tester le cron</button>';
|
. 'État sync auto</button> ';
|
||||||
|
echo '<button type="button" class="btn btn-outline-secondary btn-sm" id="ct_api_btn_cron_ping" title="Appelle auto_chronotrack_sync.php sur ce même domaine">'
|
||||||
|
. 'Lancer le script cron</button>';
|
||||||
echo '</div>';
|
echo '</div>';
|
||||||
echo '<p class="small text-muted mb-1">Envoi manuel : nouveaux / modifiés depuis le dernier push. '
|
echo '<p class="small text-muted mb-2">Envoi manuel : nouveaux / modifiés depuis le dernier push. '
|
||||||
. 'Page : refresh statut MS1 chaque minute.</p>';
|
. 'Page : refresh statut MS1 chaque minute.</p>';
|
||||||
echo '<p class="small text-muted mb-2" id="ct_api_cron_hint">Cron : utiliser <code>curl -sk</code> sur preprod (certificat). '
|
|
||||||
. 'Preuve serveur : <code>log/chronotrack_cron_last.txt</code>.</p>';
|
|
||||||
echo '<div id="ct_api_push_result" class="small mb-3"></div>';
|
echo '<div id="ct_api_push_result" class="small mb-3"></div>';
|
||||||
echo '<div id="ct_api_logs_wrap" class="mb-3 d-none"></div>';
|
echo '<div id="ct_api_logs_wrap" class="mb-3 d-none"></div>';
|
||||||
|
|
||||||
@ -1285,29 +1294,74 @@ function fxChronotrackApiAdminRenderPageScript($intEveId, $arrConfig, $blnClosed
|
|||||||
$('#ct_api_logs_wrap').addClass('d-none').empty();
|
$('#ct_api_logs_wrap').addClass('d-none').empty();
|
||||||
});
|
});
|
||||||
|
|
||||||
// MSIN-4328 — appelle auto_chronotrack_sync.php (même URL que le cron)
|
// MSIN-4328 — appelle auto_chronotrack_sync.php (même URL / même base que le CrowdJob)
|
||||||
$('#ct_api_btn_cron_ping').on('click', function () {
|
$('#ct_api_btn_cron_ping').on('click', function () {
|
||||||
var $btn = $(this);
|
var $btn = $(this);
|
||||||
var $res = $('#ct_api_push_result');
|
var $res = $('#ct_api_push_result');
|
||||||
$btn.prop('disabled', true);
|
$btn.prop('disabled', true);
|
||||||
$res.html('<span class="text-muted">Appel cron…</span>');
|
$res.html('<span class="text-muted">Appel auto_chronotrack_sync.php…</span>');
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '/auto_chronotrack_sync.php',
|
url: '/auto_chronotrack_sync.php',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
dataType: 'text',
|
dataType: 'text',
|
||||||
timeout: 120000
|
timeout: 120000
|
||||||
}).done(function (txt) {
|
}).done(function (txt) {
|
||||||
$res.html('<div class="alert alert-info small mb-0"><strong>Réponse cron :</strong><br><pre class="mb-0" style="white-space:pre-wrap;">'
|
$res.html('<div class="alert alert-info small mb-0"><strong>Réponse script :</strong><br><pre class="mb-0" style="white-space:pre-wrap;">'
|
||||||
+ $('<div/>').text(txt || '(vide)').html() + '</pre>'
|
+ $('<div/>').text(txt || '(vide)').html() + '</pre></div>');
|
||||||
+ '<div class="mt-1 text-muted">Si ran=0 : intervalle pas dû, pas de fin, ou auto OFF. Vérifier aussi log/chronotrack_cron_last.txt</div></div>');
|
loadAutoDiag();
|
||||||
|
loadSyncLogs();
|
||||||
}).fail(function (xhr) {
|
}).fail(function (xhr) {
|
||||||
$res.html('<div class="alert alert-danger small mb-0">Cron injoignable (HTTP '
|
$res.html('<div class="alert alert-danger small mb-0">Script injoignable sur ce domaine (HTTP '
|
||||||
+ (xhr.status || '?') + '). Fichier absent sur ce domaine ? Certificat / 404 ?</div>');
|
+ (xhr.status || '?') + '). Fichier pas déployé ici ?</div>');
|
||||||
}).always(function () {
|
}).always(function () {
|
||||||
$btn.prop('disabled', false);
|
$btn.prop('disabled', false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function loadAutoDiag() {
|
||||||
|
var $box = $('#ct_api_auto_diag');
|
||||||
|
if (!$box.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$box.text('Lecture état sync auto…');
|
||||||
|
$.post(strAjaxUrl, { a: 'sync_auto_diag', eve_id: intEveId }, function (res) {
|
||||||
|
if (rejectIfSessionLost(res)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!res || res.state !== 'ok' || !res.diag) {
|
||||||
|
$box.html('<span class="text-danger">'
|
||||||
|
+ escHtml((res && res.message) ? res.message : 'Diag impossible') + '</span>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var d = res.diag;
|
||||||
|
var html = '<div class="border rounded p-2 bg-light">';
|
||||||
|
html += '<div><strong>Verdict :</strong> ' + escHtml(d.would || '') + '</div>';
|
||||||
|
html += '<div>auto=' + (d.auto_enabled ? 'ON' : 'OFF')
|
||||||
|
+ ' · freq=' + escHtml(String(d.interval_min)) + ' min'
|
||||||
|
+ ' · fin=' + escHtml(d.until || '—')
|
||||||
|
+ ' · dernier passage=' + escHtml(d.last_auto_run_at || 'jamais') + '</div>';
|
||||||
|
html += '<div>logs en base pour cet event : <strong>' + escHtml(String(d.log_count)) + '</strong>';
|
||||||
|
if (d.last_log) {
|
||||||
|
html += ' · dernier : [' + escHtml(d.last_log.created_at || '') + '] '
|
||||||
|
+ escHtml(d.last_log.action || '') + ' — ' + escHtml(d.last_log.message || '');
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
if (d.cols_note) {
|
||||||
|
html += '<div class="text-danger">' + escHtml(d.cols_note) + '</div>';
|
||||||
|
}
|
||||||
|
html += '<div class="text-muted">host=' + escHtml(d.host || '') + '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
$box.html(html);
|
||||||
|
if (d.last_auto_run_at) {
|
||||||
|
$('#ct_api_auto_last').html('<strong>Dernier passage auto :</strong> '
|
||||||
|
+ escHtml(d.last_auto_run_at));
|
||||||
|
}
|
||||||
|
}, 'json').fail(function () {
|
||||||
|
$box.html('<span class="text-danger">Erreur réseau (diag).</span>');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$('#ct_api_btn_auto_diag').on('click', loadAutoDiag);
|
||||||
|
|
||||||
$('#ct_api_btn_ct_count').on('click', function () {
|
$('#ct_api_btn_ct_count').on('click', function () {
|
||||||
loadCtLiveCount();
|
loadCtLiveCount();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -481,13 +481,24 @@ function fxChronotrackApiSyncNormalizeBirthdate($strDob) {
|
|||||||
function fxChronotrackApiSyncLog($intEveId, $intParId, $strAction, $strStatus, $strMessage) {
|
function fxChronotrackApiSyncLog($intEveId, $intParId, $strAction, $strStatus, $strMessage) {
|
||||||
global $objDatabase;
|
global $objDatabase;
|
||||||
|
|
||||||
|
if (!isset($objDatabase) || !is_object($objDatabase)) {
|
||||||
|
error_log('MSIN-4328 sync_log: $objDatabase absent — action=' . $strAction);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$sql = "INSERT INTO api_chronotrack_sync_log SET eve_id = " . intval($intEveId)
|
$sql = "INSERT INTO api_chronotrack_sync_log SET eve_id = " . intval($intEveId)
|
||||||
. ", par_id = " . ($intParId > 0 ? intval($intParId) : 'NULL')
|
. ", par_id = " . ($intParId > 0 ? intval($intParId) : 'NULL')
|
||||||
. ", action = '" . $objDatabase->fxEscape(substr(trim($strAction), 0, 32)) . "'"
|
. ", action = '" . $objDatabase->fxEscape(substr(trim($strAction), 0, 32)) . "'"
|
||||||
. ", status = '" . $objDatabase->fxEscape($strStatus === 'ok' ? 'ok' : 'error') . "'"
|
. ", status = '" . $objDatabase->fxEscape($strStatus === 'ok' ? 'ok' : 'error') . "'"
|
||||||
. ", message = '" . $objDatabase->fxEscape(substr(trim($strMessage), 0, 65000)) . "'"
|
. ", message = '" . $objDatabase->fxEscape(substr(trim($strMessage), 0, 65000)) . "'"
|
||||||
. ", created_at = '" . fxGetDateTime() . "'";
|
. ", created_at = '" . fxGetDateTime() . "'";
|
||||||
$objDatabase->fxQuery($sql);
|
$blnOk = (bool)$objDatabase->fxQuery($sql);
|
||||||
|
if (!$blnOk) {
|
||||||
|
// Sans ça, push/cron « OK » mais Voir les logs = vide (INSERT silencieux).
|
||||||
|
error_log('MSIN-4328 sync_log INSERT failed eve=' . intval($intEveId)
|
||||||
|
. ' action=' . $strAction . ' sql_err=' . (isset($objDatabase->con) ? mysqli_error($objDatabase->con) : '?'));
|
||||||
|
}
|
||||||
|
return $blnOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1393,6 +1404,7 @@ function fxChronotrackApiSyncPushPrepare($intEveId) {
|
|||||||
. ($arrClass['blocked_count'] > 0 ? ' ' . $arrClass['blocked_count'] . ' exclus.' : ''))
|
. ($arrClass['blocked_count'] > 0 ? ' ' . $arrClass['blocked_count'] . ' exclus.' : ''))
|
||||||
: ('Aucun changement depuis le dernier push ('
|
: ('Aucun changement depuis le dernier push ('
|
||||||
. count($arrClass['transferable']) . ' éligibles à jour).');
|
. count($arrClass['transferable']) . ' éligibles à jour).');
|
||||||
|
fxChronotrackApiSyncLog($intEveId, 0, 'push_prepare', 'ok', 'idle — ' . $strMsg);
|
||||||
return array(
|
return array(
|
||||||
'state' => 'error',
|
'state' => 'error',
|
||||||
'message' => $strMsg,
|
'message' => $strMsg,
|
||||||
@ -1403,6 +1415,16 @@ function fxChronotrackApiSyncPushPrepare($intEveId) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fxChronotrackApiSyncLog(
|
||||||
|
$intEveId,
|
||||||
|
0,
|
||||||
|
'push_prepare',
|
||||||
|
'ok',
|
||||||
|
'job prêt — pending=' . count($tabBatch)
|
||||||
|
. ' éligibles=' . count($arrClass['transferable'])
|
||||||
|
. ' exclus=' . intval($arrClass['blocked_count'])
|
||||||
|
);
|
||||||
|
|
||||||
$arrJob = array(
|
$arrJob = array(
|
||||||
'ct_event_id' => $intCtEventId,
|
'ct_event_id' => $intCtEventId,
|
||||||
'batch' => $tabBatch,
|
'batch' => $tabBatch,
|
||||||
@ -1750,6 +1772,8 @@ function fxChronotrackApiSyncRunAutoPushForEvent($intEveId) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* MSIN-4328 — passage cron : events auto ON, fréquence / fin respectées.
|
* MSIN-4328 — passage cron : events auto ON, fréquence / fin respectées.
|
||||||
|
* Chaque décision (run / skip / expire) écrit un log pour l’événement — sinon
|
||||||
|
* « Voir les logs » reste vide alors que le CrowdJob tourne vraiment.
|
||||||
*/
|
*/
|
||||||
function fxChronotrackApiSyncRunAutoCron() {
|
function fxChronotrackApiSyncRunAutoCron() {
|
||||||
if (!fxChronotrackApiSettingsConfigured()) {
|
if (!fxChronotrackApiSettingsConfigured()) {
|
||||||
@ -1758,6 +1782,7 @@ function fxChronotrackApiSyncRunAutoCron() {
|
|||||||
'message' => fxChronotrackApiSettingsErrorMessage(),
|
'message' => fxChronotrackApiSettingsErrorMessage(),
|
||||||
'ran' => 0,
|
'ran' => 0,
|
||||||
'skipped' => 0,
|
'skipped' => 0,
|
||||||
|
'enabled_configs' => 0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1767,6 +1792,7 @@ function fxChronotrackApiSyncRunAutoCron() {
|
|||||||
$intExpired = 0;
|
$intExpired = 0;
|
||||||
$tabDetails = array();
|
$tabDetails = array();
|
||||||
$intNow = time();
|
$intNow = time();
|
||||||
|
$intEnabled = count($tabConfigs);
|
||||||
|
|
||||||
foreach ($tabConfigs as $arrCfg) {
|
foreach ($tabConfigs as $arrCfg) {
|
||||||
$intEveId = intval($arrCfg['eve_id'] ?? 0);
|
$intEveId = intval($arrCfg['eve_id'] ?? 0);
|
||||||
@ -1793,6 +1819,13 @@ function fxChronotrackApiSyncRunAutoCron() {
|
|||||||
} else {
|
} else {
|
||||||
// Pas de fin = on ne tourne pas (UI exige une fin à l’enregistrement)
|
// Pas de fin = on ne tourne pas (UI exige une fin à l’enregistrement)
|
||||||
$intSkipped++;
|
$intSkipped++;
|
||||||
|
fxChronotrackApiSyncLog(
|
||||||
|
$intEveId,
|
||||||
|
0,
|
||||||
|
'auto_cron',
|
||||||
|
'error',
|
||||||
|
'Skip: date/heure de fin manquante (réenregistrer la sync auto)'
|
||||||
|
);
|
||||||
$tabDetails[] = array('eve_id' => $intEveId, 'action' => 'skip_no_until');
|
$tabDetails[] = array('eve_id' => $intEveId, 'action' => 'skip_no_until');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1806,6 +1839,8 @@ function fxChronotrackApiSyncRunAutoCron() {
|
|||||||
$intLast = strtotime($strLast);
|
$intLast = strtotime($strLast);
|
||||||
if ($intLast !== false && ($intNow - $intLast) < ($intInterval * 60)) {
|
if ($intLast !== false && ($intNow - $intLast) < ($intInterval * 60)) {
|
||||||
$intSkipped++;
|
$intSkipped++;
|
||||||
|
// Trace légère: 1 seule fois par fenêtre d’intervalle (évite 1440 lignes/jour).
|
||||||
|
// Déjà logué ailleurs au run — ici on ne spam pas.
|
||||||
$tabDetails[] = array('eve_id' => $intEveId, 'action' => 'skip_interval');
|
$tabDetails[] = array('eve_id' => $intEveId, 'action' => 'skip_interval');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1823,12 +1858,94 @@ function fxChronotrackApiSyncRunAutoCron() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$strMsg = 'cron auto — configs_on=' . $intEnabled
|
||||||
|
. ' ran=' . $intRan . ' skipped=' . $intSkipped . ' expired=' . $intExpired;
|
||||||
|
if ($intEnabled === 0) {
|
||||||
|
$strMsg .= ' (aucun event avec sync auto ON sur cette base)';
|
||||||
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'state' => 'ok',
|
'state' => 'ok',
|
||||||
'message' => 'cron auto — ran=' . $intRan . ' skipped=' . $intSkipped . ' expired=' . $intExpired,
|
'message' => $strMsg,
|
||||||
'ran' => $intRan,
|
'ran' => $intRan,
|
||||||
'skipped' => $intSkipped,
|
'skipped' => $intSkipped,
|
||||||
'expired' => $intExpired,
|
'expired' => $intExpired,
|
||||||
'details' => $tabDetails,
|
'enabled_configs' => $intEnabled,
|
||||||
|
'details' => $tabDetails,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MSIN-4328 — état sync auto + logs pour un événement (diag UI, pas d’essai-erreur SSL).
|
||||||
|
*/
|
||||||
|
function fxChronotrackApiSyncAutoDiag($intEveId) {
|
||||||
|
global $objDatabase;
|
||||||
|
|
||||||
|
$intEveId = intval($intEveId);
|
||||||
|
$arrCfg = fxChronotrackApiConfigGet($intEveId);
|
||||||
|
if ($arrCfg === null) {
|
||||||
|
return array('state' => 'error', 'message' => 'Événement non lié à ChronoTrack');
|
||||||
|
}
|
||||||
|
|
||||||
|
$blnColsOk = true;
|
||||||
|
$strColNote = '';
|
||||||
|
$sqlCol = "SELECT COUNT(*) AS n FROM information_schema.COLUMNS"
|
||||||
|
. " WHERE TABLE_SCHEMA = DATABASE()"
|
||||||
|
. " AND TABLE_NAME = 'api_chronotrack_config'"
|
||||||
|
. " AND COLUMN_NAME = 'auto_sync_enabled'";
|
||||||
|
$arrCol = $objDatabase->fxGetRow($sqlCol);
|
||||||
|
if (intval($arrCol['n'] ?? 0) < 1) {
|
||||||
|
$blnColsOk = false;
|
||||||
|
$strColNote = 'Colonnes auto_sync absentes — exécuter sql/MSIN-4328-chronotrack-auto-sync-config.sql';
|
||||||
|
}
|
||||||
|
|
||||||
|
$sqlLog = "SELECT COUNT(*) AS n FROM api_chronotrack_sync_log WHERE eve_id = " . $intEveId;
|
||||||
|
$arrLogCnt = $objDatabase->fxGetRow($sqlLog);
|
||||||
|
$intLogCnt = intval($arrLogCnt['n'] ?? 0);
|
||||||
|
|
||||||
|
$arrLastLog = $objDatabase->fxGetRow(
|
||||||
|
"SELECT log_id, action, status, message, created_at FROM api_chronotrack_sync_log"
|
||||||
|
. " WHERE eve_id = " . $intEveId
|
||||||
|
. " ORDER BY log_id DESC LIMIT 1"
|
||||||
|
);
|
||||||
|
|
||||||
|
$blnOn = (intval($arrCfg['auto_sync_enabled'] ?? 0) === 1);
|
||||||
|
$intInterval = intval($arrCfg['auto_sync_interval_min'] ?? 15);
|
||||||
|
$strUntil = trim((string)($arrCfg['auto_sync_until'] ?? ''));
|
||||||
|
$strLastRun = trim((string)($arrCfg['last_auto_run_at'] ?? ''));
|
||||||
|
$intNow = time();
|
||||||
|
$strWould = 'inconnu';
|
||||||
|
if (!$blnColsOk) {
|
||||||
|
$strWould = 'bloqué: SQL auto_sync manquant';
|
||||||
|
} elseif (!$blnOn) {
|
||||||
|
$strWould = 'ne tourne pas: sync auto OFF';
|
||||||
|
} elseif ($strUntil === '' || $strUntil === '0000-00-00 00:00:00') {
|
||||||
|
$strWould = 'ne tourne pas: date de fin manquante';
|
||||||
|
} elseif (strtotime($strUntil) !== false && $intNow > strtotime($strUntil)) {
|
||||||
|
$strWould = 'ne tourne pas: date de fin dépassée (' . $strUntil . ')';
|
||||||
|
} elseif ($strLastRun !== '' && $strLastRun !== '0000-00-00 00:00:00'
|
||||||
|
&& strtotime($strLastRun) !== false
|
||||||
|
&& ($intNow - strtotime($strLastRun)) < ($intInterval * 60)) {
|
||||||
|
$strWould = 'en attente d’intervalle (dernier passage ' . $strLastRun
|
||||||
|
. ', fréquence ' . $intInterval . ' min)';
|
||||||
|
} else {
|
||||||
|
$strWould = 'devrait pousser au prochain appel de auto_chronotrack_sync.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'state' => 'ok',
|
||||||
|
'message' => $strWould,
|
||||||
|
'diag' => array(
|
||||||
|
'cols_ok' => $blnColsOk,
|
||||||
|
'cols_note' => $strColNote,
|
||||||
|
'auto_enabled' => $blnOn,
|
||||||
|
'interval_min' => $intInterval,
|
||||||
|
'until' => $strUntil !== '' ? $strUntil : null,
|
||||||
|
'last_auto_run_at' => $strLastRun !== '' ? $strLastRun : null,
|
||||||
|
'log_count' => $intLogCnt,
|
||||||
|
'last_log' => is_array($arrLastLog) ? $arrLastLog : null,
|
||||||
|
'host' => isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '',
|
||||||
|
'would' => $strWould,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -152,6 +152,15 @@ switch ($strAction) {
|
|||||||
$tabRetour = fxChronotrackApiSyncLogList($intEveId, $intLimit);
|
$tabRetour = fxChronotrackApiSyncLogList($intEveId, $intLimit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'sync_auto_diag':
|
||||||
|
// MSIN-4328 — pourquoi le cron pousse / ne pousse pas (sans essais curl)
|
||||||
|
if ($intEveId <= 0) {
|
||||||
|
$tabRetour = array('state' => 'error', 'message' => 'eve_id manquant');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$tabRetour = fxChronotrackApiSyncAutoDiag($intEveId);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'sync_probe_push':
|
case 'sync_probe_push':
|
||||||
if ($intEveId <= 0) {
|
if ($intEveId <= 0) {
|
||||||
$tabRetour = array('state' => 'error', 'message' => 'eve_id manquant');
|
$tabRetour = array('state' => 'error', 'message' => 'eve_id manquant');
|
||||||
|
|||||||
Reference in New Issue
Block a user