import { and, lt, isNull } from 'drizzle-orm' import { carts } from '../database/schema' /** * Cart Cleanup Utilities * * These functions prepare the structure for automatic cart cleanup. * The actual cleanup job will be implemented in a later phase using BullMQ. * * Cleanup Strategy: * - User carts: Keep until updated_at > CART_EXPIRY_DAYS * - Guest carts: Keep until updated_at > CART_EXPIRY_DAYS * - Rationale: Inactive carts consume database space and should be pruned * * Future Implementation: * - BullMQ scheduled job runs daily at night (e.g., 3 AM) * - Calls getExpiredCarts() to find carts to delete * - Deletes expired carts (cascade deletes cart_items automatically) * - Logs cleanup statistics for monitoring */ /** * Get carts that are older than the configured expiry period * * @returns Array of expired cart IDs */ export async function getExpiredCarts(): Promise { const db = useDatabase() const config = useRuntimeConfig() // Calculate expiry date const expiryDays = config.cart.expiryDays const expiryDate = new Date() expiryDate.setDate(expiryDate.getDate() - expiryDays) // Find carts not updated since expiry date const expiredCarts = await db .select({ id: carts.id }) .from(carts) .where(lt(carts.updatedAt, expiryDate)) return expiredCarts.map((cart) => cart.id) } /** * Delete expired carts * * Note: cart_items are automatically deleted via CASCADE foreign key constraint * * @param cartIds - Array of cart UUIDs to delete * @returns Number of carts deleted */ export async function deleteExpiredCarts(cartIds: string[]): Promise { if (cartIds.length === 0) { return 0 } const db = useDatabase() // Delete carts (cart_items cascade automatically) const result = await db .delete(carts) .where( and( ...cartIds.map((id) => eq(carts.id, id)) ) ) return cartIds.length } /** * Get cleanup statistics * * @returns Statistics about carts in the database */ export async function getCartStatistics() { const db = useDatabase() const config = useRuntimeConfig() // Calculate expiry date const expiryDays = config.cart.expiryDays const expiryDate = new Date() expiryDate.setDate(expiryDate.getDate() - expiryDays) // Count carts by type const [totalCarts] = await db.select({ count: count() }).from(carts) const [userCarts] = await db .select({ count: count() }) .from(carts) .where(isNull(carts.userId).not()) const [guestCarts] = await db .select({ count: count() }) .from(carts) .where(isNull(carts.userId)) const [expiredCarts] = await db .select({ count: count() }) .from(carts) .where(lt(carts.updatedAt, expiryDate)) return { totalCarts: totalCarts?.count || 0, userCarts: userCarts?.count || 0, guestCarts: guestCarts?.count || 0, expiredCarts: expiredCarts?.count || 0, expiryDays, expiryDate: expiryDate.toISOString(), } } // Note: Import count function import { count } from 'drizzle-orm' import { eq } from 'drizzle-orm'