diff --git a/examples/build.gradle b/examples/build.gradle index 0d0ec470..d06ef1e3 100644 --- a/examples/build.gradle +++ b/examples/build.gradle @@ -18,3 +18,13 @@ tasks.register('GettingStarted', JavaExec) { classpath = sourceSets.main.runtimeClasspath mainClass = "io.harness.ff.examples.GettingStarted" } + +tasks.register('EventExample', JavaExec) { + classpath = sourceSets.main.runtimeClasspath + mainClass = "io.harness.ff.examples.EventExample" +} + +tasks.register('EventExampleWithFeatureSnapshot', JavaExec) { + classpath = sourceSets.main.runtimeClasspath + mainClass = "io.harness.ff.examples.EventExampleWithFeatureSnapshot" +} diff --git a/examples/src/main/java/io/harness/ff/examples/EventExampleWithFeatureSnapshot.java b/examples/src/main/java/io/harness/ff/examples/EventExampleWithFeatureSnapshot.java new file mode 100644 index 00000000..261b1704 --- /dev/null +++ b/examples/src/main/java/io/harness/ff/examples/EventExampleWithFeatureSnapshot.java @@ -0,0 +1,106 @@ +package io.harness.ff.examples; + +import io.harness.cf.client.api.BaseConfig; +import io.harness.cf.client.api.CfClient; +import io.harness.cf.client.api.Event; +import io.harness.cf.client.api.XmlFileMapStore; +import io.harness.cf.client.connector.HarnessConfig; +import io.harness.cf.client.connector.HarnessConnector; +import io.harness.cf.client.dto.Target; +import io.harness.cf.model.FeatureSnapshot; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +@Slf4j +public class EventExamplePoC { + private static final String SDK_KEY = ""; + private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + + private static CfClient client; + + public static void main(String... args) { + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + scheduler.shutdown(); + client.close(); + })); + + final XmlFileMapStore fileStore = new XmlFileMapStore("Non-Freemium"); + // this is one way of initialising config. + final HarnessConnector hc = new HarnessConnector(SDK_KEY, HarnessConfig.builder().build()); + + BaseConfig bc = BaseConfig.builder(). + enableFeatureSnapshot(true).build(); + + // initialise the client. + client = new CfClient(hc, bc); + + client.on(Event.READY, result -> log.info("READY")); + + // example: specified prefix we can filter on. + final String FLAG_PREFIX = "FFM_"; + // example: given flag change event - get both previous and current feature if prefix is matched. + client.on(Event.CHANGED, identifier -> { + if (identifier.startsWith(FLAG_PREFIX)) { + getSnapshot(identifier); + } else { + log.info("We had an event change but flag did not have required prefix"); + } + }); + + // example : given flag change event - get all snapshots. + client.on(Event.CHANGED, identifier -> { + getAllSnapshots(); + }); + + // example : given flag change event - get all snapshots with given prefix. + client.on(Event.CHANGED, identifier -> { + getAllSnapshotsWithPrefix(); + }); + + final Target target = Target.builder().identifier("target1").attribute("testKey", "TestValue").name("target1").build(); + + scheduler.scheduleAtFixedRate(() -> { + log.info("ticking..."); + }, 0, 10, TimeUnit.SECONDS); + + } + + + // example method to extract a single snapshot. + private static void getSnapshot(String identifier) { + log.info("We had a chang event and prefix matched, lets inspect the diff"); + // fetch current and previous version of the feature + FeatureSnapshot snapshot = client.getFeatureSnapshot(identifier); + log.info("Previous flag config: {}, {}", identifier, snapshot.getPrevious()); + log.info("Current flag config: {}, {}", identifier, snapshot.getCurrent()); + } + + + // example method to extract and print all the snapshots. + private static void getAllSnapshots() { + // get all snapshots + List snapshots = client.getAllFeatureSnapshots(); + int counter = 0; + for (FeatureSnapshot snapshot : snapshots) { + log.info("snapshots {} {}", ++counter, snapshot); + } + } + + // example method to extract and print all the snapshots. + private static void getAllSnapshotsWithPrefix() { + // get all snapshots + String prefix = "FFM_"; + List snapshots = client.getAllFeatureSnapshots(prefix); + int counter = 0; + for (FeatureSnapshot snapshot : snapshots) { + log.info("snapshots {} {}", ++counter, snapshot); + } + } +} + + diff --git a/src/main/java/io/harness/cf/client/api/BaseConfig.java b/src/main/java/io/harness/cf/client/api/BaseConfig.java index cde8dee6..7986a6ef 100644 --- a/src/main/java/io/harness/cf/client/api/BaseConfig.java +++ b/src/main/java/io/harness/cf/client/api/BaseConfig.java @@ -42,6 +42,9 @@ public class BaseConfig { /** If metrics service POST call is taking > this time, we need to know about it */ @Builder.Default private final long metricsServiceAcceptableDuration = 10000; + /** store previous and current version of the FeatureConfig */ + @Builder.Default private final boolean enableFeatureSnapshot = false; + /** Get metrics post frequency in seconds */ public int getFrequency() { return Math.max(frequency, Config.MIN_FREQUENCY); diff --git a/src/main/java/io/harness/cf/client/api/CfClient.java b/src/main/java/io/harness/cf/client/api/CfClient.java index 07f580fb..111a5d00 100644 --- a/src/main/java/io/harness/cf/client/api/CfClient.java +++ b/src/main/java/io/harness/cf/client/api/CfClient.java @@ -5,6 +5,8 @@ import io.harness.cf.client.dto.Message; import io.harness.cf.client.dto.Target; import io.harness.cf.client.logger.LogUtil; +import io.harness.cf.model.FeatureSnapshot; +import java.util.List; import java.util.function.Consumer; import lombok.NonNull; @@ -83,6 +85,18 @@ public void on(@NonNull final Event event, @NonNull final Consumer consu client.on(event, consumer); } + public List getAllFeatureSnapshots(String prefix) { + return client.getFeatureSnapshots(prefix); + } + + public List getAllFeatureSnapshots() { + return client.getFeatureSnapshots(); + } + + public FeatureSnapshot getFeatureSnapshot(@NonNull String identifier) { + return client.getFeatureSnapshot(identifier); + } + public void off() { client.off(); } diff --git a/src/main/java/io/harness/cf/client/api/InnerClient.java b/src/main/java/io/harness/cf/client/api/InnerClient.java index 8ad56fbd..55192fdb 100644 --- a/src/main/java/io/harness/cf/client/api/InnerClient.java +++ b/src/main/java/io/harness/cf/client/api/InnerClient.java @@ -91,7 +91,9 @@ protected void setUp(@NonNull final Connector connector, @NonNull final BaseConf this.connector.setOnUnauthorized(this::onUnauthorized); // initialization - repository = new StorageRepository(options.getCache(), options.getStore(), this, false); + repository = + new StorageRepository( + options.getCache(), options.getStore(), this, options.isEnableFeatureSnapshot()); evaluator = new Evaluator(repository, options); authService = new AuthService(this.connector, options.getPollIntervalInSeconds(), this); pollProcessor = @@ -313,12 +315,13 @@ public synchronized void waitForInitialization() } public List getFeatureSnapshots() { - // TODO return null/empty list if snapshot is not enabled in config. return getFeatureSnapshots(""); } public List getFeatureSnapshots(String prefix) { - // TODO return null/empty list if snapshot is not enabled in config. + if (!options.isEnableFeatureSnapshot()){ + log.debug("FeatureSnapshot disabled, snapshot will contain only current version."); + } List identifiers = repository.getAllFeatureIdentifiers(prefix); List snapshots = new LinkedList<>(); @@ -331,7 +334,9 @@ public List getFeatureSnapshots(String prefix) { } public FeatureSnapshot getFeatureSnapshot(@NonNull String identifier) { - // TODO return null/empty list if snapshot is not enabled in config. + if (!options.isEnableFeatureSnapshot()){ + log.debug("FeatureSnapshot disabled, snapshot will contain only current version."); + } Optional ofc = repository.getCurrentAndPreviousFeatureConfig(identifier); FeatureSnapshot result = new FeatureSnapshot(); if (ofc.isPresent()) {