Skip to content

Commit

Permalink
Merge pull request #499 from folio-org/tmp-release-17.3.1
Browse files Browse the repository at this point in the history
CIRCSTORE-543 Release 17.3.1
  • Loading branch information
roman-barannyk authored Nov 30, 2024
2 parents 39429d6 + e13dbbf commit dd7dc86
Show file tree
Hide file tree
Showing 25 changed files with 434 additions and 98 deletions.
9 changes: 9 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## 17.3.1 2024-11-30
* Add ILR support for publishing batch request update events (CIRCSTORE-526)
* Publish request batch event when requests are reordered (CIRCSTORE-521)
* Create new transit staff slip for mediated request activities (CIRCSTORE-525)
* Update instead save with the same name circ settings (CIRCSTORE-519)
* Create CRUD API for storing `circulation-settings` (CIRCSTORE-509)
* Add `ecsRequestPhase` field to request schema (CIRCSTORE-502)
* Review and cleanup Module Descriptor for mod-circulation-storage (CIRCSTORE-524)

## 17.3.0 2024-10-30
* Upgrade RMB to 35.3.0, Vert.x to 4.5.9, Kafka wrapper to 3.1.1 (CIRCSTORE-520, CIRCSTORE-536, CIRCSTORE-499)
* Upgrade `holdings-storage` API (CIRCSTORE-533)
Expand Down
9 changes: 5 additions & 4 deletions descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
}, {
"methods": ["POST"],
"pathPattern": "/loan-storage/loans/anonymize/{userId}",
"permissionsRequired": ["circulation-storage.loans.collection.anonymize.user.post"]
"permissionsRequired": ["circulation-storage.loans.anonymize.execute"]
}
]
},
Expand Down Expand Up @@ -757,9 +757,10 @@
"description": "Delete individual loan from storage"
},
{
"permissionName": "circulation-storage.loans.collection.anonymize.user.post",
"permissionName": "circulation-storage.loans.anonymize.execute",
"displayName": "Circulation storage - anonymize loans for a user",
"description": "Anonymize closed loans for a single user"
"description": "Anonymize closed loans for a single user",
"replaces": ["circulation-storage.loans.collection.anonymize.user.post"]
},
{
"permissionName": "anonymize-storage-loans.post",
Expand Down Expand Up @@ -1082,7 +1083,7 @@
"circulation-storage.loans.item.put",
"circulation-storage.loans.item.delete",
"circulation-storage.loans.collection.delete",
"circulation-storage.loans.collection.anonymize.user.post",
"circulation-storage.loans.anonymize.execute",
"circulation-storage.loans-history.collection.get",
"circulation-storage.circulation-rules.get",
"circulation-storage.circulation-rules.put",
Expand Down
17 changes: 16 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>mod-circulation-storage</artifactId>
<groupId>org.folio</groupId>
<version>17.3.1-SNAPSHOT</version>
<version>17.3.2-SNAPSHOT</version>
<licenses>
<license>
<name>Apache License 2.0</name>
Expand Down Expand Up @@ -31,6 +31,9 @@
<vertx-version>4.5.9</vertx-version>
<raml-module-builder-version>35.3.0</raml-module-builder-version>
<spring.version>6.1.5</spring.version>

<!--Folio dependencies properties-->
<folio-module-descriptor-validator.version>1.0.0</folio-module-descriptor-validator.version>
<argLine />
</properties>

Expand Down Expand Up @@ -513,6 +516,18 @@
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.folio</groupId>
<artifactId>folio-module-descriptor-validator</artifactId>
<version>${folio-module-descriptor-validator.version}</version>
<executions>
<execution>
<goals>
<goal>validate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
35 changes: 35 additions & 0 deletions ramls/request-queue-reordering.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Requests batch update",
"description": "List of ids reordered requests",
"type": "object",
"properties": {
"instanceId": {
"description": "Instance ID of reordered requests",
"type": "string",
"$ref": "raml-util/schemas/uuid.schema"
},
"itemId": {
"description": "Item ID of reordered requests",
"type": "string",
"$ref": "raml-util/schemas/uuid.schema"
},
"requestLevel": {
"description": "Level of the request - Item or Title",
"type": "string",
"enum": ["Item", "Title"]
},
"requestIds": {
"description": "Array of requests ids",
"type": "array",
"items": {
"type": "string",
"$ref": "raml-util/schemas/uuid.schema"
}
}
},
"additionalProperties": false,
"required": [
"requestLevel"
]
}
1 change: 1 addition & 0 deletions ramls/request-storage-batch.raml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ documentation:
types:
requests-batch: !include requests-batch.json
errors: !include raml-util/schemas/errors.schema
request-queue-reordering: !include request-queue-reordering.json

traits:
validate: !include raml-util/traits/validation.raml
Expand Down
5 changes: 5 additions & 0 deletions ramls/request.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
"type": "string",
"enum": ["Hold", "Recall", "Page"]
},
"ecsRequestPhase": {
"description": "Stage in ECS request process, absence of this field means this is a single-tenant request",
"type": "string",
"enum": ["Primary", "Secondary"]
},
"requestDate": {
"description": "Date the request was made",
"type": "string",
Expand Down
18 changes: 9 additions & 9 deletions src/main/java/org/folio/rest/impl/CirculationSettingsAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,28 +47,28 @@ public void getCirculationSettingsStorageCirculationSettingsByCirculationSetting
String circulationSettingsId, Map<String, String> okapiHeaders,
Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {

new CirculationSettingsService(vertxContext, okapiHeaders)
.findById(circulationSettingsId)
.onComplete(asyncResultHandler);
new CirculationSettingsService(vertxContext, okapiHeaders)
.findById(circulationSettingsId)
.onComplete(asyncResultHandler);
}

@Override
public void putCirculationSettingsStorageCirculationSettingsByCirculationSettingsId(
String circulationSettingsId, CirculationSetting entity, Map<String, String> okapiHeaders,
Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {

new CirculationSettingsService(vertxContext, okapiHeaders)
.update(circulationSettingsId, entity)
.onComplete(asyncResultHandler);
new CirculationSettingsService(vertxContext, okapiHeaders)
.update(circulationSettingsId, entity)
.onComplete(asyncResultHandler);
}

@Override
public void deleteCirculationSettingsStorageCirculationSettingsByCirculationSettingsId(
String circulationSettingsId, Map<String, String> okapiHeaders,
Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {

new CirculationSettingsService(vertxContext, okapiHeaders)
.delete(circulationSettingsId)
.onComplete(asyncResultHandler);
new CirculationSettingsService(vertxContext, okapiHeaders)
.delete(circulationSettingsId)
.onComplete(asyncResultHandler);
}
}
25 changes: 8 additions & 17 deletions src/main/java/org/folio/rest/impl/RequestsBatchAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,14 @@
import static org.folio.rest.jaxrs.resource.RequestStorageBatch.PostRequestStorageBatchRequestsResponse.respond201;
import static org.folio.rest.jaxrs.resource.RequestStorageBatch.PostRequestStorageBatchRequestsResponse.respond422WithApplicationJson;
import static org.folio.rest.jaxrs.resource.RequestStorageBatch.PostRequestStorageBatchRequestsResponse.respond500WithTextPlain;
import static org.folio.rest.tools.utils.TenantTool.tenantId;

import java.util.Map;

import javax.ws.rs.core.Response;
import org.folio.rest.annotations.Validate;
import org.folio.rest.jaxrs.model.RequestsBatch;
import org.folio.rest.jaxrs.resource.RequestStorageBatch;
import org.folio.rest.persist.PgUtil;
import org.folio.rest.tools.utils.MetadataUtil;
import org.folio.service.BatchResourceService;
import org.folio.service.request.RequestBatchResourceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -26,7 +23,7 @@
import io.vertx.core.Handler;

public class RequestsBatchAPI implements RequestStorageBatch {
private static final Logger LOG = LoggerFactory.getLogger(RequestsBatchAPI.class);
private static final Logger log = LoggerFactory.getLogger(RequestsBatchAPI.class);

@Validate
@Override
Expand All @@ -38,36 +35,30 @@ public void postRequestStorageBatchRequests(
MetadataUtil.populateMetadata(entity.getRequests(), okapiHeaders);
} catch (Throwable e) {
String msg = "Cannot populate metadata of request list elements: " + e.getMessage();
LOG.error(msg, e);
log.error(msg, e);
asyncResultHandler.handle(succeededFuture(respond500WithTextPlain(msg)));
return;
}

BatchResourceService batchUpdateService = new BatchResourceService(
PgUtil.postgresClient(context, okapiHeaders)
);

RequestBatchResourceService requestBatchUpdateService =
new RequestBatchResourceService(tenantId(okapiHeaders), batchUpdateService);

requestBatchUpdateService.executeRequestBatchUpdate(entity.getRequests(),
updateResult -> {
log.info("postRequestStorageBatchRequests:: requests: {}", entity.getRequests());
new RequestBatchResourceService(context, okapiHeaders)
.executeRequestBatchUpdate(entity.getRequests(), updateResult -> {
// Successfully updated
if (updateResult.succeeded()) {
LOG.debug("Batch update executed successfully");
log.debug("Batch update executed successfully");
asyncResultHandler.handle(succeededFuture(respond201()));
return;
}

// Update failed due to can not have more then one request in the same position
if (hasSamePositionConstraintViolated(updateResult.cause())) {
LOG.warn("Same position constraint violated", updateResult.cause());
log.warn("Same position constraint violated", updateResult.cause());
asyncResultHandler.handle(succeededFuture(
respond422WithApplicationJson(samePositionInQueueError(null, null))
));
} else {
// Other failure occurred
LOG.warn("Unhandled error occurred during update", updateResult.cause());
log.warn("Unhandled error occurred during update", updateResult.cause());
asyncResultHandler.handle(succeededFuture(
respond500WithTextPlain(updateResult.cause().getMessage())
));
Expand Down
40 changes: 27 additions & 13 deletions src/main/java/org/folio/service/BatchResourceService.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import io.vertx.sqlclient.RowSet;

public class BatchResourceService {
private static final Logger LOG = LoggerFactory.getLogger(BatchResourceService.class);
private static final Logger log = LoggerFactory.getLogger(BatchResourceService.class);
private static final String WHERE_CLAUSE = "WHERE id = '%s'";

private final PostgresClient postgresClient;
Expand All @@ -38,14 +38,17 @@ public BatchResourceService(PostgresClient postgresClient) {
* @param batchFactories - Factory to create a batch update chunk.
* @param onFinishHandler - Callback.
*/
public void executeBatchUpdate(
public Future<Void> executeBatchUpdate(
List<Function<SQLConnection, Future<RowSet<Row>>>> batchFactories,
Handler<AsyncResult<Void>> onFinishHandler) {

Promise<Void> promise = Promise.promise();

postgresClient.startTx(connectionResult -> {
if (connectionResult.failed()) {
LOG.warn("Can not start transaction", connectionResult.cause());
log.warn("Cannot start transaction", connectionResult.cause());
onFinishHandler.handle(failedFuture(connectionResult.cause()));
promise.fail(connectionResult.cause());
return;
}

Expand All @@ -60,21 +63,32 @@ public void executeBatchUpdate(
// Handle overall update result and decide on whether to commit or rollback transaction
lastUpdate.onComplete(updateResult -> {
if (updateResult.failed()) {
LOG.warn("Batch update rejected", updateResult.cause());
log.warn("Batch update rejected", updateResult.cause());

// Rollback transaction and keep original cause.
postgresClient.rollbackTx(connectionResult,
rollback -> onFinishHandler.handle(failedFuture(updateResult.cause()))
);
postgresClient.rollbackTx(connectionResult, rollback -> {
onFinishHandler.handle(failedFuture(updateResult.cause()));
promise.fail(updateResult.cause());
});
} else {
LOG.debug("Update successful, committing transaction");

postgresClient.endTx(connectionResult, onFinishHandler);
log.debug("Update successful, committing transaction");

postgresClient.endTx(connectionResult, commitResult -> {
if (commitResult.succeeded()) {
onFinishHandler.handle(succeededFuture());
promise.complete();
} else {
log.warn("Failed to commit transaction", commitResult.cause());
onFinishHandler.handle(failedFuture(commitResult.cause()));
promise.fail(commitResult.cause());
}
});
}
});
});
}

return promise.future();
}
/**
* Creates update single entity batch function.
*
Expand All @@ -92,7 +106,7 @@ public <T> Function<SQLConnection, Future<RowSet<Row>>> updateSingleEntityBatchF
final Promise<RowSet<Row>> promise = promise();
final Future<SQLConnection> connectionResult = succeededFuture(connection);

LOG.debug("Updating entity {} with id {}", entity, id);
log.debug("Updating entity {} with id {}", entity, id);

postgresClient.update(connectionResult, tableName, entity, "jsonb",
String.format(WHERE_CLAUSE, id), false, promise);
Expand All @@ -113,7 +127,7 @@ public Function<SQLConnection, Future<RowSet<Row>>> queryWithParamsBatchFactory(
String query, Collection<?> params) {

return connection -> {
LOG.debug("Executing SQL [{}], got [{}] parameters", query, params.size());
log.debug("Executing SQL [{}], got [{}] parameters", query, params.size());

final Promise<RowSet<Row>> promise = promise();
final Future<SQLConnection> connectionResult = succeededFuture(connection);
Expand Down
18 changes: 11 additions & 7 deletions src/main/java/org/folio/service/CirculationSettingsService.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,21 @@ public Future<Response> findById(String circulationSettingsId) {
GetCirculationSettingsStorageCirculationSettingsByCirculationSettingsIdResponse.class);
}

public Future<Response> update(String circulationSettingsId, CirculationSetting circulationSetting) {
return PgUtil.put(CIRCULATION_SETTINGS_TABLE, circulationSetting, circulationSettingsId, okapiHeaders, vertxContext,
public Future<Response> update(String circulationSettingsId,
CirculationSetting circulationSetting) {

return PgUtil.put(CIRCULATION_SETTINGS_TABLE, circulationSetting, circulationSettingsId,
okapiHeaders, vertxContext,
PutCirculationSettingsStorageCirculationSettingsByCirculationSettingsIdResponse.class)
.compose(eventPublisher.publishUpdated(circulationSetting));
}

public Future<Response> delete(String circulationSettingsId) {
return repository.getById(circulationSettingsId).compose (
circulationSetting -> PgUtil.deleteById(CIRCULATION_SETTINGS_TABLE, circulationSettingsId, okapiHeaders, vertxContext,
DeleteCirculationSettingsStorageCirculationSettingsByCirculationSettingsIdResponse.class)
.compose(eventPublisher.publishRemoved(circulationSetting))
return repository.getById(circulationSettingsId)
.compose(circulationSetting -> PgUtil.deleteById(CIRCULATION_SETTINGS_TABLE,
circulationSettingsId, okapiHeaders, vertxContext,
DeleteCirculationSettingsStorageCirculationSettingsByCirculationSettingsIdResponse.class)
.compose(eventPublisher.publishRemoved(circulationSetting))
);
}

Expand Down Expand Up @@ -109,4 +113,4 @@ private Future<List<CirculationSetting>> getSettingsByName(String settingsName)

return repository.get(filter);
}
}
}
Loading

0 comments on commit dd7dc86

Please sign in to comment.