Open Alcarmor opened 5 days ago
thanks for bringing this to our attention. It would be great if you could provide a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem.
demo.zip in this spring boot sample project i have prepared 2 entities MyEntityWithDeprecatedTTL and MyEntityWithNewTTL with the same attributes as indexes, one with the new ttl annotation attribute and the other with the deprecated one.
Executing "mvn test" the DemoApplicationTests class will compare the generated indexes. (the project uses test containers, so requires docker) You will see that the test wich compare the 1 second expression ttl indexes will pass, but the test with the 0 seconds expression will fail.
Or it can be deployed to see the differences between the two entities directly on mongodb
with spring data mongodb 4.4.0 the annotation Indexed has deprecated the expireAfterSeconds in favor of expireAfter https://docs.spring.io/spring-data/data-mongodb/docs/current/api/org/springframework/data/mongodb/core/index/Indexed.html#expireAfter()
so, according to documentation an entity mapped like this
@Indexed(expireAfterSeconds = 0) private LocalDateTime retentionDate;
should be changed in this
@Indexed(expireAfter = "0s") private LocalDateTime retentionDate;
here comes the problem: the new attribute seems ignore any value that result in 0 seconds
generating a non valid ttl index and in case of an existing index a relative validation failure
Caused by: com.mongodb.MongoCommandException: Command failed with error 85 (IndexOptionsConflict): 'An equivalent index already exists with the same name but different options. Requested index: { v: 2, key: { retentionDate: 1 }, name: "retentionDate" }, existing index: { v: 2, key: { retentionDate: 1 }, name: "retentionDate", expireAfterSeconds: 0 }' on server localhost:27017. The full response is {"ok": 0.0, "errmsg": "An equivalent index already exists with the same name but different options. Requested index: { v: 2, key: { retentionDate: 1 }, name: \"retentionDate\" }, existing index: { v: 2, key: { retentionDate: 1 }, name: \"retentionDate\", expireAfterSeconds: 0 }", "code": 85, "codeName": "IndexOptionsConflict", "$clusterTime": {"clusterTime": {"$timestamp": {"t": 1732554648, "i": 1}}, "signature": {"hash": {"$binary": {"base64": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", "subType": "00"}}, "keyId": 0}}, "operationTime": {"$timestamp": {"t": 1732554648, "i": 1}}} at com.mongodb.internal.connection.ProtocolHelper.getCommandFailureException(ProtocolHelper.java:210) at com.mongodb.internal.connection.InternalStreamConnection.receiveCommandMessageResponse(InternalStreamConnection.java:520) at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceiveInternal(InternalStreamConnection.java:448) at com.mongodb.internal.connection.InternalStreamConnection.lambda$sendAndReceive$0(InternalStreamConnection.java:375) at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:378) at com.mongodb.internal.connection.UsageTrackingInternalConnection.sendAndReceive(UsageTrackingInternalConnection.java:111) at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection.sendAndReceive(DefaultConnectionPool.java:748) at com.mongodb.internal.connection.CommandProtocolImpl.execute(CommandProtocolImpl.java:68) at com.mongodb.internal.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:208) at com.mongodb.internal.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:113) at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:82) at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:73) at com.mongodb.internal.connection.DefaultServer$OperationCountTrackingConnection.command(DefaultServer.java:298) at com.mongodb.internal.operation.SyncOperationHelper.lambda$executeCommand$5(SyncOperationHelper.java:209) at com.mongodb.internal.operation.SyncOperationHelper.lambda$withSourceAndConnection$0(SyncOperationHelper.java:131) at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:156) at com.mongodb.internal.operation.SyncOperationHelper.lambda$withSourceAndConnection$1(SyncOperationHelper.java:130) at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:156) at com.mongodb.internal.operation.SyncOperationHelper.withSourceAndConnection(SyncOperationHelper.java:129) at com.mongodb.internal.operation.SyncOperationHelper.executeCommand(SyncOperationHelper.java:207) at com.mongodb.internal.operation.CreateIndexesOperation.execute(CreateIndexesOperation.java:105) at com.mongodb.internal.operation.CreateIndexesOperation.execute(CreateIndexesOperation.java:60) at com.mongodb.client.internal.MongoClusterImpl$OperationExecutorImpl.execute(MongoClusterImpl.java:379) at com.mongodb.client.internal.MongoCollectionImpl.executeCreateIndexes(MongoCollectionImpl.java:941) at com.mongodb.client.internal.MongoCollectionImpl.createIndexes(MongoCollectionImpl.java:923) at com.mongodb.client.internal.MongoCollectionImpl.createIndexes(MongoCollectionImpl.java:918) at com.mongodb.client.internal.MongoCollectionImpl.createIndex(MongoCollectionImpl.java:903) at org.springframework.data.mongodb.core.DefaultIndexOperations.lambda$ensureIndex$0(DefaultIndexOperations.java:131) at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:603) at org.springframework.data.mongodb.core.DefaultIndexOperations.execute(DefaultIndexOperations.java:217) at org.springframework.data.mongodb.core.DefaultIndexOperations.ensureIndex(DefaultIndexOperations.java:121) at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator.createIndex(MongoPersistentEntityIndexCreator.java:152)
ttl indexes are generted succesfully only if the expression result in more than 0 secods, but this is a big problem for existing indexes