All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.avanza.astrix.serviceunit.ServiceRegistryExporterWorker Maven / Gradle / Ivy

/*
 * Copyright 2014 Avanza Bank AB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.avanza.astrix.serviceunit;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.annotation.PreDestroy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.avanza.astrix.beans.config.AstrixConfig;
import com.avanza.astrix.beans.core.AstrixSettings;
import com.avanza.astrix.beans.registry.AstrixServiceRegistryFactory;
import com.avanza.astrix.beans.registry.ServiceRegistryExporterClient;
import com.avanza.astrix.beans.service.ServiceProperties;
import com.avanza.astrix.beans.util.AstrixFrameworkThread;
import com.avanza.astrix.config.DynamicLongProperty;
import com.avanza.astrix.core.ServiceUnavailableException;
/**
 * The service registry worker is a server-side component responsible for continuously publishing 
 * all exported services from the current application onto the service registry.
 * 
 * @author Elias Lindholm (elilin)
 * 
 */
public class ServiceRegistryExporterWorker extends AstrixFrameworkThread {
	
	private final List exportedServices = new CopyOnWriteArrayList<>();
	private ServiceRegistryExporterClient serviceRegistryProviderClient;
	private final Logger log = LoggerFactory.getLogger(ServiceRegistryExporterWorker.class);
	private final DynamicLongProperty exportIntervallMillis;		  
	private final DynamicLongProperty serviceLeaseTimeMillis;
	private final DynamicLongProperty retryIntervallMillis;
	private final AstrixConfig config;
	private final Timer timer = new Timer();
	private final AstrixServiceRegistryFactory serviceRegistryFactory;

	public ServiceRegistryExporterWorker(AstrixConfig config, AstrixServiceRegistryFactory serviceRegistryFactory) {
		super("ServiceRegistryExporter");
		this.config = config;
		this.serviceRegistryFactory = serviceRegistryFactory;
		this.exportIntervallMillis = config.get(AstrixSettings.SERVICE_REGISTRY_EXPORT_INTERVAL);
		this.retryIntervallMillis = config.get(AstrixSettings.SERVICE_REGISTRY_EXPORT_RETRY_INTERVAL);
		this.serviceLeaseTimeMillis = config.get(AstrixSettings.SERVICE_REGISTRY_LEASE);
	}
	
	public void startServiceExporter() {
		if (exportedServices.isEmpty()) {
			log.info("No ServiceExporters configured. No services will be published to service registry");
			return;
		}
		createServiceRegistryExporterClient();
		start();
	}

	private void createServiceRegistryExporterClient() {
		/*
		 * The ServiceRegistryExporterClient is created lazily to
		 * avoid that the service registry is attempting to create an 
		 * AstrixServiceRegistry instance against itself.
		 */
		String subsystem = config.get(AstrixSettings.SUBSYSTEM_NAME).get();
		String applicationInstanceId = config.get(AstrixSettings.APPLICATION_INSTANCE_ID).get();
		String applicationTag = config.get(AstrixSettings.APPLICATION_TAG).get();
		String zone = subsystem;
		if (applicationTag != null) {
			zone = subsystem + "#"  + applicationTag;
		}
		this.serviceRegistryProviderClient = new ServiceRegistryExporterClient(serviceRegistryFactory.createServiceRegistry(), subsystem, applicationInstanceId, zone);
	}
	
	@PreDestroy
	public void destroy() {
		interrupt();
	}
	
	public void triggerServiceExport() {
		this.timer.wakeup();
	}
	
	@Override
	public void run() {
		while (!interrupted()) {
			long sleepTimeUntilNextAttempt = this.exportIntervallMillis.get();
			try {
				exportProvidedServcies();
			} catch (ServiceUnavailableException e) {
				// Not bound to service registry
				sleepTimeUntilNextAttempt = this.retryIntervallMillis.get();
				log.info(String.format("Failed to export services to registry. Sleeping %s millis until next attempt.", sleepTimeUntilNextAttempt), e);
			} catch (Exception e) {
				log.info(String.format("Failed to export services to registry. Sleeping %s millis until next attempt.", sleepTimeUntilNextAttempt), e);
			} 
			try {
				this.timer.sleep(sleepTimeUntilNextAttempt);
			} catch (InterruptedException e) {
				interrupt();
			}
		}
		log.info("ServiceRegistryExporterWorker is interrupted, won't publish to service registry anymore.");
	}

	private void exportProvidedServcies() {
		for (ServiceRegistryExportedService exportedService : exportedServices) {
			ServiceProperties serviceProperties = exportedService.exportServiceProperties();
			serviceRegistryProviderClient.register(serviceProperties.getApi(), serviceProperties, serviceLeaseTimeMillis.get());
			log.debug("Exported to service registry. service={} properties={}", serviceProperties.getApi().getName(), serviceProperties);
		}
	}

	public void addServiceBuilder(
			ServiceRegistryExportedService serviceRegistryExportedService) {
		this.exportedServices.add(serviceRegistryExportedService);
	}

	private static class Timer {
		
		private final Object monitor = new Object();
		
		void sleep(long time) throws InterruptedException {
			synchronized (monitor) {
				monitor.wait(time);
			}
		}
		
		void wakeup() {
			synchronized (monitor) {
				monitor.notifyAll();
			}
		}
	}
	

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy