mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	Client: Experiementing with native http-connection
to replace httpclient.
This commit is contained in:
		
							parent
							
								
									d2a09d89b9
								
							
						
					
					
						commit
						8d41825f82
					
				| @ -0,0 +1,37 @@ | ||||
| package no.finn.unleash.repository; | ||||
| 
 | ||||
| import java.io.BufferedReader; | ||||
| import java.io.File; | ||||
| import java.io.FileReader; | ||||
| import java.io.FileWriter; | ||||
| import java.io.IOException; | ||||
| import java.util.Collections; | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| 
 | ||||
| class FeatureToggleBackupFileHandler { | ||||
|     private static final Logger LOG = LogManager.getLogger(); | ||||
|     private static final String BACKUP_FILE = | ||||
|             System.getProperty("java.io.tmpdir") + File.separatorChar + "unleash-repo.json"; | ||||
| 
 | ||||
| 
 | ||||
|     ToggleCollection readBackupFile() { | ||||
|         LOG.info("Unleash will try to load feature toggle states from temporary backup"); | ||||
|         try(FileReader reader = new FileReader(BACKUP_FILE)) { | ||||
|             BufferedReader br = new BufferedReader(reader); | ||||
|             return JsonToggleParser.collectionFormJson(br); | ||||
|         } catch (IOException e) { | ||||
|             //TODO: error if file corrupt, warning if file not found. | ||||
|             LOG.warn("Unleash was unable to feature toggle states from temporary backup", e); | ||||
|             return new ToggleCollection(Collections.emptyList()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void write(ToggleCollection toggleCollection) { | ||||
|         try(FileWriter writer = new FileWriter(BACKUP_FILE)) { | ||||
|             writer.write(JsonToggleParser.toJsonString(toggleCollection)); | ||||
|         } catch (IOException e) { | ||||
|             LOG.warn("Unleash was unable to backup feature toggles to file: {}", BACKUP_FILE, e); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,74 @@ | ||||
| package no.finn.unleash.repository; | ||||
| 
 | ||||
| import java.net.URI; | ||||
| import java.util.Collection; | ||||
| import java.util.concurrent.Executors; | ||||
| import java.util.concurrent.RejectedExecutionException; | ||||
| import java.util.concurrent.ScheduledFuture; | ||||
| import java.util.concurrent.ScheduledThreadPoolExecutor; | ||||
| import java.util.concurrent.ThreadFactory; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| import no.finn.unleash.Toggle; | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| 
 | ||||
| public final class FeatureToggleRepository implements ToggleRepository { | ||||
|     private static final Logger LOG = LogManager.getLogger(); | ||||
| 
 | ||||
|     private static final ScheduledThreadPoolExecutor TIMER = new ScheduledThreadPoolExecutor( | ||||
|             1, | ||||
|             new ThreadFactory() { | ||||
|                 @Override | ||||
|                 public Thread newThread(final Runnable r) { | ||||
|                     Thread thread = Executors.defaultThreadFactory().newThread(r); | ||||
|                     thread.setName("unleash-toggle-repository"); | ||||
|                     thread.setDaemon(true); | ||||
|                     return thread; | ||||
|                 } | ||||
|             }); | ||||
| 
 | ||||
|     static { | ||||
|         TIMER.setRemoveOnCancelPolicy(true); | ||||
|     } | ||||
| 
 | ||||
|     private final FeatureToggleBackupFileHandler featureToggleBackupFileHandler; | ||||
|     private final ToggleFetcher toggleFetcher; | ||||
| 
 | ||||
|     private ToggleCollection toggleCollection; | ||||
| 
 | ||||
|     public FeatureToggleRepository(URI featuresUri, long pollIntervalSeconds) { | ||||
|         featureToggleBackupFileHandler = new FeatureToggleBackupFileHandler(); | ||||
|         toggleFetcher = new HttpToggleFetcher(featuresUri); | ||||
| 
 | ||||
|         toggleCollection = featureToggleBackupFileHandler.readBackupFile(); | ||||
|         startBackgroundPolling(pollIntervalSeconds); | ||||
|     } | ||||
| 
 | ||||
|     private ScheduledFuture startBackgroundPolling(long pollIntervalSeconds) { | ||||
|         try { | ||||
|             return TIMER.scheduleAtFixedRate(new Runnable() { | ||||
|                 @Override | ||||
|                 public void run() { | ||||
|                     ToggleResponse response = toggleFetcher.fetchToggles(); | ||||
|                     if(response.getStatus() == ToggleResponse.Status.CHANGED) { | ||||
|                         featureToggleBackupFileHandler.write(toggleCollection); | ||||
|                         toggleCollection = response.getToggleCollection(); | ||||
|                     } | ||||
|                 } | ||||
|             }, pollIntervalSeconds, pollIntervalSeconds, TimeUnit.SECONDS); | ||||
|         } catch (RejectedExecutionException ex) { | ||||
|             LOG.error("Unleash background task crashed"); | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public Toggle getToggle(String name) throws ToggleException { | ||||
|         return toggleCollection.getToggle(name); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public Collection<Toggle> getToggles() throws ToggleException { | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
| @ -9,8 +9,6 @@ import java.net.MalformedURLException; | ||||
| import java.net.URI; | ||||
| import java.net.URL; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.util.Collection; | ||||
| import no.finn.unleash.Toggle; | ||||
| 
 | ||||
| public final class HttpToggleFetcher implements ToggleFetcher { | ||||
|     public static final int CONNECT_TIMEOUT = 10000; | ||||
| @ -57,7 +55,7 @@ public final class HttpToggleFetcher implements ToggleFetcher { | ||||
|         try(BufferedReader reader = new BufferedReader( | ||||
|                 new InputStreamReader((InputStream) request.getContent(), StandardCharsets.UTF_8))) { | ||||
| 
 | ||||
|             Collection<Toggle> toggles = JsonToggleParser.fromJson(reader); | ||||
|             ToggleCollection toggles = JsonToggleParser.collectionFormJson(reader); | ||||
|             return new ToggleResponse(ToggleResponse.Status.CHANGED, toggles); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -18,14 +18,30 @@ public final class JsonToggleParser { | ||||
|         return gson.toJson(new ToggleCollection(toggles)); | ||||
|     } | ||||
| 
 | ||||
|     public static String toJsonString(ToggleCollection toggleCollection) { | ||||
|         Gson gson = new GsonBuilder().create(); | ||||
|         return gson.toJson(toggleCollection); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public static Collection<Toggle> fromJson(String jsonString) { | ||||
|         Gson gson = new GsonBuilder().create(); | ||||
|         return gson.fromJson(jsonString,ToggleCollection.class).getFeatures(); | ||||
|     } | ||||
| 
 | ||||
|     public static ToggleCollection collectionFormJson(String jsonString) { | ||||
|         Gson gson = new GsonBuilder().create(); | ||||
|         return gson.fromJson(jsonString, ToggleCollection.class); | ||||
|     } | ||||
| 
 | ||||
|     public static Collection<Toggle> fromJson(Reader reader) { | ||||
|         Gson gson = new GsonBuilder().create(); | ||||
|         return gson.fromJson(reader,ToggleCollection.class).getFeatures(); | ||||
|     } | ||||
| 
 | ||||
|     public static ToggleCollection collectionFormJson(Reader reader) { | ||||
|         Gson gson = new GsonBuilder().create(); | ||||
|         ToggleCollection gsonCollection = gson.fromJson(reader,ToggleCollection.class); | ||||
|         return new ToggleCollection(gsonCollection.getFeatures()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,17 +1,26 @@ | ||||
| package no.finn.unleash.repository; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import no.finn.unleash.Toggle; | ||||
| 
 | ||||
| public final class ToggleCollection { | ||||
|     private final Collection<Toggle> features; | ||||
| final class ToggleCollection { | ||||
|     private Collection<Toggle> features = Collections.emptyList(); | ||||
|     private Map<String, Toggle> cache; | ||||
| 
 | ||||
|     public ToggleCollection(final Collection<Toggle> features) { | ||||
|     ToggleCollection(final Collection<Toggle> features) { | ||||
|         this.features = features; | ||||
|         cache = new HashMap<>(); | ||||
|         features.forEach(toggle -> cache.put(toggle.getName(), toggle)); | ||||
|     } | ||||
| 
 | ||||
|     public Collection<Toggle> getFeatures() { | ||||
|     Collection<Toggle> getFeatures() { | ||||
|         return features; | ||||
|     } | ||||
| 
 | ||||
|     Toggle getToggle(final String name) { | ||||
|         return cache.get(name); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,30 +1,28 @@ | ||||
| package no.finn.unleash.repository; | ||||
| 
 | ||||
| import java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import no.finn.unleash.Toggle; | ||||
| 
 | ||||
| public final class ToggleResponse { | ||||
|     enum Status {NOT_CHANGED, CHANGED} | ||||
| 
 | ||||
|     private final Status status; | ||||
|     private final Collection<Toggle> getToggles; | ||||
|     private final ToggleCollection toggleCollection; | ||||
| 
 | ||||
|     public ToggleResponse(Status status, Collection<Toggle> getToggles) { | ||||
|     public ToggleResponse(Status status, ToggleCollection toggleCollection) { | ||||
|         this.status = status; | ||||
|         this.getToggles = getToggles; | ||||
|         this.toggleCollection = toggleCollection; | ||||
|     } | ||||
| 
 | ||||
|     public ToggleResponse(Status status) { | ||||
|         this.status = status; | ||||
|         this.getToggles = Collections.emptyList(); | ||||
|         this.toggleCollection = new ToggleCollection(Collections.emptyList()); | ||||
|     } | ||||
| 
 | ||||
|     public Status getStatus() { | ||||
|         return status; | ||||
|     } | ||||
| 
 | ||||
|     public Collection<Toggle> getGetToggles() { | ||||
|         return getToggles; | ||||
|     public ToggleCollection getToggleCollection() { | ||||
|         return toggleCollection; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,14 +1,15 @@ | ||||
| package no.finn.unleash; | ||||
| 
 | ||||
| import java.net.URI; | ||||
| import java.util.Random; | ||||
| import no.finn.unleash.repository.FeatureToggleRepository; | ||||
| import no.finn.unleash.repository.HTTPToggleRepository; | ||||
| import no.finn.unleash.repository.PollingToggleRepository; | ||||
| import no.finn.unleash.repository.ToggleRepository; | ||||
| 
 | ||||
| public class ManualTesting { | ||||
|     public static void main(String[] args) throws Exception { | ||||
|         HTTPToggleRepository httpRepo = new HTTPToggleRepository("http://localhost:4242/features"); | ||||
|         ToggleRepository repository = new PollingToggleRepository(httpRepo, 1); | ||||
|         ToggleRepository repository = new FeatureToggleRepository(URI.create("http://localhost:4242/features"), 1); | ||||
| 
 | ||||
| 
 | ||||
|         Unleash unleash = new Unleash(repository); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user