diff --git a/src/database/mongo/main.js b/src/database/mongo/main.js index 59e3f94481..67a209dfdb 100644 --- a/src/database/mongo/main.js +++ b/src/database/mongo/main.js @@ -134,4 +134,12 @@ module.exports = function (module) { timestamp = Math.min(timestamp, 8640000000000000); await module.setObjectField(key, 'expireAt', new Date(timestamp)); }; + + module.ttl = async function (key) { + return Math.round((await module.getObjectField(key, 'expireAt') - Date.now()) / 1000); + }; + + module.pttl = async function (key) { + return await module.getObjectField(key, 'expireAt') - Date.now(); + }; }; diff --git a/src/database/postgres/main.js b/src/database/postgres/main.js index 37e8f695a1..e122eafc07 100644 --- a/src/database/postgres/main.js +++ b/src/database/postgres/main.js @@ -210,4 +210,26 @@ UPDATE "legacy_object" module.pexpireAt = async function (key, timestamp) { await doExpire(key, new Date(timestamp)); }; + + async function getExpire(key) { + const res = await module.pool.query({ + name: 'ttl', + text: ` +SELECT "expireAt"::TEXT + FROM "legacy_object" + WHERE "_key" = $1::TEXT + LIMIT 1`, + values: [key], + }); + + return res.rows.length ? new Date(res.rows[0].expireAt).getTime() : null; + } + + module.ttl = async function (key) { + return Math.round((await getExpire(key) - Date.now()) / 1000); + }; + + module.pttl = async function (key) { + return await getExpire(key) - Date.now(); + }; }; diff --git a/src/database/redis/main.js b/src/database/redis/main.js index 5c5bee9428..5f31ee2da2 100644 --- a/src/database/redis/main.js +++ b/src/database/redis/main.js @@ -100,4 +100,12 @@ module.exports = function (module) { module.pexpireAt = async function (key, timestamp) { await module.client.async.pexpireat(key, timestamp); }; + + module.ttl = async function (key) { + return await module.client.async.ttl(key); + }; + + module.pttl = async function (key) { + return await module.client.async.pttl(key); + }; }; diff --git a/src/database/redis/promisify.js b/src/database/redis/promisify.js index d768baad59..91132f484a 100644 --- a/src/database/redis/promisify.js +++ b/src/database/redis/promisify.js @@ -19,6 +19,8 @@ module.exports = function (redisClient) { expireat: util.promisify(redisClient.expireat).bind(redisClient), pexpire: util.promisify(redisClient.pexpire).bind(redisClient), pexpireat: util.promisify(redisClient.pexpireat).bind(redisClient), + ttl: util.promisify(redisClient.ttl).bind(redisClient), + pttl: util.promisify(redisClient.pttl).bind(redisClient), hmset: util.promisify(redisClient.hmset).bind(redisClient), hset: util.promisify(redisClient.hset).bind(redisClient), diff --git a/test/database/keys.js b/test/database/keys.js index 7c5fe7cc25..bff084376f 100644 --- a/test/database/keys.js +++ b/test/database/keys.js @@ -327,5 +327,27 @@ describe('Key methods', function () { }); }); }); + + it('should expire a key using seconds', function (done) { + db.expire('testKey', 86400, function (err) { + assert.ifError(err); + db.ttl('testKey', function (err, ttl) { + assert.ifError(err); + assert.equal(Math.round(86400 / 1000), Math.round(ttl / 1000)); + done(); + }); + }); + }); + + it('should expire a key using milliseconds', function (done) { + db.pexpire('testKey', 86400000, function (err) { + assert.ifError(err); + db.pttl('testKey', function (err, pttl) { + assert.ifError(err); + assert.equal(Math.round(86400000 / 1000000), Math.round(pttl / 1000000)); + done(); + }); + }); + }); }); });