optimize ui loading and dashboard performance
This commit is contained in:
@@ -202,10 +202,10 @@ export class PrismaCdrsRepository implements CdrsRepository {
|
||||
|
||||
async list(query: CdrQuery): Promise<{ items: CdrListItem[]; meta: CdrPageMeta }> {
|
||||
const where = this.where(query);
|
||||
const [items, total] = await this.prisma.$transaction([
|
||||
const [items, total] = await Promise.all([
|
||||
this.prisma.rawCdr.findMany({
|
||||
where,
|
||||
orderBy: [{ startedAt: 'desc' }],
|
||||
orderBy: [{ startedAt: 'desc' }, { id: 'desc' }],
|
||||
take: query.take,
|
||||
skip: query.skip,
|
||||
include: this.includeCdr()
|
||||
|
||||
@@ -75,6 +75,15 @@ class MemoryCdrsRepository implements CdrsRepository {
|
||||
}
|
||||
|
||||
describe('CDR service', () => {
|
||||
it('uses a 25-row default page to keep the first list response small', async () => {
|
||||
const repository = new MemoryCdrsRepository();
|
||||
const service = new CdrsService(repository);
|
||||
|
||||
await service.list({});
|
||||
|
||||
expect(repository.lastQuery).toMatchObject({ take: 25, skip: 0 });
|
||||
});
|
||||
|
||||
it('normalizes filters for city, carrier and time range queries', async () => {
|
||||
const repository = new MemoryCdrsRepository();
|
||||
const service = new CdrsService(repository);
|
||||
|
||||
@@ -15,7 +15,7 @@ export class CdrsService {
|
||||
carrier: rawQuery.carrier === undefined ? undefined : this.carrier(rawQuery.carrier),
|
||||
startedFrom: this.optionalDate(rawQuery.startedFrom ?? rawQuery.startTime ?? rawQuery.from),
|
||||
startedTo: this.optionalDate(rawQuery.startedTo ?? rawQuery.endTime ?? rawQuery.to),
|
||||
take: this.int(rawQuery.take, 100, 1, 500),
|
||||
take: this.int(rawQuery.take, 25, 1, 500),
|
||||
skip: this.int(rawQuery.skip, 0, 0, 1_000_000)
|
||||
};
|
||||
if (query.startedFrom && query.startedTo && query.startedFrom > query.startedTo) {
|
||||
|
||||
@@ -14,6 +14,12 @@ export class DashboardController {
|
||||
return this.dashboardService.summary();
|
||||
}
|
||||
|
||||
@Get('overview')
|
||||
@RequirePermissions('dashboard.view')
|
||||
overview(@Query() query: { hours?: string; bucketMinutes?: string }) {
|
||||
return this.dashboardService.overview(query);
|
||||
}
|
||||
|
||||
@Get('trends')
|
||||
@RequirePermissions('dashboard.view')
|
||||
trends(@Query() query: { hours?: string; bucketMinutes?: string }) {
|
||||
|
||||
@@ -4,6 +4,22 @@ import { buildTrendBuckets, callMetrics, DashboardService, startOfShanghaiDayUtc
|
||||
import type { DashboardRepository } from './dashboard.repository.js';
|
||||
|
||||
describe('dashboard service', () => {
|
||||
it('loads summary and trends together for the overview response', async () => {
|
||||
const repository = {
|
||||
summaryWindow: async () => ({
|
||||
cdrs: [], ratedCdrs: [], failureCodes: [], abnormalGateways: [],
|
||||
activeCustomers: 0, activeCustomerGateways: 0, activeVendorGateways: 0, pendingQuality: 0
|
||||
}),
|
||||
trendWindow: async () => ({ cdrs: [], ratedCdrs: [] })
|
||||
} as unknown as DashboardRepository;
|
||||
const service = new DashboardService(repository);
|
||||
|
||||
const result = await service.overview({ hours: 1, bucketMinutes: 60 });
|
||||
|
||||
expect(result.summary).toHaveProperty('calls.totalCalls', 0);
|
||||
expect(result.trends.buckets).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('uses Asia/Shanghai day boundary for today summary', async () => {
|
||||
const calls: Array<{ start: Date; end: Date }> = [];
|
||||
const repository = {
|
||||
|
||||
@@ -36,6 +36,14 @@ export interface DashboardTrendBucket {
|
||||
export class DashboardService {
|
||||
constructor(@Inject(DASHBOARD_REPOSITORY) private readonly dashboard: DashboardRepository) {}
|
||||
|
||||
async overview(query: { hours?: unknown; bucketMinutes?: unknown } = {}) {
|
||||
const [summary, trends] = await Promise.all([
|
||||
this.summary(),
|
||||
this.trends(query)
|
||||
]);
|
||||
return { summary, trends };
|
||||
}
|
||||
|
||||
async summary(now = new Date()) {
|
||||
const start = startOfShanghaiDayUtc(now);
|
||||
const snapshot = await this.dashboard.summaryWindow(start, now);
|
||||
|
||||
Reference in New Issue
Block a user