api/insights: daily sleep uses the app-timezone day
The sleep insight floored its window in the server timezone, so its today-versus-yesterday comparison could land a day off for a Brazilian user. Both days now resolve in America/Sao_Paulo
Pedro Lucas Porcellis porcellis@eletrotupi.com · 12 days ago
6b26342b4c2a6455f9f53eba33dca2c0bc5a4cee Browse filesParents
a6fd253Changed files
2
Additions
+12
Deletions
-16
api/src/lib/queue/processors/insights/dailySleep.ts
1 1
import { prisma } from "@app/lib/prisma";
2 2
import { InsightType, InsightPeriod } from "@prisma/client";
3 3
import { InsightPeriodPayload } from "@app/lib/queue/types";
4 4
import { logger } from "@app/lib/logger";
5 -
// XXX: date-fns?
6 5
import { formatHours, formatDiff } from "@app/utils/calc";
7 -
import { startOfDay, addDays, subDays } from "date-fns";
6 +
import { appDayWindow } from "@app/lib/queue/processors/insights/utils";
8 7
9 8
export async function processDailySleep({
10 9
userId,
11 10
periodStart,
12 11
}: InsightPeriodPayload): Promise<void> {
13 -
const today = startOfDay(new Date(periodStart));
14 -
const tomorrow = addDays(today, 1);
15 -
const yesterday = subDays(today, 1);
12 +
const { start: today, end: tomorrow } = appDayWindow(new Date(periodStart));
13 +
const { start: yesterday } = appDayWindow(new Date(today.getTime() - 1));
16 14
17 15
const [todayRecords, yesterdayRecords] = await Promise.all([
18 16
prisma.sleepRecord.findMany({
19 17
where: { userId, date: { gte: today, lt: tomorrow } },
20 18
select: { average: true },
106 104
function buildBody(total: number): string {
107 105
const totalStr = formatHours(total);
108 106
109 107
return `${totalStr} de sono hoje`;
110 108
}
api/src/services/sleepRecord.service.ts
1 1
import { prisma } from '@app/lib/prisma';
2 2
import { SleepRecord } from '@prisma/client';
3 3
4 4
import { CreateSleepRecordInput, UpdateSleepRecordInput } from '@app/schemas';
5 -
import { rollingPeriod } from "@app/lib/queue/processors/insights/utils";
5 +
import {
6 +
rollingPeriod,
7 +
appDayPeriod,
8 +
} from "@app/lib/queue/processors/insights/utils";
6 9
import { InsightJobName } from "@app/lib/queue/types";
7 10
import { getQueue } from "@app/lib/queue";
8 -
import { startOfDay } from "date-fns";
9 11
10 12
export const createSleepRecord = async (
11 13
userId: number, input: CreateSleepRecordInput
12 14
): Promise<SleepRecord> => {
13 15
const sleepRecord = await prisma.sleepRecord.create({
98 100
return sleepRecord;
99 101
}
100 102
101 103
async function enqueueEnergySleepInsights(userId: number): Promise<void> {
102 104
const queue = getQueue("insights");
103 -
const period = rollingPeriod(7);
104 -
const payload = { userId, ...period };
105 +
const week = { userId, ...rollingPeriod(7) };
106 +
const day = { userId, ...appDayPeriod() };
105 107
106 -
await getQueue('insights').addBulk([
108 +
await queue.addBulk([
107 109
{
108 110
name: InsightJobName.EnergySleep,
109 -
data: payload,
111 +
data: week,
110 112
opts: {
111 113
jobId: `energy-sleep-${userId}-${new Date().toDateString()}`,
112 114
removeOnComplete: true,
113 115
removeOnFail: true,
114 116
}
115 117
},
116 118
{
117 119
name: InsightJobName.DailySleep,
118 -
data: {
119 -
userId,
120 -
periodStart: startOfDay(new Date()).toISOString(),
121 -
periodEnd: new Date()
122 -
},
120 +
data: day,
123 121
opts: {
124 122
jobId: `daily-sleep-${userId}-${new Date().toDateString()}`,
125 123
removeOnComplete: true,
126 124
removeOnFail: true,
127 125
},
128 126
},
129 127
]);
130 128
}