Skip to content

Instantly share code, notes, and snippets.

@maietta
Last active February 21, 2025 17:55
Show Gist options
  • Save maietta/463cb785234ed2b1fabf462228697d92 to your computer and use it in GitHub Desktop.
Save maietta/463cb785234ed2b1fabf462228697d92 to your computer and use it in GitHub Desktop.
This program uses limbo-wasm to create an in-memory SQLite database that tracks and logs changes to a users table using triggers and a polling listener.
import { Database } from 'limbo-wasm';
// Initialize Limbo database in memory
const db = new Database(':memory:');
// Function to initialize the database with error handling
function initializeDatabase() {
try {
db.exec(`
CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT);
CREATE TABLE IF NOT EXISTS change_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
table_name TEXT,
rowid INTEGER,
event_type TEXT,
ts INTEGER
);
CREATE TRIGGER IF NOT EXISTS user_insert AFTER INSERT ON users
BEGIN
INSERT INTO change_log (table_name, rowid, event_type, ts)
VALUES ('users', NEW.id, 'INSERT', strftime('%s', 'now'));
END;
CREATE TRIGGER IF NOT EXISTS user_update AFTER UPDATE ON users
BEGIN
INSERT INTO change_log (table_name, rowid, event_type, ts)
VALUES ('users', NEW.id, 'UPDATE', strftime('%s', 'now'));
END;
CREATE TRIGGER IF NOT EXISTS user_delete AFTER DELETE ON users
BEGIN
INSERT INTO change_log (table_name, rowid, event_type, ts)
VALUES ('users', OLD.id, 'DELETE', strftime('%s', 'now'));
END;
`);
console.log('Database schema initialized successfully');
// Verify tables exist
const tables = db.prepare("SELECT name FROM sqlite_master WHERE type='table'").all();
console.log('Tables in database:', tables);
} catch (e) {
console.error('Failed to initialize database:', e);
process.exit(1);
}
}
// Polling function to detect changes
let lastId = 0;
function startChangeListener() {
console.log('Starting change listener...');
try {
setInterval(() => {
const stmt = db.prepare(
'SELECT * FROM change_log WHERE id > ? AND table_name = "users" ORDER BY id DESC LIMIT 1'
);
const changes = stmt.all();
if (changes.length > 0) {
const change = changes[0];
console.log(
`[Change Detected] Event: ${change.event_type}, RowID: ${change.rowid}, Timestamp: ${change.ts}`
);
lastId = change.id;
}
}, 500); // Poll every 500ms
} catch (e) {
console.error('Error in change listener:', e);
}
}
// Simulate slow data population
function startDataPopulation() {
console.log('Starting data population...');
let counter = 1;
setInterval(() => {
try {
if (counter <= 5) {
db.exec(`INSERT INTO users (name) VALUES ('User-${counter}')`);
console.log(`Inserted User-${counter}`);
} else if (counter === 6) {
db.exec(`UPDATE users SET name = 'Updated-User-1' WHERE id = 1`);
console.log('Updated User-1');
} else if (counter === 7) {
db.exec(`DELETE FROM users WHERE id = 2`);
console.log('Deleted User-2');
}
counter++;
} catch (e) {
console.error('Error in data population:', e);
}
}, 1000); // Insert/update/delete every 1 second
}
// Main execution
console.log('Main process starting...');
initializeDatabase();
// Start listener and population after a short delay to ensure schema is ready
setTimeout(() => {
startChangeListener();
startDataPopulation();
}, 100); // 100ms delay
// Keep Bun alive
setInterval(() => {}, 1000);
// Cleanup on exit
process.on('SIGINT', () => {
db.free();
console.log('Database closed. Exiting...');
process.exit(0);
});
{
"dependencies": {
"limbo-wasm": "^0.0.14"
},
"devDependencies": {
"@types/bun": "^1.2.2"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment