Skip to content

Commit c0dd691

Browse files
committed
check fhir ts and openehr for availability
1 parent 4a202ec commit c0dd691

6 files changed

Lines changed: 399 additions & 13 deletions

File tree

src/main/java/de/uksh/medic/etl/OpenEhrObds.java

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import de.uksh.medic.etl.settings.ConfigurationLoader;
3232
import de.uksh.medic.etl.settings.CxxMdrSettings;
3333
import de.uksh.medic.etl.settings.Mapping;
34+
import de.uksh.medic.etl.settings.ServerCheckSettings;
3435
import de.uksh.medic.etl.settings.Settings;
3536
import groovy.lang.Binding;
3637
import groovy.lang.GroovyShell;
@@ -98,6 +99,7 @@ public final class OpenEhrObds {
9899
private static FhirResolver fr;
99100
private static UtilMethods um = new UtilMethods();
100101
private static IGenericClient fc;
102+
private static IGenericClient fhirTsClient;
101103

102104
private OpenEhrObds() {
103105
}
@@ -112,7 +114,10 @@ public static void main(String[] args) throws IOException, KeyStoreException, Ge
112114
ConfigurationLoader configLoader = new ConfigurationLoader();
113115
configLoader.loadConfiguration(settingsYaml, Settings.class);
114116

117+
// Initialize FHIR terminology server client
115118
fr = new FhirResolver();
119+
fhirTsClient = FhirResolver.getTerminologyClient();
120+
116121
if (Settings.getFhirServerUrl() != null) {
117122
FhirContext fcCtx = FhirContext.forR4();
118123

@@ -159,6 +164,9 @@ public static void main(String[] args) throws IOException, KeyStoreException, Ge
159164

160165
openEhrClient = new DefaultRestClient(new OpenEhrClientConfig(ehrBaseUrl));
161166

167+
// Initialize server availability monitoring
168+
ServerAvailability.init(openEhrClient, fhirTsClient);
169+
162170
ObjectMapper mapper;
163171
JsonMapper jm = new JsonMapper();
164172

@@ -170,6 +178,17 @@ public static void main(String[] args) throws IOException, KeyStoreException, Ge
170178

171179
Settings.getMapping().values().forEach(m -> m.forEach(n -> initializeAttribute(n, jm)));
172180

181+
// Start server availability monitoring and wait for servers
182+
ServerCheckSettings serverCheck = Settings.getServerCheck();
183+
if (serverCheck.isEnabled()) {
184+
ServerAvailability.startMonitor(serverCheck.getIntervalMs());
185+
186+
if (!ServerAvailability.waitUntilAvailable(serverCheck.getIntervalMs(), serverCheck.getTimeoutMs())) {
187+
Logger.error("Servers not available within timeout, shutting down");
188+
System.exit(1);
189+
}
190+
}
191+
173192
spark.Spark.get("/health", (request, response) -> {
174193
response.type("application/json");
175194
return "{\"msgsPerMinute\": " + SPEED.estimatedSize() + ", \"cacheSize\": " + fr.getCacheSize() + "}";
@@ -179,6 +198,10 @@ public static void main(String[] args) throws IOException, KeyStoreException, Ge
179198

180199
if (Settings.getKafka().getUrl() == null || Settings.getKafka().getUrl().isEmpty()) {
181200
Logger.debug("Kafka URL not set, loading local file");
201+
// Pause monitor during local file processing
202+
if (serverCheck.isEnabled()) {
203+
ServerAvailability.pauseMonitor();
204+
}
182205
File[] files = new File(Settings.getTestDataDir()).listFiles();
183206
for (File f : files) {
184207
if (f.isDirectory()) {
@@ -220,10 +243,27 @@ public static void main(String[] args) throws IOException, KeyStoreException, Ge
220243
reconnectDelay = DEFAULT_RECONNECT_DELAY_MS;
221244

222245
while (true) {
246+
// Check server availability before polling
247+
if (serverCheck.isEnabled() && !ServerAvailability.allAvailable()) {
248+
Logger.info("Server unavailable, waiting before next poll...");
249+
try {
250+
Thread.sleep(serverCheck.getIntervalMs());
251+
} catch (InterruptedException ie) {
252+
Thread.currentThread().interrupt();
253+
break;
254+
}
255+
continue;
256+
}
257+
223258
Logger.debug("Polling Kafka topic");
224259
ConsumerRecords<String, String> records = consumer.poll(
225260
Duration.ofMillis(Settings.getKafka().getPollDuration()));
226261

262+
// Pause server availability monitor during data processing
263+
// to avoid unnecessary FHIR server queries while processing
264+
if (serverCheck.isEnabled()) {
265+
ServerAvailability.pauseMonitor();
266+
}
227267
for (ConsumerRecord<String, String> record : records) {
228268
Logger.debug("Processing record.");
229269
try {
@@ -239,8 +279,9 @@ public static void main(String[] args) throws IOException, KeyStoreException, Ge
239279
sendToErrorTopic(producer, record.value());
240280
} catch (Exception e) {
241281
Logger.error(
242-
"Unexpected error processing record, "
243-
+ "wrapping as ProcessingException, writing to error topic!", e);
282+
"Unexpected error processing record, "
283+
+ "wrapping as ProcessingException, writing to error topic!",
284+
e);
244285
sendToErrorTopic(producer, record.value());
245286
}
246287
SPEED.put(UUID.randomUUID().toString(), "success");
@@ -249,18 +290,27 @@ public static void main(String[] args) throws IOException, KeyStoreException, Ge
249290
consumer.commitSync();
250291
} catch (CommitFailedException e) {
251292
Logger.warn(
252-
"CommitFailedException: consumer got kicked out of consumer "
253-
+ "group. Breaking inner loop to re-subscribe.");
293+
"CommitFailedException: consumer got kicked out of consumer "
294+
+ "group. Breaking inner loop to re-subscribe.");
295+
// Resume monitor before breaking
296+
if (serverCheck.isEnabled()) {
297+
ServerAvailability.resumeMonitor();
298+
}
254299
break; // Break inner loop to allow consumer group rebalance
255300
}
301+
// Resume server availability monitor after processing
302+
if (serverCheck.isEnabled()) {
303+
ServerAvailability.resumeMonitor();
304+
}
256305
}
257306
} catch (WakeupException e) {
258307
Logger.info("Caught WakeupException (shutdown requested). Exiting.");
259308
break; // Shutdown was requested, exit the outer loop
260309
} catch (Exception e) {
261310
Logger.error(
262-
"Unexpected exception in consumer loop, "
263-
+ "restarting consumer in {}ms...", reconnectDelay, e);
311+
"Unexpected exception in consumer loop, "
312+
+ "restarting consumer in {}ms...",
313+
reconnectDelay, e);
264314
try {
265315
TimeUnit.MILLISECONDS.sleep(reconnectDelay);
266316
} catch (InterruptedException ie) {
@@ -580,6 +630,7 @@ private static void buildOpenEhrComposition(String templateId, Map<String, Objec
580630
throw new ProcessingException();
581631
}
582632
} catch (WrongStatusCodeException e) {
633+
ServerAvailability.markOpenEhrUnavailable();
583634
Logger.error("Unable to create EHR due to internal server error. Trying again. Error was: {}",
584635
e.getMessage());
585636
try {
@@ -603,6 +654,7 @@ private static void buildOpenEhrComposition(String templateId, Map<String, Objec
603654
try {
604655
openEhrClient.compositionEndpoint(ehrId).mergeRaw(composition);
605656
} catch (WrongStatusCodeException e) {
657+
ServerAvailability.markOpenEhrUnavailable();
606658
String comp = "";
607659
try {
608660
JacksonUtil.getObjectMapper().writeValueAsString(composition);

0 commit comments

Comments
 (0)