danfang / me-api

An extensible, personal API with custom integrations
http://api.danielfang.org
MIT License
823 stars 42 forks source link

Refresh data on interval #11

Closed marvinroger closed 6 years ago

marvinroger commented 9 years ago

Right now, the data is cached in memory for DEFAULT_CACHE_MSEC and is refreshed upon a client request if the cached data expired. So, this client will receive its reponse after more time than if data was still cached.

A solution to this would be to cache data at start without expiration date, and to refresh these datas using setInterval. Therefore, only the cached data needs to be served, so the response happens pretty instantly. Another advantage to this is that if the remote API is down, the cached data still exists, so there is always data available from the Me API.

Here is how I would see the implementation, for example using the GitHub middleware:

var request = require('request');
var handleError = require('../util/util');
var cache = require('memory-cache');

var REFRESH_INTERVAL_SEC = 60 * 5; // 5 mins

var Github = {
    source: "github",
    routes: [
        {
            method: "GET",
            path: "",
            refreshInterval: REFRESH_INTERVAL_SEC,
            refresh: function() {
                var url = 'https://api.github.com/users/' + this.me + "/events/public";
                request({ url: url, headers: { 'User-Agent': this.me }}, function(err, response, body) {
                    if (err || response.statusCode != 200) return false;
                    var data = JSON.parse(body);
                    cache.put('github', data); // Store forever
                    console.log('refreshed');
                    return true;
                });
            },
            handler: function(req, res) {
                var cachedResult = cache.get('github');
                if (cachedResult) {
                    return res.json(cachedResult);
                } else { // Happens only if a client requests before refresh method succeeds
                    return res.json({ error: true });
                }
            }
        }
    ]
};

module.exports = Github;

To make this middleware functional, it is a matter of a dozen of lines in lib/routes/me.js.

Data might event be cached on the disk, so that if Me API restarts for some reason and the remote API is down, cache would still be available.

Hope you get the idea, let me know what you think. ;)

danfang commented 9 years ago

This sounds like a good idea! Although, each piece of middleware would have to be refactored - at this stage that seems fine to make breaking changes.

marvinroger commented 9 years ago

Well, refactoring middleware should not be take too long. As you can see, it is only a matter of putting handler's code in refresh with some minors adjustments, and putting a generic handler.

What about cached data on the disk? I was thinking of https://github.com/simonlast/node-persist, that stores data on the fs.