You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
3.0 KiB
116 lines
3.0 KiB
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<string[]> {
|
|
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<number> {
|
|
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'
|
|
|