query('START TRANSACTION') === false) { return; } $done = self::supersedePending('policy_migration'); if ($done === false || $wpdb->query('COMMIT') === false || $wpdb->last_error !== '') { $wpdb->query('ROLLBACK'); return; } } // add_option is atomic: a concurrent run that lost the race changes nothing a second time. add_option(self::FLAG, gmdate('c'), '', true); } /** * Mark every request waiting for human approval as superseded. The caller owns the transaction. * * @return int|false Number of requests cancelled, false when the table could not be written. */ public static function supersedePending(string $reason): int|false { global $wpdb; $table = Schema::tableNames()['operations']; $ids = $wpdb->get_col($wpdb->prepare("SELECT id FROM %i WHERE status = 'aborted' AND error_code = 'awaiting_approval'", $table)); if ($wpdb->last_error !== '') { return false; } if (!$ids) { return 0; } $updated = $wpdb->query($wpdb->prepare( "UPDATE %i SET error_code = 'approval_superseded', updated_at = %s WHERE status = 'aborted' AND error_code = 'awaiting_approval'", $table, gmdate('Y-m-d H:i:s') )); if ($updated === false || $wpdb->last_error !== '') { return false; } $user = get_current_user_id(); if (!AuditLog::append('approval_superseded', ['reason' => sanitize_key($reason), 'count' => count($ids), 'operation_ids' => array_slice(array_map('strval', $ids), 0, 50)], $user > 0 ? $user : null, null, $user > 0 ? 'admin:' . $user : null)) { return false; } return count($ids); } }