- Restored correct behavior for event publishing with workflow id only sent back
- Extracted `AbstractHTTPWithJWTTokenAuthEventSender` class for easy subclassing - Added new outcome check methods to inspect last send and last check actions results and some other facilities
This commit is contained in:
parent
38259734b1
commit
d761dac8ac
|
@ -13,8 +13,9 @@
|
||||||
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
|
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||||
<attributes>
|
<attributes>
|
||||||
|
<attribute name="module" value="true"/>
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
eclipse.preferences.version=1
|
eclipse.preferences.version=1
|
||||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
||||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=11
|
||||||
|
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
||||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
|
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
|
||||||
org.eclipse.jdt.core.compiler.release=disabled
|
org.eclipse.jdt.core.compiler.release=disabled
|
||||||
org.eclipse.jdt.core.compiler.source=1.8
|
org.eclipse.jdt.core.compiler.source=11
|
||||||
|
|
|
@ -3,6 +3,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||||
# Changelog for "event-publisher-library"
|
# Changelog for "event-publisher-library"
|
||||||
|
|
||||||
## [v1.2.0-SNAPSHOT]
|
## [v1.2.0-SNAPSHOT]
|
||||||
|
- Restored correct behavior for event publishing with workflow id only sent back
|
||||||
|
- Extracted `AbstractHTTPWithJWTTokenAuthEventSender` class for easy subclassing
|
||||||
|
- Added new outcome check methods to inspect last send and last check actions results and some other facilities
|
||||||
|
|
||||||
## [v1.1.0]
|
## [v1.1.0]
|
||||||
- Added `BufferedEventProcessor` to manual send bunch of events and controlling their output status (#23628)
|
- Added `BufferedEventProcessor` to manual send bunch of events and controlling their output status (#23628)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package org.gcube.event.publisher;
|
package org.gcube.event.publisher;
|
||||||
|
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -34,16 +36,61 @@ public abstract class AbstractEventPublisher implements EventPublisher {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLastPublishOK() {
|
||||||
|
return getLastPublishEventHTTPResponseCode() == HttpURLConnection.HTTP_OK
|
||||||
|
|| getLastPublishEventHTTPResponseCode() == HttpURLConnection.HTTP_CREATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLastPublishEventHTTPResponseCode() {
|
||||||
|
return eventSender.getLastSendHTTPResponseCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventStatus publishAndCheck(Event event) {
|
||||||
|
return publishAndCheck(event, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventStatus publishAndCheck(Event event, int delayMS) {
|
||||||
|
String instanceId = publish(event, true);
|
||||||
|
try {
|
||||||
|
if (delayMS > 0) {
|
||||||
|
Thread.sleep(delayMS);
|
||||||
|
}
|
||||||
|
return check(instanceId);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
logger.error("Sleeping before performing the event status check", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EventStatus check(String instanceId) {
|
public EventStatus check(String instanceId) {
|
||||||
if (instanceId != null) {
|
if (instanceId != null) {
|
||||||
return getResultsParser().parseResults(eventSender.retrive(instanceId));
|
return getResultsParser().parseResults(instanceId, eventSender.retrive(instanceId));
|
||||||
} else {
|
} else {
|
||||||
logger.warn("Cannot check with a null instance ID");
|
logger.warn("Cannot check with a null instance ID");
|
||||||
return EventStatus.NOT_FOUND();
|
return EventStatus.NOT_FOUND(instanceId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventStatus refresh(EventStatus eventStatus) {
|
||||||
|
return check(eventStatus.getInstanceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLastCheckOK() {
|
||||||
|
return getLastCheckHTTPResponseCode() == 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLastCheckHTTPResponseCode() {
|
||||||
|
return eventSender.getLastRetrieveHTTPResponseCode();
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract EventSender createEventSender();
|
protected abstract EventSender createEventSender();
|
||||||
|
|
||||||
protected ResultsParser createResultsParser() {
|
protected ResultsParser createResultsParser() {
|
||||||
|
|
|
@ -26,6 +26,8 @@ public abstract class AbstractHTTPWithJWTTokenAuthEventSender implements EventSe
|
||||||
protected URL tokenURL;
|
protected URL tokenURL;
|
||||||
protected int connectionTimeout;
|
protected int connectionTimeout;
|
||||||
protected int readTimeout;
|
protected int readTimeout;
|
||||||
|
protected HTTPPost lastHTTPPost;
|
||||||
|
protected HTTPGet lastHTTPGet;
|
||||||
|
|
||||||
public AbstractHTTPWithJWTTokenAuthEventSender(URL baseEndpointURL, String clientId, String clientSecret,
|
public AbstractHTTPWithJWTTokenAuthEventSender(URL baseEndpointURL, String clientId, String clientSecret,
|
||||||
URL tokenURL) {
|
URL tokenURL) {
|
||||||
|
@ -35,8 +37,8 @@ public abstract class AbstractHTTPWithJWTTokenAuthEventSender implements EventSe
|
||||||
this.clientId = clientId;
|
this.clientId = clientId;
|
||||||
this.clientSecret = clientSecret;
|
this.clientSecret = clientSecret;
|
||||||
this.tokenURL = tokenURL;
|
this.tokenURL = tokenURL;
|
||||||
connectionTimeout = getDefaultConnectionTimeout();
|
this.connectionTimeout = getDefaultConnectionTimeout();
|
||||||
readTimeout = getDefaultReadTimeout();
|
this.readTimeout = getDefaultReadTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getDefaultReadTimeout() {
|
protected int getDefaultReadTimeout() {
|
||||||
|
@ -65,19 +67,25 @@ public abstract class AbstractHTTPWithJWTTokenAuthEventSender implements EventSe
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void send(Event event) {
|
public void send(Event event) {
|
||||||
log.debug("Starting HTTP POST thread to: {}", baseEndpointURL);
|
log.debug("Starting HTTP POST thread with base URL: {}", baseEndpointURL);
|
||||||
new Thread(new HTTPPost(baseEndpointURL, event)).start();
|
lastHTTPPost = new HTTPPost(baseEndpointURL, event);
|
||||||
|
new Thread(lastHTTPPost).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLastSendHTTPResponseCode() {
|
||||||
|
return lastHTTPPost != null ? lastHTTPPost.gethttpResponseCode() : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String sendAndGetResult(Event event) {
|
public String sendAndGetResult(Event event) {
|
||||||
log.debug("Starting HTTP POST thread to: {}", baseEndpointURL);
|
log.debug("Starting HTTP POST thread to: {}", baseEndpointURL);
|
||||||
HTTPPost post = new HTTPPost(baseEndpointURL, event);
|
lastHTTPPost = new HTTPPost(baseEndpointURL, event);
|
||||||
Thread postThread = new Thread(post);
|
Thread postThread = new Thread(lastHTTPPost);
|
||||||
postThread.start();
|
postThread.start();
|
||||||
try {
|
try {
|
||||||
postThread.join();
|
postThread.join();
|
||||||
return post.getResult();
|
return lastHTTPPost.getResult();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
log.error("While waiting for HTTP Post thread termination", e);
|
log.error("While waiting for HTTP Post thread termination", e);
|
||||||
return null;
|
return null;
|
||||||
|
@ -86,7 +94,13 @@ public abstract class AbstractHTTPWithJWTTokenAuthEventSender implements EventSe
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONObject retrive(String id) {
|
public JSONObject retrive(String id) {
|
||||||
return new HTTPGet(baseEndpointURL, id).readJSON();
|
lastHTTPGet = new HTTPGet(baseEndpointURL, id);
|
||||||
|
return lastHTTPGet.readJSON();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLastRetrieveHTTPResponseCode() {
|
||||||
|
return lastHTTPGet != null ? lastHTTPGet.gethttpResponseCode() : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected URL getTokenURL() {
|
protected URL getTokenURL() {
|
||||||
|
@ -101,11 +115,17 @@ public abstract class AbstractHTTPWithJWTTokenAuthEventSender implements EventSe
|
||||||
protected static final int DEFAULT_READ_TIMEOUT = 5000;
|
protected static final int DEFAULT_READ_TIMEOUT = 5000;
|
||||||
|
|
||||||
protected URL baseEndpoint;
|
protected URL baseEndpoint;
|
||||||
|
protected int httpResponseCode = -1;
|
||||||
|
protected String httpContentType;
|
||||||
|
|
||||||
public HTTPVerb(URL baseEndpoint) {
|
public HTTPVerb(URL baseEndpoint) {
|
||||||
this.baseEndpoint = baseEndpoint;
|
this.baseEndpoint = baseEndpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int gethttpResponseCode() {
|
||||||
|
return httpResponseCode;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class HTTPPost extends HTTPVerb implements Runnable {
|
public class HTTPPost extends HTTPVerb implements Runnable {
|
||||||
|
@ -131,19 +151,23 @@ public abstract class AbstractHTTPWithJWTTokenAuthEventSender implements EventSe
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
URL eventEndpoint = null;
|
URL eventEndpoint = null;
|
||||||
try {
|
if (baseEndpoint.toString().endsWith("/")) {
|
||||||
eventEndpoint = new URL(baseEndpointURL, event.getName());
|
try {
|
||||||
} catch (MalformedURLException e) {
|
log.debug("Removing trailing slash from base URL since the endpoint computation API changed");
|
||||||
log.error("Cannot compute event endpoint URL. Event name: " + event.getName() + ", base endpoint: "
|
eventEndpoint = new URL(baseEndpoint.toString().substring(0, baseEndpoint.toString().length() - 1));
|
||||||
+ baseEndpointURL, e);
|
} catch (MalformedURLException e) {
|
||||||
return;
|
log.error("Cannot remove trailing slash from base endpoint URL", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eventEndpoint = baseEndpoint;
|
||||||
}
|
}
|
||||||
boolean OK = false;
|
boolean OK = false;
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
log.debug("Getting auth token for client '{}' if needed", clientId);
|
log.debug("Getting auth token for client '{}' if needed", clientId);
|
||||||
JWTToken token = getAuthorizationToken();
|
JWTToken token = getAuthorizationToken();
|
||||||
log.debug("Performing HTTP POST to: {}", baseEndpoint);
|
log.debug("Performing HTTP POST to: {}", eventEndpoint);
|
||||||
HttpURLConnection connection = (HttpURLConnection) eventEndpoint.openConnection();
|
HttpURLConnection connection = (HttpURLConnection) eventEndpoint.openConnection();
|
||||||
connection.setRequestMethod("POST");
|
connection.setRequestMethod("POST");
|
||||||
connection.setConnectTimeout(connectionTimeout);
|
connection.setConnectTimeout(connectionTimeout);
|
||||||
|
@ -151,8 +175,7 @@ public abstract class AbstractHTTPWithJWTTokenAuthEventSender implements EventSe
|
||||||
connection.setReadTimeout(readTimeout);
|
connection.setReadTimeout(readTimeout);
|
||||||
log.trace("HTTP connection Read timeout set to: {}", connection.getReadTimeout());
|
log.trace("HTTP connection Read timeout set to: {}", connection.getReadTimeout());
|
||||||
connection.setRequestProperty("Content-Type", "application/json");
|
connection.setRequestProperty("Content-Type", "application/json");
|
||||||
// Commented out as per the Conductor issue: https://github.com/Netflix/conductor/issues/376
|
connection.setRequestProperty("Accept", "text/plain");
|
||||||
// connection.setRequestProperty("Accept", "application/json");
|
|
||||||
connection.setDoOutput(true);
|
connection.setDoOutput(true);
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
log.debug("Setting authorization header as: {}", token.getAccessTokenAsBearer());
|
log.debug("Setting authorization header as: {}", token.getAccessTokenAsBearer());
|
||||||
|
@ -168,12 +191,14 @@ public abstract class AbstractHTTPWithJWTTokenAuthEventSender implements EventSe
|
||||||
os.close();
|
os.close();
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
int httpResultCode = connection.getResponseCode();
|
httpResponseCode = connection.getResponseCode();
|
||||||
log.trace("HTTP Response code: {}", httpResultCode);
|
log.trace("HTTP Response code: {}", httpResponseCode);
|
||||||
|
httpContentType = connection.getContentType();
|
||||||
|
log.trace("HTTP Response content type is: {}", httpContentType);
|
||||||
|
|
||||||
log.trace("Reading response");
|
log.trace("Reading response");
|
||||||
InputStreamReader isr = null;
|
InputStreamReader isr = null;
|
||||||
if (httpResultCode == HttpURLConnection.HTTP_OK) {
|
if (httpResponseCode == HttpURLConnection.HTTP_OK) {
|
||||||
OK = true;
|
OK = true;
|
||||||
// From this point ahead every exception should not set OK to false
|
// From this point ahead every exception should not set OK to false
|
||||||
// since the server acknowledged with 200
|
// since the server acknowledged with 200
|
||||||
|
@ -191,12 +216,12 @@ public abstract class AbstractHTTPWithJWTTokenAuthEventSender implements EventSe
|
||||||
sb.deleteCharAt(0);
|
sb.deleteCharAt(0);
|
||||||
result = sb.toString();
|
result = sb.toString();
|
||||||
if (OK) {
|
if (OK) {
|
||||||
log.debug("[{}] Event publish for {} is OK", httpResultCode, event.getName());
|
log.debug("[{}] Event publish for {} is OK", httpResponseCode, event.getName());
|
||||||
} else {
|
} else {
|
||||||
log.trace("Response message from server:\n{}", result);
|
log.trace("Response message from server:\n{}", result);
|
||||||
if (shouldRetryWithCode(httpResultCode)) {
|
if (shouldRetryWithCode(httpResponseCode)) {
|
||||||
if (retryings <= MAX_RETRYINGS) {
|
if (retryings <= MAX_RETRYINGS) {
|
||||||
log.warn("[{}] Event publish ERROR, retrying in {} seconds", httpResultCode,
|
log.warn("[{}] Event publish ERROR, retrying in {} seconds", httpResponseCode,
|
||||||
actualPause);
|
actualPause);
|
||||||
|
|
||||||
Thread.sleep(actualPause * 1000);
|
Thread.sleep(actualPause * 1000);
|
||||||
|
@ -205,20 +230,21 @@ public abstract class AbstractHTTPWithJWTTokenAuthEventSender implements EventSe
|
||||||
retryings += 1;
|
retryings += 1;
|
||||||
} else {
|
} else {
|
||||||
log.error("[{}] Event publish ERROR, exhausted tries after {} retryings",
|
log.error("[{}] Event publish ERROR, exhausted tries after {} retryings",
|
||||||
httpResultCode,
|
httpResponseCode,
|
||||||
retryings);
|
retryings);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.info("[{}] Event publish ERROR but should not retry with this HTTP code",
|
log.info("[{}] Event publish ERROR but should not retry with this HTTP code",
|
||||||
httpResultCode);
|
httpResponseCode);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException | OpenIdConnectRESTHelperException e) {
|
} catch (IOException | OpenIdConnectRESTHelperException e) {
|
||||||
log.error("POSTing JSON to: " + eventEndpoint, e);
|
log.error("POSTing JSON to: " + eventEndpoint, e);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} while (!OK);
|
} while (!OK);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
@ -249,7 +275,12 @@ public abstract class AbstractHTTPWithJWTTokenAuthEventSender implements EventSe
|
||||||
URL endpoint = null;
|
URL endpoint = null;
|
||||||
JSONObject results = null;
|
JSONObject results = null;
|
||||||
try {
|
try {
|
||||||
endpoint = new URL(baseEndpoint, id);
|
String baseEndpointString = baseEndpoint.toString();
|
||||||
|
if (baseEndpointString.endsWith("/")) {
|
||||||
|
endpoint = new URL(baseEndpointString + id);
|
||||||
|
} else {
|
||||||
|
endpoint = new URL(baseEndpointString + "/" + id);
|
||||||
|
}
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
log.error("Cannot compute retrieve endpoint URL. ID: " + id + ", base endpoint: " + baseEndpointURL, e);
|
log.error("Cannot compute retrieve endpoint URL. ID: " + id + ", base endpoint: " + baseEndpointURL, e);
|
||||||
return null;
|
return null;
|
||||||
|
@ -273,12 +304,14 @@ public abstract class AbstractHTTPWithJWTTokenAuthEventSender implements EventSe
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
int httpResultCode = connection.getResponseCode();
|
httpResponseCode = connection.getResponseCode();
|
||||||
log.trace("HTTP Response code: {}", httpResultCode);
|
log.trace("HTTP Response code: {}", httpResponseCode);
|
||||||
|
httpContentType = connection.getContentType();
|
||||||
|
log.trace("HTTP Response content type is: {}", httpContentType);
|
||||||
|
|
||||||
log.trace("Reading response");
|
log.trace("Reading response");
|
||||||
InputStreamReader isr = null;
|
InputStreamReader isr = null;
|
||||||
if (httpResultCode == HttpURLConnection.HTTP_OK) {
|
if (httpResponseCode == HttpURLConnection.HTTP_OK) {
|
||||||
isr = new InputStreamReader(connection.getInputStream(), "UTF-8");
|
isr = new InputStreamReader(connection.getInputStream(), "UTF-8");
|
||||||
} else {
|
} else {
|
||||||
isr = new InputStreamReader(connection.getErrorStream(), "UTF-8");
|
isr = new InputStreamReader(connection.getErrorStream(), "UTF-8");
|
||||||
|
@ -290,15 +323,19 @@ public abstract class AbstractHTTPWithJWTTokenAuthEventSender implements EventSe
|
||||||
}
|
}
|
||||||
br.close();
|
br.close();
|
||||||
isr.close();
|
isr.close();
|
||||||
if (httpResultCode == HttpURLConnection.HTTP_OK) {
|
if (httpResponseCode == HttpURLConnection.HTTP_OK) {
|
||||||
log.debug("[{}] Got results for {}", httpResultCode, id);
|
log.debug("[{}] Got results for {}", httpResponseCode, id);
|
||||||
try {
|
if (httpContentType.equals("application/json")) {
|
||||||
results = (JSONObject) new JSONParser().parse(sb.toString());
|
try {
|
||||||
} catch (ParseException e) {
|
results = (JSONObject) new JSONParser().parse(sb.toString());
|
||||||
log.warn("Error parsing results string as JSON: {}", sb.toString());
|
} catch (ParseException e) {
|
||||||
|
log.warn("Error parsing results string as JSON: {}", sb.toString());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.warn("Received a non JSON reponse: {}", sb.toString());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.warn("[{}] Error getting results for ID {}", httpResultCode, id);
|
log.warn("[{}] Error getting results for ID {}", httpResponseCode, id);
|
||||||
}
|
}
|
||||||
} catch (IOException | OpenIdConnectRESTHelperException e) {
|
} catch (IOException | OpenIdConnectRESTHelperException e) {
|
||||||
log.error("Getting results from: " + endpoint, e);
|
log.error("Getting results from: " + endpoint, e);
|
||||||
|
|
|
@ -12,32 +12,32 @@ public class ConductorResultsParser implements ResultsParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EventStatus parseResults(JSONObject results) {
|
public EventStatus parseResults(String uuid, JSONObject results) {
|
||||||
EventStatus eventStatus = null;
|
EventStatus eventStatus = null;
|
||||||
if (results != null) {
|
if (results != null) {
|
||||||
JSONObject input = (JSONObject) results.get("input");
|
JSONObject input = (JSONObject) results.get("input");
|
||||||
JSONObject output = (JSONObject) results.get("output");
|
JSONObject output = (JSONObject) results.get("output");
|
||||||
switch ((String) results.get("status")) {
|
switch ((String) results.get("status")) {
|
||||||
case "COMPLETED":
|
case "COMPLETED":
|
||||||
eventStatus = EventStatus.COMPLETED(input, output);
|
eventStatus = EventStatus.COMPLETED(uuid, input, output);
|
||||||
break;
|
break;
|
||||||
case "FAILED":
|
case "FAILED":
|
||||||
eventStatus = EventStatus.FAILED(input, output);
|
eventStatus = EventStatus.FAILED(uuid, input, output);
|
||||||
break;
|
break;
|
||||||
case "NOT_FOUND":
|
case "NOT_FOUND":
|
||||||
eventStatus = EventStatus.NOT_FOUND();
|
eventStatus = EventStatus.NOT_FOUND(uuid);
|
||||||
break;
|
break;
|
||||||
case "PAUSED":
|
case "PAUSED":
|
||||||
eventStatus = EventStatus.PAUSED(input);
|
eventStatus = EventStatus.PAUSED(uuid, input);
|
||||||
break;
|
break;
|
||||||
case "RUNNING":
|
case "RUNNING":
|
||||||
eventStatus = EventStatus.RUNNING(input);
|
eventStatus = EventStatus.RUNNING(uuid, input);
|
||||||
break;
|
break;
|
||||||
case "TERMINATED":
|
case "TERMINATED":
|
||||||
eventStatus = EventStatus.TERMINATED(input, output);
|
eventStatus = EventStatus.TERMINATED(uuid, input, output);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
eventStatus = EventStatus.NOT_FOUND();
|
eventStatus = EventStatus.NOT_FOUND(uuid);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.warn("Nothing to parse since JSON object is null");
|
logger.warn("Nothing to parse since JSON object is null");
|
||||||
|
|
|
@ -2,10 +2,76 @@ package org.gcube.event.publisher;
|
||||||
|
|
||||||
public interface EventPublisher {
|
public interface EventPublisher {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publish a new event and nothing more. The sender is not interested to the success/failure of the send.
|
||||||
|
* The results on the workflow engine, is the start of an instance of the workflow identified by the {@link Event#getName()} string.
|
||||||
|
* @param event the event to be published
|
||||||
|
*/
|
||||||
void publish(Event event);
|
void publish(Event event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publishes a new event and optionally wait for the result.
|
||||||
|
* If <code>waitForResult</code> parameter is <code>false</code> the behavior is the same of the {@link #publish(Event)} method,
|
||||||
|
* if true, the workflow id is returned as string if the publish had success.
|
||||||
|
* @param event the vent to be published
|
||||||
|
* @param waitForResult if the sender is interested or not to the resulting workflow id
|
||||||
|
* @return the resulting workflow id
|
||||||
|
*/
|
||||||
String publish(Event event, boolean waitForResult);
|
String publish(Event event, boolean waitForResult);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells if the last publish was a success or not.
|
||||||
|
* @return <code>true</code> if the publish was OK, <code>false</code> otherwise
|
||||||
|
*/
|
||||||
|
boolean isLastPublishOK();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the last returned HTTP response code of a publish. E.g. 200 if the send was OK or 404 if the event doesn't have a corresponding workflow definition.
|
||||||
|
* @return the HTTP response code of the last publish or -1 if an error occurred before the call (e.g. during the authorization or connection)
|
||||||
|
*/
|
||||||
|
int getLastPublishEventHTTPResponseCode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publish an event and immediately checks for the results status.
|
||||||
|
* The behavior is the same of the {@link #publishAndCheck(Event, int)} with <code>delayMS</code> argument less or equal to 0.
|
||||||
|
* @param event the event to be published
|
||||||
|
* @return an object with info about the event's running status
|
||||||
|
*/
|
||||||
|
EventStatus publishAndCheck(Event event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publish an event and checks for the results status after a delay.
|
||||||
|
* The behavior is the same of the {@link #publishAndCheck(Event)} if delayMS argument is less or equal to 0.
|
||||||
|
* @param event the event to be published
|
||||||
|
* @param delayMS the delay betwen the publish and the query calls
|
||||||
|
* @return an object with info about the event's running status
|
||||||
|
*/
|
||||||
|
EventStatus publishAndCheck(Event event, int delayMS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for the workflow results status.
|
||||||
|
* @param instanceId the workflow instance id, resulting of the {@link #publish(Event, boolean)} with <code>waitForResult</code> as true.
|
||||||
|
* @return an object with info about the event's running status
|
||||||
|
*/
|
||||||
EventStatus check(String instanceId);
|
EventStatus check(String instanceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes an event status by checking for the status of the workflow execution represented by the {@link EventStatus#getInstanceId()} string.
|
||||||
|
* @param eventStatus a previously obtained event status.
|
||||||
|
* @return an object with new info about the event's running status
|
||||||
|
*/
|
||||||
|
EventStatus refresh(EventStatus eventStatus);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells if the last check was a success or not.
|
||||||
|
* @return <code>true</code> if the publish was OK, <code>false</code> otherwise
|
||||||
|
*/
|
||||||
|
boolean isLastCheckOK();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the last returned HTTP response code of a check. E.g. 200 if the send was OK or 404 if the event doesn't have a corresponding workflow instance.
|
||||||
|
* @return the HTTP response code of the last publish or -1 if an error occurred before the call (e.g. during the authorization or connection)
|
||||||
|
*/
|
||||||
|
int getLastCheckHTTPResponseCode();
|
||||||
|
|
||||||
}
|
}
|
|
@ -4,10 +4,36 @@ import org.json.simple.JSONObject;
|
||||||
|
|
||||||
public interface EventSender {
|
public interface EventSender {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends an event.
|
||||||
|
* @param event the event to send
|
||||||
|
*/
|
||||||
void send(Event event);
|
void send(Event event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the last send HTTP response code.
|
||||||
|
* @return the HTTP response code or -1 if an error occurred before the call (e.g. during the authorization or connection)
|
||||||
|
*/
|
||||||
|
int getLastSendHTTPResponseCode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an event and get results.
|
||||||
|
* @param event the event to send
|
||||||
|
* @return the result of the call
|
||||||
|
*/
|
||||||
String sendAndGetResult(Event event);
|
String sendAndGetResult(Event event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the instance of the provided workflow instance.
|
||||||
|
* @param id the workflow instance id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
JSONObject retrive(String id);
|
JSONObject retrive(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the last retrieve HTTP response code.
|
||||||
|
* @return the HTTP response code or -1 if an error occurred before the call (e.g. during the authorization or connection)
|
||||||
|
*/
|
||||||
|
int getLastRetrieveHTTPResponseCode();
|
||||||
|
|
||||||
}
|
}
|
|
@ -8,52 +8,62 @@ public class EventStatus {
|
||||||
RUNNING, COMPLETED, FAILED, TIMED_OUT, TERMINATED, PAUSED, NOT_FOUND;
|
RUNNING, COMPLETED, FAILED, TIMED_OUT, TERMINATED, PAUSED, NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EventStatus RUNNING(JSONObject input) {
|
public static EventStatus RUNNING(String instanceId, JSONObject input) {
|
||||||
return new EventStatus(Status.RUNNING, input);
|
return new EventStatus(instanceId, Status.RUNNING, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EventStatus COMPLETED(JSONObject input, JSONObject output) {
|
public static EventStatus COMPLETED(String instanceId, JSONObject input, JSONObject output) {
|
||||||
return new EventStatus(Status.COMPLETED, input, output);
|
return new EventStatus(instanceId, Status.COMPLETED, input, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EventStatus FAILED(JSONObject input, JSONObject output) {
|
public static EventStatus FAILED(String instanceId, JSONObject input, JSONObject output) {
|
||||||
return new EventStatus(Status.FAILED, input, output);
|
return new EventStatus(instanceId, Status.FAILED, input, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EventStatus TIMED_OUT(JSONObject input) {
|
public static EventStatus TIMED_OUT(String instanceId, JSONObject input) {
|
||||||
return new EventStatus(Status.TIMED_OUT, input);
|
return new EventStatus(instanceId, Status.TIMED_OUT, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EventStatus TERMINATED(JSONObject input, JSONObject output) {
|
public static EventStatus TERMINATED(String instanceId, JSONObject input, JSONObject output) {
|
||||||
return new EventStatus(Status.TERMINATED, input, output);
|
return new EventStatus(instanceId, Status.TERMINATED, input, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EventStatus PAUSED(JSONObject input) {
|
public static EventStatus PAUSED(String instanceId, JSONObject input) {
|
||||||
return new EventStatus(Status.PAUSED, input);
|
return new EventStatus(instanceId, Status.PAUSED, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EventStatus NOT_FOUND() {
|
public static EventStatus NOT_FOUND(String instanceId) {
|
||||||
return new EventStatus(Status.NOT_FOUND);
|
return new EventStatus(instanceId, Status.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String instanceId;
|
||||||
private Status status;
|
private Status status;
|
||||||
private JSONObject input;
|
private JSONObject input;
|
||||||
private JSONObject output;
|
private JSONObject output;
|
||||||
|
|
||||||
private EventStatus(Status status) {
|
private EventStatus(String uuid, Status status) {
|
||||||
this(status, null);
|
this(uuid, status, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EventStatus(Status status, JSONObject input) {
|
private EventStatus(String instanceId, Status status, JSONObject input) {
|
||||||
this(status, input, null);
|
this(instanceId, status, input, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EventStatus(Status status, JSONObject input, JSONObject output) {
|
private EventStatus(String instanceId, Status status, JSONObject input, JSONObject output) {
|
||||||
|
setInstanceId(instanceId);
|
||||||
setStatus(status);
|
setStatus(status);
|
||||||
setInput(input);
|
setInput(input);
|
||||||
setOutput(output);
|
setOutput(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setInstanceId(String instanceId) {
|
||||||
|
this.instanceId = instanceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInstanceId() {
|
||||||
|
return instanceId;
|
||||||
|
}
|
||||||
|
|
||||||
public void setStatus(Status status) {
|
public void setStatus(Status status) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,6 @@ import org.json.simple.JSONObject;
|
||||||
|
|
||||||
public interface ResultsParser {
|
public interface ResultsParser {
|
||||||
|
|
||||||
EventStatus parseResults(JSONObject results);
|
EventStatus parseResults(String uuid, JSONObject results);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,13 @@ package org.gcube.event.publisher;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class HTTPEventSenderTest {
|
public class HTTPEventSenderTest {
|
||||||
|
|
||||||
|
protected static final Logger logger = LoggerFactory.getLogger(HTTPEventSenderTest.class);
|
||||||
|
|
||||||
public HTTPEventSenderTest() {
|
public HTTPEventSenderTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +19,8 @@ public class HTTPEventSenderTest {
|
||||||
protected EventSender createEventSender() {
|
protected EventSender createEventSender() {
|
||||||
try {
|
try {
|
||||||
return new HTTPWithOIDCAuthEventSender(
|
return new HTTPWithOIDCAuthEventSender(
|
||||||
new URL("https://conductor.dev.d4science.org/api/workflow/"), "lr62_portal",
|
new URL("https://conductor.cloud-dev.d4science.org/api/workflow/"),
|
||||||
|
"lr62_portal",
|
||||||
"6937125d-6d70-404a-9d63-908c1e6415c4",
|
"6937125d-6d70-404a-9d63-908c1e6415c4",
|
||||||
new URL("https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token"));
|
new URL("https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token"));
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
|
@ -24,9 +30,31 @@ public class HTTPEventSenderTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
System.out.println("Published: " + publisher.publish(new Event("startup", "portal", "gcube"), true));
|
String id = publisher.publish(new Event("test", "test", "test"), true);
|
||||||
EventStatus status = publisher.check("93675866-c209-4584-8576-ec641df63e9a");
|
logger.info("*** Published: {}", id);
|
||||||
System.out.println(status);
|
logger.info("*** Publish was {} and HTTP response status is: {}",
|
||||||
|
publisher.isLastPublishOK() ? "OK" : "KO", publisher.getLastPublishEventHTTPResponseCode());
|
||||||
|
|
||||||
|
EventStatus status = null;
|
||||||
|
do {
|
||||||
|
status = publisher.check(id);
|
||||||
|
logger.trace("*** Check was {} and HTTP response status is: {}", publisher.isLastCheckOK() ? "OK" : "KO",
|
||||||
|
publisher.getLastCheckHTTPResponseCode());
|
||||||
|
} while (status.getStatus() != EventStatus.Status.COMPLETED && status.getStatus() != EventStatus.Status.FAILED);
|
||||||
|
|
||||||
|
logger.info("*** Final status is: {}", status.toString());
|
||||||
|
|
||||||
|
status = publisher.publishAndCheck(new Event("test", "test", "test"), 1000);
|
||||||
|
logger.info("*** Publish was {} and HTTP response status is: {}",
|
||||||
|
publisher.isLastPublishOK() ? "OK" : "KO", publisher.getLastPublishEventHTTPResponseCode());
|
||||||
|
|
||||||
|
do {
|
||||||
|
status = publisher.refresh(status);
|
||||||
|
logger.trace("*** Check was {} and HTTP response status is: {}", publisher.isLastCheckOK() ? "OK" : "KO",
|
||||||
|
publisher.getLastCheckHTTPResponseCode());
|
||||||
|
} while (status.getStatus() != EventStatus.Status.COMPLETED && status.getStatus() != EventStatus.Status.FAILED);
|
||||||
|
|
||||||
|
logger.info("*** Final status is: {}", status.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue