Implement auto-sync functionality in ChronoTrack API, including new methods for managing auto-sync events and handling expiration. Update push panel messages for clarity on cron job execution and enhance user feedback. This change supports improved synchronization management and lays the foundation for future enhancements.
This commit is contained in:
@ -298,11 +298,11 @@ function fxChronotrackApiAdminRenderPushPanel($intEveId, $blnClosed = false, $ar
|
||||
echo '</div>';
|
||||
echo '<p class="small text-muted mb-0 mt-2" id="ct_api_auto_hint">';
|
||||
if ($blnAutoOn && $strUntilRaw !== '') {
|
||||
echo 'Config enregistrée — exécution serveur (cron) à brancher. Arrêt prévu : '
|
||||
echo 'Config enregistrée — cron <code>auto_chronotrack_sync.php</code> (toutes les minutes). Arrêt : '
|
||||
. fxChronotrackApiAdminEsc($strUntilRaw) . '.';
|
||||
} else {
|
||||
echo 'Quand c’est coché, le serveur (cron) poussera le différentiel à cet intervalle jusqu’à la date de fin. '
|
||||
. 'Pas encore actif côté serveur.';
|
||||
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>';
|
||||
echo '<div id="ct_api_auto_msg" class="small mt-1"></div>';
|
||||
@ -1174,10 +1174,10 @@ function fxChronotrackApiAdminRenderPageScript($intEveId, $arrConfig, $blnClosed
|
||||
$msg.addClass('text-success').text(res.message || 'Enregistré');
|
||||
if (res.auto_sync) {
|
||||
if (res.auto_sync.enabled && res.auto_sync.until) {
|
||||
$hint.text('Config enregistrée — exécution serveur (cron) à brancher. Arrêt prévu : '
|
||||
$hint.text('Config OK — cron toutes les minutes lit cette config (auto_chronotrack_sync.php). Arrêt : '
|
||||
+ res.auto_sync.until + '.');
|
||||
} else {
|
||||
$hint.text('Sync auto désactivée. Le cron (phase B) ne traitera pas cet événement.');
|
||||
$hint.text('Sync auto désactivée.');
|
||||
}
|
||||
}
|
||||
}, 'json').fail(function () {
|
||||
|
||||
@ -197,7 +197,7 @@ function fxChronotrackApiConfigSaveAutoSync($intEveId, $blnEnabled, $intInterval
|
||||
'state' => 'ok',
|
||||
'message' => $blnEnabled
|
||||
? ('Sync auto enregistrée (toutes les ' . $intIntervalMin . ' min jusqu’au '
|
||||
. trim((string)($arrFresh['auto_sync_until'] ?? '')) . '). Le cron démarrera en phase B.')
|
||||
. trim((string)($arrFresh['auto_sync_until'] ?? '')) . '). Cron : auto_chronotrack_sync.php')
|
||||
: 'Sync auto désactivée.',
|
||||
'auto_sync' => array(
|
||||
'enabled' => intval($arrFresh['auto_sync_enabled'] ?? 0) === 1,
|
||||
@ -208,6 +208,60 @@ function fxChronotrackApiConfigSaveAutoSync($intEveId, $blnEnabled, $intInterval
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* MSIN-4328 — events avec sync auto ON (pas fermés).
|
||||
*/
|
||||
function fxChronotrackApiConfigListAutoSyncEnabled() {
|
||||
global $objDatabase;
|
||||
|
||||
$sql = "SELECT c.*"
|
||||
. " FROM api_chronotrack_config c"
|
||||
. " WHERE IFNULL(c.auto_sync_enabled, 0) = 1"
|
||||
. " AND c.sync_status <> '" . $objDatabase->fxEscape(MSIN_API_CHRONOTRACK_SYNC_FERME) . "'"
|
||||
. " ORDER BY c.eve_id ASC";
|
||||
$arrRows = $objDatabase->fxGetResults($sql);
|
||||
$tabOut = array();
|
||||
if (!is_array($arrRows)) {
|
||||
return $tabOut;
|
||||
}
|
||||
for ($i = 1; $i <= count($arrRows); $i++) {
|
||||
$tabOut[] = $arrRows[$i];
|
||||
}
|
||||
return $tabOut;
|
||||
}
|
||||
|
||||
/**
|
||||
* MSIN-4328 — horodatage dernier passage cron auto.
|
||||
*/
|
||||
function fxChronotrackApiConfigTouchAutoRun($intEveId) {
|
||||
global $objDatabase;
|
||||
|
||||
$intEveId = intval($intEveId);
|
||||
if ($intEveId <= 0) {
|
||||
return false;
|
||||
}
|
||||
$sql = "UPDATE api_chronotrack_config SET last_auto_run_at = '" . fxGetDateTime() . "'"
|
||||
. ", updated_at = '" . fxGetDateTime() . "'"
|
||||
. " WHERE eve_id = " . $intEveId;
|
||||
return (bool)$objDatabase->fxQuery($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* MSIN-4328 — coupe la sync auto (échéance atteinte).
|
||||
*/
|
||||
function fxChronotrackApiConfigDisableAutoSync($intEveId) {
|
||||
global $objDatabase;
|
||||
|
||||
$intEveId = intval($intEveId);
|
||||
if ($intEveId <= 0) {
|
||||
return false;
|
||||
}
|
||||
$sql = "UPDATE api_chronotrack_config SET auto_sync_enabled = 0"
|
||||
. ", updated_at = '" . fxGetDateTime() . "'"
|
||||
. " WHERE eve_id = " . $intEveId;
|
||||
return (bool)$objDatabase->fxQuery($sql);
|
||||
}
|
||||
|
||||
function fxChronotrackApiRaceMapGetForEvent($intEveId) {
|
||||
global $objDatabase;
|
||||
|
||||
|
||||
@ -1661,3 +1661,143 @@ function fxChronotrackApiSyncListCtOrphans($intEveId) {
|
||||
'orphans' => $tabOrphans,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* MSIN-4328 — push différentiel complet pour un event (cron auto).
|
||||
*/
|
||||
function fxChronotrackApiSyncRunAutoPushForEvent($intEveId) {
|
||||
$intEveId = intval($intEveId);
|
||||
$arrPrep = fxChronotrackApiSyncPushPrepare($intEveId);
|
||||
if (($arrPrep['state'] ?? '') !== 'ok') {
|
||||
// Rien à pousser = succès « idle »
|
||||
$strMsg = (string)($arrPrep['message'] ?? 'prepare failed');
|
||||
if (stripos($strMsg, 'Aucun changement') !== false || intval($arrPrep['pending_push'] ?? -1) === 0) {
|
||||
fxChronotrackApiSyncLog($intEveId, 0, 'auto_push', 'ok', 'idle — ' . $strMsg);
|
||||
return array('state' => 'ok', 'message' => $strMsg, 'pushed_ok' => 0, 'idle' => true);
|
||||
}
|
||||
fxChronotrackApiSyncLog($intEveId, 0, 'auto_push', 'error', $strMsg);
|
||||
return $arrPrep;
|
||||
}
|
||||
|
||||
$intOffset = 0;
|
||||
$intLimit = MSIN_API_CHRONOTRACK_SYNC_CHUNK_SIZE;
|
||||
$intOkSum = 0;
|
||||
$intErrSum = 0;
|
||||
$intLoops = 0;
|
||||
$intMaxLoops = 500;
|
||||
|
||||
while ($intLoops < $intMaxLoops) {
|
||||
$intLoops++;
|
||||
$arrChunk = fxChronotrackApiSyncPushEvent($intEveId, array(
|
||||
'offset' => $intOffset,
|
||||
'limit' => $intLimit,
|
||||
));
|
||||
$intOkSum += intval($arrChunk['pushed_ok'] ?? 0);
|
||||
$intErrSum += intval($arrChunk['pushed_error'] ?? 0);
|
||||
if (!empty($arrChunk['done'])) {
|
||||
break;
|
||||
}
|
||||
if (($arrChunk['state'] ?? '') === 'error' && intval($arrChunk['pushed_ok'] ?? 0) === 0) {
|
||||
break;
|
||||
}
|
||||
$intOffset = intval($arrChunk['next_offset'] ?? ($intOffset + $intLimit));
|
||||
}
|
||||
|
||||
$strState = ($intErrSum === 0) ? 'ok' : (($intOkSum > 0) ? 'partial' : 'error');
|
||||
$strMsg = 'auto push ok=' . $intOkSum . ' err=' . $intErrSum
|
||||
. ' total_job=' . intval($arrPrep['total'] ?? 0);
|
||||
fxChronotrackApiSyncLog($intEveId, 0, 'auto_push', ($strState === 'ok') ? 'ok' : 'error', $strMsg);
|
||||
|
||||
return array(
|
||||
'state' => $strState,
|
||||
'message' => $strMsg,
|
||||
'pushed_ok' => $intOkSum,
|
||||
'pushed_error' => $intErrSum,
|
||||
'idle' => false,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* MSIN-4328 — passage cron : events auto ON, fréquence / fin respectées.
|
||||
*/
|
||||
function fxChronotrackApiSyncRunAutoCron() {
|
||||
if (!fxChronotrackApiSettingsConfigured()) {
|
||||
return array(
|
||||
'state' => 'error',
|
||||
'message' => fxChronotrackApiSettingsErrorMessage(),
|
||||
'ran' => 0,
|
||||
'skipped' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
$tabConfigs = fxChronotrackApiConfigListAutoSyncEnabled();
|
||||
$intRan = 0;
|
||||
$intSkipped = 0;
|
||||
$intExpired = 0;
|
||||
$tabDetails = array();
|
||||
$intNow = time();
|
||||
|
||||
foreach ($tabConfigs as $arrCfg) {
|
||||
$intEveId = intval($arrCfg['eve_id'] ?? 0);
|
||||
if ($intEveId <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$strUntil = trim((string)($arrCfg['auto_sync_until'] ?? ''));
|
||||
if ($strUntil !== '' && $strUntil !== '0000-00-00 00:00:00') {
|
||||
$intUntil = strtotime($strUntil);
|
||||
if ($intUntil !== false && $intNow > $intUntil) {
|
||||
fxChronotrackApiConfigDisableAutoSync($intEveId);
|
||||
fxChronotrackApiSyncLog(
|
||||
$intEveId,
|
||||
0,
|
||||
'auto_sync',
|
||||
'ok',
|
||||
'Échéance atteinte (' . $strUntil . ') — sync auto désactivée'
|
||||
);
|
||||
$intExpired++;
|
||||
$tabDetails[] = array('eve_id' => $intEveId, 'action' => 'expired');
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Pas de fin = on ne tourne pas (UI exige une fin à l’enregistrement)
|
||||
$intSkipped++;
|
||||
$tabDetails[] = array('eve_id' => $intEveId, 'action' => 'skip_no_until');
|
||||
continue;
|
||||
}
|
||||
|
||||
$intInterval = intval($arrCfg['auto_sync_interval_min'] ?? 15);
|
||||
if (!in_array($intInterval, fxChronotrackApiConfigAutoSyncIntervals(), true)) {
|
||||
$intInterval = 15;
|
||||
}
|
||||
$strLast = trim((string)($arrCfg['last_auto_run_at'] ?? ''));
|
||||
if ($strLast !== '' && $strLast !== '0000-00-00 00:00:00') {
|
||||
$intLast = strtotime($strLast);
|
||||
if ($intLast !== false && ($intNow - $intLast) < ($intInterval * 60)) {
|
||||
$intSkipped++;
|
||||
$tabDetails[] = array('eve_id' => $intEveId, 'action' => 'skip_interval');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$arrRes = fxChronotrackApiSyncRunAutoPushForEvent($intEveId);
|
||||
fxChronotrackApiConfigTouchAutoRun($intEveId);
|
||||
$intRan++;
|
||||
$tabDetails[] = array(
|
||||
'eve_id' => $intEveId,
|
||||
'action' => 'run',
|
||||
'result' => $arrRes['state'] ?? 'error',
|
||||
'message' => $arrRes['message'] ?? '',
|
||||
'ok' => intval($arrRes['pushed_ok'] ?? 0),
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'state' => 'ok',
|
||||
'message' => 'cron auto — ran=' . $intRan . ' skipped=' . $intSkipped . ' expired=' . $intExpired,
|
||||
'ran' => $intRan,
|
||||
'skipped' => $intSkipped,
|
||||
'expired' => $intExpired,
|
||||
'details' => $tabDetails,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user