diff --git a/lib/CleantalkSP/SpbctWP/Sync.php b/lib/CleantalkSP/SpbctWP/Sync.php index 58dd25553..4c73fcba1 100644 --- a/lib/CleantalkSP/SpbctWP/Sync.php +++ b/lib/CleantalkSP/SpbctWP/Sync.php @@ -25,6 +25,14 @@ class Sync 'finalize' => 'Sync end...', ); + private const MODE_SYNC = 'sync'; + private const MODE_BACKGROUND = 'background'; + + /** + * Seconds without step progress after which a synchronous sync is considered dead. + */ + private const SYNC_MODE_STALE_TIMEOUT = 300; + /** * @return array */ @@ -32,6 +40,7 @@ private static function getDefaultProgress() { return array( 'in_progress' => false, + 'mode' => '', 'step_index' => 0, 'account_is_ok' => false, 'message' => '', @@ -91,32 +100,18 @@ public static function formatStatus($progress) */ public static function run() { - global $spbc; + // Sync mode turns queued background continuations and status polling into no-ops. + self::initializeProgress(self::MODE_SYNC); - $progress = self::getProgress(); - if ( ! empty($progress['in_progress']) ) { - self::saveProgress(self::getDefaultProgress()); - } - - $account_is_ok = false; + do { + self::runCurrentStep(); + $progress = self::getProgress(); + } while ( ! empty($progress['in_progress']) ); - self::stepAccessKeyCheck($account_is_ok); - self::stepSecfwUpdate($account_is_ok); - self::stepSignaturesUpdate(); - self::stepSettingsExclusions(); - self::stepAdjustEnv(); - self::stepVulnerabilityCheck(); - self::stepAnalysisLogUpdate($account_is_ok); - self::stepPscCacheWarm(); - - $out = array( - 'success' => true, - 'reload' => self::needsReloadPage($spbc), + return array( + 'success' => ! empty($progress['success']), + 'reload' => ! empty($progress['reload']), ); - - self::stepFinalize(); - - return $out; } /** @@ -193,12 +188,13 @@ public static function runCurrentStep() self::stepPscCacheWarm(); break; case 'finalize': + $reload = self::needsReloadPage($spbc); self::stepFinalize(); $progress = self::getProgress(); $progress['in_progress'] = false; $progress['success'] = true; - $progress['reload'] = self::needsReloadPage($spbc); + $progress['reload'] = $reload; $progress['percent'] = 100; $progress['message'] = self::STEPS['finalize']; $progress['last_step_at'] = time(); @@ -241,6 +237,16 @@ public static function maybeResume() return; } + if ( $progress['mode'] === self::MODE_SYNC ) { + // Synchronous sync is running in another process. Take it over only if that process has died. + if ( time() - (int) $progress['last_step_at'] < self::SYNC_MODE_STALE_TIMEOUT ) { + return; + } + + $progress['mode'] = self::MODE_BACKGROUND; + self::saveProgress($progress); + } + $steps = array_keys(self::STEPS); if ( (int) $progress['step_index'] >= count($steps) ) { return; @@ -276,20 +282,7 @@ public static function startBackground() return self::formatStatus(self::getProgress()); } - $steps = array_keys(self::STEPS); - $labels = self::STEPS; - - $progress = array( - 'in_progress' => true, - 'step_index' => 0, - 'account_is_ok' => false, - 'message' => $labels[ $steps[0] ], - 'percent' => 0, - 'reload' => false, - 'success' => false, - 'last_step_at' => time(), - ); - self::saveProgress($progress); + self::initializeProgress(self::MODE_BACKGROUND); self::runCurrentStep(); @@ -301,11 +294,31 @@ public static function startBackground() return self::formatStatus(self::getProgress()); } + /** + * Initialize progress for synchronous and background sync. + * + * @param string $mode self::MODE_SYNC or self::MODE_BACKGROUND + */ + private static function initializeProgress($mode) + { + $progress = self::getDefaultProgress(); + $progress['in_progress'] = true; + $progress['mode'] = $mode; + $progress['message'] = self::STEPS['access_key_check']; + $progress['last_step_at'] = time(); + self::saveProgress($progress); + } + /** * Remote call handler: run the next sync step. */ public static function continueSync() { + $progress = self::getProgress(); + if ( $progress['mode'] === self::MODE_SYNC ) { + return; + } + self::runCurrentStep(); $progress = self::getProgress();