189 lines
6.3 KiB
JavaScript
189 lines
6.3 KiB
JavaScript
const sqliteClient = require('../../services/sqliteClient');
|
|
|
|
function getById(id) {
|
|
const db = sqliteClient.getDb();
|
|
return new Promise((resolve, reject) => {
|
|
db.get('SELECT * FROM sessions WHERE id = ?', [id], (err, row) => {
|
|
if (err) reject(err);
|
|
else resolve(row);
|
|
});
|
|
});
|
|
}
|
|
|
|
function create(uid, type = 'ask') {
|
|
const db = sqliteClient.getDb();
|
|
return new Promise((resolve, reject) => {
|
|
const sessionId = require('crypto').randomUUID();
|
|
const now = Math.floor(Date.now() / 1000);
|
|
const query = `INSERT INTO sessions (id, uid, title, session_type, started_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)`;
|
|
|
|
db.run(query, [sessionId, uid, `Session @ ${new Date().toLocaleTimeString()}`, type, now, now], function(err) {
|
|
if (err) {
|
|
console.error('SQLite: Failed to create session:', err);
|
|
reject(err);
|
|
} else {
|
|
console.log(`SQLite: Created session ${sessionId} for user ${uid} (type: ${type})`);
|
|
resolve(sessionId);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function getAllByUserId(uid) {
|
|
const db = sqliteClient.getDb();
|
|
return new Promise((resolve, reject) => {
|
|
const query = "SELECT id, uid, title, session_type, started_at, ended_at, sync_state, updated_at FROM sessions WHERE uid = ? ORDER BY started_at DESC";
|
|
db.all(query, [uid], (err, rows) => {
|
|
if (err) reject(err);
|
|
else resolve(rows);
|
|
});
|
|
});
|
|
}
|
|
|
|
function updateTitle(id, title) {
|
|
const db = sqliteClient.getDb();
|
|
return new Promise((resolve, reject) => {
|
|
db.run('UPDATE sessions SET title = ? WHERE id = ?', [title, id], function(err) {
|
|
if (err) reject(err);
|
|
else resolve({ changes: this.changes });
|
|
});
|
|
});
|
|
}
|
|
|
|
function deleteWithRelatedData(id) {
|
|
const db = sqliteClient.getDb();
|
|
return new Promise((resolve, reject) => {
|
|
db.serialize(() => {
|
|
db.run("BEGIN TRANSACTION;");
|
|
const queries = [
|
|
"DELETE FROM transcripts WHERE session_id = ?",
|
|
"DELETE FROM ai_messages WHERE session_id = ?",
|
|
"DELETE FROM summaries WHERE session_id = ?",
|
|
"DELETE FROM sessions WHERE id = ?"
|
|
];
|
|
queries.forEach(query => {
|
|
db.run(query, [id], (err) => {
|
|
if (err) {
|
|
db.run("ROLLBACK;");
|
|
return reject(err);
|
|
}
|
|
});
|
|
});
|
|
db.run("COMMIT;", (err) => {
|
|
if (err) {
|
|
db.run("ROLLBACK;");
|
|
return reject(err);
|
|
}
|
|
resolve({ success: true });
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
function end(id) {
|
|
const db = sqliteClient.getDb();
|
|
return new Promise((resolve, reject) => {
|
|
const now = Math.floor(Date.now() / 1000);
|
|
const query = `UPDATE sessions SET ended_at = ?, updated_at = ? WHERE id = ?`;
|
|
db.run(query, [now, now, id], function(err) {
|
|
if (err) reject(err);
|
|
else resolve({ changes: this.changes });
|
|
});
|
|
});
|
|
}
|
|
|
|
function updateType(id, type) {
|
|
const db = sqliteClient.getDb();
|
|
return new Promise((resolve, reject) => {
|
|
const now = Math.floor(Date.now() / 1000);
|
|
const query = 'UPDATE sessions SET session_type = ?, updated_at = ? WHERE id = ?';
|
|
db.run(query, [type, now, id], function(err) {
|
|
if (err) {
|
|
reject(err);
|
|
} else {
|
|
resolve({ changes: this.changes });
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function touch(id) {
|
|
const db = sqliteClient.getDb();
|
|
return new Promise((resolve, reject) => {
|
|
const now = Math.floor(Date.now() / 1000);
|
|
const query = 'UPDATE sessions SET updated_at = ? WHERE id = ?';
|
|
db.run(query, [now, id], function(err) {
|
|
if (err) reject(err);
|
|
else resolve({ changes: this.changes });
|
|
});
|
|
});
|
|
}
|
|
|
|
async function getOrCreateActive(uid, requestedType = 'ask') {
|
|
const db = sqliteClient.getDb();
|
|
|
|
// 1. Look for ANY active session for the user (ended_at IS NULL).
|
|
// Prefer 'listen' sessions over 'ask' sessions to ensure continuity.
|
|
const findQuery = `
|
|
SELECT id, session_type FROM sessions
|
|
WHERE uid = ? AND ended_at IS NULL
|
|
ORDER BY CASE session_type WHEN 'listen' THEN 1 WHEN 'ask' THEN 2 ELSE 3 END
|
|
LIMIT 1
|
|
`;
|
|
|
|
const activeSession = await new Promise((resolve, reject) => {
|
|
db.get(findQuery, [uid], (err, row) => {
|
|
if (err) reject(err);
|
|
else resolve(row);
|
|
});
|
|
});
|
|
|
|
if (activeSession) {
|
|
// An active session exists.
|
|
console.log(`[Repo] Found active session ${activeSession.id} of type ${activeSession.session_type}`);
|
|
|
|
// 2. Promotion Logic: If it's an 'ask' session and we need 'listen', promote it.
|
|
if (activeSession.session_type === 'ask' && requestedType === 'listen') {
|
|
await updateType(activeSession.id, 'listen');
|
|
console.log(`[Repo] Promoted session ${activeSession.id} to 'listen' type.`);
|
|
}
|
|
|
|
// 3. Touch the session and return its ID.
|
|
await touch(activeSession.id);
|
|
return activeSession.id;
|
|
} else {
|
|
// 4. No active session found, create a new one.
|
|
console.log(`[Repo] No active session for user ${uid}. Creating new '${requestedType}' session.`);
|
|
return create(uid, requestedType);
|
|
}
|
|
}
|
|
|
|
function endAllActiveSessions() {
|
|
const db = sqliteClient.getDb();
|
|
return new Promise((resolve, reject) => {
|
|
const now = Math.floor(Date.now() / 1000);
|
|
const query = `UPDATE sessions SET ended_at = ?, updated_at = ? WHERE ended_at IS NULL`;
|
|
db.run(query, [now, now], function(err) {
|
|
if (err) {
|
|
console.error('SQLite: Failed to end all active sessions:', err);
|
|
reject(err);
|
|
} else {
|
|
console.log(`[Repo] Ended ${this.changes} active session(s).`);
|
|
resolve({ changes: this.changes });
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
module.exports = {
|
|
getById,
|
|
create,
|
|
getAllByUserId,
|
|
updateTitle,
|
|
deleteWithRelatedData,
|
|
end,
|
|
updateType,
|
|
touch,
|
|
getOrCreateActive,
|
|
endAllActiveSessions,
|
|
};
|