mirror of
https://github.com/apricote/Listory.git
synced 2026-01-13 13:11:02 +00:00
feat: improve listens report response time
Reduce response time for larger intervals (e.g. all time) from 9 seconds to 150ms in my tests.
This commit is contained in:
parent
26087e4e6d
commit
89440daf7b
2 changed files with 19 additions and 13 deletions
|
|
@ -77,7 +77,7 @@ export const ReportListens: React.FC = () => {
|
|||
{isLoading && <Spinner className="m-8" />}
|
||||
{!reportHasItems && !isLoading && (
|
||||
<div>
|
||||
<p>Report is emtpy! :(</p>
|
||||
<p>Report is empty! :(</p>
|
||||
</div>
|
||||
)}
|
||||
{reportHasItems && (
|
||||
|
|
@ -128,7 +128,7 @@ const ReportGraph: React.FC<{
|
|||
<AreaChart
|
||||
data={dataLocal}
|
||||
margin={{
|
||||
left: -20,
|
||||
left: -5,
|
||||
}}
|
||||
>
|
||||
<defs>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import {
|
|||
isSameMonth,
|
||||
isSameWeek,
|
||||
isSameYear,
|
||||
min,
|
||||
parseJSON,
|
||||
startOfDay,
|
||||
sub,
|
||||
|
|
@ -73,7 +72,13 @@ export class ReportsService {
|
|||
async getListens(options: GetListenReportDto): Promise<ListenReportDto> {
|
||||
const { timeFrame, time: timePreset } = options;
|
||||
|
||||
const listens = await this.getListensQueryFromOptions(options).getMany();
|
||||
const results = await this.getListensQueryFromOptions(options)
|
||||
.select(`count(*) as "listenCount"`)
|
||||
.addSelect(`date_trunc(:timeFrame, "playedAt") as date`)
|
||||
.groupBy("date")
|
||||
.orderBy("date")
|
||||
.setParameter("timeFrame", timeFrame)
|
||||
.getRawMany<{ listenCount: string; date: Date }>();
|
||||
|
||||
const interval = this.getIntervalFromPreset(timePreset);
|
||||
const { eachOfInterval, isSame } = timeframeToDateFns[timeFrame];
|
||||
|
|
@ -81,18 +86,19 @@ export class ReportsService {
|
|||
// Optimize performance for ALL_TIME by skipping eachOfInterval for time
|
||||
// between 1970 and first listen
|
||||
if (timePreset.timePreset === TimePreset.ALL_TIME) {
|
||||
let firstListen = min(listens.map(({ playedAt }) => playedAt));
|
||||
interval.start = startOfDay(firstListen);
|
||||
interval.start = startOfDay(results[0].date);
|
||||
}
|
||||
|
||||
// TODO: This code blocks the eventloop for multiple seconds if running for
|
||||
// a large interval and with many listens. Refactor to make this more
|
||||
// efficient or make pauses for event loop.
|
||||
const reportItems = eachOfInterval(interval).map((date) => {
|
||||
const count = listens.filter((listen) =>
|
||||
isSame(date, listen.playedAt),
|
||||
).length;
|
||||
return { date: formatISO(date), count };
|
||||
const dayResults = results.find((listen) => isSame(date, listen.date));
|
||||
|
||||
return {
|
||||
date: formatISO(date),
|
||||
count:
|
||||
dayResults && dayResults.listenCount
|
||||
? Number.parseInt(dayResults.listenCount)
|
||||
: 0,
|
||||
};
|
||||
});
|
||||
|
||||
return { items: reportItems };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue