package io.muoncore.extension.amqp.discovery; import io.muoncore.Discovery; import io.muoncore.InstanceDescriptor; import io.muoncore.ServiceDescriptor; import io.muoncore.codec.Codecs; import io.muoncore.extension.amqp.AmqpConnection; import io.muoncore.extension.amqp.QueueListener; import io.muoncore.extension.amqp.QueueListenerFactory; import io.muoncore.extension.amqp.QueueMessageBuilder; import io.muoncore.transport.ServiceCache; import java.io.IOException; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class AmqpDiscovery implements Discovery { private QueueListenerFactory queueListenerFactory; private AmqpConnection connection; private ServiceCache serviceCache; final private Codecs codecs; private QueueListener listener; private DiscoveryOnReady onReady; private ExecutorService spinner; private InstanceDescriptor localDescriptor; private CountDownLatch countdown = new CountDownLatch(1); private volatile boolean started = false; private volatile boolean executedOnReady = false; public AmqpDiscovery( QueueListenerFactory queueListenerFactory, AmqpConnection connection, ServiceCache cache, Codecs codecs) { this.queueListenerFactory = queueListenerFactory; this.connection = connection; this.serviceCache = cache; this.codecs = codecs; this.spinner = Executors.newCachedThreadPool(); } public void start() { synchronized (this) { listener = queueListenerFactory.listenOnBroadcast("discovery", data -> { serviceCache.addService(codecs.decode(data.getBody(), data.getContentType(), InstanceDescriptor.class)); }); startAnnouncePing(); spinner.execute(() -> { try { Thread.sleep(4000); executedOnReady = true; if (onReady != null) { onReady.call(); } } catch (Exception e) { e.printStackTrace(); } }); started = true; countdown.countDown(); } } private void startAnnouncePing() { spinner.execute(() -> { try { while (true) { if (localDescriptor != null) { Codecs.EncodingResult payload = codecs.encode(localDescriptor, new String[] {"application/json" }); if (payload != null && !payload.isFailed()) { try { connection.broadcast( QueueMessageBuilder.queue("discovery") .body(payload.getPayload()) .contentType(payload.getContentType()).build() ); } catch (IOException e) { e.printStackTrace(); } } } Thread.sleep(3000); } } catch (InterruptedException e) { } }); } @Override public List<ServiceDescriptor> getKnownServices() { if (!started) { try { countdown.await(4, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } } return serviceCache.getServices(); } @Override public void advertiseLocalService(InstanceDescriptor descriptor) { this.localDescriptor = descriptor; } @Override public void onReady(DiscoveryOnReady onReady) { synchronized (this) { if (executedOnReady) { try { onReady.call(); } catch (Exception e) { e.printStackTrace(); } } else { this.onReady = onReady; } } } @Override public void shutdown() { spinner.shutdownNow(); listener.cancel(); connection.close(); } }