Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@

<groupId>dev.dsf</groupId>
<artifactId>dsf-process-ping-pong</artifactId>
<version>2.0.0.0-SNAPSHOT</version>
<version>2.0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<compileSource>17</compileSource>
<compileTarget>17</compileTarget>

<dsf.version>1.8.0</dsf.version>
<dsf.version>1.9.0</dsf.version>
<spring.version>6.2.12</spring.version>
<dsf.location>../dsf</dsf.location>
</properties>

Expand Down Expand Up @@ -45,14 +46,7 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>6.0.10</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.7</version>
<version>${spring.version}</version>
<scope>provided</scope>
</dependency>

Expand Down
38 changes: 37 additions & 1 deletion src/main/java/dev/dsf/bpe/CodeSystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,10 @@ public enum Concept
"send-message-http-502",
"Sending a message to the remote instance resulted in HTTP status 502"
),
SEND_MESSAGE_HTTP_504(
"send-message-http-504",
"Sending a message to the remote instance resulted in HTTP status 504"
),
SEND_MESSAGE_HTTP_UNEXPECTED(
"send-message-http-unexpected",
"Sending a message to the remote instance resulted in an unexpected HTTP status code"
Expand Down Expand Up @@ -428,6 +432,10 @@ public enum Concept
"receive-message-http-502",
"Received a message and responded with HTTP status 502"
),
RECEIVE_MESSAGE_HTTP_504(
"receive-message-http-504",
"Received a message and responded with HTTP status 504"
),
RECEIVE_MESSAGE_HTTP_UNEXPECTED(
"receive-message-http-unexpected",
"Received a message and responded with an unexpected HTTP status code"
Expand Down Expand Up @@ -477,6 +485,10 @@ public enum Concept
"local-binary-delete-http-502",
"Local instance encountered a HTTP status 502 trying to clean up the binary resource"
),
LOCAL_BINARY_DELETE_HTTP_504(
"local-binary-delete-http-504",
"Local instance encountered a HTTP status 504 trying to clean up the binary resource"
),
LOCAL_BINARY_DELETE_HTTP_UNEXPECTED(
"local-binary-delete-http-unexpected",
"Local instance encountered an unexpected HTTP status code trying to clean up the binary resource"
Expand Down Expand Up @@ -510,6 +522,10 @@ public enum Concept
"remote-binary-delete-http-502",
"Remote instance encountered a HTTP status 502 trying to clean up the binary resource"
),
REMOTE_BINARY_DELETE_HTTP_504(
"remote-binary-delete-http-504",
"Remote instance encountered a HTTP status 504 trying to clean up the binary resource"
),
REMOTE_BINARY_DELETE_HTTP_UNEXPECTED(
"remote-binary-delete-http-unexpected",
"Remote instance encountered an unexpected HTTP status code trying to clean up the binary resource"
Expand All @@ -535,6 +551,10 @@ public enum Concept
"local-binary-post-http-502",
"Local instance encountered a HTTP status 502 trying to post the binary resource to its own FHIR server"
),
LOCAL_BINARY_POST_HTTP_504(
"local-binary-post-http-504",
"Local instance encountered a HTTP status 504 trying to post the binary resource to its own FHIR server"
),
LOCAL_BINARY_POST_HTTP_UNEXPECTED(
"local-binary-post-http-unexpected",
"Local instance encountered an unexpected HTTP status code trying to post the binary resource to its own FHIR server"
Expand Down Expand Up @@ -572,6 +592,10 @@ public enum Concept
"remote-binary-post-http-502",
"Remote instance encountered a HTTP status 502 trying to post the binary resource to its own FHIR server"
),
REMOTE_BINARY_POST_HTTP_504(
"remote-binary-post-http-504",
"Remote instance encountered a HTTP status 504 trying to post the binary resource to its own FHIR server"
),
REMOTE_BINARY_POST_HTTP_UNEXPECTED(
"remote-binary-post-http-unexpected",
"Remote instance encountered an unexpected HTTP status code trying to post the binary resource to its own FHIR server"
Expand Down Expand Up @@ -626,6 +650,10 @@ public enum Concept
"response-message-timeout-http-502",
"Response message timed out. Received HTTP status 502 trying to check request status on the target"
),
RESPONSE_MESSAGE_TIMEOUT_HTTP_504(
"response-message-timeout-http-504",
"Response message timed out. Received HTTP status 504 trying to check request status on the target"
),
RESPONSE_MESSAGE_TIMEOUT_HTTP_UNEXPECTED(
"response-message-timeout-http-unexpected",
"Response message timed out. Received an unexpected HTTP status code trying to check request status on the target"
Expand Down Expand Up @@ -654,7 +682,11 @@ public enum Concept
),
LOCAL_BINARY_DOWNLOAD_HTTP_502(
"local-binary-download-http-502",
"Local instance received HTTP status 500 trying to download the binary resource from the target"
"Local instance received HTTP status 502 trying to download the binary resource from the target"
),
LOCAL_BINARY_DOWNLOAD_HTTP_504(
"local-binary-download-http-504",
"Local instance received HTTP status 504 trying to download the binary resource from the target"
),
LOCAL_BINARY_DOWNLOAD_HTTP_UNEXPECTED(
"local-binary-download-http-unexpected",
Expand Down Expand Up @@ -697,6 +729,10 @@ public enum Concept
"remote-binary-download-http-502",
"Remote instance received HTTP status 502 trying to download the binary resource from this server"
),
REMOTE_BINARY_DOWNLOAD_HTTP_504(
"remote-binary-download-http-504",
"Remote instance received HTTP status 504 trying to download the binary resource from this server"
),
REMOTE_BINARY_DOWNLOAD_HTTP_UNEXPECTED(
"remote-binary-download-http-unexpected",
"Remote instance received an unexpected HTTP status trying to download the binary resource from this server"
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/dev/dsf/bpe/ConstantsPing.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ private ConstantsPing()

public static final String TIMER_INTERVAL_DEFAULT_VALUE = "PT24H";

public static final String PONG_TIMEOUT_DURATION_DEFAULT_VALUE = "PT30S";

public static final String BPMN_ERROR_CODE_UNEXPECTED_ERROR = "unexpected-error";

public static final String POTENTIAL_FIX_URL_BASE = "https://dsf.dev/s";
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/dev/dsf/bpe/PingProcessPluginDefinition.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class PingProcessPluginDefinition implements ProcessPluginDefinition
public static final String RESOURCE_VERSION = "2.0";
public static final String NON_RESOURCE_VERSION = "0.0";
public static final String VERSION = RESOURCE_VERSION + "." + NON_RESOURCE_VERSION;
public static final LocalDate RELEASE_DATE = LocalDate.of(2023, 9, 12);
public static final LocalDate RELEASE_DATE = LocalDate.of(2025, 10, 21);

@Override
public String getName()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,27 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.DecimalType;
import org.hl7.fhir.r4.model.MetadataResource;
import org.hl7.fhir.r4.model.Resource;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.StructureDefinition;
import org.hl7.fhir.r4.model.Task;
import org.springframework.beans.factory.InitializingBean;

import dev.dsf.bpe.ConstantsPing;
import dev.dsf.bpe.PingProcessPluginDefinition;
import dev.dsf.bpe.v1.ProcessPluginApi;
import dev.dsf.bpe.v1.ProcessPluginDeploymentStateListener;
import dev.dsf.fhir.client.FhirWebserviceClient;

public class PingPongProcessPluginDeploymentStateListener
implements ProcessPluginDeploymentStateListener, InitializingBean
Expand Down Expand Up @@ -52,6 +58,61 @@ public void onProcessesDeployed(List<String> activeProcesses)

updateOlderResourcesIfCurrentIsNewestResource(ConstantsPing.STRUCTURE_DEFINITION_URL_EXTENSION_PING_STATUS,
StructureDefinition.class, adaptExtensionStructureDefinitions());

updateDraftTaskResources();
}

private void updateDraftTaskResources()
{
FhirWebserviceClient client = api.getFhirWebserviceClientProvider().getLocalWebserviceClient();

List<String> draftTaskResourceProfiles = List.of("http://dsf.dev/fhir/StructureDefinition/task-start-ping",
"http://dsf.dev/fhir/StructureDefinition/task-start-ping-autostart");

for (String profile : draftTaskResourceProfiles)
{
Optional<Task> optionalTask = searchTask(profile, PingProcessPluginDefinition.RESOURCE_VERSION).getEntry()
.stream().map(Bundle.BundleEntryComponent::getResource).map(Task.class::cast).findFirst();

if (optionalTask.isPresent())
{
Task toUpdate = optionalTask.get();
adaptDraftTask(toUpdate);
client.update(toUpdate);
}
}
}

private void adaptDraftTask(Task task)
{
Coding downloadResourceSizeBytesCoding = new Coding();
downloadResourceSizeBytesCoding.setSystem(dev.dsf.bpe.CodeSystem.DsfPing.URL)
.setCode(dev.dsf.bpe.CodeSystem.DsfPing.Code.DOWNLOAD_RESOURCE_SIZE_BYTES.getValue())
.setVersion(PingProcessPluginDefinition.RESOURCE_VERSION);

Optional<Task.ParameterComponent> optInput = api.getTaskHelper().getFirstInputParameter(task,
downloadResourceSizeBytesCoding, DecimalType.class);
if (optInput.isEmpty())
{
Task.ParameterComponent downloadResourceSizeBytes = new Task.ParameterComponent();
downloadResourceSizeBytes.getType().addCoding(downloadResourceSizeBytesCoding);
downloadResourceSizeBytes.setValue(new DecimalType(ConstantsPing.DOWNLOAD_RESOURCE_SIZE_BYTES_DEFAULT));
task.addInput(downloadResourceSizeBytes);
}

Coding pongTimeoutDurationCoding = new Coding();
pongTimeoutDurationCoding.setSystem(dev.dsf.bpe.CodeSystem.DsfPing.URL)
.setCode(dev.dsf.bpe.CodeSystem.DsfPing.Code.PONG_TIMEOUT_DURATION_ISO_8601.getValue())
.setVersion(PingProcessPluginDefinition.RESOURCE_VERSION);

optInput = api.getTaskHelper().getFirstInputParameter(task, pongTimeoutDurationCoding, StringType.class);
if (optInput.isEmpty())
{
Task.ParameterComponent pongTimeoutDuration = new Task.ParameterComponent();
pongTimeoutDuration.getType().addCoding(pongTimeoutDurationCoding);
pongTimeoutDuration.setValue(new StringType(ConstantsPing.PONG_TIMEOUT_DURATION_DEFAULT_VALUE));
task.addInput(pongTimeoutDuration);
}
}

private <T extends MetadataResource> void updateOlderResourcesIfCurrentIsNewestResource(String url, Class<T> type,
Expand All @@ -74,6 +135,12 @@ private Bundle search(Class<? extends Resource> type, String url)
Map.of("url", List.of(url)));
}

private Bundle searchTask(String profile, String version)
{
return api.getFhirWebserviceClientProvider().getLocalWebserviceClient().search(Task.class,
Map.of("_profile", List.of(profile + "|" + version), "status", List.of("draft")));
}

private <T extends MetadataResource> List<T> extractAndSortResources(Bundle bundle, Class<T> type, String url)
{
return bundle.getEntry().stream().filter(Bundle.BundleEntryComponent::hasResource)
Expand Down Expand Up @@ -104,6 +171,11 @@ private boolean currentIsNewestResource(List<? extends MetadataResource> resourc
.equals(resources.get(resources.size() - 1).getVersion());
}

private <T> Optional<T> getNewestResource(List<T> resources)
{
return resources.isEmpty() ? Optional.empty() : Optional.of(resources.get(resources.size() - 1));
}

private MinorMajorVersion getMajorMinorVersion(String version)
{
if (version.matches("\\d\\.\\d"))
Expand Down
54 changes: 21 additions & 33 deletions src/main/java/dev/dsf/bpe/mail/AggregateErrorMailService.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;

import dev.dsf.bpe.ConstantsPing;
import dev.dsf.bpe.ProcessError;
import dev.dsf.bpe.v1.ProcessPluginApi;
import dev.dsf.bpe.v1.variables.Target;
Expand All @@ -18,15 +17,19 @@ public class AggregateErrorMailService implements InitializingBean
{
private static final Logger errorMailServiceLogger = LoggerFactory.getLogger("error-mail-service-logger");
private static final String MAIL_MESSAGE_INTRO = "Error(s) while executing ping-pong process:";
private static final String PING_PROCESS_HAS_ERRORS = "Ping process has errors";

public static final String PING_PROCESS_HAS_ERRORS = "Ping process has errors";
public static final String PONG_PROCESS_HAS_ERRORS = "Pong process has errors";

private final ProcessPluginApi api;
private final boolean sendProcessFailedMail;
private final String subject;

public AggregateErrorMailService(ProcessPluginApi api, boolean sendProcessFailedMail)
public AggregateErrorMailService(ProcessPluginApi api, boolean sendProcessFailedMail, String subject)
{
this.api = api;
this.sendProcessFailedMail = sendProcessFailedMail;
this.subject = subject;
}

@Override
Expand All @@ -39,7 +42,7 @@ public void send(IdType taskId, Map<Target, List<ProcessError>> errorsPerTarget)
{
if (sendProcessFailedMail)
{
api.getMailService().send(PING_PROCESS_HAS_ERRORS, buildMailMessage(taskId, errorsPerTarget));
api.getMailService().send(subject, buildMailMessage(taskId, errorsPerTarget));
errorMailServiceLogger.info("Sent e-mail with process errors");
}
}
Expand Down Expand Up @@ -72,40 +75,25 @@ protected String createMessage(Target target, ProcessError error)

if (error != null && error.process() != null)
{
if (ConstantsPing.PROCESS_NAME_PING.equals(error.process()))
{
b.append(api.getOrganizationProvider().getLocalOrganizationIdentifierValue().orElse("?"));
b.append('/');
b.append(api.getEndpointProvider().getLocalEndpointIdentifierValue().orElse("?"));

b.append(" -> ");

b.append(target.getOrganizationIdentifierValue());
b.append('/');
b.append(target.getEndpointIdentifierValue());

b.append(":");
}
else
{
b.append(target.getOrganizationIdentifierValue());
b.append('/');
b.append(target.getEndpointIdentifierValue());

b.append(" -> ");

b.append(api.getOrganizationProvider().getLocalOrganizationIdentifierValue().orElse("?"));
b.append('/');
b.append(api.getEndpointProvider().getLocalEndpointIdentifierValue().orElse("?"));

b.append(": ");
}
b.append(api.getOrganizationProvider().getLocalOrganizationIdentifierValue().orElse("?"));
b.append('/');
b.append(api.getEndpointProvider().getLocalEndpointIdentifierValue().orElse("?"));

b.append(" -> ");

b.append(target.getOrganizationIdentifierValue());
b.append('/');
b.append(target.getEndpointIdentifierValue());

b.append(":");
b.append("\n\t");
b.append("Description: ").append(error.concept().getDisplay());
}
else
{
b.append("Unable to display error because error is null or process is neither of 'ping' or 'pong'");
b.append("Other:");
b.append("\n\t");
b.append("Description: ").append(error.concept().getDisplay());
}

return b.toString();
Expand Down
Loading