Apply sync incrementally so unchanged tunnels stay running
CI / Build & Test (push) Successful in 4m21s
CI / Build & Test (push) Successful in 4m21s
- Add getStateSnapshot, applySnapshotData, setStateSaveSuppressed to holesail-manager - Sync diffs snapshot vs current state and only removes/adds/updates changed tunnels - Suppress saves during apply and write state.json once at the end - Fall back to full cleanup + restore when incremental APIs are unavailable
This commit is contained in:
@@ -26,6 +26,16 @@ function emit(event, payload) { if (eventEmit) eventEmit(event, payload); }
|
||||
// Collects current state from all sub-modules and persists it.
|
||||
|
||||
let onStateSaved = null;
|
||||
let stateSaveSuppressed = false;
|
||||
|
||||
/**
|
||||
* When true, saveState() is a no-op. Used during sync apply so only the final
|
||||
* state is written once by the sync-manager.
|
||||
* @param {boolean} v
|
||||
*/
|
||||
function setStateSaveSuppressed(v) {
|
||||
stateSaveSuppressed = !!v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback invoked after each saveState() with the snapshot object.
|
||||
@@ -37,6 +47,7 @@ function setOnStateSaved(fn) {
|
||||
}
|
||||
|
||||
function saveState() {
|
||||
if (stateSaveSuppressed) return;
|
||||
const serversList = serversModule.getServers().map(s => ({
|
||||
id: s.id, port: s.port, host: s.host, secure: s.secure, udp: s.udp || false, label: s.label || ''
|
||||
}));
|
||||
@@ -60,6 +71,48 @@ function saveState() {
|
||||
if (onStateSaved) onStateSaved(snapshot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return current in-memory state in the same shape as saveState() snapshot.
|
||||
* Used by sync-manager to diff and apply only changes.
|
||||
* @returns {{ version: number, settings: object, nextServerId: number, nextServiceTunnelId: number, servers: Array, virtualHosts: Array, serviceTunnels: Array, sshConnections: Array, rdpConnections: Array }}
|
||||
*/
|
||||
function getStateSnapshot() {
|
||||
const serversList = serversModule.getServers().map(s => ({
|
||||
id: s.id, port: s.port, host: s.host, secure: s.secure, udp: s.udp || false, label: s.label || ''
|
||||
}));
|
||||
const virtualHostsList = vhostsModule.getVirtualHosts()
|
||||
.map(v => ({ hostname: v.hostname, hsUrl: v.hsUrl, useTls: v.useTls === true }));
|
||||
const serviceTunnelsList = svcModule.getServiceTunnels().map(t => ({
|
||||
id: t.id, label: t.label, hsUrl: t.hsUrl, localPort: t.localPort
|
||||
}));
|
||||
return {
|
||||
version: 2,
|
||||
settings: settingsModule.getSettings(),
|
||||
nextServerId: serversModule.getNextServerId(),
|
||||
nextServiceTunnelId: svcModule.getNextServiceTunnelId(),
|
||||
servers: serversList,
|
||||
virtualHosts: virtualHostsList,
|
||||
serviceTunnels: serviceTunnelsList,
|
||||
sshConnections: connectionsModule.getSshConnections(),
|
||||
rdpConnections: connectionsModule.getRdpConnections()
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply non-tunnel state from a snapshot (settings, connection lists, ID counters).
|
||||
* Does not start/stop tunnels; used by sync-manager before applying tunnel diffs.
|
||||
* @param {object} snapshot - Snapshot with settings, sshConnections, rdpConnections, nextServerId, nextServiceTunnelId
|
||||
*/
|
||||
function applySnapshotData(snapshot) {
|
||||
if (!snapshot || typeof snapshot !== 'object') return;
|
||||
if (snapshot.settings != null) settingsModule.applyLoaded(snapshot.settings);
|
||||
const ssh = Array.isArray(snapshot.sshConnections) ? snapshot.sshConnections : [];
|
||||
const rdp = Array.isArray(snapshot.rdpConnections) ? snapshot.rdpConnections : [];
|
||||
connectionsModule.applyLoaded(ssh, rdp);
|
||||
if (typeof snapshot.nextServerId === 'number') serversModule.applyLoaded(snapshot.nextServerId);
|
||||
if (typeof snapshot.nextServiceTunnelId === 'number') svcModule.applyLoaded(snapshot.nextServiceTunnelId);
|
||||
}
|
||||
|
||||
// Inject the shared saveState and emit callbacks into each sub-module
|
||||
settingsModule.init(saveState);
|
||||
connectionsModule.init(saveState);
|
||||
@@ -127,6 +180,9 @@ module.exports = {
|
||||
setStoragePath,
|
||||
ensureStorageDir,
|
||||
setOnStateSaved,
|
||||
setStateSaveSuppressed,
|
||||
getStateSnapshot,
|
||||
applySnapshotData,
|
||||
// Settings
|
||||
getSettings: settingsModule.getSettings,
|
||||
updateSettings: settingsModule.updateSettings,
|
||||
|
||||
Reference in New Issue
Block a user