Files
linux-odyssey/server/src/containers/expiryChecker.ts
T
Justin Lin 2feedc329c refactor: use bun for package management
+ add package.json to each packages
+ update import path
2026-10-11 16:50:01 +11:00

64 lines
2.0 KiB
TypeScript

import schedule from 'node-schedule'
import type { HydratedDocument } from 'mongoose'
import { Session } from '@odyssey/models'
import type { ISession } from '@odyssey/models'
import config from '../config.js'
import { deleteContainer } from './docker.js'
import logger from '../utils/logger.js'
async function disableSession(session: HydratedDocument<ISession>) {
if (!session.containerId) {
logger.warn(`Deleting session ${session._id} has no containerId`)
return
}
try {
await deleteContainer(session.containerId)
} catch (err) {
// Perform runtime check to safely access statusCode
if (typeof err === 'object' && err !== null && 'statusCode' in err) {
const error = err as { statusCode: number }
if (error.statusCode !== 404) {
throw new Error(
`Failed to delete container ${session.containerId} for session ${session._id}`
)
}
} else {
// Handle the case where err is not the expected type
logger.error(`An unexpected error occurred: ${err}`)
}
}
if (session.status === 'active') {
session.status = 'inactive'
}
session.containerId = null
try {
await session.save()
} catch (err) {
throw new Error(`Failed to save session ${session._id}\n${err}`)
}
}
export async function removeExpired() {
// Find all sessions that are containerId is not null and lastActivityAt is
// less than the current time minus the expiry time
try {
const sessions = await Session.find({
containerId: { $ne: null },
lastActivityAt: { $lt: new Date(Date.now() - config.containerExpiry) },
})
await Promise.all(
sessions.map((session) =>
disableSession(session).catch((err) => {
throw new Error(`Failed to expire session: ${session._id}\n${err}`)
})
)
)
} catch (err) {
logger.error('Remove expiring failed:', err)
}
}
export default function expiryRemovalScheduler() {
schedule.scheduleJob('*/5 * * * *', removeExpired)
}