Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import sleeper.core.statestore.FileReferenceSerDe;
import sleeper.core.util.GsonConfig;

import java.util.Optional;

public class CompactionCommitMessageSerDe {

private static final Logger LOGGER = LoggerFactory.getLogger(CompactionCommitMessageSerDe.class);

private final Gson gson;
private final Gson gsonPrettyPrint;

Expand All @@ -40,9 +47,15 @@ public String toJsonPrettyPrint(CompactionCommitMessage message) {
return gsonPrettyPrint.toJson(message);
}

public CompactionCommitMessageHandle fromJsonWithCallbackOnFail(String json, Runnable callbackOnFail) {
CompactionCommitMessage message = gson.fromJson(json, CompactionCommitMessage.class);
return new CompactionCommitMessageHandle(message.tableId(), message.request(), callbackOnFail);
public Optional<CompactionCommitMessageHandle> fromJsonWithCallbackOnFail(String json, Runnable callbackOnFail) {
try {
CompactionCommitMessage message = gson.fromJson(json, CompactionCommitMessage.class);
return Optional.of(new CompactionCommitMessageHandle(message.tableId(), message.request(), callbackOnFail));
} catch (RuntimeException e) {
LOGGER.error("Found invalid compaction commit message: {}", json, e);
callbackOnFail.run();
return Optional.empty();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
import sleeper.core.table.TableFilePaths;
import sleeper.core.table.TableIdGenerator;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.IntStream;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -68,7 +70,7 @@ void shouldSerialiseCompactionCommitRequest() {

// When
String json = serDe.toJson(message);
CompactionCommitMessageHandle found = serDe.fromJsonWithCallbackOnFail(json, callbackOnFail);
CompactionCommitMessageHandle found = serDe.fromJsonWithCallbackOnFail(json, callbackOnFail).orElseThrow();

// Then
assertThat(found).isEqualTo(new CompactionCommitMessageHandle("test-table", filesRequest, callbackOnFail));
Expand All @@ -84,7 +86,7 @@ void shouldSerialiseRepresentativeCompactionCommitRequest() {

// When
String json = serDe.toJson(message);
CompactionCommitMessageHandle found = serDe.fromJsonWithCallbackOnFail(json, callbackOnFail);
CompactionCommitMessageHandle found = serDe.fromJsonWithCallbackOnFail(json, callbackOnFail).orElseThrow();

// Then
assertThat(found).isEqualTo(new CompactionCommitMessageHandle(tableId, filesRequest, callbackOnFail));
Expand All @@ -100,6 +102,21 @@ void shouldGenerateExpectedJson() {
.withName("example-compaction-commit", ".json"));
}

@Test
void shouldTrackDeserialisationFailure() {
// Given
List<Boolean> callbackResults = new ArrayList<>();
Runnable callbackOnFail = () -> callbackResults.add(true);
String json = "not-a-commit";

// When
Optional<CompactionCommitMessageHandle> found = serDe.fromJsonWithCallbackOnFail(json, callbackOnFail);

// Then
assertThat(found).isEmpty();
assertThat(callbackResults).containsExactly(true);
}

private ReplaceFileReferencesRequest createExampleFilesRequestOfRepresentativeSize() {
PartitionTree partitions = new PartitionsBuilder(schema).singlePartition(exampleUUID("partn", 0)).buildTree();
List<String> inputFiles = IntStream.rangeClosed(1, 11)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ private void lambdaToBatchUpCompactionCommits(
.batchSize(instanceProperties.getInt(COMPACTION_COMMIT_BATCH_SIZE))
.maxBatchingWindow(Duration.seconds(instanceProperties.getInt(COMPACTION_COMMIT_BATCHING_WINDOW_IN_SECONDS)))
.maxConcurrency(instanceProperties.getIntOrNull(COMPACTION_COMMIT_BATCHER_LAMBDA_CONCURRENCY_MAXIMUM))
.reportBatchItemFailures(true)
.build());
coreStacks.grantSendStateStoreCommits(function);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17332,6 +17332,9 @@
"Arn"
]
},
"FunctionResponseTypes": [
"ReportBatchItemFailures"
],
"Tags": [
{
"Key": "DeploymentStack",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse;
import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse.BatchItemFailure;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.services.s3.S3Client;
Expand Down Expand Up @@ -64,17 +63,14 @@ public CompactionCommitBatcherLambda(CompactionCommitBatcher batcher) {
public SQSBatchResponse handleRequest(SQSEvent event, Context context) {
List<BatchItemFailure> failures = new ArrayList<>();
List<CompactionCommitMessageHandle> requests = event.getRecords().stream()
.map(message -> readMessageTrackingFailure(message, failures))
.flatMap(message -> serDe.fromJsonWithCallbackOnFail(message.getBody(),
() -> failures.add(new BatchItemFailure(message.getMessageId())))
.stream())
.toList();
batcher.sendBatch(requests);
return new SQSBatchResponse(failures);
}

private CompactionCommitMessageHandle readMessageTrackingFailure(SQSMessage message, List<BatchItemFailure> failures) {
return serDe.fromJsonWithCallbackOnFail(message.getBody(),
() -> failures.add(new BatchItemFailure(message.getMessageId())));
}

/**
* Creates the batcher used to send requests to the state store committer queue via SQS.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,30 @@ void shouldFailWhenUnableToGetToTheSQSQueue() {
assertThat(response.getBatchItemFailures())
.extracting(BatchItemFailure::getItemIdentifier)
.containsExactly(sqsMessage.getMessageId());
}

@Test
void shouldFailWhenInvalidAndValidMessagesAreMixedInOneBatch() {
// Given
ReplaceFileReferencesRequest filesRequest = createFilesRequest();
List<SQSMessage> messages = List.of(
createMessageWithId("1-valid", new CompactionCommitMessage("table-1", filesRequest)),
createMessageWithId("2-invalid", "not-a-commit"),
createMessageWithId("3-valid", new CompactionCommitMessage("table-2", filesRequest)),
createMessageWithId("4-invalid", "not-a-commit"));

// When
SQSBatchResponse response = lambda().handleRequest(createEvent(messages), null);

// Then
assertThat(receiveCommitRequests()).containsExactly(
StateStoreCommitRequest.create("table-1",
new ReplaceFileReferencesTransaction(List.of(filesRequest))),
StateStoreCommitRequest.create("table-2",
new ReplaceFileReferencesTransaction(List.of(filesRequest))));
assertThat(response.getBatchItemFailures())
.extracting(BatchItemFailure::getItemIdentifier)
.containsExactly("2-invalid", "4-invalid");
}

private ReplaceFileReferencesRequest createFilesRequest() {
Expand All @@ -109,15 +132,27 @@ private SQSEvent createEvent(String tableId, ReplaceFileReferencesRequest reques
}

private SQSEvent createEvent(SQSMessage... messages) {
return createEvent(List.of(messages));
}

private SQSEvent createEvent(List<SQSMessage> messages) {
SQSEvent event = new SQSEvent();
event.setRecords(List.of(messages));
event.setRecords(messages);
return event;
}

private SQSMessage createMessage(String tableId, ReplaceFileReferencesRequest request) {
return createMessageWithId(UUID.randomUUID().toString(), new CompactionCommitMessage(tableId, request));
}

private SQSMessage createMessageWithId(String id, CompactionCommitMessage commit) {
return createMessageWithId(id, compactionSerDe.toJson(commit));
}

private SQSMessage createMessageWithId(String id, String body) {
SQSMessage message = new SQSMessage();
message.setMessageId(UUID.randomUUID().toString());
message.setBody(compactionSerDe.toJson(new CompactionCommitMessage(tableId, request)));
message.setMessageId(id);
message.setBody(body);
return message;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ private Set<CompactionCommitMessageHandle> drainCommitQueue() {
}

private CompactionCommitMessageHandle readCommitMessage(Message message) {
return serDe.fromJsonWithCallbackOnFail(message.body(), null);
return serDe.fromJsonWithCallbackOnFail(message.body(), null).orElseThrow();
}

private CompactionCommitMessageHandle handle(ReplaceFileReferencesRequest request) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ void shouldReportFailureCreatingCompactionJobsForSomeTables(SleeperDsl sleeper)
}

@Test
@Disabled("Failing until issue https://github.com/gchq/sleeper/issues/8365")
void shouldReportFailureCommittingSomeCompactionJobs(SleeperDsl sleeper) {
// Given a Sleeper table with 5 compaction jobs ready to be committed to the state store
sleeper.tables().createWithProperties("test", DEFAULT_SCHEMA, Map.of(
Expand Down
Loading