fix(nodes): clamp traffic reset day to month length#360
Conversation
Greptile SummaryThis PR fixes a bug in
Confidence Score: 4/5Safe to merge — the core isValid() overflow bug is correctly fixed for both utilities and no regressions were found in edge-case analysis. The clamping logic in getNodeResetDaysUtil is correct across all tested month-length combinations. In getNodeResetPeriodUtil the end-date path is also correct, but the start-date is derived by subtracting one month from the clamped current-month date rather than independently clamping the target day for the previous month, so it can be off by a few days when the prior month is longer than the current one. Only get-node-reset-days.util.ts changed; the start-date computation in getNodeResetPeriodUtil is worth a follow-up. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[targetDay input] --> B{targetDay greater than daysInMonth?}
B -- No --> C[clampedDay = targetDay]
B -- Yes --> D[clampedDay = daysInMonth]
C --> E[correctedDate = today.date clampedDay]
D --> E
subgraph getNodeResetDaysUtil
E --> G[daysToThisMonth = correctedThisMonth.diff today]
E --> H[daysToNextMonth = correctedNextMonth.diff today using nextMonth.daysInMonth]
G --> I{daysToThisMonth less than 0?}
I -- Yes --> J[return daysToNextMonth]
I -- No --> K{thisMonth less than nextMonth?}
K -- Yes --> L[return daysToThisMonth]
K -- No --> J
end
subgraph getNodeResetPeriodUtil
E --> M{today.date greater than targetDay?}
M -- isPast --> N[startDate = correctedThisMonth endDate = correctedThisMonth plus 1 month]
M -- isNotPast --> O[startDate = correctedThisMonth minus 1 month endDate = correctedThisMonth]
O --> P[startDate may be off by 1-3 days when prior month is longer]
end
|
getNodeResetDaysUtil/getNodeResetPeriodUtil tried to fall back to the end of the month when the configured trafficResetDay does not exist in the current month (e.g. 31 in April, 30 in February). The guard relied on dayjs().date(targetDay).isValid(), but dayjs silently rolls an overflowing day into the next month and still reports isValid() === true, so the fallback never ran. As a result nodes with a reset day of 29/30/31 showed an incorrect 'days until reset' countdown and reset period in short months (off by 1-2 days, and the period leaked into the next month). Clamp targetDay to daysInMonth() so it lands on the last day of the month instead. In getNodeResetPeriodUtil the previous and next month reset dates are clamped independently as well, otherwise deriving them by subtracting/adding a month can land on the wrong day when the adjacent month has a different number of days.
326092f to
4a7cb96
Compare
|
Поправил в getNodeResetPeriodUtil начало и конец периода. Теперь даты предыдущего и следующего месяца клампятся независимо, каждая по своему daysInMonth, а не выводятся прибавлением или вычитанием месяца от текущей даты. |
Что было не так
Утилиты getNodeResetDaysUtil и getNodeResetPeriodUtil показывают на карточке ноды сколько дней осталось до сброса трафика и сам период сброса. Они должны были откатываться на последний день месяца, если заданного дня в текущем месяце нет, например 31 в апреле или 30 в феврале.
Проверка использовала dayjs().date(targetDay).isValid(), но dayjs при переполнении дня молча переносит дату на следующий месяц и всё равно считает её валидной. Поэтому откат на конец месяца никогда не срабатывал.
Из-за этого у нод с днём сброса 29, 30 или 31 в коротких месяцах счётчик дней до сброса и период показывались неверно, с ошибкой на один или два дня, а период заезжал в следующий месяц.
Как исправлено
Теперь день обрезается до количества дней в месяце через dayjs().daysInMonth(), поэтому дата всегда попадает на последний день месяца и никуда не уезжает.
Проверка
Февраль с днём сброса 31, период был 3 Feb по 3 Mar, стало 28 Jan по 28 Feb. Апрель с днём сброса 31, дней до сброса было 21, стало 20.