68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
import { createBatteriesResponse, createDashboardSnapshot } from '@/domain/battery'
|
|
import { os } from '@/server/api/server'
|
|
import {
|
|
getBatteryHistory,
|
|
getBatteryPredictionHistories,
|
|
getLatestBatteryPage,
|
|
getLatestBatteryPerDevice,
|
|
} from '@/server/battery/mysql'
|
|
import { isPredictionEnabled, predictSoh } from '@/server/prediction/client'
|
|
|
|
const dashboardPredictionConcurrency = 5
|
|
|
|
async function mapWithConcurrency<T, R>(
|
|
items: T[],
|
|
concurrency: number,
|
|
handler: (item: T) => Promise<R>,
|
|
): Promise<R[]> {
|
|
const results: R[] = []
|
|
let nextIndex = 0
|
|
|
|
async function worker() {
|
|
while (nextIndex < items.length) {
|
|
const index = nextIndex
|
|
nextIndex += 1
|
|
const item = items[index]
|
|
if (item !== undefined) results[index] = await handler(item)
|
|
}
|
|
}
|
|
|
|
await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, worker))
|
|
|
|
return results
|
|
}
|
|
|
|
export const dashboard = os.battery.dashboard.handler(async () => {
|
|
const items = await getLatestBatteryPerDevice()
|
|
const predictionHistories = isPredictionEnabled()
|
|
? await getBatteryPredictionHistories(items.map((item) => item.mac))
|
|
: new Map()
|
|
const predictionEntries = isPredictionEnabled()
|
|
? await mapWithConcurrency(items, dashboardPredictionConcurrency, async (item) => {
|
|
const prediction = await predictSoh(item, predictionHistories.get(item.mac) ?? [])
|
|
|
|
return prediction ? ([item.mac, prediction] as const) : null
|
|
})
|
|
: []
|
|
const predictions = new Map(predictionEntries.filter((entry) => entry !== null))
|
|
|
|
return createDashboardSnapshot(items, new Date(), predictions)
|
|
})
|
|
|
|
export const batteries = os.battery.batteries.handler(async ({ input }) => {
|
|
const page = await getLatestBatteryPage(input)
|
|
|
|
return createBatteriesResponse(
|
|
page.items,
|
|
new Date(),
|
|
{ total: page.total, lowPower: page.lowPower, charging: page.charging },
|
|
page.nextCursor,
|
|
)
|
|
})
|
|
|
|
export const history = os.battery.history.handler(async ({ input }) => {
|
|
const items = await getBatteryHistory(input.mac)
|
|
|
|
return createBatteriesResponse(items)
|
|
})
|