Skip to content

Commit 50a41a3

Browse files
committed
Optimize sequence handling in MongoDB job repository
1 parent 6c330d6 commit 50a41a3

File tree

4 files changed

+33
-56
lines changed

4 files changed

+33
-56
lines changed

spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/MongoSequenceIncrementer.java

Lines changed: 10 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,20 @@
1515
*/
1616
package org.springframework.batch.core.repository.dao;
1717

18+
import com.mongodb.client.model.FindOneAndUpdateOptions;
19+
import com.mongodb.client.model.ReturnDocument;
20+
import org.bson.Document;
21+
1822
import org.springframework.dao.DataAccessException;
1923
import org.springframework.data.mongodb.core.MongoOperations;
20-
import org.springframework.data.mongodb.core.query.Query;
21-
import org.springframework.data.mongodb.core.query.Update;
2224
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
2325

24-
import static org.springframework.data.mongodb.core.query.Criteria.where;
25-
import static org.springframework.data.mongodb.core.query.Query.query;
26-
2726
// Based on https://www.mongodb.com/blog/post/generating-globally-unique-identifiers-for-use-with-mongodb
2827
// Section: Use a single counter document to generate unique identifiers one at a time
2928

3029
/**
3130
* @author Mahmoud Ben Hassine
31+
* @author Christoph Strobl
3232
* @since 5.2.0
3333
*/
3434
public class MongoSequenceIncrementer implements DataFieldMaxValueIncrementer {
@@ -44,13 +44,11 @@ public MongoSequenceIncrementer(MongoOperations mongoTemplate, String sequenceNa
4444

4545
@Override
4646
public long nextLongValue() throws DataAccessException {
47-
// TODO optimize
48-
MongoSequence sequence = mongoTemplate.findOne(new Query(), MongoSequence.class, sequenceName);
49-
Query query = query(where("_id").is(sequence.getId()));
50-
Update update = new Update().inc("count", 1);
51-
// The following does not return the modified document
52-
mongoTemplate.findAndModify(query, update, MongoSequence.class, sequenceName);
53-
return mongoTemplate.findOne(new Query(), MongoSequence.class, sequenceName).getCount();
47+
return mongoTemplate.execute("BATCH_SEQUENCES",
48+
collection -> collection
49+
.findOneAndUpdate(new Document("_id", sequenceName), new Document("$inc", new Document("count", 1)),
50+
new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER))
51+
.getLong("count"));
5452
}
5553

5654
@Override
@@ -63,33 +61,4 @@ public String nextStringValue() throws DataAccessException {
6361
throw new UnsupportedOperationException();
6462
}
6563

66-
public static final class MongoSequence {
67-
68-
private String id;
69-
70-
private long count;
71-
72-
public String getId() {
73-
return id;
74-
}
75-
76-
public void setId(String id) {
77-
this.id = id;
78-
}
79-
80-
public long getCount() {
81-
return count;
82-
}
83-
84-
public void setCount(long count) {
85-
this.count = count;
86-
}
87-
88-
@Override
89-
public String toString() {
90-
return "MongoSequence{" + "id='" + id + '\'' + ", count=" + count + '}';
91-
}
92-
93-
}
94-
9564
}

spring-batch-core/src/main/resources/org/springframework/batch/core/schema-drop-mongodb.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,4 @@
22
db.getCollection("BATCH_JOB_INSTANCE").drop();
33
db.getCollection("BATCH_JOB_EXECUTION").drop();
44
db.getCollection("BATCH_STEP_EXECUTION").drop();
5-
db.getCollection("BATCH_JOB_INSTANCE_SEQ").drop();
6-
db.getCollection("BATCH_JOB_EXECUTION_SEQ").drop();
7-
db.getCollection("BATCH_STEP_EXECUTION_SEQ").drop();
5+
db.getCollection("BATCH_SEQUENCES").drop();

spring-batch-core/src/main/resources/org/springframework/batch/core/schema-mongodb.js

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,17 @@
22
db.createCollection("BATCH_JOB_INSTANCE");
33
db.createCollection("BATCH_JOB_EXECUTION");
44
db.createCollection("BATCH_STEP_EXECUTION");
5-
db.createCollection("BATCH_JOB_INSTANCE_SEQ");
6-
db.createCollection("BATCH_JOB_EXECUTION_SEQ");
7-
db.createCollection("BATCH_STEP_EXECUTION_SEQ");
8-
db.getCollection("BATCH_JOB_INSTANCE_SEQ").insertOne({count : 0});
9-
db.getCollection("BATCH_JOB_EXECUTION_SEQ").insertOne({count : 0});
10-
db.getCollection("BATCH_STEP_EXECUTION_SEQ").insertOne({count : 0});
5+
6+
// SEQUENCES
7+
db.createCollection("BATCH_SEQUENCES");
8+
db.getCollection("BATCH_SEQUENCES").insertOne({_id: "BATCH_JOB_INSTANCE_SEQ", count: Long(0)});
9+
db.getCollection("BATCH_SEQUENCES").insertOne({_id: "BATCH_JOB_EXECUTION_SEQ", count: Long(0)});
10+
db.getCollection("BATCH_SEQUENCES").insertOne({_id: "BATCH_STEP_EXECUTION_SEQ", count: Long(0)});
11+
12+
// INDICES
13+
db.getCollection("BATCH_JOB_INSTANCE").createIndex("job_name_idx", {"jobName": 1}, {});
14+
db.getCollection("BATCH_JOB_INSTANCE").createIndex("job_name_key_idx", {"jobName": 1, "jobKey": 1}, {});
15+
db.getCollection("BATCH_JOB_INSTANCE").createIndex("job_instance_idx", {"jobInstanceId": -1}, {});
16+
db.getCollection("BATCH_JOB_EXECUTION").createIndex("job_instance_idx", {"jobInstanceId": 1}, {});
17+
db.getCollection("BATCH_JOB_EXECUTION").createIndex("job_instance_idx", {"jobInstanceId": 1, "status": 1}, {});
18+
db.getCollection("BATCH_STEP_EXECUTION").createIndex("step_execution_idx", {"stepExecutionId": 1}, {});

spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/MongoDBJobRepositoryIntegrationTests.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.springframework.batch.core.repository.support;
1717

1818
import java.time.LocalDateTime;
19+
import java.util.Map;
1920

2021
import com.mongodb.client.MongoClient;
2122
import com.mongodb.client.MongoClients;
@@ -75,12 +76,13 @@ public void setUp() {
7576
mongoTemplate.createCollection("BATCH_JOB_INSTANCE");
7677
mongoTemplate.createCollection("BATCH_JOB_EXECUTION");
7778
mongoTemplate.createCollection("BATCH_STEP_EXECUTION");
78-
mongoTemplate.createCollection("BATCH_JOB_INSTANCE_SEQ");
79-
mongoTemplate.createCollection("BATCH_JOB_EXECUTION_SEQ");
80-
mongoTemplate.createCollection("BATCH_STEP_EXECUTION_SEQ");
81-
mongoTemplate.getCollection("BATCH_JOB_INSTANCE_SEQ").insertOne(new Document("count", 0));
82-
mongoTemplate.getCollection("BATCH_JOB_EXECUTION_SEQ").insertOne(new Document("count", 0));
83-
mongoTemplate.getCollection("BATCH_STEP_EXECUTION_SEQ").insertOne(new Document("count", 0));
79+
mongoTemplate.createCollection("BATCH_SEQUENCES");
80+
mongoTemplate.getCollection("BATCH_SEQUENCES")
81+
.insertOne(new Document(Map.of("_id", "BATCH_JOB_INSTANCE_SEQ", "count", 0L)));
82+
mongoTemplate.getCollection("BATCH_SEQUENCES")
83+
.insertOne(new Document(Map.of("_id", "BATCH_JOB_EXECUTION_SEQ", "count", 0L)));
84+
mongoTemplate.getCollection("BATCH_SEQUENCES")
85+
.insertOne(new Document(Map.of("_id", "BATCH_STEP_EXECUTION_SEQ", "count", 0L)));
8486
}
8587

8688
@Test

0 commit comments

Comments
 (0)