feat(storage): add offline data validation and strengthen storage/index integrity checks

This commit is contained in:
2026-04-05 02:46:05 +00:00
parent b8567ebe08
commit 418e8dc052
13 changed files with 724 additions and 41 deletions

View File

@@ -1,4 +1,6 @@
import * as crypto from 'crypto';
import * as fs from 'fs/promises';
import * as net from 'net';
import * as path from 'path';
import * as os from 'os';
import { SmartdbServer } from '../ts_smartdb/index.js';
@@ -66,6 +68,55 @@ export class LocalSmartDb {
return path.join(os.tmpdir(), `smartdb-${randomId}.sock`);
}
/**
* Check if a Unix socket is alive by attempting to connect.
*/
private static isSocketAlive(socketPath: string): Promise<boolean> {
return new Promise((resolve) => {
const client = net.createConnection({ path: socketPath }, () => {
client.destroy();
resolve(true);
});
client.on('error', () => {
resolve(false);
});
client.setTimeout(500, () => {
client.destroy();
resolve(false);
});
});
}
/**
* Remove stale smartdb-*.sock files from /tmp.
* A socket is considered stale if connecting to it fails.
*/
private static async cleanStaleSockets(): Promise<void> {
const tmpDir = os.tmpdir();
let entries: string[];
try {
entries = await fs.readdir(tmpDir);
} catch {
return;
}
const socketFiles = entries.filter(
(f) => f.startsWith('smartdb-') && f.endsWith('.sock')
);
for (const name of socketFiles) {
const fullPath = path.join(tmpDir, name);
try {
const stat = await fs.stat(fullPath);
if (!stat.isSocket()) continue;
const alive = await LocalSmartDb.isSocketAlive(fullPath);
if (!alive) {
await fs.unlink(fullPath);
}
} catch {
// File may have been removed already; ignore
}
}
}
/**
* Start the local SmartDB server and return connection info
*/
@@ -74,6 +125,9 @@ export class LocalSmartDb {
throw new Error('LocalSmartDb is already running');
}
// Clean up stale sockets from previous crashed instances
await LocalSmartDb.cleanStaleSockets();
// Run storage migration before starting the Rust engine
const migrator = new StorageMigrator(this.options.folderPath);
await migrator.run();