use of org.folio.rest.jaxrs.model.ParsedRecordsBatchResponse in project mod-source-record-storage by folio-org.
the class SourceStorageBatchApiTest method shouldReturnErrorMessagesOnUpdateParsedRecordsIfRecordIdNotFound.
@Test
public void shouldReturnErrorMessagesOnUpdateParsedRecordsIfRecordIdNotFound(TestContext testContext) {
postSnapshots(testContext, snapshot_1);
Async async = testContext.async();
Record record1 = new Record().withId(UUID.randomUUID().toString()).withMatchedId(UUID.randomUUID().toString()).withSnapshotId(snapshot_1.getJobExecutionId()).withRecordType(Record.RecordType.MARC_BIB).withRawRecord(rawRecord).withParsedRecord(new ParsedRecord().withContent(marcRecord.getContent()));
Record record2 = new Record().withId(UUID.randomUUID().toString()).withMatchedId(UUID.randomUUID().toString()).withSnapshotId(snapshot_1.getJobExecutionId()).withRecordType(Record.RecordType.MARC_BIB).withRawRecord(rawRecord).withParsedRecord(new ParsedRecord().withContent(marcRecord.getContent()));
RecordCollection recordCollection = new RecordCollection().withRecords(Arrays.asList(record1, record2)).withTotalRecords(2);
RestAssured.given().spec(spec).body(recordCollection).when().post(SOURCE_STORAGE_BATCH_RECORDS_PATH).then().statusCode(HttpStatus.SC_CREATED).body("records.size()", is(recordCollection.getRecords().size())).body("totalRecords", is(recordCollection.getRecords().size())).body("errorMessages.size()", is(0));
async.complete();
async = testContext.async();
record1.setParsedRecord(new ParsedRecord().withContent(marcRecord.getContent()).withId(record1.getId()));
record2.setParsedRecord(new ParsedRecord().withContent(marcRecord.getContent()).withId(record2.getId()));
recordCollection = new RecordCollection().withRecords(Arrays.asList(record1.withId(UUID.randomUUID().toString()), record2.withId(UUID.randomUUID().toString()))).withTotalRecords(2);
ParsedRecordsBatchResponse updatedParsedRecordCollection = RestAssured.given().spec(spec).body(recordCollection).when().put(SOURCE_STORAGE_BATCH_PARSED_RECORDS_PATH).then().statusCode(HttpStatus.SC_OK).body("parsedRecords.size()", is(2)).body("totalRecords", is(2)).body("errorMessages.size()", is(2)).extract().response().body().as(ParsedRecordsBatchResponse.class);
testContext.assertEquals(marcRecord.getContent(), updatedParsedRecordCollection.getParsedRecords().get(0).getContent());
testContext.assertEquals(marcRecord.getContent(), updatedParsedRecordCollection.getParsedRecords().get(1).getContent());
testContext.assertEquals(format("Record with id %s was not updated", record1.getId()), updatedParsedRecordCollection.getErrorMessages().get(0));
testContext.assertEquals(format("Record with id %s was not updated", record2.getId()), updatedParsedRecordCollection.getErrorMessages().get(1));
async.complete();
}
use of org.folio.rest.jaxrs.model.ParsedRecordsBatchResponse in project mod-source-record-storage by folio-org.
the class RecordDaoImpl method updateParsedRecords.
@Override
public Future<ParsedRecordsBatchResponse> updateParsedRecords(RecordCollection recordCollection, String tenantId) {
Promise<ParsedRecordsBatchResponse> promise = Promise.promise();
Set<String> recordTypes = new HashSet<>();
List<Record> records = new ArrayList<>();
List<String> errorMessages = new ArrayList<>();
List<UpdateConditionStep<RecordsLbRecord>> recordUpdates = new ArrayList<>();
List<UpdateConditionStep<org.jooq.Record>> parsedRecordUpdates = new ArrayList<>();
Field<UUID> prtId = field(name(ID), UUID.class);
Field<JSONB> prtContent = field(name(CONTENT), JSONB.class);
List<ParsedRecord> parsedRecords = recordCollection.getRecords().stream().map(this::validateParsedRecordId).peek(record -> {
// make sure only one record type
recordTypes.add(record.getRecordType().name());
if (recordTypes.size() > 1) {
throw new BadRequestException("Batch record collection only supports single record type");
}
UpdateSetFirstStep<RecordsLbRecord> updateFirstStep = DSL.update(RECORDS_LB);
UpdateSetMoreStep<RecordsLbRecord> updateStep = null;
// check for external record properties to update
ExternalIdsHolder externalIdsHolder = record.getExternalIdsHolder();
AdditionalInfo additionalInfo = record.getAdditionalInfo();
Metadata metadata = record.getMetadata();
if (Objects.nonNull(externalIdsHolder)) {
var recordType = record.getRecordType();
String externalId = getExternalId(externalIdsHolder, recordType);
String externalHrid = getExternalHrid(externalIdsHolder, recordType);
if (StringUtils.isNotEmpty(externalId)) {
updateStep = updateFirstStep.set(RECORDS_LB.EXTERNAL_ID, UUID.fromString(externalId));
}
if (StringUtils.isNotEmpty(externalHrid)) {
updateStep = (Objects.isNull(updateStep) ? updateFirstStep : updateStep).set(RECORDS_LB.EXTERNAL_HRID, externalHrid);
}
}
if (Objects.nonNull(additionalInfo)) {
if (Objects.nonNull(additionalInfo.getSuppressDiscovery())) {
updateStep = (Objects.isNull(updateStep) ? updateFirstStep : updateStep).set(RECORDS_LB.SUPPRESS_DISCOVERY, additionalInfo.getSuppressDiscovery());
}
}
if (Objects.nonNull(metadata)) {
if (StringUtils.isNotEmpty(metadata.getCreatedByUserId())) {
updateStep = (Objects.isNull(updateStep) ? updateFirstStep : updateStep).set(RECORDS_LB.CREATED_BY_USER_ID, UUID.fromString(metadata.getCreatedByUserId()));
}
if (Objects.nonNull(metadata.getCreatedDate())) {
updateStep = (Objects.isNull(updateStep) ? updateFirstStep : updateStep).set(RECORDS_LB.CREATED_DATE, metadata.getCreatedDate().toInstant().atOffset(ZoneOffset.UTC));
}
if (StringUtils.isNotEmpty(metadata.getUpdatedByUserId())) {
updateStep = (Objects.isNull(updateStep) ? updateFirstStep : updateStep).set(RECORDS_LB.UPDATED_BY_USER_ID, UUID.fromString(metadata.getUpdatedByUserId()));
}
if (Objects.nonNull(metadata.getUpdatedDate())) {
updateStep = (Objects.isNull(updateStep) ? updateFirstStep : updateStep).set(RECORDS_LB.UPDATED_DATE, metadata.getUpdatedDate().toInstant().atOffset(ZoneOffset.UTC));
}
}
// only attempt update if has id and external values to update
if (Objects.nonNull(updateStep) && Objects.nonNull(record.getId())) {
records.add(record);
recordUpdates.add(updateStep.where(RECORDS_LB.ID.eq(UUID.fromString(record.getId()))));
}
try {
RecordType recordType = toRecordType(record.getRecordType().name());
recordType.formatRecord(record);
parsedRecordUpdates.add(DSL.update(table(name(recordType.getTableName()))).set(prtContent, JSONB.valueOf(ParsedRecordDaoUtil.normalizeContent(record.getParsedRecord()))).where(prtId.eq(UUID.fromString(record.getParsedRecord().getId()))));
} catch (Exception e) {
errorMessages.add(format(INVALID_PARSED_RECORD_MESSAGE_TEMPLATE, record.getId(), e.getMessage()));
// if invalid parsed record, set id to null to filter out
record.getParsedRecord().setId(null);
}
}).map(Record::getParsedRecord).filter(parsedRecord -> Objects.nonNull(parsedRecord.getId())).collect(Collectors.toList());
try (Connection connection = getConnection(tenantId)) {
DSL.using(connection).transaction(ctx -> {
DSLContext dsl = DSL.using(ctx);
// update records
int[] recordUpdateResults = dsl.batch(recordUpdates).execute();
// check record update results
for (int i = 0; i < recordUpdateResults.length; i++) {
int result = recordUpdateResults[i];
if (result == 0) {
errorMessages.add(format("Record with id %s was not updated", records.get(i).getId()));
}
}
// update parsed records
int[] parsedRecordUpdateResults = dsl.batch(parsedRecordUpdates).execute();
// check parsed record update results
List<ParsedRecord> parsedRecordsUpdated = new ArrayList<>();
for (int i = 0; i < parsedRecordUpdateResults.length; i++) {
int result = parsedRecordUpdateResults[i];
ParsedRecord parsedRecord = parsedRecords.get(i);
if (result == 0) {
errorMessages.add(format("Parsed Record with id '%s' was not updated", parsedRecord.getId()));
} else {
parsedRecordsUpdated.add(parsedRecord);
}
}
promise.complete(new ParsedRecordsBatchResponse().withErrorMessages(errorMessages).withParsedRecords(parsedRecordsUpdated).withTotalRecords(parsedRecordsUpdated.size()));
});
} catch (SQLException e) {
LOG.error("Failed to update records", e);
promise.fail(e);
}
return promise.future();
}
use of org.folio.rest.jaxrs.model.ParsedRecordsBatchResponse in project mod-source-record-storage by folio-org.
the class SourceStorageBatchApiTest method shouldUpdateParsedRecordsWithJsonContent.
@Test
public void shouldUpdateParsedRecordsWithJsonContent(TestContext testContext) {
postSnapshots(testContext, snapshot_2);
Record newRecord = new Record().withSnapshotId(snapshot_2.getJobExecutionId()).withRecordType(Record.RecordType.MARC_BIB).withRawRecord(rawRecord).withParsedRecord(marcRecord).withMatchedId(UUID.randomUUID().toString()).withAdditionalInfo(new AdditionalInfo().withSuppressDiscovery(false));
Async async = testContext.async();
Response createResponse = RestAssured.given().spec(spec).body(newRecord).when().post(SOURCE_STORAGE_RECORDS_PATH);
assertThat(createResponse.statusCode(), is(HttpStatus.SC_CREATED));
Record createdRecord = createResponse.body().as(Record.class);
async.complete();
ParsedRecord parsedRecordJson = new ParsedRecord().withId(createdRecord.getParsedRecord().getId()).withContent(new JsonObject().put("leader", "01542ccm a2200361 4500").put("fields", new JsonArray()));
RecordCollection recordCollection = new RecordCollection().withRecords(Collections.singletonList(createdRecord.withParsedRecord(parsedRecordJson))).withTotalRecords(1);
async = testContext.async();
ParsedRecordsBatchResponse updatedParsedRecordCollection = RestAssured.given().spec(spec).body(recordCollection).when().put(SOURCE_STORAGE_BATCH_PARSED_RECORDS_PATH).then().statusCode(HttpStatus.SC_OK).extract().response().body().as(ParsedRecordsBatchResponse.class);
ParsedRecord updatedParsedRecord = updatedParsedRecordCollection.getParsedRecords().get(0);
assertThat(updatedParsedRecord.getId(), notNullValue());
assertThat(JsonObject.mapFrom(updatedParsedRecord).encode(), containsString("\"leader\":\"01542ccm a2200361 4500\""));
async.complete();
}
use of org.folio.rest.jaxrs.model.ParsedRecordsBatchResponse in project mod-source-record-storage by folio-org.
the class SourceStorageBatchApiTest method shouldReturnErrorMessagesOnUpdateParsedRecordsIfParsedRecordIdNotFound.
@Test
public void shouldReturnErrorMessagesOnUpdateParsedRecordsIfParsedRecordIdNotFound(TestContext testContext) {
postSnapshots(testContext, snapshot_1);
Async async = testContext.async();
Record record1 = new Record().withId(UUID.randomUUID().toString()).withMatchedId(UUID.randomUUID().toString()).withSnapshotId(snapshot_1.getJobExecutionId()).withRecordType(Record.RecordType.MARC_BIB).withRawRecord(rawRecord);
Record record2 = new Record().withId(UUID.randomUUID().toString()).withMatchedId(UUID.randomUUID().toString()).withSnapshotId(snapshot_1.getJobExecutionId()).withRecordType(Record.RecordType.MARC_BIB).withRawRecord(rawRecord);
RecordCollection recordCollection = new RecordCollection().withRecords(Arrays.asList(record1, record2)).withTotalRecords(2);
RestAssured.given().spec(spec).body(recordCollection).when().post(SOURCE_STORAGE_BATCH_RECORDS_PATH).then().statusCode(HttpStatus.SC_CREATED).body("records.size()", is(recordCollection.getRecords().size())).body("errorMessages.size()", is(0)).body("totalRecords", is(recordCollection.getRecords().size()));
async.complete();
async = testContext.async();
record1.setParsedRecord(new ParsedRecord().withContent(marcRecord.getContent()).withId(UUID.randomUUID().toString()));
record2.setParsedRecord(new ParsedRecord().withContent(marcRecord.getContent()).withId(UUID.randomUUID().toString()));
recordCollection = new RecordCollection().withRecords(Arrays.asList(record1, record2)).withTotalRecords(2);
ParsedRecordsBatchResponse updatedParsedRecordCollection = RestAssured.given().spec(spec).body(recordCollection).when().put(SOURCE_STORAGE_BATCH_PARSED_RECORDS_PATH).then().statusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR).body("errorMessages.size()", is(2)).body("parsedRecords.size()", is(0)).body("totalRecords", is(0)).extract().response().body().as(ParsedRecordsBatchResponse.class);
testContext.assertEquals(format("Parsed Record with id '%s' was not updated", record1.getParsedRecord().getId()), updatedParsedRecordCollection.getErrorMessages().get(0));
testContext.assertEquals(format("Parsed Record with id '%s' was not updated", record2.getParsedRecord().getId()), updatedParsedRecordCollection.getErrorMessages().get(1));
async.complete();
}
use of org.folio.rest.jaxrs.model.ParsedRecordsBatchResponse in project mod-source-record-storage by folio-org.
the class SourceStorageBatchApiTest method shouldUpdateParsedRecords.
@Test
public void shouldUpdateParsedRecords(TestContext testContext) {
postSnapshots(testContext, snapshot_2);
String matchedId = UUID.randomUUID().toString();
Record newRecord = new Record().withId(matchedId).withSnapshotId(snapshot_2.getJobExecutionId()).withRecordType(Record.RecordType.MARC_BIB).withRawRecord(rawRecord).withParsedRecord(marcRecord).withMatchedId(matchedId).withState(Record.State.ACTUAL).withAdditionalInfo(new AdditionalInfo().withSuppressDiscovery(false));
Async async = testContext.async();
Response createResponse = RestAssured.given().spec(spec).body(newRecord).when().post(SOURCE_STORAGE_RECORDS_PATH);
assertThat(createResponse.statusCode(), is(HttpStatus.SC_CREATED));
Record createdRecord = createResponse.body().as(Record.class);
async.complete();
RecordCollection recordCollection = new RecordCollection().withRecords(Collections.singletonList(createdRecord)).withTotalRecords(1);
async = testContext.async();
ParsedRecordsBatchResponse updatedParsedRecordCollection = RestAssured.given().spec(spec).body(recordCollection).when().put(SOURCE_STORAGE_BATCH_PARSED_RECORDS_PATH).then().statusCode(HttpStatus.SC_OK).extract().response().body().as(ParsedRecordsBatchResponse.class);
ParsedRecord updatedParsedRecord = updatedParsedRecordCollection.getParsedRecords().get(0);
assertThat(updatedParsedRecord.getId(), notNullValue());
assertThat(JsonObject.mapFrom(updatedParsedRecord).encode(), containsString("\"leader\":\"01542ccm a2200361 4500\""));
async.complete();
RestAssured.given().spec(spec).body(recordCollection).when().get(SOURCE_STORAGE_RECORDS_PATH + "/" + createdRecord.getId()).then().statusCode(HttpStatus.SC_OK).body("metadata", notNullValue()).body("metadata.createdDate", notNullValue(String.class)).body("metadata.createdByUserId", notNullValue(String.class)).body("metadata.updatedDate", notNullValue(String.class)).body("metadata.updatedByUserId", notNullValue(String.class));
}
Aggregations