Delete old sessions when VibeTunnel version changes (#254)

This commit is contained in:
Peter Steinberger 2025-07-07 00:05:26 +01:00 committed by GitHub
parent 9db8fd284b
commit 7e697d6774
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 129 additions and 0 deletions

View file

@ -32,6 +32,7 @@ import {
shouldInjectTitle,
} from '../utils/terminal-title.js';
import { WriteQueue } from '../utils/write-queue.js';
import { VERSION } from '../version.js';
import { AsciinemaWriter } from './asciinema-writer.js';
import { ProcessUtils } from './process-utils.js';
import { SessionManager } from './session-manager.js';
@ -244,6 +245,7 @@ export class PtyManager extends EventEmitter {
startedAt: new Date().toISOString(),
initialCols: cols,
initialRows: rows,
version: VERSION,
};
// Save initial session info

View file

@ -12,6 +12,7 @@ import * as os from 'os';
import * as path from 'path';
import type { Session, SessionInfo } from '../../shared/types.js';
import { createLogger } from '../utils/logger.js';
import { VERSION } from '../version.js';
import { ProcessUtils } from './process-utils.js';
import { PtyError } from './types.js';
@ -49,6 +50,44 @@ export class SessionManager {
}
}
/**
* Get the path to the version tracking file
*/
private getVersionFilePath(): string {
return path.join(this.controlPath, '.version');
}
/**
* Read the last known version from the version file
*/
private readLastVersion(): string | null {
try {
const versionFile = this.getVersionFilePath();
if (fs.existsSync(versionFile)) {
const content = fs.readFileSync(versionFile, 'utf8').trim();
logger.debug(`read last version from file: ${content}`);
return content;
}
return null;
} catch (error) {
logger.warn(`failed to read version file: ${error}`);
return null;
}
}
/**
* Write the current version to the version file
*/
private writeCurrentVersion(): void {
try {
const versionFile = this.getVersionFilePath();
fs.writeFileSync(versionFile, VERSION, 'utf8');
logger.debug(`wrote current version to file: ${VERSION}`);
} catch (error) {
logger.warn(`failed to write version file: ${error}`);
}
}
/**
* Create a new session directory structure
*/
@ -396,6 +435,76 @@ export class SessionManager {
}
}
/**
* Cleanup sessions from old VibeTunnel versions
* This is called during server startup to clean sessions when version changes
*/
cleanupOldVersionSessions(): { versionChanged: boolean; cleanedCount: number } {
const lastVersion = this.readLastVersion();
const currentVersion = VERSION;
// If no version file exists, this is likely a fresh install or first time with version tracking
if (!lastVersion) {
logger.debug('no previous version found, checking for legacy sessions');
// Clean up any sessions without version field
let cleanedCount = 0;
const sessions = this.listSessions();
for (const session of sessions) {
if (!session.version) {
logger.debug(`cleaning up legacy session ${session.id} (no version field)`);
this.cleanupSession(session.id);
cleanedCount++;
}
}
this.writeCurrentVersion();
return { versionChanged: false, cleanedCount };
}
// If version hasn't changed, nothing to do
if (lastVersion === currentVersion) {
logger.debug(`version unchanged (${currentVersion}), skipping cleanup`);
return { versionChanged: false, cleanedCount: 0 };
}
logger.log(chalk.yellow(`VibeTunnel version changed from ${lastVersion} to ${currentVersion}`));
logger.log(chalk.yellow('cleaning up old sessions...'));
let cleanedCount = 0;
try {
const sessions = this.listSessions();
for (const session of sessions) {
// Clean all sessions that don't match the current version
// Sessions without version field are considered old
if (!session.version || session.version !== currentVersion) {
logger.debug(
`cleaning up session ${session.id} (version: ${session.version || 'unknown'})`
);
this.cleanupSession(session.id);
cleanedCount++;
}
}
// Update the version file to current version
this.writeCurrentVersion();
if (cleanedCount > 0) {
logger.log(chalk.green(`cleaned up ${cleanedCount} sessions from previous version`));
} else {
logger.log(chalk.gray('no old sessions to clean up'));
}
return { versionChanged: true, cleanedCount };
} catch (error) {
logger.error(`failed to cleanup old version sessions: ${error}`);
// Still update version file to prevent repeated cleanup attempts
this.writeCurrentVersion();
return { versionChanged: true, cleanedCount };
}
}
/**
* Get session paths for a given session ID
*/

View file

@ -396,6 +396,23 @@ export async function createApp(): Promise<AppInstance> {
const ptyManager = new PtyManager(CONTROL_DIR);
logger.debug('Initialized PTY manager');
// Clean up sessions from old VibeTunnel versions
const sessionManager = ptyManager.getSessionManager();
const cleanupResult = sessionManager.cleanupOldVersionSessions();
if (cleanupResult.versionChanged) {
logger.log(
chalk.yellow(
`Version change detected - cleaned up ${cleanupResult.cleanedCount} sessions from previous version`
)
);
} else if (cleanupResult.cleanedCount > 0) {
logger.log(
chalk.yellow(
`Cleaned up ${cleanupResult.cleanedCount} legacy sessions without version information`
)
);
}
// Initialize Terminal Manager for server-side terminal state
const terminalManager = new TerminalManager(CONTROL_DIR);
logger.debug('Initialized terminal manager');

View file

@ -22,6 +22,7 @@ export interface SessionInfo {
pid?: number;
initialCols?: number;
initialRows?: number;
version?: string; // VibeTunnel version that created this session
}
/**