signalk-race-control 0.10.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +26 -12
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1576,6 +1576,28 @@ module.exports = function (app) {
1576
1576
  let dataFile = null;
1577
1577
  const scheduleTimers = new Map(); // raceId -> Timeout, for scheduledStart
1578
1578
  const callOffTimers = new Map(); // raceId -> Timeout, for scheduledCallOff
1579
+
1580
+ // setTimeout's delay is a 32-bit signed int internally — anything past
1581
+ // ~24.8 days silently wraps and fires almost immediately instead of
1582
+ // waiting (this bit a race scheduled weeks out: it — and, since its
1583
+ // call-off got armed right after, that too — fired within moments of
1584
+ // being scheduled, leaving the race already stopped/DNF'd). This chains
1585
+ // multiple max-length timeouts instead of one long one, re-checking the
1586
+ // actual remaining delay each time it fires so it also self-corrects
1587
+ // for clock changes over a long wait; `timers` is keyed by raceId so
1588
+ // disarming always clears whichever leg of the chain is currently
1589
+ // pending, the same way a single setTimeout's handle would.
1590
+ const MAX_TIMEOUT_MS = 2147483647;
1591
+ function scheduleAt(timers, raceId, atTime, fn) {
1592
+ const delay = Math.min(Math.max(atTime - Date.now(), 0), MAX_TIMEOUT_MS);
1593
+ timers.set(
1594
+ raceId,
1595
+ setTimeout(() => {
1596
+ if (Date.now() >= atTime) fn();
1597
+ else scheduleAt(timers, raceId, atTime, fn);
1598
+ }, delay)
1599
+ );
1600
+ }
1579
1601
  let handicapCache = { fetchedAt: 0, boats: [], sourceUrl: null, csvUrl: null };
1580
1602
  let ktkCache = { fetchedAt: 0, boats: [], sourceUrl: null };
1581
1603
 
@@ -1978,14 +2000,10 @@ module.exports = function (app) {
1978
2000
  function armSchedule(race) {
1979
2001
  disarmSchedule(race.id);
1980
2002
  if (race.scheduledStart && !race.startTime) {
1981
- const delay = race.scheduledStart - Date.now();
1982
- if (delay <= 0) {
2003
+ if (race.scheduledStart - Date.now() <= 0) {
1983
2004
  doStart(race, race.scheduledStart);
1984
2005
  } else {
1985
- scheduleTimers.set(
1986
- race.id,
1987
- setTimeout(() => doStart(race, race.scheduledStart), delay)
1988
- );
2006
+ scheduleAt(scheduleTimers, race.id, race.scheduledStart, () => doStart(race, race.scheduledStart));
1989
2007
  }
1990
2008
  }
1991
2009
  }
@@ -2038,14 +2056,10 @@ module.exports = function (app) {
2038
2056
  function armCallOffSchedule(race) {
2039
2057
  disarmCallOffSchedule(race.id);
2040
2058
  if (race.scheduledCallOff && race.startTime && !race.stopTime) {
2041
- const delay = race.scheduledCallOff - Date.now();
2042
- if (delay <= 0) {
2059
+ if (race.scheduledCallOff - Date.now() <= 0) {
2043
2060
  doStop(race, race.scheduledCallOff);
2044
2061
  } else {
2045
- callOffTimers.set(
2046
- race.id,
2047
- setTimeout(() => doStop(race, race.scheduledCallOff), delay)
2048
- );
2062
+ scheduleAt(callOffTimers, race.id, race.scheduledCallOff, () => doStop(race, race.scheduledCallOff));
2049
2063
  }
2050
2064
  }
2051
2065
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signalk-race-control",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "description": "SignalK plugin and webapp for tracking elapsed and handicap-corrected (Time-on-Time) race time, with a per-boat editable TCF and boat names pulled from AIS when available.",
5
5
  "main": "index.js",
6
6
  "author": "Joachim Bakke <github@heiamoss.com>",