Skip to content

Commit

Permalink
Assume atomic action
Browse files Browse the repository at this point in the history
  • Loading branch information
southeo committed Nov 21, 2023
1 parent 33bb36b commit c836635
Show file tree
Hide file tree
Showing 8 changed files with 12 additions and 96 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import eu.dissco.core.handlemanager.domain.repsitoryobjects.HandleAttribute;
import eu.dissco.core.handlemanager.domain.repsitoryobjects.HandleFullRow;
import eu.dissco.core.handlemanager.exceptions.CopyDatabaseException;
import eu.dissco.core.handlemanager.exceptions.PidCreationException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
Expand All @@ -21,27 +21,18 @@ public class BatchInserter {
private final CopyManager copyManager;

public void batchCopy(long recordTimestamp, List<HandleAttribute> handleAttributes)
throws CopyDatabaseException {
throws PidCreationException {
var rows = handleAttributes.stream()
.map(attribute -> new HandleFullRow(attribute, recordTimestamp)).toList();
try (var outputStream = new ByteArrayOutputStream()) {
for (var row : rows) {
outputStream.write(row.getCsvRow());
}
var inputStream = new ByteArrayInputStream(outputStream.toByteArray());
var rowsChanged = copyManager.copyIn("COPY handles FROM stdin DELIMITER ','", inputStream);
verifyAllRowsPosted(rowsChanged, handleAttributes.size());
copyManager.copyIn("COPY handles FROM stdin DELIMITER ','", inputStream);
} catch (IOException | SQLException e) {
log.error("Sql error: ", e);
throw new CopyDatabaseException(e.getMessage());
}
}

private void verifyAllRowsPosted(long rowsChanged, int rowsToPost)
throws CopyDatabaseException {
if (rowsChanged != rowsToPost) {
log.error("Expected to post {} rows, but only {} rows changed", rowsToPost, rowsChanged);
throw new CopyDatabaseException("Failed to post correct rows");
throw new PidCreationException("Unable to insert handles into database.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import static eu.dissco.core.handlemanager.domain.FdoProfile.PRIMARY_SPECIMEN_OBJECT_ID;

import eu.dissco.core.handlemanager.domain.repsitoryobjects.HandleAttribute;
import eu.dissco.core.handlemanager.exceptions.CopyDatabaseException;
import eu.dissco.core.handlemanager.exceptions.PidCreationException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashSet;
Expand Down Expand Up @@ -147,7 +147,7 @@ private HandleAttribute mapToAttribute(Record4<Integer, byte[], byte[], byte[]>

// Post
public void postAttributesToDb(long recordTimestamp, List<HandleAttribute> handleAttributes)
throws CopyDatabaseException {
throws PidCreationException {
batchInserter.batchCopy(recordTimestamp, handleAttributes);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import eu.dissco.core.handlemanager.domain.requests.objects.DigitalSpecimenRequest;
import eu.dissco.core.handlemanager.domain.requests.objects.MediaObjectRequest;
import eu.dissco.core.handlemanager.domain.requests.vocabulary.specimen.ObjectType;
import eu.dissco.core.handlemanager.exceptions.CopyDatabaseException;
import eu.dissco.core.handlemanager.exceptions.InvalidRequestException;
import eu.dissco.core.handlemanager.exceptions.PidCreationException;
import eu.dissco.core.handlemanager.exceptions.PidResolutionException;
Expand Down Expand Up @@ -94,14 +93,9 @@ public JsonApiWrapperWrite createRecords(

log.info("Persisting new DOIs to db");
var recordTimestamp = Instant.now().getEpochSecond();
try {
pidRepository.postAttributesToDb(recordTimestamp, handleAttributes);
} catch (CopyDatabaseException e) {
log.info("Rolling back handles");
var handlesString = handles.stream().map(h -> new String(h, StandardCharsets.UTF_8)).toList();
rollbackHandles(handlesString);
throw new PidCreationException("Unable to insert handles into database");
}

pidRepository.postAttributesToDb(recordTimestamp, handleAttributes);

return new JsonApiWrapperWrite(formatCreateRecords(handleAttributes, recordTypes));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import eu.dissco.core.handlemanager.domain.requests.objects.OrganisationRequest;
import eu.dissco.core.handlemanager.domain.requests.objects.SourceSystemRequest;
import eu.dissco.core.handlemanager.domain.requests.vocabulary.specimen.ObjectType;
import eu.dissco.core.handlemanager.exceptions.CopyDatabaseException;
import eu.dissco.core.handlemanager.exceptions.InvalidRequestException;
import eu.dissco.core.handlemanager.exceptions.PidCreationException;
import eu.dissco.core.handlemanager.exceptions.PidResolutionException;
Expand Down Expand Up @@ -145,14 +144,7 @@ public JsonApiWrapperWrite createRecords(

validateDigitalSpecimens(digitalSpecimenList);
log.info("Persisting new handles to db");
try {
pidRepository.postAttributesToDb(recordTimestamp, handleAttributes);
} catch (CopyDatabaseException e) {
log.info("Rolling back handles");
var handlesString = handles.stream().map(h -> new String(h, StandardCharsets.UTF_8)).toList();
rollbackHandles(handlesString);
throw new PidCreationException("Unable to insert handles into database");
}
pidRepository.postAttributesToDb(recordTimestamp, handleAttributes);
return new JsonApiWrapperWrite(formatCreateRecords(handleAttributes, recordTypes));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import eu.dissco.core.handlemanager.database.jooq.tables.Handles;
import eu.dissco.core.handlemanager.domain.FdoProfile;
import eu.dissco.core.handlemanager.domain.repsitoryobjects.HandleAttribute;
import eu.dissco.core.handlemanager.exceptions.CopyDatabaseException;
import eu.dissco.core.handlemanager.exceptions.PidCreationException;
import java.nio.charset.StandardCharsets;
import java.sql.DriverManager;
import java.sql.SQLException;
Expand Down Expand Up @@ -55,7 +55,7 @@ void testBatchInsertIllegalChar() {
);

// Then
assertThrows(CopyDatabaseException.class,
assertThrows(PidCreationException.class,
() -> batchInserter.batchCopy(CREATED.getEpochSecond(), attributes));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,20 @@
import static eu.dissco.core.handlemanager.testUtils.TestUtils.RECORD_TYPE_HANDLE;
import static eu.dissco.core.handlemanager.testUtils.TestUtils.genCreateRecordRequest;
import static eu.dissco.core.handlemanager.testUtils.TestUtils.genDigitalSpecimenAttributes;
import static eu.dissco.core.handlemanager.testUtils.TestUtils.genDoiRecordAttributes;
import static eu.dissco.core.handlemanager.testUtils.TestUtils.givenDigitalSpecimenRequestObjectNullOptionals;
import static eu.dissco.core.handlemanager.testUtils.TestUtils.givenDoiRecordRequestObject;
import static eu.dissco.core.handlemanager.testUtils.TestUtils.givenRecordResponseWriteSmallResponse;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mockStatic;

import eu.dissco.core.handlemanager.Profiles;
import eu.dissco.core.handlemanager.domain.repsitoryobjects.HandleAttribute;
import eu.dissco.core.handlemanager.domain.requests.vocabulary.specimen.ObjectType;
import eu.dissco.core.handlemanager.exceptions.CopyDatabaseException;
import eu.dissco.core.handlemanager.exceptions.InvalidRequestException;
import eu.dissco.core.handlemanager.exceptions.PidCreationException;
import eu.dissco.core.handlemanager.properties.ProfileProperties;
import eu.dissco.core.handlemanager.repository.PidRepository;
import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -122,29 +116,6 @@ void testCreateDoiRecordDoiProfile() throws Exception {
assertThat(responseReceived).isEqualTo(responseExpected);
}

@Test
void testCreateDoiRecordDbException() throws Exception {
// Given
byte[] handle = handles.get(0);
var request = genCreateRecordRequest(givenDigitalSpecimenRequestObjectNullOptionals(),
RECORD_TYPE_DS);
List<HandleAttribute> doiRecord = genDoiRecordAttributes(handle, ObjectType.DIGITAL_SPECIMEN);

given(pidNameGeneratorService.genHandleList(1)).willReturn(new ArrayList<>(List.of(handle)));
given(fdoRecordService.prepareDigitalSpecimenRecordAttributes(any(), any(),
eq(ObjectType.DIGITAL_SPECIMEN))).willReturn(
doiRecord);
doThrow(CopyDatabaseException.class).when(pidRepository)
.postAttributesToDb(CREATED.getEpochSecond(), doiRecord);

// When
assertThrows(PidCreationException.class, () -> service.createRecords(List.of(request)));

// Then
then(pidRepository).should()
.rollbackHandles(List.of(new String(handle, StandardCharsets.UTF_8)));
}

@Test
void testCreateInvalidType() {
// Given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mockStatic;

import com.fasterxml.jackson.databind.JsonNode;
Expand All @@ -73,7 +72,6 @@
import eu.dissco.core.handlemanager.domain.jsonapi.JsonApiWrapperWrite;
import eu.dissco.core.handlemanager.domain.repsitoryobjects.HandleAttribute;
import eu.dissco.core.handlemanager.domain.requests.vocabulary.specimen.ObjectType;
import eu.dissco.core.handlemanager.exceptions.CopyDatabaseException;
import eu.dissco.core.handlemanager.exceptions.InvalidRequestException;
import eu.dissco.core.handlemanager.exceptions.PidCreationException;
import eu.dissco.core.handlemanager.exceptions.PidResolutionException;
Expand Down Expand Up @@ -344,27 +342,6 @@ void testCreateDoiRecord() throws Exception {
assertThat(responseReceived).isEqualTo(responseExpected);
}

@Test
void testCreateDoiRecordDbException() throws Exception {
// Given
byte[] handle = handles.get(0);
var request = genCreateRecordRequest(givenDoiRecordRequestObject(), RECORD_TYPE_DOI);
List<HandleAttribute> doiRecord = genDoiRecordAttributes(handle, ObjectType.HANDLE);

given(pidNameGeneratorService.genHandleList(1)).willReturn(new ArrayList<>(List.of(handle)));
given(fdoRecordService.prepareDoiRecordAttributes(any(), any(), eq(ObjectType.DOI))).willReturn(
doiRecord);
doThrow(CopyDatabaseException.class).when(pidRepository)
.postAttributesToDb(CREATED.getEpochSecond(), doiRecord);

// When
assertThrows(PidCreationException.class, () -> service.createRecords(List.of(request)));

// Then
then(pidRepository).should()
.rollbackHandles(List.of(new String(handle, StandardCharsets.UTF_8)));
}

@Test
void testCreateDigitalSpecimen() throws Exception {
// Given
Expand Down

0 comments on commit c836635

Please sign in to comment.