improve db
Some checks failed
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline failed

This commit is contained in:
Madison Grubb
2026-02-12 13:28:36 -05:00
parent 9d153c852d
commit fbb38c5dd7
17 changed files with 292 additions and 654 deletions

View File

@@ -1,43 +1,17 @@
/**
* In-memory store for live sharing sessions (camera + location).
* Sessions expire after TTL_MS without an update.
*/
import { closeRouter, getProducer, getTransport } from './mediasoup.js'
const TTL_MS = 60_000 // 60 seconds without update = inactive
const TTL_MS = 60_000
const sessions = new Map()
/**
* @typedef {{
* id: string
* userId: string
* label: string
* lat: number
* lng: number
* updatedAt: number
* routerId: string | null
* producerId: string | null
* transportId: string | null
* }} LiveSession
*/
/**
* @param {string} userId
* @param {string} [label]
* @returns {LiveSession} The created live session.
*/
export function createSession(userId, label = '') {
export const createSession = (userId, label = '') => {
const id = crypto.randomUUID()
const now = Date.now()
const session = {
id,
userId,
label: (label || 'Live').trim() || 'Live',
lat: 0,
lng: 0,
updatedAt: now,
updatedAt: Date.now(),
routerId: null,
producerId: null,
transportId: null,
@@ -46,34 +20,16 @@ export function createSession(userId, label = '') {
return session
}
/**
* @param {string} id
* @returns {LiveSession | undefined} The session or undefined.
*/
export function getLiveSession(id) {
return sessions.get(id)
}
export const getLiveSession = (id) => sessions.get(id)
/**
* Get an existing active session for a user (for replacing with a new one).
* @param {string} userId
* @returns {LiveSession | undefined} The first active session for the user, or undefined.
*/
export function getActiveSessionByUserId(userId) {
export const getActiveSessionByUserId = (userId) => {
const now = Date.now()
for (const [, s] of sessions) {
if (s.userId === userId && now - s.updatedAt <= TTL_MS) {
return s
}
for (const s of sessions.values()) {
if (s.userId === userId && now - s.updatedAt <= TTL_MS) return s
}
return undefined
}
/**
* @param {string} id
* @param {{ lat?: number, lng?: number, routerId?: string | null, producerId?: string | null, transportId?: string | null }} updates
*/
export function updateLiveSession(id, updates) {
export const updateLiveSession = (id, updates) => {
const session = sessions.get(id)
if (!session) return
const now = Date.now()
@@ -85,74 +41,52 @@ export function updateLiveSession(id, updates) {
session.updatedAt = now
}
/**
* @param {string} id
*/
export function deleteLiveSession(id) {
sessions.delete(id)
export const deleteLiveSession = (id) => sessions.delete(id)
export const clearSessions = () => sessions.clear()
const cleanupSession = async (session) => {
if (session.producerId) {
const producer = getProducer(session.producerId)
producer?.close()
}
if (session.transportId) {
const transport = getTransport(session.transportId)
transport?.close()
}
if (session.routerId) {
await closeRouter(session.id).catch((err) => {
console.error(`[liveSessions] Error closing router for expired session ${session.id}:`, err)
})
}
}
/**
* Clear all sessions (for tests only).
*/
export function clearSessions() {
sessions.clear()
}
/**
* Returns sessions updated within TTL_MS (active only).
* Also cleans up expired sessions.
* @returns {Promise<Array<{ id: string, userId: string, label: string, lat: number, lng: number, updatedAt: number, hasStream: boolean }>>} Active sessions with hasStream flag.
*/
export async function getActiveSessions() {
export const getActiveSessions = async () => {
const now = Date.now()
const result = []
const expiredIds = []
for (const [id, s] of sessions) {
if (now - s.updatedAt <= TTL_MS) {
result.push({
id: s.id,
userId: s.userId,
label: s.label,
lat: s.lat,
lng: s.lng,
updatedAt: s.updatedAt,
hasStream: Boolean(s.producerId),
const active = []
const expired = []
for (const session of sessions.values()) {
if (now - session.updatedAt <= TTL_MS) {
active.push({
id: session.id,
userId: session.userId,
label: session.label,
lat: session.lat,
lng: session.lng,
updatedAt: session.updatedAt,
hasStream: Boolean(session.producerId),
})
}
else {
expiredIds.push(id)
expired.push(session)
}
}
// Clean up expired sessions and their WebRTC resources
for (const id of expiredIds) {
const session = sessions.get(id)
if (session) {
// Clean up producer if it exists
if (session.producerId) {
const producer = getProducer(session.producerId)
if (producer) {
producer.close()
}
}
// Clean up transport if it exists
if (session.transportId) {
const transport = getTransport(session.transportId)
if (transport) {
transport.close()
}
}
// Clean up router
if (session.routerId) {
await closeRouter(id).catch((err) => {
console.error(`[liveSessions] Error closing router for expired session ${id}:`, err)
})
}
sessions.delete(id)
}
for (const session of expired) {
await cleanupSession(session)
sessions.delete(session.id)
}
return result
return active
}