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-08-31 12:12:05 +0000
commitdaaff3b1445848a645e2ab883d6836b37ffc8a83 (patch)
treec352252478b2112356739fb6c3fb0286e490644f
parent0c4e155bf4652a629658758e0869b3c22ad597cf (diff)
downloadmongo-daaff3b1445848a645e2ab883d6836b37ffc8a83.tar.gz
SERVER-68477 TTL monitor skips indexes with NaN expireAfterSeconds
(cherry-picked from commit 14c07b53186ee88497abd0ba492d2d9157891718) (cherry picked from commit 7d76329f8915ec80ba07c07e4a0adbc7fd187107)
-rw-r--r--jstests/noPassthrough/ttl_expire_nan.js45
-rw-r--r--src/mongo/db/ttl.cpp15
2 files changed, 54 insertions, 6 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 bc76b345f40..8da9e1ee46a 100644
--- a/src/mongo/db/ttl.cpp
+++ b/src/mongo/db/ttl.cpp
@@ -175,12 +175,15 @@ const IndexDescriptor* getValidTTLIndex(OperationContext* opCtx,
}
BSONElement secondsExpireElt = spec[IndexDescriptor::kExpireAfterSecondsFieldName];
- if (!secondsExpireElt.isNumber()) {
- LOGV2_ERROR(22542,
- "TTL indexes require the expire field to be numeric, skipping TTL job",
- "field"_attr = IndexDescriptor::kExpireAfterSecondsFieldName,
- "type"_attr = typeName(secondsExpireElt.type()),
- "index"_attr = spec);
+ if (!secondsExpireElt.isNumber() || secondsExpireElt.isNaN()) {
+ LOGV2_ERROR(
+ 22542,
+ "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);
return nullptr;
}
return desc;