Skip to content

Commit a6983c5

Browse files
author
Jonah Calvo
committed
Do acknowledgements in batches per shard
Signed-off-by: Jonah Calvo <caljonah@amazon.com>
1 parent 672ef56 commit a6983c5

8 files changed

Lines changed: 256 additions & 279 deletions

File tree

data-prepper-plugins/dynamodb-source/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ dependencies {
2323

2424
implementation project(path: ':data-prepper-plugins:aws-plugin-api')
2525
implementation project(path: ':data-prepper-plugins:buffer-common')
26+
implementation project(path: ':data-prepper-plugins:common')
2627

2728

2829
testImplementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml'

data-prepper-plugins/dynamodb-source/src/main/java/org/opensearch/dataprepper/plugins/source/dynamodb/stream/ShardAcknowledgementManager.java

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import org.opensearch.dataprepper.model.acknowledgements.AcknowledgementSet;
44
import org.opensearch.dataprepper.model.acknowledgements.AcknowledgementSetManager;
55
import org.opensearch.dataprepper.model.source.coordinator.enhanced.EnhancedSourceCoordinator;
6-
6+
import org.opensearch.dataprepper.common.concurrent.BackgroundThreadFactory;
77
import org.opensearch.dataprepper.model.source.coordinator.enhanced.EnhancedSourcePartition;
88
import org.opensearch.dataprepper.plugins.source.dynamodb.DynamoDBSourceConfig;
99
import org.opensearch.dataprepper.plugins.source.dynamodb.coordination.partition.StreamPartition;
@@ -36,11 +36,11 @@ public class ShardAcknowledgementManager {
3636

3737
private static final long WAIT_FOR_ACKNOWLEDGMENTS_TIMEOUT = 10L;
3838

39-
static final Duration CHECKPOINT_INTERVAL = Duration.ofSeconds(10);
39+
static final Duration CHECKPOINT_INTERVAL = Duration.ofMinutes(2);
4040

4141
private final DynamoDBSourceConfig dynamoDBSourceConfig;
4242
private final Map<StreamPartition, ConcurrentLinkedQueue<ShardCheckpointStatus>> checkpoints = new ConcurrentHashMap<>();
43-
private final ConcurrentHashMap<StreamPartition, ConcurrentHashMap<String, ShardCheckpointStatus>> ackStatus = new ConcurrentHashMap<>();
43+
private final ConcurrentHashMap<StreamPartition, ConcurrentHashMap<String, ShardCheckpointStatus>> ackStatuses = new ConcurrentHashMap<>();
4444

4545
private final AcknowledgementSetManager acknowledgementSetManager;
4646

@@ -59,11 +59,7 @@ public ShardAcknowledgementManager(final AcknowledgementSetManager acknowledgeme
5959
this.acknowledgementSetManager = acknowledgementSetManager;
6060
this.sourceCoordinator = sourceCoordinator;
6161
this.dynamoDBSourceConfig = dynamoDBSourceConfig;
62-
this.executorService = Executors.newSingleThreadExecutor(r -> {
63-
Thread t = new Thread(r, "dynamodb-shard-ack-monitor");
64-
t.setDaemon(true);
65-
return t;
66-
});
62+
this.executorService = Executors.newSingleThreadExecutor(BackgroundThreadFactory.defaultExecutorThreadFactory("dynamodb-shard-ack-monitor"));
6763
this.partitionsToRemove = Collections.synchronizedList(new ArrayList<>());
6864
this.lastCheckpointTime = Instant.now();
6965
}
@@ -97,7 +93,7 @@ boolean runMonitorAcknowledgmentLoop(final Consumer<StreamPartition> stopWorkerC
9793
ShardCheckpointStatus latestCheckpointForShard = null;
9894
boolean gaveUpPartition = false;
9995
while (!checkpointStatuses.isEmpty()) {
100-
updateOwnershipForAllSegmentPartitions();
96+
updateOwnershipForAllShardPartitions();
10197

10298
if (checkpointStatuses.peek().isPositiveAcknowledgement()) {
10399
latestCheckpointForShard = checkpointStatuses.poll();
@@ -122,15 +118,15 @@ boolean runMonitorAcknowledgmentLoop(final Consumer<StreamPartition> stopWorkerC
122118
}
123119

124120
if (!gaveUpPartition) {
125-
updateOwnershipForAllSegmentPartitions();
121+
updateOwnershipForAllShardPartitions();
126122
}
127123

128124
if (gaveUpPartition || latestCheckpointForShard == null) {
129125
continue;
130126
}
131127

132128
if (latestCheckpointForShard.isFinalAcknowledgmentForPartition()) {
133-
handleCompletedSegment(streamPartition);
129+
handleCompletedShard(streamPartition);
134130
} else {
135131
streamProgressState.setSequenceNumber(Objects.equals(latestCheckpointForShard.getSequenceNumber(), NULL_SEQUENCE_NUMBER) ? null : latestCheckpointForShard.getSequenceNumber());
136132
sourceCoordinator.saveProgressStateForPartition(streamPartition, dynamoDBSourceConfig.getShardAcknowledgmentTimeout());
@@ -151,12 +147,12 @@ public AcknowledgementSet createAcknowledgmentSet(
151147
final String sequenceNumberNoNull = sequenceNumber == null ? NULL_SEQUENCE_NUMBER : sequenceNumber;
152148
final ShardCheckpointStatus shardCheckpointStatus = new ShardCheckpointStatus(sequenceNumber, Instant.now().toEpochMilli(), isFinalSetForPartition);
153149
checkpoints.computeIfAbsent(streamPartition, segment -> new ConcurrentLinkedQueue<>()).add(shardCheckpointStatus);
154-
ackStatus.computeIfAbsent(streamPartition, segment -> new ConcurrentHashMap<>());
155-
ackStatus.get(streamPartition).put(sequenceNumberNoNull, shardCheckpointStatus);
150+
ackStatuses.computeIfAbsent(streamPartition, segment -> new ConcurrentHashMap<>());
151+
ackStatuses.get(streamPartition).put(sequenceNumberNoNull, shardCheckpointStatus);
156152

157153
return acknowledgementSetManager.create((result) -> {
158-
if (ackStatus.containsKey(streamPartition) && ackStatus.get(streamPartition).containsKey(sequenceNumberNoNull)) {
159-
final ShardCheckpointStatus ackCheckpointStatus = ackStatus.get(streamPartition).get(sequenceNumberNoNull);
154+
if (ackStatuses.containsKey(streamPartition) && ackStatuses.get(streamPartition).containsKey(sequenceNumberNoNull)) {
155+
final ShardCheckpointStatus ackCheckpointStatus = ackStatuses.get(streamPartition).get(sequenceNumberNoNull);
160156

161157
ackCheckpointStatus.setAcknowledgedTimestamp(Instant.now().toEpochMilli());
162158

@@ -173,7 +169,7 @@ public AcknowledgementSet createAcknowledgmentSet(
173169
}, dynamoDBSourceConfig.getShardAcknowledgmentTimeout());
174170
}
175171

176-
void updateOwnershipForAllSegmentPartitions() {
172+
void updateOwnershipForAllShardPartitions() {
177173
if (Duration.between(lastCheckpointTime, Instant.now()).compareTo(CHECKPOINT_INTERVAL) > 0) {
178174
for (final StreamPartition streamPartition : checkpoints.keySet()) {
179175
if (!partitionsToRemove.contains(streamPartition)) {
@@ -196,7 +192,7 @@ private void handleFailure(final StreamPartition streamPartition,
196192
sourceCoordinator.giveUpPartition(streamPartition);
197193
}
198194

199-
private void handleCompletedSegment(final StreamPartition streamPartition) {
195+
private void handleCompletedShard(final StreamPartition streamPartition) {
200196
sourceCoordinator.completePartition(streamPartition);
201197
partitionsToRemove.add(streamPartition);
202198
LOG.info("Received all acknowledgments for partition {}, marking partition as completed", streamPartition.getPartitionKey());
@@ -206,7 +202,7 @@ public void shutdown() {
206202
shutdownTriggered = true;
207203
executorService.shutdown();
208204
try {
209-
if (!executorService.awaitTermination(WAIT_FOR_ACKNOWLEDGMENTS_TIMEOUT, TimeUnit.SECONDS)) {
205+
if (!executorService.awaitTermination(WAIT_FOR_ACKNOWLEDGMENTS_TIMEOUT, TimeUnit.MINUTES)) {
210206
executorService.shutdownNow();
211207
}
212208
} catch (InterruptedException e) {
@@ -218,7 +214,7 @@ public void shutdown() {
218214
private void removePartitions() {
219215
partitionsToRemove.forEach(streamPartition -> {
220216
checkpoints.remove(streamPartition);
221-
ackStatus.remove(streamPartition);
217+
ackStatuses.remove(streamPartition);
222218
});
223219

224220
partitionsToRemove.clear();

0 commit comments

Comments
 (0)