summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2022-08-03 15:01:22 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-08-03 15:17:26 +0000
commit14c07b53186ee88497abd0ba492d2d9157891718 (patch)
treebe59bce158c74a9e683cb46f3bd8806a4cf6082a
parent8cc10fbb4a54982fa8631f92aa09eb5fe3bed8d9 (diff)
downloadmongo-14c07b53186ee88497abd0ba492d2d9157891718.tar.gz
SERVER-68359 TTL monitor skips indexes with NaN expireAfterSeconds
-rw-r--r--jstests/noPassthrough/ttl_expire_nan.js45
-rw-r--r--src/mongo/db/ttl.cpp9
2 files changed, 50 insertions, 4 deletions
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);