use of org.eclipse.microprofile.lra.annotation.LRAStatus in project narayana by jbosstm.
the class Coordinator method getLRAStatus.
@GET
@Path("{LraId}/status")
@Produces(MediaType.TEXT_PLAIN)
@Operation(summary = "Obtain the status of an LRA as a string")
@APIResponses({ @APIResponse(responseCode = "200", description = "The LRA exists. The status is reported in the content body.", content = @Content(schema = @Schema(implementation = String.class)), headers = { @Header(ref = LRAConstants.NARAYANA_LRA_API_VERSION_HEADER_NAME) }), @APIResponse(responseCode = "404", description = "The coordinator has no knowledge of this LRA", content = @Content(schema = @Schema(implementation = String.class))), @APIResponse(responseCode = "417", description = "The requested version provided in HTTP Header is not supported by this end point", content = @Content(schema = @Schema(implementation = String.class))) })
public Response getLRAStatus(@Parameter(name = "LraId", description = "The unique identifier of the LRA." + "Expecting to be a valid URL where the participant can be contacted at. If not in URL format it will be considered " + "to be an id which will be declared to exist at URL where coordinator is deployed at.", required = true) @PathParam("LraId") String lraId, @Parameter(ref = LRAConstants.NARAYANA_LRA_API_VERSION_HEADER_NAME) @HeaderParam(LRAConstants.NARAYANA_LRA_API_VERSION_HEADER_NAME) @DefaultValue(CURRENT_API_VERSION_STRING) String version) throws NotFoundException {
// throws NotFoundException -> response 404
LongRunningAction transaction = lraService.getTransaction(toURI(lraId));
LRAStatus status = transaction.getLRAStatus();
if (status == null) {
status = LRAStatus.Active;
}
return Response.ok().entity(status.name()).header(NARAYANA_LRA_API_VERSION_HEADER_NAME, version).build();
}
use of org.eclipse.microprofile.lra.annotation.LRAStatus in project narayana by jbosstm.
the class Coordinator method getAllLRAs.
@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Returns all LRAs", description = "Gets both active and recovering LRAs")
@APIResponses({ @APIResponse(responseCode = "200", description = "The LRAData json array which is known to coordinator", content = @Content(schema = @Schema(type = SchemaType.ARRAY, implementation = LRAData.class)), headers = { @Header(ref = LRAConstants.NARAYANA_LRA_API_VERSION_HEADER_NAME) }), @APIResponse(responseCode = "400", description = "Provided Status is not recognized as a valid LRA status value", content = @Content(schema = @Schema(implementation = String.class)), headers = { @Header(ref = LRAConstants.NARAYANA_LRA_API_VERSION_HEADER_NAME) }), @APIResponse(responseCode = "417", description = "The requested version provided in HTTP Header is not supported by this end point", content = @Content(schema = @Schema(implementation = String.class))) })
public Response getAllLRAs(@Parameter(name = STATUS_PARAM_NAME, description = "Filter the returned LRAs to only those in the give state (see CompensatorStatus)") @QueryParam(STATUS_PARAM_NAME) @DefaultValue("") String state, @Parameter(ref = LRAConstants.NARAYANA_LRA_API_VERSION_HEADER_NAME) @HeaderParam(LRAConstants.NARAYANA_LRA_API_VERSION_HEADER_NAME) @DefaultValue(CURRENT_API_VERSION_STRING) String version) {
LRAStatus requestedLRAStatus = null;
if (!state.isEmpty()) {
try {
requestedLRAStatus = LRAStatus.valueOf(state);
} catch (IllegalArgumentException e) {
String errorMsg = "Status " + state + " is not a valid LRAStatus value";
LRALogger.logger.debugf(errorMsg);
throw new WebApplicationException(errorMsg, e, Response.status(BAD_REQUEST).header(NARAYANA_LRA_API_VERSION_HEADER_NAME, version).entity(errorMsg).build());
}
}
List<LRAData> lras = lraService.getAll(requestedLRAStatus);
return Response.ok().entity(lras).header(NARAYANA_LRA_API_VERSION_HEADER_NAME, version).build();
}
use of org.eclipse.microprofile.lra.annotation.LRAStatus in project narayana by jbosstm.
the class LRACoordinatorRecoveryIT method lraCoordinatorShortTimeoutLRA.
@Test
public void lraCoordinatorShortTimeoutLRA(@ArquillianResource @OperateOnDeployment(LRA_PARTICIPANT_DEPLOYMENT_QUALIFIER) URL baseURL) throws URISyntaxException {
String lraId;
URI lraListenerURI = UriBuilder.fromUri(baseURL.toURI()).path(LRAListener.LRA_LISTENER_PATH).build();
// Starts an LRA with a short time limit by invoking a resource annotated with @LRA. The time limit is
// defined as LRAListener.LRA_SHORT_TIMELIMIT
Response response = client.target(lraListenerURI).path(LRAListener.LRA_LISTENER_ACTION).request().put(null);
Assert.assertEquals("LRA participant action", 200, response.getStatus());
// Restarts lra-coordinator to simulate a crash
restartContainer(LRA_COORDINATOR_CONTAINER_QUALIFIER);
// Waits for a period of time longer than the timeout of the LRA Transaction
doWait((LRAListener.LRA_SHORT_TIMELIMIT + 1L) * 1000);
// The LRA transaction could have been started via lraClient but it is useful to test the filters as well
lraId = getFirstLRAFromFS();
assertNotNull("A new LRA should have been added to the object store before the JVM was halted.", lraId);
lraId = String.format("%s/%s", lraClient.getCoordinatorUrl(), lraId);
// Waits for a period of time longer than the timeout of the LRA Transaction
doWait((LRAListener.LRA_SHORT_TIMELIMIT + 1L) * 1000);
// Checks recovery
LRAStatus status = getStatus(new URI(lraId));
LRALogger.logger.infof("%s: Status after restart is %s%n", status == null ? "GONE" : status.name());
if (status == null || status == LRAStatus.Cancelling) {
int sc = recover();
if (sc != 0) {
recover();
}
}
// LRA with short timeout should have timed out and cancelled
status = getStatus(new URI(lraId));
Assert.assertTrue(String.format("LRA %s should have cancelled", lraId), status == null || status == LRAStatus.Cancelled);
// Verifies that the resource was notified that the LRA finished
String listenerStatus = getStatusFromListener(lraListenerURI);
assertEquals(String.format("The service lra-listener should have been told that the final state of the LRA %s was cancelled", lraId), LRAStatus.Cancelled.name(), listenerStatus);
}
use of org.eclipse.microprofile.lra.annotation.LRAStatus in project narayana by jbosstm.
the class LRACoordinatorRecoveryIT method lraCoordinatorRecoveryTwoLRAs.
@Test
public void lraCoordinatorRecoveryTwoLRAs(@ArquillianResource @OperateOnDeployment(LRA_PARTICIPANT_DEPLOYMENT_QUALIFIER) URL deploymentUrl) throws URISyntaxException {
URI lraListenerURI = UriBuilder.fromUri(deploymentUrl.toURI()).path(LRAListener.LRA_LISTENER_PATH).build();
// Starts an LRA with a long timeout to validate that long LRAs do not finish early during recovery
URI longLRA = lraClient.startLRA(null, "Long Timeout Recovery Test", LONG_TIMEOUT, ChronoUnit.MILLIS);
// Starts an LRA with a short timeout to validate that short LRAs (which timed out when the coordinator was unavailable) are cancelled
URI shortLRA = lraClient.startLRA(null, "Short Timeout Recovery Test", SHORT_TIMEOUT, ChronoUnit.MILLIS);
// Restarts lra-coordinator to simulate a crash
restartContainer(LRA_COORDINATOR_CONTAINER_QUALIFIER);
// Waits for a period of time longer than the timeout of the short LRA transaction
doWait((LRAListener.LRA_SHORT_TIMELIMIT + 1L) * 1000);
int sc = recover();
if (sc != 0) {
recover();
}
LRAStatus longStatus = getStatus(longLRA);
LRAStatus shortStatus = getStatus(shortLRA);
Assert.assertEquals("LRA with long timeout should still be active", LRAStatus.Active.name(), longStatus.name());
Assert.assertTrue("LRA with short timeout should not be active", shortStatus == null || LRAStatus.Cancelled.equals(shortStatus) || LRAStatus.Cancelling.equals(shortStatus));
// state of this new transaction.
try (Response response = client.target(lraListenerURI).path(LRA_LISTENER_UNTIMED_ACTION).request().header(LRA_HTTP_CONTEXT_HEADER, longLRA).put(Entity.text(""))) {
Assert.assertEquals("LRA participant action", 200, response.getStatus());
}
lraClient.closeLRA(longLRA);
lraClient.closeLRA(shortLRA);
// Checks that lra-participant was notified when the long LRA transaction was closed
String listenerStatus = getStatusFromListener(lraListenerURI);
assertEquals("LRA listener should have been told that the final state of the LRA was closed", LRAStatus.Closed.name(), listenerStatus);
}
use of org.eclipse.microprofile.lra.annotation.LRAStatus in project narayana by jbosstm.
the class LRARecoveryModule method doRecoverTransaction.
private void doRecoverTransaction(Uid recoverUid) {
// Retrieve the transaction status from its original process.
int theStatus = _transactionStatusConnectionMgr.getTransactionStatus(_transactionType, recoverUid);
try {
RecoveringLRA lra = new RecoveringLRA(service, recoverUid, theStatus);
boolean inFlight = (lra.getLRAStatus() == LRAStatus.Active);
LRAStatus lraStatus = lra.getLRAStatus();
if (LRAStatus.FailedToCancel.equals(lraStatus) || LRAStatus.FailedToClose.equals(lraStatus)) {
moveEntryToFailedLRAPath(recoverUid);
return;
}
if (!service.hasTransaction(lra.getId())) {
// make sure LRAService knows about it
service.addTransaction(lra);
}
if (LRALogger.logger.isDebugEnabled()) {
LRALogger.logger.debug("LRARecoverModule: transaction type is " + _transactionType + " uid is " + recoverUid.toString() + "\n Status is " + lraStatus + " in flight is " + inFlight);
}
if (!inFlight && lra.hasPendingActions()) {
lra.replayPhase2();
if (!lra.isRecovering()) {
service.finished(lra, false);
}
}
} catch (Exception e) {
if (LRALogger.logger.isInfoEnabled()) {
LRALogger.logger.infof("LRARecoverModule: Error '%s' while recovering LRA record %s", e.getMessage(), recoverUid.fileStringForm());
}
}
}
Aggregations