domotz-remote-pawn
Version:
Domotz Agent
167 lines (144 loc) • 6.17 kB
JavaScript
/** This file is part of Domotz Agent.
* Copyright (C) 2016 Domotz Ltd
*
* Domotz Agent is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Domotz Agent is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Domotz Agent. If not, see <http://www.gnu.org/licenses/>.
*
* Maintains a cache with the devices list, as the engine knows it
*
* Created by Tommaso Latini <tommaso@domotz.com> on 23/09/15.
*/
var devicesInfo = function (q, async, time, engineRequest, configuration) {
var toMs = time.toMs;
var maxCacheAge = configuration.device_cache_duration || toMs(0, 10);
var servicesRunInterval = configuration.cache_expiration_time || toMs(6);
var devicesCache = null;
var servicesExecutions = {};
var cacheFillTime = null;
var deviceFetchQueue = async.queue(_getList, 1);
function _handleError(error) {
console.warn("DeviceCache: Cannot fetch devices list from engine");
console.warn(JSON.stringify(error));
}
function isCacheValid() {
"use strict";
var currentCacheAge = new Date() - (cacheFillTime || 0);
return devicesCache !== null && currentCacheAge <= maxCacheAge;
}
function _getList(_, callback) {
"use strict";
_ = null; // ignore parameter, suppress js lint error
if (isCacheValid()) {
console.debug("DeviceCache: Devices cache valid, returning it");
callback(devicesCache);
} else {
if (devicesCache === null) {
console.info("DeviceCache: Devices cache empty, filling it");
} else {
console.info("DeviceCache: Devices cache expired, refreshing it");
}
engineRequest.sendWithPromise('/device', 'GET', {})
.then(function (devicesList) {
console.info("DeviceCache: engine reply arrived");
devicesCache = {};
devicesList.forEach(function (device) {
devicesCache[device.mac] = device;
});
cacheFillTime = new Date();
})
.catch(function (error) {
_handleError(error);
}).finally(function () {
callback(devicesCache);
});
}
}
function getList() {
var deferred = q.defer();
deviceFetchQueue.push(['devices'], function (deviceList) {
deferred.resolve(deviceList);
});
return deferred.promise;
}
function assureServiceExecutionExists(mac, service) {
"use strict";
servicesExecutions[mac] = servicesExecutions[mac] || {};
servicesExecutions[mac][service] = servicesExecutions[mac][service] || {last_run: null};
}
function isToBeUpdated(mac, service) {
assureServiceExecutionExists(mac, service);
var oldOrMissing = false;
if (servicesExecutions[mac][service].last_run === null) {
oldOrMissing = true;
console.debug("DeviceDiscovery: %s for device with mac %s has not executed yet", service, mac);
}
else {
var elapsed = new Date() - servicesExecutions[mac][service].last_run;
oldOrMissing = elapsed > servicesRunInterval;
if (oldOrMissing) {
console.info("DeviceDiscovery: %s last run too old for device with mac %s (%s seconds)", service,
mac,
(elapsed / 1000));
}
}
return oldOrMissing;
}
function setUpdateTimeToNow(mac, service) {
"use strict";
assureServiceExecutionExists(mac, service);
servicesExecutions[mac][service].last_run = new Date();
console.info("DeviceDiscovery: %s last run set now: %s " + servicesExecutions[mac][service].last_run,
service, mac);
}
function get(mac) {
return getList().then(function (devicesList) {
if (devicesList[mac] === undefined) {
console.info("DeviceCache: cache miss for device " + mac);
return forceRefreshList().then(function () {
console.debug("DeviceCache: device just fetched from Engine: " +
mac + " - " + JSON.stringify(devicesCache[mac]));
return devicesCache[mac];
});
} else {
var deferred = q.defer();
deferred.resolve(devicesList[mac]);
console.debug("DeviceCache: hit for device " + mac + " - " + JSON.stringify(devicesList[mac]));
return deferred.promise;
}
});
}
function forceRefreshList() {
"use strict";
console.info("DeviceCache: forcing refresh");
devicesCache = null;
return getList();
}
function getDevicesCache(){
if(devicesCache){
return devicesCache;
}
else{
return {};
}
}
return {
isToBeUpdated: isToBeUpdated,
get: get,
getList: getList,
invalidateList: forceRefreshList,
setUpdateTimeToNow: setUpdateTimeToNow,
getDevicesCache: getDevicesCache
};
}
;
module.exports.factory = devicesInfo;