UNPKG

redis-expiry

Version:

Use redis to expire your keys and handling the value

530 lines (504 loc) 16.8 kB
const redisUrl = process.env.REDIS_URL; const Promise = require("bluebird"); const test = require("ava"); const Redis = require("redis"); Promise.promisifyAll(Redis.RedisClient.prototype); Promise.promisifyAll(Redis.Multi.prototype); const redisExpiry = require("../index"); const redisSetter = Redis.createClient(redisUrl); const redisGetter = Redis.createClient(redisUrl); const rexp = redisExpiry(redisSetter, redisGetter); test("Basic - Natif function", async t => { t.deepEqual( rexp.redisSetter, redisSetter, "Redis setter instances are different" ); t.deepEqual( rexp.redisGetter, redisGetter, "Redis getter instances are different" ); (() => t.pass())( await Promise.map( await (await redisSetter .multi() .keys(`set_*`) .execAsync()).shift(), element => redisSetter.del(element) ) ); }); test("Basic - Set function", async t => { const result = await rexp.set("set_expiration", "now_call"); t.deepEqual( Object.keys(result), ["infinit", "timeout", "now", "at", "cron"], "Invalid method returned" ); }); const valueForNow = "now_call"; test("Expiration - Now function", async t => { const verifyKey = await rexp.get("set_expiration_for_now"); t.deepEqual(verifyKey, [], `"set_expiration_for_now" key already exists`); const currentTime = new Date(); await rexp.set("set_expiration_for_now", valueForNow).now(); await new Promise((resolve, reject) => { rexp.on("set_expiration_for_now", value => { const newTime = new Date(); t.is(value, valueForNow, "Expected value is not consistent"); if (newTime.getTime() - currentTime.getTime() < 999) { return resolve(); } return reject(); }); setTimeout(reject, 999); }) .then(() => t.pass()) .catch(() => t.fail(`"now" function take too much time`)); const verifyKeyAgain = await rexp.get("set_expiration_for_now"); t.deepEqual( verifyKeyAgain, [], `"set_expiration_for_now" key hasn't been removed` ); }); const valueForTimeout = "timeout_call"; test("Expiration - Timeout function", async t => { const verifyKey = await rexp.get("set_expiration_for_timeout"); t.deepEqual(verifyKey, [], `"set_expiration_for_timeout" key already exists`); const currentTime = new Date(); await rexp.set("set_expiration_for_timeout", valueForTimeout).timeout(1000); await new Promise((resolve, reject) => { rexp.on("set_expiration_for_timeout", value => { const newTime = new Date(); t.is(value, valueForTimeout, "Expected value is not consistent"); if ( newTime.getTime() - currentTime.getTime() >= 1000 && newTime.getTime() - currentTime.getTime() < 1999 ) { return resolve(); } return reject(); }); setTimeout(reject, 1999); }) .then(() => t.pass()) .catch(() => t.fail(`"timeout" function take too much time`)); const verifyKeyAgain = await rexp.get("set_expiration_for_timeout"); t.deepEqual( verifyKeyAgain, [], `"set_expiration_for_timeout" key hasn't been removed` ); }); const valueForCron = "cron_call"; test("Expiration - Cron function", async t => { const verifyKey = await rexp.get("set_expiration_for_cron"); t.deepEqual(verifyKey, [], `"set_expiration_for_cron" key already exists`); const currentTime = new Date(); const timeoutCron = (4 - ((currentTime.getSeconds() % 4) + currentTime.getMilliseconds() * 0.001)) * 1000 - 100; await rexp.set("set_expiration_for_cron", valueForCron).cron("*/4 * * * * *"); await new Promise((resolve, reject) => { rexp.on("set_expiration_for_cron", (value, guuid, stop) => { stop(); const newTime = new Date(); t.is(value, valueForCron, "Expected value is not consistent"); if ( newTime.getTime() - currentTime.getTime() >= timeoutCron && newTime.getTime() - currentTime.getTime() < timeoutCron + 999 ) { return resolve(); } return reject(); }); setTimeout(reject, timeoutCron + 999); }) .then(() => t.pass()) .catch(() => t.fail(`"cron" function take too much time`)); const verifyKeyAgain = await rexp.get("set_expiration_for_cron"); t.deepEqual( verifyKeyAgain, [], `"set_expiration_for_cron" key hasn't been removed` ); }); const valueForCronRepeatMode = "cron_repeat_mode_call"; test("Expiration - Cron function (repeate mode)", async t => { let countRepeat = 0; const currentTime = new Date(); const timeoutCron = (4 - ((currentTime.getSeconds() % 4) + currentTime.getMilliseconds() * 0.001)) * 1000 - 100; const result = await rexp .set("set_expiration_for_cron_repeat_mode", valueForCronRepeatMode) .cron("*/4 * * * * *"); await new Promise((resolve, reject) => { rexp.on("set_expiration_for_cron_repeat_mode", (value, guuid, stop) => { countRepeat += 1; if (countRepeat === 3) { stop(); resolve(); } }); setTimeout(reject, timeoutCron + 4000 * 2 + 999); }) .then(() => t.pass()) .catch(() => t.fail(`"cron" function take too much time`)); t.is( result.expiration_extra, undefined, "`expiration_extra` field is different than the original" ); }); const valueForCronOptionsMode = "cron_options_mode_call"; test("Expiration - Cron function (options mode)", async t => { const currentTime = new Date(); const currentDateCron = new Date(); currentDateCron.setSeconds(currentDateCron.getSeconds() + 6); const timeoutCron = (4 - ((currentTime.getSeconds() % 4) + currentTime.getMilliseconds() * 0.001)) * 1000 - 100 + 4000; const result = await rexp .set("set_expiration_for_cron_options_mode", valueForCronOptionsMode) .cron("*/4 * * * * *", { currentDate: currentDateCron }); await new Promise((resolve, reject) => { rexp.on("set_expiration_for_cron_options_mode", (value, guuid, stop) => { stop(); const newTime = new Date(); t.is(value, valueForCronOptionsMode, "Expected value is not consistent"); if ( newTime.getTime() - currentTime.getTime() >= timeoutCron && newTime.getTime() - currentTime.getTime() < timeoutCron + 999 ) { return resolve(); } return reject(); }); setTimeout(reject, timeoutCron + 999); }) .then(() => t.pass()) .catch(() => t.fail(`"cron" function take too much time`)); t.deepEqual( result.expiration_extra, { currentDate: currentDateCron }, "`expiration_extra` field is different than the original" ); }); const valueForAt = "at_call"; test("Expiration - At function", async t => { const verifyKey = await rexp.get("set_expiration_for_at"); t.deepEqual(verifyKey, [], `"set_expiration_for_at" key already exists`); const currentTime = new Date(); const dateTest = new Date(); dateTest.setSeconds(dateTest.getSeconds() + 3); await rexp.set("set_expiration_for_at", valueForAt).at(dateTest); await new Promise((resolve, reject) => { rexp.on("set_expiration_for_at", value => { const newTime = new Date(); t.is(value, valueForAt, "Expected value is not consistent"); if ( newTime.getTime() - currentTime.getTime() >= 3000 && newTime.getTime() - currentTime.getTime() < 3999 ) { return resolve(); } return reject(); }); setTimeout(reject, 3999); }) .then(() => t.pass()) .catch(() => t.fail(`"at" function take too much time`)); const verifyKeyAgain = await rexp.get("set_expiration_for_at"); t.deepEqual( verifyKeyAgain, [], `"set_expiration_for_at" key hasn't been removed` ); }); const valueForReschedule = "reschedule_call"; test("Reschedule - Verify functions", async t => { const result = await rexp .set("set_expiration_for_reschedule", valueForReschedule) .timeout(5000); t.deepEqual( Object.keys(await rexp.rescheduleByGuuid(result.guuid)), ["andUpdateValue", "infinit", "timeout", "now", "at", "cron"], `Invalid method returned with "andUpdateValue" function` ); t.deepEqual( Object.keys( await rexp.rescheduleByGuuid(result.guuid).andUpdateValue("newValue") ), ["infinit", "timeout", "now", "at", "cron"], "Invalid method returned" ); await rexp.del("set_expiration_for_reschedule", valueForReschedule); }); const valueForRescheduleTimeout = "reschedule_timeout_call"; test("Reschedule - Verify timeout function", async t => { const currentTime = new Date(); const result = await rexp .set("set_expiration_for_reschedule_for_timeout", valueForRescheduleTimeout) .timeout(60000); await rexp.rescheduleByGuuid(result.guuid).timeout(1000); await new Promise((resolve, reject) => { rexp.on("set_expiration_for_reschedule_for_timeout", value => { const newTime = new Date(); t.is( value, valueForRescheduleTimeout, "Expected value is not consistent" ); if ( newTime.getTime() - currentTime.getTime() >= 1000 && newTime.getTime() - currentTime.getTime() < 1999 ) { return resolve(); } return reject(); }); setTimeout(reject, 1999); }) .then(() => t.pass()) .catch(e => t.fail(`"timeout" function take too much time ${e}`)); }); const valueForRescheduleAndUpdateValue = "reschedule_and_update_value_call"; test("Reschedule - Verify chainable API", async t => { const result = await rexp .set( "set_expiration_for_reschedule_and_update_value", valueForRescheduleAndUpdateValue ) .timeout(10000); await rexp .rescheduleByGuuid(result.guuid) .andUpdateValue("newValue") .timeout(1000); await new Promise((resolve, reject) => { rexp.on("set_expiration_for_reschedule_and_update_value", value => value === "newValue" ? resolve() : reject(new Error(`"andUpdateValue" doesn't works => ${value}`)) ); setTimeout( () => reject(new Error(`"timeout" function take too much time`)), 1999 ); }) .then(() => t.pass()) .catch(err => t.fail(err)); }); const valueForRegexpSubscriber = "value_for_regexp_subscriber"; test("Regexp - Verify subscriber", async t => { await rexp .set("set_expiration_for_regexp_subscriber", valueForRegexpSubscriber) .timeout(1000); await rexp .set("set_expiration_for_regexp_subscriber3", valueForRegexpSubscriber) .timeout(1000); await rexp .set("set_expiration_for_expreg_subscriber", valueForRegexpSubscriber) .timeout(1000); const keyRetrieved = []; await new Promise(resolve => { rexp.on(/set_expiration_for_regexp_(.*)/, (value, key) => keyRetrieved.push(key) ); setTimeout(resolve, 1999); }); t.deepEqual( [ "set_expiration_for_regexp_subscriber", "set_expiration_for_regexp_subscriber3" ], keyRetrieved.sort(), "Regexp subscriber failed" ); await rexp.del( "set_expiration_for_expreg_subscriber", valueForRegexpSubscriber ); }); const valueForGetByRegexp = "get_by_guuid_call"; test("Regexp - get/del/update functions", async t => { const rSet = await rexp .set("set_expiration_for_regexp_func", valueForGetByRegexp) .now(); const rSet2 = await rexp .set("set_expiration_for_2_regexp_func", valueForGetByRegexp) .now(); const result = (await rexp.get(/(.*)_regexp_func/)).sort((a, b) => a.key < b.key ? 1 : -1 ); t.deepEqual([rSet, rSet2], result, "get doesn't works"); // --- rSet.value = "get_by_regexp_new_call"; await rexp.update(/(.*)_for_regexp_func/)(rSet.value); const resultUpdate = (await rexp.get(/(.*)_regexp_func/)).sort((a, b) => a.key < b.key ? 1 : -1 ); t.deepEqual([rSet, rSet2], resultUpdate, "update doesn't works"); // --- await rexp.del(/(.*)_regexp_func/); const resultDelete = await rexp.get(/(.*)_regexp_func/); t.deepEqual([], resultDelete, "del doesn't works"); }); const valueForInfinit = "infinit_call"; test("Other - Infinit function", async t => { const verifyKey = await rexp.get("set_expiration_for_infinit"); t.deepEqual(verifyKey, [], `"set_expiration_for_infinit" key already exists`); // --- const dataInfinit = await rexp .set("set_expiration_for_infinit", valueForInfinit) .infinit(); const verifyKeyAgain = await rexp.get("set_expiration_for_infinit"); t.deepEqual( verifyKeyAgain, [dataInfinit], `"set_expiration_for_infinit" key doesn't exists` ); // --- await rexp.del("set_expiration_for_infinit", valueForInfinit); const verifyKeyAgain2 = await rexp.get("set_expiration_for_infinit"); t.deepEqual( verifyKeyAgain2, [], `"set_expiration_for_infinit" key hasn't been removed` ); }); const valueForOn = "on_call"; test("Other - on event after key has been expired", async t => { const verifyKey = await rexp.get("set_expiration_for_on"); t.deepEqual(verifyKey, [], `"set_expiration_for_on" key already exists`); const currentTime = new Date(); await rexp.set("set_expiration_for_on", valueForOn).now(); await new Promise((resolve, reject) => { setTimeout(() => { rexp.on("set_expiration_for_on", value => { const newTime = new Date(); t.is(value, valueForOn, "Expected value is not consistent"); if (newTime.getTime() - currentTime.getTime() < 2999) { return resolve(); } return reject(); }); setTimeout(reject, 999); }, 2000); }) .then(() => t.pass()) .catch(err => t.fail(`"on" event take too much time${err}`)); await new Promise(resolve => { setTimeout(async () => { const verifyKeyAgain = await rexp.get("set_expiration_for_on"); t.deepEqual( verifyKeyAgain, [], `"set_expiration_for_on" key hasn't been removed` ); resolve(); }, 100); }); }); const valueForGet = "get_call"; test("Other - get/set/del/update functions", async t => { const verifyKey = await rexp.get("set_expiration_for_get"); t.deepEqual(verifyKey, [], `"set_expiration_for_get" key already exists`); // --- const rSet = await rexp .set("set_expiration_for_get", valueForGet) .timeout(100000); const result = (await rexp.get( "set_expiration_for_get", valueForGet )).shift(); t.deepEqual(result, rSet, "`get` result is different than `set` return"); delete result.guuid; delete result.created_at; delete result.expiration_at; t.deepEqual( result, { value: valueForGet, key: "set_expiration_for_get", expiration_type: "TIMEOUT", expiration_value: 100000, expiration_expression: 100000, expiration_extra: undefined }, "`get` result have some different fields than the original" ); // --- rSet.value = "get_new_call"; await rexp.update("set_expiration_for_get", valueForGet)(rSet.value); const resultBadValue = await rexp.get("set_expiration_for_get", valueForGet); t.deepEqual(resultBadValue, [], "old value was wrongly deleted"); const resultSuccessValue = (await rexp.get( "set_expiration_for_get", rSet.value )).shift(); t.deepEqual( resultSuccessValue, rSet, "`get` result is different than the data updated" ); // --- await rexp.del("set_expiration_for_get", rSet.value); const verifyKeyAgain = await rexp.get("set_expiration_for_get"); t.deepEqual( verifyKeyAgain, [], `"set_expiration_for_get" key already exists` ); }); const valueForGetByGuuid = "get_by_guuid_call"; test("Other - getByGuuid/delByGuuid/delByGuuid functions", async t => { const rSet = await rexp .set("set_expiration_for_guuid", valueForGetByGuuid) .now(); const result = await rexp.getByGuuid(rSet.guuid); t.deepEqual(rSet, result, "getByGuuid doesn't works"); // --- rSet.value = "get_by_guuid_new_call"; await rexp.updateByGuuid(rSet.guuid)(rSet.value); const resultUpdate = await rexp.getByGuuid(rSet.guuid); t.deepEqual(rSet, resultUpdate, "updateByGuuid doesn't works"); // --- await rexp.delByGuuid(rSet.guuid); const resultDelete = await rexp.getByGuuid(rSet.guuid); t.is(undefined, resultDelete, "delByGuuid doesn't works"); }); test("Other - no keys in redis", async t => { const verifyKey = (await redisSetter .multi() .keys(`set_expiration_for_*`) .execAsync()).shift(); t.deepEqual([], verifyKey, `there are still traces of the test`); }); test.serial("Removing traces", async t => (() => t.pass())( await Promise.map( await (await redisSetter .multi() .keys(`set_expiration_for_*`) .execAsync()).shift(), element => redisSetter.del(element) ) ) );