feat(storage): add offline data validation and strengthen storage/index integrity checks
This commit is contained in:
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@push.rocks/smartdb',
|
||||
version: '2.4.1',
|
||||
version: '2.5.0',
|
||||
description: 'A MongoDB-compatible embedded database server with wire protocol support, backed by a high-performance Rust engine.'
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user