summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2022-08-27 07:59:58 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-10-11 15:23:19 +0000
commit1c970f7c593cfe5ffd3a8ed29cee51ef0a3dffe5 (patch)
treefa888131942af140a1ebc4b6f6c89878a8af1444
parenta64f677d8ea94db2147c385829435a3465bff2ae (diff)
downloadmongo-1c970f7c593cfe5ffd3a8ed29cee51ef0a3dffe5.tar.gz
SERVER-68477 TTL monitor skips indexes with NaN expireAfterSeconds
(cherry-picked from commit 14c07b53186ee88497abd0ba492d2d9157891718) (cherry picked from commit 7d76329f8915ec80ba07c07e4a0adbc7fd187107) (cherry picked from commit 0f56fdb4c92f6728a8560469e66f4432fabc468d)
-rw-r--r--jstests/noPassthrough/ttl_expire_nan.js45
-rw-r--r--src/mongo/db/ttl.cpp7
2 files changed, 50 insertions, 2 deletions
diff --git a/jstests/noPassthrough/ttl_expire_nan.js b/jstests/noPassthrough/ttl_expire_nan.js
new file mode 100644
index 00000000000..5d26b214487
--- /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();
+
+let primary = rst.getPrimary();
+const db = primary.getDB('test');
+const coll = db.t;
+
+assert.commandWorked(coll.createIndex({t: 1}, {expireAfterSeconds: NaN}));
+assert.commandWorked(coll.insert({_id: 0, t: ISODate()}));
+
+// 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 c682282100f..7e02d6816d0 100644
--- a/src/mongo/db/ttl.cpp
+++ b/src/mongo/db/ttl.cpp
@@ -376,9 +376,12 @@ private:
}
BSONElement secondsExpireElt = spec[IndexDescriptor::kExpireAfterSecondsFieldName];
- if (!secondsExpireElt.isNumber()) {
+ if (!secondsExpireElt.isNumber() || secondsExpireElt.isNaN()) {
LOGV2_ERROR(22542,
- "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 = spec);