Cache TaM information on disk

This commit is contained in:
Mattéo Delabre 2021-05-11 15:36:13 +02:00
parent 3600e0b2bf
commit ef6b4b9741
Signed by: matteo
GPG Key ID: AE3FBD02DC583ABB
2 changed files with 60 additions and 6 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
node_modules node_modules
dist dist
.cache .cache
cache

View File

@ -1,5 +1,7 @@
const csv = require("csv-parse"); const csv = require("csv-parse");
const axios = require("axios"); const axios = require("axios");
const path = require("path");
const fs = require("fs").promises;
const { snakeToCamelCase, unzipFile } = require("../../util"); const { snakeToCamelCase, unzipFile } = require("../../util");
/** /**
@ -17,15 +19,65 @@ const { snakeToCamelCase, unzipFile } = require("../../util");
* @property {string} directionId Route identifier inside the line. * @property {string} directionId Route identifier inside the line.
* @property {string} departureTime Theoretical time at which the * @property {string} departureTime Theoretical time at which the
* vehicle will depart the stop (HH:MM:SS format). * vehicle will depart the stop (HH:MM:SS format).
* @property {string} isTheorical (sic) Whether the arrival time is only * @property {string} isTheorical (sic) True if this is only the planned
* a theoretical information. * passing time, false if this is real-time information.
* @property {string} delaySec Number of seconds before the vehicle arrives * @property {string} delaySec Number of seconds before the vehicle arrives
* at the station. * at the station (only if isTheorical is false).
* @property {string} destArCode Unique network identifier for the final * @property {string} destArCode Unique network identifier for the final
* stop of this trip. * stop of this trip (only if isTheorical is false).
*/ */
/**
* Wrap a passing-fetching function to use a filesystem-based cache.
*
* @param {function} func Fetching function to wrap.
* @param {string} cachePath Path to the file to use as a cache (will be
* overwritten, may be non-existing).
* @return {function} Wrapped function.
*/
const makeCached = (func, cachePath) => {
return async function *() {
try {
const cacheRaw = await fs.readFile(cachePath, {encoding: "utf8"});
const cache = JSON.parse(cacheRaw);
if (Date.now() < cache.timing.nextUpdate) {
yield cache.timing;
for (const passing of cache.passings) {
yield passing;
}
return;
}
} catch (err) {
// Ignore missing cache file
if (err.code !== 'ENOENT') {
throw err;
}
}
const passings = func();
const newCache = {
timing: (await passings.next()).value,
passings: [],
};
yield newCache.timing;
for await (const passing of passings) {
newCache.passings.push(passing);
yield passing;
}
fs.writeFile(cachePath, JSON.stringify(newCache));
};
};
const cacheDir = path.join(__dirname, "..", "..", "..", "cache");
const realtimeEndpoint = "http://data.montpellier3m.fr/node/10732/download"; const realtimeEndpoint = "http://data.montpellier3m.fr/node/10732/download";
const realtimeCachePath = path.join(cacheDir, "realtime.json");
/** /**
* Fetch real time passings of vehicles across the network. * Fetch real time passings of vehicles across the network.
@ -54,9 +106,10 @@ const fetchRealtime = async function *() {
} }
}; };
exports.fetchRealtime = fetchRealtime; exports.fetchRealtime = makeCached(fetchRealtime, realtimeCachePath);
const theoreticalEndpoint = "http://data.montpellier3m.fr/node/10731/download"; const theoreticalEndpoint = "http://data.montpellier3m.fr/node/10731/download";
const theoreticalCachePath = path.join(cacheDir, "theoretical.json");
/** /**
* Fetch theoretical passings for the current day across the network. * Fetch theoretical passings for the current day across the network.
@ -101,4 +154,4 @@ const fetchTheoretical = async function *() {
} }
}; };
exports.fetchTheoretical = fetchTheoretical; exports.fetchTheoretical = makeCached(fetchTheoretical, theoreticalCachePath);