Newer
Older
EnvoyControlPlane / static / consistency.js
// consistency.js
import { API_BASE_URL, CONSISTENCY_POLL_INTERVAL, setInconsistencyData, inconsistencyData } from './global.js';
import { hideConsistencyModal, showConsistencyModal } from './modals.js';
import { loadAllData } from './data_loader.js'; // Will be imported later

/**
 * Core function to resolve consistency by making a POST call to a sync endpoint.
 * @param {string} action - 'flush' (Cache -> DB) or 'rollback' (DB -> Cache).
 */
async function resolveConsistency(action) {
    let url = '';
    let message = '';

    if (action === 'flush') {
        url = `${API_BASE_URL}/flush-to-db`;
        message = 'Flushing cache to DB...';
    } else if (action === 'rollback') {
        url = `${API_BASE_URL}/load-from-db`;
        message = 'Rolling back cache from DB...';
    } else {
        return;
    }

    if (!confirm(`Are you sure you want to perform the action: ${action.toUpperCase()}? This will overwrite the target configuration.`)) {
        return;
    }

    const modal = document.getElementById('consistencyModal');
    if (modal) modal.style.display = 'none'; 

    const button = document.getElementById('consistency-button');
    if (button) {
        button.textContent = message;
        button.classList.remove('consistent', 'inconsistent', 'error');
        button.classList.add('loading');
        button.disabled = true;
    }

    try {
        const response = await fetch(url, { method: 'POST' });

        if (!response.ok) {
            const errorBody = await response.text();
            throw new Error(`HTTP Error ${response.status}: ${errorBody}`);
        }

        alert(`Sync successful via ${action.toUpperCase()}. Reloading data.`);
        loadAllData();
        checkConsistency(); 
    } catch (error) {
        alert(`Failed to sync via ${action}. Check console for details.`);
        console.error(`Sync operation (${action}) failed:`, error);
        checkConsistency(); 
    }
}


/**
 * Periodically checks the consistency status with the backend.
 */
export async function checkConsistency() {
    const button = document.getElementById('consistency-button');
    if (!button) return;

    // Save previous state before fetch
    const hadConflict = inconsistencyData !== null && inconsistencyData.inconsistent === true;
    const isCurrentlyError = button.classList.contains('error');

    button.textContent = 'Checking...';
    button.classList.add('loading');
    button.classList.remove('consistent', 'inconsistent', 'error');
    button.disabled = true;

    try {
        const response = await fetch(`${API_BASE_URL}/is-consistent`);
        if (!response.ok) throw new Error(response.statusText);

        const data = await response.json();
        const consistencyStatus = data.consistent;
        const hasConflict = consistencyStatus.inconsistent === true;

        setInconsistencyData(hasConflict ? consistencyStatus : null);

        button.classList.remove('loading');
        button.disabled = !hasConflict; // Only enable if inconsistent

        if (hasConflict) {
            button.textContent = '🚨 CONFLICT';
            button.classList.remove('consistent', 'error');
            button.classList.add('inconsistent');
            // If conflict is new or if we recovered from an error, show the modal
            if (!hadConflict || isCurrentlyError) {
                // Optionally show the modal automatically here, or leave it to user click
            }
        } else {
            button.textContent = '✅ Consistent';
            button.classList.remove('inconsistent', 'error');
            button.classList.add('consistent');
            hideConsistencyModal();
        }

    } catch (error) {
        button.classList.remove('loading', 'consistent', 'inconsistent');
        button.classList.add('error');
        button.textContent = '❌ Error';
        button.disabled = true;
        setInconsistencyData(null);
        console.error("Consistency check failed:", error);
    }
}


// Exported functions must be attached to 'window' if called from inline HTML attributes
export function manualFlush() {
    resolveConsistency('flush');
}

export function manualRollback() {
    resolveConsistency('rollback');
}