feat: new session update

This commit is contained in:
Steve Korshakov 2025-07-13 13:18:01 -07:00
parent b0735b28a3
commit 4853e0ed52
2 changed files with 89 additions and 40 deletions

View File

@ -124,7 +124,6 @@ export async function startApi() {
take: 150, take: 150,
select: { select: {
id: true, id: true,
tag: true,
seq: true, seq: true,
createdAt: true, createdAt: true,
updatedAt: true, updatedAt: true,
@ -144,7 +143,6 @@ export async function startApi() {
return reply.send({ return reply.send({
sessions: sessions.map((v) => ({ sessions: sessions.map((v) => ({
id: v.id, id: v.id,
tag: v.tag,
seq: v.seq, seq: v.seq,
createdAt: v.createdAt.getTime(), createdAt: v.createdAt.getTime(),
updatedAt: v.updatedAt.getTime(), updatedAt: v.updatedAt.getTime(),
@ -170,36 +168,81 @@ export async function startApi() {
const userId = request.user.id; const userId = request.user.id;
const { tag } = request.body; const { tag } = request.body;
const session = await db.session.upsert({ const session = await db.session.findFirst({
where: { where: {
accountId_tag: {
accountId: userId,
tag: tag
}
},
update: {},
create: {
accountId: userId, accountId: userId,
tag: tag tag: tag
},
select: {
id: true,
tag: true,
seq: true,
createdAt: true,
updatedAt: true
} }
}); });
if (session) {
return reply.send({
session: {
id: session.id,
seq: session.seq,
createdAt: session.createdAt.getTime(),
updatedAt: session.updatedAt.getTime()
}
});
} else {
// Create new session with update
const result = await db.$transaction(async (tx) => {
// Get user for update sequence
const user = await tx.account.findUnique({
where: { id: userId }
});
return reply.send({ if (!user) {
session: { throw new Error('User not found');
id: session.id, }
tag: session.tag,
seq: session.seq, const updSeq = user.seq + 1;
createdAt: session.createdAt.getTime(),
updatedAt: session.updatedAt.getTime() // Create session
} const session = await tx.session.create({
}); data: {
accountId: userId,
tag: tag
}
});
// Create update
const updContent: PrismaJson.UpdateBody = {
t: 'new-session',
id: session.id,
seq: session.seq,
createdAt: session.createdAt.getTime(),
updatedAt: session.updatedAt.getTime()
};
const update = await tx.update.create({
data: {
accountId: userId,
seq: updSeq,
content: updContent
}
});
// Update user sequence
await tx.account.update({
where: { id: userId },
data: { seq: updSeq }
});
return { session, update };
});
// Emit update to connected sockets
pubsub.emit('update', userId, result.update);
return reply.send({
session: {
id: result.session.id,
seq: result.session.seq,
createdAt: result.session.createdAt.getTime(),
updatedAt: result.session.updatedAt.getTime()
}
});
}
}); });
// Messages API // Messages API
@ -258,7 +301,7 @@ export async function startApi() {
if (!app.server) { if (!app.server) {
throw new Error('Fastify server not available'); throw new Error('Fastify server not available');
} }
const io = new Server(app.server, { const io = new Server(app.server, {
cors: { cors: {
origin: "*", origin: "*",
@ -275,7 +318,7 @@ export async function startApi() {
connectTimeout: 20000, connectTimeout: 20000,
serveClient: false // Don't serve the client files serveClient: false // Don't serve the client files
}); });
// Track connected users // Track connected users
const userSockets = new Map<string, Set<Socket>>(); const userSockets = new Map<string, Set<Socket>>();
@ -350,7 +393,7 @@ export async function startApi() {
t: 'encrypted', t: 'encrypted',
c: message c: message
}; };
// Start transaction to ensure consistency // Start transaction to ensure consistency
const result = await db.$transaction(async (tx) => { const result = await db.$transaction(async (tx) => {
@ -365,20 +408,20 @@ export async function startApi() {
if (!session) { if (!session) {
throw new Error('Session not found'); throw new Error('Session not found');
} }
// Get user for update // Get user for update
const user = await tx.account.findUnique({ const user = await tx.account.findUnique({
where: { id: userId } where: { id: userId }
}); });
if (!user) { if (!user) {
throw new Error('User not found'); throw new Error('User not found');
} }
// Get next sequence numbers // Get next sequence numbers
const msgSeq = session.seq + 1; const msgSeq = session.seq + 1;
const updSeq = user.seq + 1; const updSeq = user.seq + 1;
// Create message // Create message
const msg = await tx.sessionMessage.create({ const msg = await tx.sessionMessage.create({
data: { data: {
@ -387,7 +430,7 @@ export async function startApi() {
content: msgContent content: msgContent
} }
}); });
// Create update // Create update
const updContent: PrismaJson.UpdateBody = { const updContent: PrismaJson.UpdateBody = {
t: 'new-message', t: 'new-message',
@ -395,7 +438,7 @@ export async function startApi() {
mid: msg.id, mid: msg.id,
c: msgContent c: msgContent
}; };
const update = await tx.update.create({ const update = await tx.update.create({
data: { data: {
accountId: userId, accountId: userId,
@ -403,18 +446,18 @@ export async function startApi() {
content: updContent content: updContent
} }
}); });
// Update sequences // Update sequences
await tx.session.update({ await tx.session.update({
where: { id: sid }, where: { id: sid },
data: { seq: msgSeq } data: { seq: msgSeq }
}); });
await tx.account.update({ await tx.account.update({
where: { id: userId }, where: { id: userId },
data: { seq: updSeq } data: { seq: updSeq }
}); });
return { msg, update }; return { msg, update };
}).catch((error) => { }).catch((error) => {
if (error.message === 'Session not found') { if (error.message === 'Session not found') {
@ -422,9 +465,9 @@ export async function startApi() {
} }
throw error; throw error;
}); });
if (!result) return; if (!result) return;
// Emit update to connected sockets // Emit update to connected sockets
pubsub.emit('update', userId, result.update); pubsub.emit('update', userId, result.update);
}); });

View File

@ -12,6 +12,12 @@ declare global {
sid: string; sid: string;
mid: string; mid: string;
c: SessionMessageContent; c: SessionMessageContent;
} | {
t: 'new-session';
id: string;
seq: number;
createdAt: number;
updatedAt: number;
}; };
} }
} }