use of org.eclipse.microprofile.lra.annotation.LRAStatus in project narayana by jbosstm.
the class LRAParticipantRecord method retryGetEndStatus.
private int retryGetEndStatus(URI endPath, boolean compensate) {
assert accepted;
// the participant has previously returned a HTTP 202 Accepted response so the status URI
// must be valid - try that first for the status
// first check that this isn't a nested coordinator running locally
URI nestedLraId = extractParentLRA(endPath);
trace_progress("retryGetEndStatus");
if (nestedLraId != null && lraService != null) {
LongRunningAction transaction = lraService.getTransaction(nestedLraId);
if (transaction != null) {
LRAStatus cStatus = transaction.getLRAStatus();
trace_progress("retryGetEndStatus: local status " + cStatus);
if (cStatus == null) {
LRALogger.logger.warnf("LRAParticipantRecord.retryGetEndStatus: local LRA %s accepted but has a null status", endPath);
// shouldn't happen since it imples it's still be active - force end to be called
return -1;
}
switch(cStatus) {
case Closed:
case Cancelled:
return TwoPhaseOutcome.FINISH_OK;
case Closing:
case Cancelling:
return TwoPhaseOutcome.HEURISTIC_HAZARD;
case FailedToClose:
case FailedToCancel:
return reportFailure(compensate, endPath, "unknown");
default:
return TwoPhaseOutcome.HEURISTIC_HAZARD;
}
}
} else if (statusURI != null) {
// it is a standard participant - check the status URI
Response response;
Client client = null;
try {
// since this method is called from the recovery thread do not block
client = ClientBuilder.newClient();
response = // .path(getLRAId(lraId))
client.target(statusURI).request().header(LRA_HTTP_CONTEXT_HEADER, lraId.toASCIIString()).header(LRA_HTTP_RECOVERY_HEADER, recoveryURI.toASCIIString()).header(LRA_HTTP_PARENT_CONTEXT_HEADER, parentId).async().get().get(PARTICIPANT_TIMEOUT, // if the attempt times out the catch block below will return a heuristic
TimeUnit.SECONDS);
// 200 and 410 are the only valid response code for reporting the participant status
if (response.getStatus() == Response.Status.GONE.getStatusCode()) {
/*
* The specification states (in section 3.2.10. Reporting the status of a participant):
* If the participant has already responded successfully to an @Compensate or @Complete method
* invocation then it MAY report 410 Gone HTTP status code
*
* This means that if the participant was asked to compensate then it has now compensated, or
* if the participant was asked to complete then it has now completed.
*/
status = compensate ? ParticipantStatus.Compensated : ParticipantStatus.Completed;
return TwoPhaseOutcome.FINISH_OK;
} else if (response.getStatus() == Response.Status.ACCEPTED.getStatusCode() || Response.Status.Family.familyOf(response.getStatus()).equals(Response.Status.Family.SERVER_ERROR)) {
// these response codes indicate that the implementation should retry later
return TwoPhaseOutcome.HEURISTIC_HAZARD;
} else if (response.getStatus() == Response.Status.OK.getStatusCode() && response.hasEntity()) {
// the participant is available again and has reported its status
status = ParticipantStatus.valueOf(response.readEntity(String.class));
switch(status) {
case Completed:
case Compensated:
return TwoPhaseOutcome.FINISH_OK;
case Completing:
case Compensating:
// still in progress - make sure recovery keeps retrying it
return TwoPhaseOutcome.HEURISTIC_HAZARD;
case FailedToCompensate:
case FailedToComplete:
// the participant could not finish - log a warning and forget
LRALogger.logger.warnf("LRAParticipantRecord.doEnd(compensate %b) get status %s did not finish: %s: WILL NOT RETRY", compensate, endPath, status);
if (forgetURI != null) {
if (!forget()) {
// we will retry the forget on the next recovery cycle
return TwoPhaseOutcome.HEURISTIC_HAZARD;
}
}
return reportFailure(compensate, endPath, "Unknown");
default:
return TwoPhaseOutcome.HEURISTIC_HAZARD;
}
}
} catch (Throwable e) {
if (LRALogger.logger.isInfoEnabled()) {
LRALogger.logger.infof("LRAParticipantRecord.doEnd status URI %s is invalid (%s)", statusURI, e.getMessage());
}
// force recovery to keep retrying
return TwoPhaseOutcome.HEURISTIC_HAZARD;
} finally {
trace_progress("retryGetEndStatus");
Current.pop();
if (client != null) {
client.close();
}
}
}
return -1;
}
use of org.eclipse.microprofile.lra.annotation.LRAStatus in project narayana by jbosstm.
the class Coordinator method getNestedLRAStatus.
@GET
@Path("nested/{NestedLraId}/status")
public Response getNestedLRAStatus(@PathParam("NestedLraId") String nestedLraId) {
if (!lraService.hasTransaction(nestedLraId)) {
// it must have compensated
return Response.ok(ParticipantStatus.Compensated.name()).build();
}
LongRunningAction lra = lraService.getTransaction(toURI(nestedLraId));
LRAStatus status = lra.getLRAStatus();
if (status == null || lra.getLRAStatus() == null) {
String logMsg = LRALogger.i18nLogger.error_cannotGetStatusOfNestedLraURI(nestedLraId, lra.getId());
LRALogger.logger.debug(logMsg);
throw new WebApplicationException(logMsg, Response.status(Response.Status.PRECONDITION_FAILED).entity(logMsg).build());
}
return Response.ok(mapToParticipantStatus(lra.getLRAStatus()).name()).build();
}
use of org.eclipse.microprofile.lra.annotation.LRAStatus in project narayana by jbosstm.
the class LRARecoveryModule method getFailedLRAs.
public void getFailedLRAs(Map<URI, LongRunningAction> lras) {
InputObjectState aa_uids = new InputObjectState();
Consumer<Uid> failedLRACreator = uid -> {
FailedLongRunningAction lra = new FailedLongRunningAction(service, new Uid(uid));
lra.activate();
LRAStatus status = lra.getLRAStatus();
if (LRAStatus.FailedToCancel.equals(status) || LRAStatus.FailedToClose.equals(status)) {
lras.put(lra.getId(), lra);
}
};
if (getUids(FailedLongRunningAction.FAILED_LRA_TYPE, aa_uids)) {
forEach(aa_uids, failedLRACreator, FailedLongRunningAction.FAILED_LRA_TYPE);
}
}
use of org.eclipse.microprofile.lra.annotation.LRAStatus in project narayana by jbosstm.
the class LRATest method assertStatus.
private void assertStatus(String message, URI lraId, LRAStatus... expectedValues) {
LRAStatus status = getStatus(lraId);
assertTrue(message + ": LRA status: " + status, Arrays.stream(expectedValues).anyMatch(s -> s == status));
}
use of org.eclipse.microprofile.lra.annotation.LRAStatus in project narayana by jbosstm.
the class LRATest method runLRA.
private void runLRA(boolean cancel) {
URI parentId = lraClient.startLRA("parent");
URI childId = lraClient.startLRA(parentId, "child", 0L, ChronoUnit.SECONDS);
// enlist a participant with the child
enlistParticipant(childId.toASCIIString().split("\\?")[0]);
// enlist a participant with the parent
enlistParticipant(parentId.toASCIIString().split("\\?")[0]);
if (cancel)
lraClient.cancelLRA(parentId);
else
lraClient.closeLRA(parentId);
assertEquals("parent and child should both have finished", 2, cancel ? compensateCount.get() : completeCount.get());
LRAStatus pStatus = getStatus(parentId);
LRAStatus cStatus = getStatus(childId);
assertTrue("parent LRA finished in wrong state", pStatus == null || pStatus == (cancel ? LRAStatus.Cancelled : LRAStatus.Closed));
assertTrue("child LRA finished in wrong state", cStatus == null || cStatus == (cancel ? LRAStatus.Cancelled : LRAStatus.Closed));
}
Aggregations