mirror of
https://github.com/xtr-dev/rondevu-server.git
synced 2025-12-10 02:43:24 +00:00
feat: Implement content-based offer IDs with SHA-256 hashing
- Added hash-id.ts utility for SHA-256 content hashing
- Offer IDs now generated from hash of {sdp, topics} (sorted)
- Removed peerId from hash (inferred from authentication)
- Server generates deterministic IDs for idempotent offer creation
- Updated SQLite and D1 storage implementations
- Removed optional id field from CreateOfferRequest
- Same offer content always produces same ID
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
75
src/index.ts
Normal file
75
src/index.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { serve } from '@hono/node-server';
|
||||
import { createApp } from './app.ts';
|
||||
import { loadConfig } from './config.ts';
|
||||
import { SQLiteStorage } from './storage/sqlite.ts';
|
||||
import { Storage } from './storage/types.ts';
|
||||
|
||||
/**
|
||||
* Main entry point for the standalone Node.js server
|
||||
*/
|
||||
async function main() {
|
||||
const config = loadConfig();
|
||||
|
||||
console.log('Starting Rondevu server...');
|
||||
console.log('Configuration:', {
|
||||
port: config.port,
|
||||
storageType: config.storageType,
|
||||
storagePath: config.storagePath,
|
||||
offerDefaultTtl: `${config.offerDefaultTtl}ms`,
|
||||
offerMaxTtl: `${config.offerMaxTtl}ms`,
|
||||
offerMinTtl: `${config.offerMinTtl}ms`,
|
||||
cleanupInterval: `${config.cleanupInterval}ms`,
|
||||
maxOffersPerRequest: config.maxOffersPerRequest,
|
||||
maxTopicsPerOffer: config.maxTopicsPerOffer,
|
||||
corsOrigins: config.corsOrigins,
|
||||
version: config.version,
|
||||
});
|
||||
|
||||
let storage: Storage;
|
||||
|
||||
if (config.storageType === 'sqlite') {
|
||||
storage = new SQLiteStorage(config.storagePath);
|
||||
console.log('Using SQLite storage');
|
||||
} else {
|
||||
throw new Error('Unsupported storage type');
|
||||
}
|
||||
|
||||
// Start periodic cleanup of expired offers
|
||||
const cleanupInterval = setInterval(async () => {
|
||||
try {
|
||||
const now = Date.now();
|
||||
const deleted = await storage.deleteExpiredOffers(now);
|
||||
if (deleted > 0) {
|
||||
console.log(`Cleanup: Deleted ${deleted} expired offer(s)`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Cleanup error:', err);
|
||||
}
|
||||
}, config.cleanupInterval);
|
||||
|
||||
const app = createApp(storage, config);
|
||||
|
||||
const server = serve({
|
||||
fetch: app.fetch,
|
||||
port: config.port,
|
||||
});
|
||||
|
||||
console.log(`Server running on http://localhost:${config.port}`);
|
||||
console.log('Ready to accept connections');
|
||||
|
||||
// Graceful shutdown handler
|
||||
const shutdown = async () => {
|
||||
console.log('\nShutting down gracefully...');
|
||||
clearInterval(cleanupInterval);
|
||||
await storage.close();
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
process.on('SIGINT', shutdown);
|
||||
process.on('SIGTERM', shutdown);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error('Fatal error:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user