Cache TaM information on disk
This commit is contained in:
		
							parent
							
								
									3600e0b2bf
								
							
						
					
					
						commit
						ef6b4b9741
					
				| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
node_modules
 | 
			
		||||
dist
 | 
			
		||||
.cache
 | 
			
		||||
cache
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
const csv = require("csv-parse");
 | 
			
		||||
const axios = require("axios");
 | 
			
		||||
const path = require("path");
 | 
			
		||||
const fs = require("fs").promises;
 | 
			
		||||
const { snakeToCamelCase, unzipFile } = require("../../util");
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -17,15 +19,65 @@ const { snakeToCamelCase, unzipFile } = require("../../util");
 | 
			
		|||
 * @property {string} directionId Route identifier inside the line.
 | 
			
		||||
 * @property {string} departureTime Theoretical time at which the
 | 
			
		||||
 * vehicle will depart the stop (HH:MM:SS format).
 | 
			
		||||
 * @property {string} isTheorical (sic) Whether the arrival time is only
 | 
			
		||||
 * a theoretical information.
 | 
			
		||||
 * @property {string} isTheorical (sic) True if this is only the planned
 | 
			
		||||
 * passing time, false if this is real-time information.
 | 
			
		||||
 * @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
 | 
			
		||||
 * 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 realtimeCachePath = path.join(cacheDir, "realtime.json");
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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 theoreticalCachePath = path.join(cacheDir, "theoretical.json");
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue