Created
October 22, 2019 19:51
-
-
Save MorningLightMountain713/69fd57216111ccadc4c822d05613cb8f to your computer and use it in GitHub Desktop.
Genieacs extension script to return how many times provision has been run per day.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Genieacs provision usage | |
// let ts = new Date().getTime() / 1000; // unix timestamp | |
// let serial = declare("InternetGatewayDevice.DeviceInfo.SerialNumber", {value:null}).value[0]; | |
// let unique_ts = serial + "_" + parseInt(ts, 10); | |
// let limit = ext("checkFirmware","counter", unique_ts); | |
// limit is boolean. If the limit has been reached or this provision has been run already (idempotency) limit will be true. | |
// script resets at midnight. | |
var redis = require('redis'); | |
const TODAY_KEY = "today"; | |
const LIMIT_KEY = "fw_update_count"; | |
const LIMIT_PER_DAY = 200; | |
const REDIS_URL = null; | |
class redisCounter { | |
// written to run on node 6 and above. (no promisify on node 6) | |
constructor(today_key, fw_limit_key, limit, device_timestamp) { | |
this.today_key = today_key; | |
this.fw_limit_key = fw_limit_key; | |
this.limit = limit; | |
this.device_timestamp = device_timestamp; | |
this.client = redis.createClient(REDIS_URL); | |
// 'connect' can be used to check if connected. | |
this.client.on('error', function (err) { | |
console.log('Unable to connect to redis: ' + err); | |
process.exit(1); | |
}); | |
} | |
prov_has_run_already() { | |
var self = this; | |
return new Promise((resolve, reject) => { | |
self.client.get(self.device_timestamp, function (err, reply) { | |
if (err) { | |
reject(err); | |
} | |
else { | |
if (reply === null) { | |
// this is first run | |
// set a key to expire in 30 seconds, value isn't important. | |
self.client.set(self.device_timestamp, "some_info", 'EX', 30); | |
resolve(false); | |
} | |
else { | |
resolve(true); | |
} | |
} | |
}); | |
}); | |
} | |
atCounterLimit() { | |
var self = this; | |
return new Promise((resolve, reject) => { | |
self.client.get(self.fw_limit_key, function (err, reply) { | |
if (err) { | |
reject(err) | |
} | |
else { | |
if (parseInt(reply, 10) < self.limit) { | |
self.client.incr(self.fw_limit_key); | |
resolve(false) | |
} | |
resolve(true) | |
} | |
}); | |
}); | |
} | |
resetCounter() { | |
this.client.set(this.fw_limit_key, 0) | |
} | |
keyIsToday() { | |
var self = this; | |
// checks if the passed in key is today. I.e if it's the 21st the key should be 21, if they key isn't today - it is set to today | |
// returns a promise with a value of true for today (or if key doesn't exist) and false if it's not today. | |
var todayAsDay = new Date().getDate(); | |
return new Promise((resolve, reject) => { | |
self.client.get(self.today_key, function (err, reply) { | |
if (err) { | |
reject(err) | |
} | |
else { | |
switch (reply) { | |
case todayAsDay.toString(10): | |
resolve(true); | |
break; | |
default: | |
self.client.set(self.today_key, todayAsDay); | |
resolve(false); | |
} | |
} | |
}); | |
}); | |
} | |
close() { | |
this.client.quit() | |
} | |
} | |
function counter(device_ts, callback) { | |
// args is actually an array, doesn't say that in the Genieacs docs - just infers it. | |
counter = new redisCounter(TODAY_KEY, LIMIT_KEY, LIMIT_PER_DAY, device_ts[0]) | |
// to make the script idempotent, we look at the timestamp passed by the provision | |
// it can run multiple times but will have the same timestamp. | |
counter.prov_has_run_already().then((isTrue) => { | |
if (isTrue) { | |
counter.close(); | |
return callback(null, true); | |
} | |
// check if it's a new day - if it is reset the counter | |
counter.keyIsToday().then((keyIsToday) => { | |
if (!keyIsToday) { | |
// we need to reset the counter | |
counter.resetCounter(); | |
} | |
//check if counter is at limit, if not, it gets incremented | |
counter.atCounterLimit().then((result) => { | |
counter.close(); | |
callback(null, result); | |
}).catch((err) => { | |
counter.close(); | |
callback(err); | |
}); | |
}).catch((err) => { | |
counter.close(); | |
callback(err); | |
}); | |
}).catch((err) => { | |
counter.close(); | |
callback(err); | |
}); | |
} | |
exports.counter = counter; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment