Current approach to working with transactions in RMB
To enable the work with a database in FOLIO project there is a custom solution implemented on top of the VERT.X Postgres Client. The main feature of working with RMB and VERT.X is the usage of the asynchronous approach. Sequential execution of operations requires handling the completion of each operation and occurring errors. Each subsequent operation can be executed only if the previous one is succeeded. In order to maintain data consistency there is a need to execute the operations in transaction and be able to rollback the changes in case an error occurred. At the moment, this possibility is implemented as follows:
...
The First and the last operations the RMB PostgresClient does automatically.
Example method with two operation in scope of one transaction
Code Block | ||||
---|---|---|---|---|
| ||||
public Future<Void> example() { Future future = Future.future(); PostgresClient client = PostgresClient.getInstance(vertx, tenantId); // start tx client.startTx(tx -> { // first operation client.get(tx, "upload_definition", UploadDefinition.class, new Criterion(), true, false, getHandler -> { if (getHandler.succeeded()) { // second operation client.save(tx, "upload_definition", UUID.randomUUID().toString(), getHandler.result(), saveHandler -> { if (saveHandler.succeeded()) { client.endTx(tx, endHandler -> { if (endHandler.succeeded()) { future.succeeded(); } else { client.rollbackTx(tx, rollbackHandler -> { future.fail(getHandler.cause()); }); } }); } else { client.rollbackTx(tx, rollbackHandler -> { future.fail(getHandler.cause()); }); } }); } else { client.rollbackTx(tx, rollbackHandler -> { future.fail(getHandler.cause()); }); } }); }); return future; } |
Note that .startTx method is deprecated, .withTrans should be used instead.
Note that callback lambda handlers are deprecated since Vert.x 4, use Future returning methods instead (see https://github.com/folio-org/raml-module-builder/blob/master/doc/futurisation.md).
Example method rewritten using withTrans and futurisation
Code Block | ||||
---|---|---|---|---|
| ||||
public Future<Void> example() { PostgresClient client = PostgresClient.getInstance(vertx, tenantId); return client.withTrans(conn -> { return conn.getByIdForUpdate("upload_definition", id, UploadDefinition.class) .map(uploadDefinition -> uploadDefinition.withStatus(UploadDefinition.Status.COMPLETED)) .compose(uploadDefinition -> conn.update("upload_definition", uploadDefinition, id)) .mapEmpty(); }); } |
...
Note that .startTx, .rollbackTx and .endTx are deprecated methods. Use .withTrans instead, see example above, or this commit:
https://github.com/folio-org/mod-data-import/commit/da177ddd585258c6f975c01888b46397f11a1bda
Method with file upload logic
...