From 6ca0c2792cea05a1f2314e78eb78fffdfba313d1 Mon Sep 17 00:00:00 2001 From: redmitry Date: Fri, 2 Feb 2024 15:32:35 +0100 Subject: [PATCH] dynamically update metadata --- .../network/config/NetworkConfiguration.java | 2 +- .../network/info/BeaconInfoProducer.java | 95 ++++++++++++++----- 2 files changed, 70 insertions(+), 27 deletions(-) diff --git a/src/main/java/es/bsc/inb/ga4gh/beacon/network/config/NetworkConfiguration.java b/src/main/java/es/bsc/inb/ga4gh/beacon/network/config/NetworkConfiguration.java index 4f38a59..9886d0a 100644 --- a/src/main/java/es/bsc/inb/ga4gh/beacon/network/config/NetworkConfiguration.java +++ b/src/main/java/es/bsc/inb/ga4gh/beacon/network/config/NetworkConfiguration.java @@ -193,7 +193,7 @@ private void updateBeacon(String endpoint) { } /** - * Updats Beacon's metadata. + * Update Beacon's metadata. * * @param endpoint Beacon's API endpoint * @param schema Beacon's metadata type (INFO, MAP, ENTRY_TYPES, etc.) diff --git a/src/main/java/es/bsc/inb/ga4gh/beacon/network/info/BeaconInfoProducer.java b/src/main/java/es/bsc/inb/ga4gh/beacon/network/info/BeaconInfoProducer.java index d60f033..b63b3fd 100644 --- a/src/main/java/es/bsc/inb/ga4gh/beacon/network/info/BeaconInfoProducer.java +++ b/src/main/java/es/bsc/inb/ga4gh/beacon/network/info/BeaconInfoProducer.java @@ -43,12 +43,16 @@ import jakarta.json.JsonObjectBuilder; import jakarta.json.bind.JsonbBuilder; import jakarta.servlet.ServletContext; +import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.nio.file.Files; import java.nio.file.NoSuchFileException; +import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -70,31 +74,62 @@ public class BeaconInfoProducer implements Serializable { @Inject private NetworkConfiguration config; - private BeaconNetworkInfoResponse beacon_info; + private FileTime last_modified_time; + private volatile BeaconNetworkInfoResponse beacon_info; @PostConstruct public void init() { - String config_dir = System.getenv(BEACON_NETWORK_CONFIG_DIR_PROPERTY_NAME); + beacon_info = readBeaconInfo(); + } + + private BeaconNetworkInfoResponse readBeaconInfo() { + final String config_dir = System.getenv(BEACON_NETWORK_CONFIG_DIR_PROPERTY_NAME); if (config_dir != null) { - try(InputStream in = Files.newInputStream(Paths.get(config_dir, BEACON_INFO_FILE), StandardOpenOption.READ)) { - beacon_info = JsonbBuilder.create().fromJson(in, BeaconNetworkInfoResponse.class); - return; - } catch (NoSuchFileException ex) { - } catch (Exception ex) { - Logger.getLogger(BeaconInfoProducer.class.getName()).log(Level.WARNING, null, ex); + final Path path = Paths.get(config_dir, BEACON_INFO_FILE); + if (Files.exists(path)) { + try { + final BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class); + synchronized(BeaconNetworkInfoResponse.class) { + if (last_modified_time == null || last_modified_time.compareTo(attr.lastModifiedTime()) != 0) { + try(InputStream in = Files.newInputStream(path, StandardOpenOption.READ)) { + beacon_info = JsonbBuilder.create().fromJson(in, BeaconNetworkInfoResponse.class); + injectResponses(); + last_modified_time = attr.lastModifiedTime(); + } catch (NoSuchFileException ex) { + } catch (Exception ex) { + Logger.getLogger(BeaconInfoProducer.class.getName()).log(Level.WARNING, null, ex); + } + } + } + } catch (IOException ex) { + Logger.getLogger(BeaconInfoProducer.class.getName()).log(Level.WARNING, null, ex); + } + } else if (last_modified_time != null) { + // switch to embedded 'beacon-info.json' if custom one has been removed + beacon_info = null; + last_modified_time = null; } } - try(InputStream in = ctx.getResourceAsStream(BEACON_NETWORK_CONFIG_DIR + BEACON_INFO_FILE)) { - if (in == null) { - Logger.getLogger(BeaconInfoProducer.class.getName()).log( - Level.SEVERE, "no service info file found: %s", BEACON_NETWORK_CONFIG_DIR + BEACON_INFO_FILE); - } else { - beacon_info = JsonbBuilder.create().fromJson(in, BeaconNetworkInfoResponse.class); + if (beacon_info == null) { + synchronized(BeaconNetworkInfoResponse.class) { + if (beacon_info == null) { + try(InputStream in = ctx.getResourceAsStream(BEACON_NETWORK_CONFIG_DIR + BEACON_INFO_FILE)) { + if (in == null) { + Logger.getLogger(BeaconInfoProducer.class.getName()).log( + Level.SEVERE, "no service info file found: %s", BEACON_NETWORK_CONFIG_DIR + BEACON_INFO_FILE); + } else { + beacon_info = JsonbBuilder.create().fromJson(in, BeaconNetworkInfoResponse.class); + injectResponses(); + } + } catch (Exception ex) { + Logger.getLogger(BeaconInfoProducer.class.getName()).log(Level.SEVERE, null, ex); + } + } } - } catch (Exception ex) { - Logger.getLogger(BeaconInfoProducer.class.getName()).log(Level.SEVERE, null, ex); } + + return beacon_info; } /** @@ -103,19 +138,27 @@ public void init() { * @param event update event */ public void onEvent(@ObservesAsync NetworkConfigUpdatedEvent event) { + injectResponses(); + } + + /** + * Inject Beacons` '/info' responses into the BN '/info' + */ + private void injectResponses() { if (beacon_info != null) { - final List responses = new ArrayList(); - - for (BeaconNetworkInfoResponse response : config.getInfos().values()) { - responses.add(response); + synchronized(BeaconNetworkInfoResponse.class) { + if (beacon_info != null) { + final List responses = new ArrayList(); + for (BeaconNetworkInfoResponse response : config.getInfos().values()) { + responses.add(response); + } + beacon_info.setResponses(responses.isEmpty() ? null : responses); + setMetadataParsingErrors(); + } } - - beacon_info.setResponses(responses.isEmpty() ? null : responses); - - setMetadataParsingErrors(); } } - + private void setMetadataParsingErrors() { final Map> errors = config.getErrors(); if (!errors.isEmpty()) { @@ -153,7 +196,7 @@ private void setMetadataParsingErrors() { @Produces public BeaconNetworkInfoResponse beaconInfo() { - return beacon_info; + return readBeaconInfo(); } }