User model — streak fields
models/User.ts
How streaks are incremented
Streak incrementing happens insidetaskCompletionService.completeTask(), triggered by POST /api/task-completions. Only the first task completion of the day advances the streak; subsequent completions on the same day have no further effect on current_streak.
services/taskCompletion.service.ts
“Today” is determined by the UTC date. The query in
taskCompletionRepository.findByUserIdToday() compares completed_at against the current UTC date. Users in time zones where midnight differs from UTC may see a streak advance slightly earlier or later than their local midnight.The overnight streak-reset cron job
Incrementing the streak at completion time is only half of the mechanism. The other half is detecting when a user missed a day. This is handled by a scheduled cron job defined insrc/jobs/streakReset.job.ts and started at server boot via startStreakCronJob().
The job runs every day at midnight UTC using node-cron:
jobs/streakReset.job.ts
current_streak is greater than 0 and who has no task_completions row with a completed_at in yesterday’s date window has their current_streak set to 0.
Streak timeline example
| Day | Action | current_streak | max_streak |
|---|---|---|---|
| Day 1 | Completes a task | 1 | 1 |
| Day 2 | Completes a task | 2 | 2 |
| Day 3 | Completes a task | 3 | 3 |
| Day 4 | No task completed | 0 | 3 |
| Day 5 | Completes a task | 1 | 3 |
| Day 6 | Completes a task | 2 | 3 |
current_streak to 0. When the user resumes on Day 5, the streak begins rebuilding from 1. The max_streak of 3 is preserved throughout.