Implement caching of API responses including setting to prefer cache to avoid api requests

This commit is contained in:
Victor Hagelbäck 2021-02-08 22:23:54 +01:00
parent 7c0fc24bc6
commit be86f08bec
2 changed files with 70 additions and 7 deletions

View file

@ -1,4 +1,5 @@
const axios = require('axios').default;
const fs = require('fs');
const Configuration = require('./Configuration');
const Logger = require('./Logger');
@ -25,12 +26,74 @@ class PlejdApi {
async init() {
logger.info('init()');
await this.login();
await this.getSites();
await this.getSiteDetails();
const cache = await this.getCachedCopy();
const cacheExists = cache && cache.siteId && cache.siteDetails && cache.sessionToken;
logger.debug(`Prefer cache? ${this.config.preferCachedApiResponse}`);
logger.debug(`Cache exists? ${cacheExists ? `Yes, created ${cache.dtCache}` : 'No'}`);
if (this.config.preferCachedApiResponse && cacheExists) {
logger.info(
`Cache preferred. Skipping api requests and setting api data to response from ${cache.dtCache}`,
);
logger.silly(`Cached response: ${JSON.stringify(cache, null, 2)}`);
this.siteId = cache.siteId;
this.siteDetails = cache.siteDetails;
this.sessionToken = cache.sessionToken;
} else {
try {
await this.login();
await this.getSites();
await this.getSiteDetails();
this.saveCachedCopy();
} catch (err) {
if (cacheExists) {
logger.warn('Failed to get api response, using cached copy instead');
this.siteId = cache.siteId;
this.siteDetails = cache.siteDetails;
this.sessionToken = cache.sessionToken;
} else {
logger.error('Api request failed, no cached fallback available', err);
throw err;
}
}
}
this.deviceRegistry.setApiSite(this.siteDetails);
this.deviceRegistry.cryptoKey = this.siteDetails.plejdMesh.cryptoKey;
this.getDevices();
}
// eslint-disable-next-line class-methods-use-this
async getCachedCopy() {
logger.info('Getting cached api response from disk');
try {
const rawData = await fs.promises.readFile('/data/cachedApiResponse.json');
const cachedCopy = JSON.parse(rawData);
return cachedCopy;
} catch (err) {
logger.warn('No cached api response could be read. This is normal on the first run', err);
return null;
}
}
async saveCachedCopy() {
logger.info('Saving cached copy');
try {
const rawData = JSON.stringify({
siteId: this.siteId,
siteDetails: this.siteDetails,
sessionToken: this.sessionToken,
dtCache: new Date().toISOString(),
});
await fs.promises.writeFile('/data/cachedApiResponse.json', rawData);
} catch (err) {
logger.error('Failed to save cache of api response', err);
}
}
async login() {
logger.info('login()');
logger.info(`logging into ${this.config.site}`);
@ -115,13 +178,11 @@ class PlejdApi {
}
this.siteDetails = response.data.result[0];
this.deviceRegistry.setApiSite(this.siteDetails);
logger.info(`Site details for site id ${this.siteId} found`);
logger.silly(JSON.stringify(this.siteDetails, null, 2));
this.deviceRegistry.cryptoKey = this.siteDetails.plejdMesh.cryptoKey;
if (!this.deviceRegistry.cryptoKey) {
if (!this.siteDetails.plejdMesh.cryptoKey) {
throw new Error('API: No crypto key set for site');
}
} catch (error) {

View file

@ -1,6 +1,6 @@
{
"name": "Plejd",
"version": "0.5.1",
"version": "0.6.0-dev",
"slug": "plejd",
"description": "Adds support for the Swedish home automation devices from Plejd.",
"url": "https://github.com/icanos/hassio-plejd/",
@ -18,6 +18,7 @@
"mqttUsername": "",
"mqttPassword": "",
"includeRoomsAsLights": false,
"preferCachedApiResponse": false,
"logLevel": "info",
"connectionTimeout": 2,
"writeQueueWaitTime": 400
@ -30,6 +31,7 @@
"mqttUsername": "str",
"mqttPassword": "str",
"includeRoomsAsLights": "bool",
"preferCachedApiResponse": "bool",
"logLevel": "list(error|warn|info|debug|verbose|silly)",
"connectionTimeout": "int",
"writeQueueWaitTime": "int"