From 14c07b53186ee88497abd0ba492d2d9157891718 Mon Sep 17 00:00:00 2001 From: Benety Goh Date: Wed, 3 Aug 2022 15:01:22 +0000 Subject: SERVER-68359 TTL monitor skips indexes with NaN expireAfterSeconds --- jstests/noPassthrough/ttl_expire_nan.js | 45 +++++++++++++++++++++++++++++++++ src/mongo/db/ttl.cpp | 9 ++++--- 2 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 jstests/noPassthrough/ttl_expire_nan.js diff --git a/jstests/noPassthrough/ttl_expire_nan.js b/jstests/noPassthrough/ttl_expire_nan.js new file mode 100644 index 00000000000..e6c300b8ce2 --- /dev/null +++ b/jstests/noPassthrough/ttl_expire_nan.js @@ -0,0 +1,45 @@ +/** + * Tests TTL indexes with NaN for 'expireAfterSeconds'. + * + * Existing TTL indexes from older versions of the server may contain a NaN for the duration. + * Newer server versions (5.0+) normalize the TTL duration to 0. + * + * @tags: [ + * requires_replication, + * ] + */ +(function() { +'use strict'; + +const rst = new ReplSetTest({ + nodes: [{}, {rsConfig: {votes: 0, priority: 0}}], + nodeOptions: {setParameter: {ttlMonitorSleepSecs: 5}}, +}); +rst.startSet(); +rst.initiate(); + +const primary = rst.getPrimary(); +const db = primary.getDB('test'); +const coll = db.t; + +assert.commandWorked(coll.insert({_id: 0, t: ISODate()})); +assert.commandWorked(coll.createIndex({t: 1}, {expireAfterSeconds: NaN})); + +// Wait for "TTL indexes require the expire field to be numeric, skipping TTL job" log message. +checkLog.containsJson(primary, 22542, {ns: coll.getFullName()}); + +// TTL index should be replicated to the secondary with a NaN 'expireAfterSeconds'. +const secondary = rst.getSecondary(); +checkLog.containsJson(secondary, 20384, { + namespace: coll.getFullName(), + properties: (spec) => { + jsTestLog('TTL index on secondary: ' + tojson(spec)); + return isNaN(spec.expireAfterSeconds); + } +}); + +assert.eq( + coll.countDocuments({}), 1, 'ttl index with NaN duration should not remove any documents.'); + +rst.stopSet(); +})(); diff --git a/src/mongo/db/ttl.cpp b/src/mongo/db/ttl.cpp index a3e872d5288..342cb1f3eb5 100644 --- a/src/mongo/db/ttl.cpp +++ b/src/mongo/db/ttl.cpp @@ -283,11 +283,12 @@ private: } BSONElement secondsExpireElt = idx[IndexDescriptor::kExpireAfterSecondsFieldName]; - if (!secondsExpireElt.isNumber()) { + if (!secondsExpireElt.isNumber() || secondsExpireElt.isNaN()) { LOGV2_ERROR(22542, - "ttl indexes require the {expireField} field to be numeric but received a " - "type of {typeName_secondsExpireElt_type}, skipping ttl job for: {idx}", - "TTL indexes require the expire field to be numeric, skipping TTL job", + "TTL indexes require the expire field to be numeric and not a NaN, " + "skipping TTL job", + "ns"_attr = collection->ns(), + "uuid"_attr = collection->uuid(), "field"_attr = IndexDescriptor::kExpireAfterSecondsFieldName, "type"_attr = typeName(secondsExpireElt.type()), "index"_attr = idx); -- cgit v1.2.1