159 lines
3.9 KiB
JavaScript
159 lines
3.9 KiB
JavaScript
/**
|
|
* 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 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 = '') {
|
|
const id = crypto.randomUUID()
|
|
const now = Date.now()
|
|
const session = {
|
|
id,
|
|
userId,
|
|
label: (label || 'Live').trim() || 'Live',
|
|
lat: 0,
|
|
lng: 0,
|
|
updatedAt: now,
|
|
routerId: null,
|
|
producerId: null,
|
|
transportId: null,
|
|
}
|
|
sessions.set(id, session)
|
|
return session
|
|
}
|
|
|
|
/**
|
|
* @param {string} id
|
|
* @returns {LiveSession | undefined} The session or undefined.
|
|
*/
|
|
export function getLiveSession(id) {
|
|
return 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) {
|
|
const now = Date.now()
|
|
for (const [, s] of sessions) {
|
|
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) {
|
|
const session = sessions.get(id)
|
|
if (!session) return
|
|
const now = Date.now()
|
|
if (Number.isFinite(updates.lat)) session.lat = updates.lat
|
|
if (Number.isFinite(updates.lng)) session.lng = updates.lng
|
|
if (updates.routerId !== undefined) session.routerId = updates.routerId
|
|
if (updates.producerId !== undefined) session.producerId = updates.producerId
|
|
if (updates.transportId !== undefined) session.transportId = updates.transportId
|
|
session.updatedAt = now
|
|
}
|
|
|
|
/**
|
|
* @param {string} id
|
|
*/
|
|
export function deleteLiveSession(id) {
|
|
sessions.delete(id)
|
|
}
|
|
|
|
/**
|
|
* 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() {
|
|
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),
|
|
})
|
|
}
|
|
else {
|
|
expiredIds.push(id)
|
|
}
|
|
}
|
|
// 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)
|
|
}
|
|
}
|
|
return result
|
|
}
|