import mysql, { type Pool, type RowDataPacket } from 'mysql2/promise' import { type BatteryInfo, type BatteryInfoSourceRow, toBatteryInfo } from '@/domain/battery' import { env } from '@/env' const historyLimit = 500 const predictionHistoryLimit = 10 type BatteryInfoMysqlRow = RowDataPacket & BatteryInfoSourceRow let pool: Pool | undefined function getBatteryPool() { pool ??= mysql.createPool({ uri: env.DATABASE_URL, waitForConnections: true, connectionLimit: 5, namedPlaceholders: true, }) return pool } export async function closeBatteryPool() { if (!pool) return await pool.end() pool = undefined } const sourceColumns = ` id, user_id AS userId, mac, dev_model AS devModel, dev_name AS devName, is_low_power AS isLowPower, power_status AS powerStatus, power, create_time AS createTime, remark ` export async function getBatteryHistory(mac: string): Promise { const [rows] = await getBatteryPool().query( ` SELECT ${sourceColumns} FROM ls_battery_info WHERE mac = :mac ORDER BY create_time DESC, id DESC LIMIT :limit `, { mac, limit: historyLimit }, ) return rows.map(toBatteryInfo) } export async function getBatteryPredictionHistory(mac: string): Promise { const [rows] = await getBatteryPool().query( ` SELECT ${sourceColumns} FROM ls_battery_info WHERE mac = :mac ORDER BY create_time DESC, id DESC LIMIT :limit `, { mac, limit: predictionHistoryLimit }, ) return rows.map(toBatteryInfo).reverse() } export async function getLatestBatteryPerDevice(): Promise { const [rows] = await getBatteryPool().query(` SELECT ${sourceColumns} FROM ls_battery_info AS current_record WHERE NOT EXISTS ( SELECT 1 FROM ls_battery_info AS newer_record WHERE newer_record.mac = current_record.mac AND ( newer_record.create_time > current_record.create_time OR (newer_record.create_time = current_record.create_time AND newer_record.id > current_record.id) ) ) ORDER BY current_record.create_time DESC, current_record.id DESC `) return rows.map(toBatteryInfo) }