feat(mysql): 接入只读电池数据源
This commit is contained in:
+1
-1
@@ -3,7 +3,7 @@ import { z } from 'zod'
|
|||||||
|
|
||||||
export const env = createEnv({
|
export const env = createEnv({
|
||||||
server: {
|
server: {
|
||||||
DATABASE_URL: z.url({ protocol: /^postgres(ql)?$/ }),
|
DATABASE_URL: z.url({ protocol: /^mysql$/ }),
|
||||||
LOG_DB: z.stringbool().default(false),
|
LOG_DB: z.stringbool().default(false),
|
||||||
LOG_FORMAT: z.enum(['pretty', 'json']).optional(),
|
LOG_FORMAT: z.enum(['pretty', 'json']).optional(),
|
||||||
LOG_LEVEL: z.enum(['trace', 'debug', 'info', 'warning', 'error', 'fatal']).default('info'),
|
LOG_LEVEL: z.enum(['trace', 'debug', 'info', 'warning', 'error', 'fatal']).default('info'),
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
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<BatteryInfo[]> {
|
||||||
|
const [rows] = await getBatteryPool().query<BatteryInfoMysqlRow[]>(
|
||||||
|
`
|
||||||
|
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 getLatestBatteryPerDevice(): Promise<BatteryInfo[]> {
|
||||||
|
const [rows] = await getBatteryPool().query<BatteryInfoMysqlRow[]>(`
|
||||||
|
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)
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { db } from '@/server/db'
|
import { closeBatteryPool } from '@/server/battery/mysql'
|
||||||
import { getLogger } from '@/server/logger'
|
import { getLogger } from '@/server/logger'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
@@ -17,8 +17,8 @@ export default () => {
|
|||||||
|
|
||||||
await Bun.sleep(500)
|
await Bun.sleep(500)
|
||||||
try {
|
try {
|
||||||
await db.$client.end()
|
await closeBatteryPool()
|
||||||
logger.info('DB pool closed, exiting')
|
logger.info('Battery MySQL pool closed, exiting')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('DB pool close failed during shutdown', { error })
|
logger.error('DB pool close failed during shutdown', { error })
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user