diff --git a/Dockerfile.core b/Dockerfile.core index ef0d273..7a86f00 100644 --- a/Dockerfile.core +++ b/Dockerfile.core @@ -1,5 +1,5 @@ FROM 193044292705.dkr.ecr.ap-south-1.amazonaws.com/common/maven:3.8.3-openjdk-17-slim as builder -ARG ARTIFACT_VERSION=2.0.5-RELEASE +ARG ARTIFACT_VERSION=2.0.6-RELEASE RUN mkdir -p /build WORKDIR /build COPY . /build @@ -7,7 +7,7 @@ RUN mvn clean install RUN mvn clean verify -DskipTests -Dartifact.version=${ARTIFACT_VERSION} FROM 193044292705.dkr.ecr.ap-south-1.amazonaws.com/common/openjdk:17-slim-bullseye -ARG ARTIFACT_VERSION=2.0.5-RELEASE +ARG ARTIFACT_VERSION=2.0.6-RELEASE RUN mkdir -p /usr/local RUN apt-get update -y && apt-get -y install fontconfig libpng-dev WORKDIR /usr/local/ diff --git a/Dockerfile.proxy b/Dockerfile.proxy index 0f0423b..ce4a58f 100644 --- a/Dockerfile.proxy +++ b/Dockerfile.proxy @@ -1,5 +1,5 @@ FROM 193044292705.dkr.ecr.ap-south-1.amazonaws.com/common/maven:3.8.3-openjdk-17-slim as builder -ARG ARTIFACT_VERSION=2.0.5-RELEASE +ARG ARTIFACT_VERSION=2.0.6-RELEASE RUN mkdir -p /build WORKDIR /build COPY . /build @@ -7,7 +7,7 @@ RUN mvn clean install -DskipTests RUN mvn clean verify -DskipTests -Dartifact.version=${ARTIFACT_VERSION} FROM 193044292705.dkr.ecr.ap-south-1.amazonaws.com/common/openjdk:17-slim-bullseye -ARG ARTIFACT_VERSION=2.0.5-RELEASE +ARG ARTIFACT_VERSION=2.0.6-RELEASE RUN mkdir -p /usr/local RUN apt-get update -y && apt-get -y install fontconfig libpng-dev WORKDIR /usr/local/ diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..d8ce480 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,26 @@ +version: '3.0' + +services: + db: + image: "postgres:11" + ports: + - "5432:5432" + environment: + - POSTGRES_DB=communication-service-test + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=admin + + spring-boot-app: + depends_on: + - db + image: "maven:3.8.3-openjdk-17-slim" + ports: + - "8080:8080" + environment: + - DATASOURCE_URL=jdbc:postgresql://db:5432/litmus + - DATASOURCE_USERNAME=litmus-test + - DATASOURCE_PASSWORD=litmus-test + volumes: + - .:/app + working_dir: /app + command: mvn clean verify \ No newline at end of file diff --git a/litmus-cache/pom.xml b/litmus-cache/pom.xml index 7534b8c..c9bcd8e 100644 --- a/litmus-cache/pom.xml +++ b/litmus-cache/pom.xml @@ -4,11 +4,11 @@ litmus com.navi.medici - 2.0.5-RELEASE + 2.0.6-RELEASE litmus-cache - 2.0.5-RELEASE + 2.0.6-RELEASE jar litmus-cache diff --git a/litmus-client/pom.xml b/litmus-client/pom.xml index 9458000..dc391b9 100644 --- a/litmus-client/pom.xml +++ b/litmus-client/pom.xml @@ -5,11 +5,11 @@ litmus com.navi.medici - 2.0.5-RELEASE + 2.0.6-RELEASE litmus-client - 2.0.5-RELEASE + 2.0.6-RELEASE jar litmus-client @@ -43,7 +43,7 @@ com.navi.medici litmus-model - 2.0.5-RELEASE + 2.0.6-RELEASE diff --git a/litmus-client/src/main/java/com/navi/medici/client/ClickStreamClient.java b/litmus-client/src/main/java/com/navi/medici/client/ClickStreamClient.java index 8e85b3c..0ce79b9 100644 --- a/litmus-client/src/main/java/com/navi/medici/client/ClickStreamClient.java +++ b/litmus-client/src/main/java/com/navi/medici/client/ClickStreamClient.java @@ -3,51 +3,40 @@ package com.navi.medici.client; import com.navi.medici.clickstream.ClickStreamPayload; import com.navi.medici.config.LitmusConfig; -import com.navi.medici.response.LitmusExperimentResponse; import com.navi.medici.util.JacksonUtils; import io.micrometer.core.annotation.Timed; -import io.micrometer.core.instrument.Counter; -import io.micrometer.core.instrument.MeterRegistry; import lombok.extern.log4j.Log4j2; import okhttp3.MediaType; -import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; +import static com.navi.medici.util.MetricsUtils.counterMetrics; + @Log4j2 public class ClickStreamClient { public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); - private final String clickStreamAPI; - private final String appName; - private final String vertical; - private final MeterRegistry meterRegistry; + private final LitmusConfig litmusConfig; - public ClickStreamClient(String clickStreamAPI, String appName, - String vertical, MeterRegistry meterRegistry) { - this.clickStreamAPI = clickStreamAPI; - this.appName = appName; - this.vertical = vertical; - this.meterRegistry = meterRegistry; + public ClickStreamClient(LitmusConfig litmusConfig) { + this.litmusConfig = litmusConfig; } @Timed(value = "litmus_client_click_stream_publish_latency", percentiles = {0.90, 0.95, 0.99}) public void publish(String experimentName, ClickStreamPayload payload) { String requestBody = JacksonUtils.objectToString(payload); Request request = new Request.Builder() - .url(clickStreamAPI) + .url(litmusConfig.getClickStreamAPI()) .post(RequestBody.create(JSON, requestBody)) .build(); try(Response response = OkHttpClientContainer.getInstance().newCall(request).execute()) { - Counter.builder("litmus_client_click_stream_event_ingestion") - .tag("vertical", vertical) + counterMetrics(litmusConfig, "litmus_client_click_stream_event_ingestion") .tag("status", String.valueOf(response.code())) .tag("experiment_name", experimentName) - .tag("app_name", appName) - .register(meterRegistry) + .register(litmusConfig.getMeterRegistry()) .increment(); if (response.code() < 300) { var responseBody = response.body(); @@ -59,12 +48,10 @@ public class ClickStreamClient { } } catch (Exception e) { log.error("clickstream event ingestion failed. ", e); - Counter.builder("litmus_client_click_stream_event_ingestion_failed") - .tag("vertical", vertical) + counterMetrics(litmusConfig, "litmus_client_click_stream_event_ingestion_failed") .tag("experiment_name", experimentName) - .tag("app_name", appName) .tag("exception", e.getMessage()) - .register(meterRegistry) + .register(litmusConfig.getMeterRegistry()) .increment(); } } diff --git a/litmus-client/src/main/java/com/navi/medici/client/ExperimentBackupHandlerFile.java b/litmus-client/src/main/java/com/navi/medici/client/ExperimentBackupHandlerFile.java index b776670..018aad8 100644 --- a/litmus-client/src/main/java/com/navi/medici/client/ExperimentBackupHandlerFile.java +++ b/litmus-client/src/main/java/com/navi/medici/client/ExperimentBackupHandlerFile.java @@ -5,15 +5,12 @@ import com.navi.medici.exception.LitmusException; import com.navi.medici.request.v1.LitmusExperiment; import com.navi.medici.response.LitmusExperimentCollection; import com.navi.medici.util.JacksonUtils; -import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; -import java.nio.file.Files; import java.util.Collections; import java.util.List; -import java.util.concurrent.ConcurrentHashMap; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.core.util.IOUtils; @@ -42,7 +39,7 @@ public class ExperimentBackupHandlerFile implements ExperimentBackupHandler { return JacksonUtils.stringToObject(data, LitmusExperimentCollection.class); } catch (FileNotFoundException e) { log.info( - " Litmus could not find the backup-file '" + "Litmus could not find the backup-file '" + backupFile + ". This is expected behavior the first time litmus runs in a new environment."); } catch (IOException | IllegalStateException e) { diff --git a/litmus-client/src/main/java/com/navi/medici/client/HttpExperimentFetcher.java b/litmus-client/src/main/java/com/navi/medici/client/HttpExperimentFetcher.java index 7d0cca3..95c481f 100644 --- a/litmus-client/src/main/java/com/navi/medici/client/HttpExperimentFetcher.java +++ b/litmus-client/src/main/java/com/navi/medici/client/HttpExperimentFetcher.java @@ -6,54 +6,34 @@ import com.navi.medici.response.LitmusExperimentCollection; import com.navi.medici.response.LitmusExperimentResponse; import com.navi.medici.response.LitmusResponse; import com.navi.medici.util.JacksonUtils; -import com.navi.medici.util.LitmusURLs; import io.micrometer.core.annotation.Timed; -import io.micrometer.core.instrument.Counter; -import io.micrometer.core.instrument.MeterRegistry; import java.net.URL; import lombok.extern.log4j.Log4j2; -import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import static com.navi.medici.util.MetricsUtils.counterMetrics; + @Log4j2 public class HttpExperimentFetcher implements ExperimentFetcher { + private final LitmusConfig litmusConfig; - private final LitmusURLs litmusURLs; - private final String appName; - private final String projectNamePrefix; - private final String projectName; - private final String vertical; - private final MeterRegistry meterRegistry; - - public HttpExperimentFetcher(LitmusURLs litmusURLs, - String appName, - String projectNamePrefix, - String projectName, - String vertical, - MeterRegistry meterRegistry) { - this.litmusURLs = litmusURLs; - this.appName = appName; - this.projectNamePrefix = projectNamePrefix; - this.projectName = projectName; - this.vertical = vertical; - this.meterRegistry = meterRegistry; + public HttpExperimentFetcher(LitmusConfig litmusConfig) { + this.litmusConfig = litmusConfig; } @Override @Timed(value = "litmus_client_fetch_experiments_latency", percentiles = {0.90, 0.95, 0.99}) public LitmusExperimentResponse fetchExperiments(String vertical, Long pollingTime) throws LitmusException { - URL experimentUrl = litmusURLs - .getLitmusExperimentsURL(projectName, projectNamePrefix); + URL experimentUrl = litmusConfig.getLitmusURLs() + .getLitmusExperimentsURL(litmusConfig.getProjectName(), litmusConfig.getNamePrefix()); Request request = new Request.Builder() .url(String.format("%s/vertical?vertical=%s&polling_time=%s", experimentUrl, vertical, pollingTime)) .build(); try (Response response = OkHttpClientContainer.getInstance().newCall(request).execute()) { - Counter.builder("litmus_client_fetch_experiment_polling") - .tag("vertical", this.vertical) - .tag("app_name", this.appName) - .register(this.meterRegistry) + counterMetrics(litmusConfig, "litmus_client_fetch_experiment_polling") + .register(litmusConfig.getMeterRegistry()) .increment(); if (response.code() < 300) { @@ -62,41 +42,34 @@ public class HttpExperimentFetcher implements ExperimentFetcher { LitmusExperimentCollection experiments = JacksonUtils.stringToObject(responseBody.string(), LitmusExperimentCollection.class); - Counter.builder("litmus_client_fetch_experiment_polling_total_request") - .tag("vertical", vertical) + counterMetrics(litmusConfig, "litmus_client_fetch_experiment_polling_total_request") .tag("status", String.valueOf(response.code())) .tag("experiment_state", LitmusExperimentResponse.Status.CHANGED.name()) - .tag("app_name", this.appName) - .register(this.meterRegistry) + .register(litmusConfig.getMeterRegistry()) .increment(); return new LitmusExperimentResponse(LitmusExperimentResponse.Status.CHANGED, experiments); } else if (response.code() == 304) { - Counter.builder("litmus_client_fetch_experiment_polling_request_status") - .tag("vertical", vertical) - .tag("app_name", this.appName) + counterMetrics(litmusConfig, "litmus_client_fetch_experiment_polling_request_status") .tag("status", String.valueOf(response.code())) .tag("experiment_state", LitmusExperimentResponse.Status.NOT_CHANGED.name()) - .register(this.meterRegistry) + .register(litmusConfig.getMeterRegistry()) .increment(); return new LitmusExperimentResponse(LitmusExperimentResponse.Status.NOT_CHANGED, response.code()); } else { - Counter.builder("litmus_client_fetch_experiment_polling_request_status") - .tag("vertical", this.vertical) - .tag("app_name", this.appName) + counterMetrics(litmusConfig, "litmus_client_fetch_experiment_polling_request_status") .tag("status", String.valueOf(response.code())) .tag("experiment_state", LitmusExperimentResponse.Status.NOT_CHANGED.name()) - .register(this.meterRegistry) + .register(litmusConfig.getMeterRegistry()) .increment(); return new LitmusExperimentResponse(LitmusExperimentResponse.Status.UNAVAILABLE, response.code()); } } catch (Exception e) { - Counter.builder("litmus_client_fetch_experiment_polling_request_failed") - .tag("vertical", this.vertical) - .tag("app_name", this.appName) - .register(this.meterRegistry) + counterMetrics(litmusConfig, "litmus_client_fetch_experiment_polling_request_failed") + .tag("exception", e.getMessage()) + .register(litmusConfig.getMeterRegistry()) .increment(); throw new LitmusException("fetch experiments failed.", e); } @@ -104,7 +77,7 @@ public class HttpExperimentFetcher implements ExperimentFetcher { @Timed(value = "litmus_client_segment_id_exists_latency", percentiles = {0.90, 0.95, 0.99}) public LitmusResponse segmentIdExists(String segmentName, String id) { - URL segmentIdUrl = this.litmusURLs.getSegmentIdURL(); + URL segmentIdUrl = litmusConfig.getLitmusURLs().getSegmentIdURL(); Request request = new Request.Builder() .url(String.format("%s?segment_name=%s&id=%s", segmentIdUrl, segmentName, id)) .build(); @@ -113,20 +86,16 @@ public class HttpExperimentFetcher implements ExperimentFetcher { var responseBody = response.body(); assert responseBody != null; - Counter.builder("litmus_client_segment_id_exist_request") - .tag("vertical", this.vertical) - .tag("app_name", this.appName) - .tag("status", String.valueOf(response.code())) - .register(this.meterRegistry) - .increment(); + counterMetrics(litmusConfig, "litmus_client_segment_id_exist_request") + .tag("status", String.valueOf(response.code())) + .register(litmusConfig.getMeterRegistry()) + .increment(); return JacksonUtils.stringToObject(responseBody.string(), LitmusResponse.class); } catch (Exception e) { - Counter.builder("litmus_client_segment_id_exist_request_failed") - .tag("vertical", this.vertical) + counterMetrics(litmusConfig, "litmus_client_segment_id_exist_request_failed") .tag("segment_name", segmentName) - .tag("app_name", this.appName) .tag("exception", e.getMessage()) - .register(this.meterRegistry) + .register(litmusConfig.getMeterRegistry()) .increment(); throw new LitmusException("segment name to id matching doesn't exists.", e); diff --git a/litmus-client/src/main/java/com/navi/medici/config/LitmusConfig.java b/litmus-client/src/main/java/com/navi/medici/config/LitmusConfig.java index d5088b9..af3e219 100644 --- a/litmus-client/src/main/java/com/navi/medici/config/LitmusConfig.java +++ b/litmus-client/src/main/java/com/navi/medici/config/LitmusConfig.java @@ -7,6 +7,7 @@ import com.navi.medici.scheduler.LitmusScheduledExecutor; import com.navi.medici.scheduler.LitmusScheduledExecutorImpl; import com.navi.medici.strategy.Strategy; import com.navi.medici.strategy.UnknownStrategy; +import com.navi.medici.util.LitmusProperties; import com.navi.medici.util.LitmusURLs; import io.micrometer.core.instrument.MeterRegistry; import java.io.File; @@ -15,6 +16,13 @@ import java.net.URI; import java.net.UnknownHostException; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + import lombok.Setter; public class LitmusConfig { @@ -41,7 +49,11 @@ public class LitmusConfig { private final String clickStreamAPI; private final String vertical; private final MeterRegistry meterRegistry; + private final ExecutorService executorService; + private final String litmusClientVersion; + + private final boolean enableClickStream; private LitmusConfig( URI litmusAPI, @@ -58,7 +70,10 @@ public class LitmusConfig { LitmusExperimentBootstrapProvider litmusBootstrapProvider, String clickStreamAPI, String vertical, - MeterRegistry meterRegistry) { + MeterRegistry meterRegistry, + ExecutorService executorService, + String litmusClientVersion, + boolean enableClickStream) { if (appName == null) { throw new IllegalStateException("You are required to specify the litmus appName"); @@ -88,6 +103,13 @@ public class LitmusConfig { throw new IllegalStateException("You are required to specify meter registry"); } + if (executorService == null) { + RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy(); + executorService = new ThreadPoolExecutor(20, 20, + 5000L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue(1000, true), handler); + } + this.fallbackStrategy = Objects.requireNonNullElseGet(fallbackStrategy, UnknownStrategy::new); @@ -106,6 +128,9 @@ public class LitmusConfig { this.clickStreamAPI = clickStreamAPI; this.vertical = vertical; this.meterRegistry = meterRegistry; + this.executorService = executorService; + this.litmusClientVersion = LitmusProperties.getProperty("litmus.client.version"); + this.enableClickStream = enableClickStream; } public static Builder builder() { @@ -125,6 +150,7 @@ public class LitmusConfig { return instanceId; } + //schedule periodic experiment poll interval in seconds public long getFetchLitmusExperimentsInterval() { return fetchLitmusExperimentsInterval; } @@ -177,6 +203,17 @@ public class LitmusConfig { return meterRegistry; } + public ExecutorService getExecutorService() { + return executorService; + } + + public String getLitmusClientVersion() { + return litmusClientVersion; + } + + public boolean isEnableClickStream() { + return enableClickStream; + } public static class Builder { private URI litmusAPI; @@ -195,6 +232,12 @@ public class LitmusConfig { private String vertical; private MeterRegistry meterRegistry; + private ExecutorService executorService; + + private String litmusClientVersion; + + private boolean enableClickStream; + private static String getHostname() { String hostName = System.getProperty("hostname"); if (hostName == null || hostName.length() == 0) { @@ -291,6 +334,20 @@ public class LitmusConfig { return this; } + public Builder executorService(ExecutorService executorService) { + this.executorService = executorService; + return this; + } + + public Builder getLitmusClient(String litmusClientVersion) { + this.litmusClientVersion = litmusClientVersion; + return this; + } + + public Builder enableClickStream(boolean enableClickStream) { + this.enableClickStream = enableClickStream; + return this; + } private String getBackupFile() { if (backupFile != null) { @@ -319,14 +376,10 @@ public class LitmusConfig { litmusExperimentBootstrapProvider, clickStreamAPI, vertical, - meterRegistry); - } - - public String getDefaultSdkVersion() { - String version = - Optional.ofNullable(getClass().getPackage().getImplementationVersion()) - .orElse("development"); - return "litmus-client:" + version; + meterRegistry, + executorService, + litmusClientVersion, + enableClickStream); } } } diff --git a/litmus-client/src/main/java/com/navi/medici/event/EventDispatcher.java b/litmus-client/src/main/java/com/navi/medici/event/EventDispatcher.java index 14cd6a1..bdacc87 100644 --- a/litmus-client/src/main/java/com/navi/medici/event/EventDispatcher.java +++ b/litmus-client/src/main/java/com/navi/medici/event/EventDispatcher.java @@ -22,8 +22,7 @@ public class EventDispatcher { private final LitmusConfig litmusConfig; public EventDispatcher(LitmusConfig litmusConfig) { - this.clickStreamClient = new ClickStreamClient(litmusConfig.getClickStreamAPI(), litmusConfig.getAppName(), - litmusConfig.getVertical(), litmusConfig.getMeterRegistry()); + this.clickStreamClient = new ClickStreamClient(litmusConfig); this.litmusConfig = litmusConfig; } @@ -56,14 +55,14 @@ public class EventDispatcher { clickStreamPayload.setClickStreamEvent(List.of(event)); clickStreamPayload.setSource("Litmus"); clickStreamPayload.setUser(User.builder() - .customerReferenceId(litmusContext.getUserId().orElse("")) + .customerReferenceId(litmusContext.getUserId() + .orElse("")) .build()); - CompletableFuture.supplyAsync(() -> { + CompletableFuture.runAsync(() -> { litmusConfig.getMeterRegistry().timer("litmus_client_click_stream_publish_latency") .record(() -> clickStreamClient.publish(litmusExperiment.getName(), clickStreamPayload)); - return null; - }); + }, litmusConfig.getExecutorService()); } } diff --git a/litmus-client/src/main/java/com/navi/medici/litmus/DefaultLitmus.java b/litmus-client/src/main/java/com/navi/medici/litmus/DefaultLitmus.java index b68a253..1cc8ea3 100644 --- a/litmus-client/src/main/java/com/navi/medici/litmus/DefaultLitmus.java +++ b/litmus-client/src/main/java/com/navi/medici/litmus/DefaultLitmus.java @@ -2,7 +2,6 @@ package com.navi.medici.litmus; import com.navi.medici.annotation.Nullable; -import com.navi.medici.client.ClickStreamClient; import com.navi.medici.client.ExperimentBackupHandlerFile; import com.navi.medici.client.HttpExperimentFetcher; import com.navi.medici.config.LitmusConfig; @@ -13,6 +12,7 @@ import com.navi.medici.provider.LitmusContextProvider; import com.navi.medici.repository.ExperimentRepository; import com.navi.medici.repository.LitmusExperimentRepository; import com.navi.medici.request.v1.LitmusExperiment; +import com.navi.medici.strategy.CustomParameterWithIdStrategy; import com.navi.medici.strategy.DefaultStrategy; import com.navi.medici.strategy.DeviceWithIdStrategy; import com.navi.medici.strategy.FlexibleRolloutStrategy; @@ -23,21 +23,16 @@ import com.navi.medici.strategy.UserWithIdStrategy; import com.navi.medici.util.VariantUtil; import com.navi.medici.variants.Variant; -import io.micrometer.core.instrument.Counter; - -import java.io.IOException; -import java.net.URLClassLoader; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; -import java.util.jar.Attributes; -import java.util.jar.Manifest; import lombok.extern.log4j.Log4j2; +import static com.navi.medici.util.MetricsUtils.counterMetrics; + @Log4j2 public class DefaultLitmus implements Litmus { @@ -53,8 +48,7 @@ public class DefaultLitmus implements Litmus { private static ExperimentRepository defaultExperimentRepository(LitmusConfig litmusConfig) { return new LitmusExperimentRepository( litmusConfig, - new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(), - litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry()), + new HttpExperimentFetcher(litmusConfig), new ExperimentBackupHandlerFile(litmusConfig)) { }; } @@ -146,8 +140,7 @@ public class DefaultLitmus implements Litmus { } } else { - enabled = - litmusExperiment.getStrategies().stream() + enabled = litmusExperiment.getStrategies().stream() .anyMatch( strategy -> { Strategy configuredStrategy = @@ -157,20 +150,23 @@ public class DefaultLitmus implements Litmus { experimentName, strategy.getName()); } - return configuredStrategy.isEnabled( - strategy.getParameters(), - context, - strategy.getConstraints()); + boolean result = configuredStrategy.isEnabled(strategy.getParameters(), + context, strategy.getConstraints()); + log.debug("experiment_name: {}, strategy: {}, result: {}", + litmusExperiment.getName(), configuredStrategy.getName(), result); + return result; }); } - Counter.builder("litmus_client_experiment_check_enabled") + counterMetrics(config, "litmus_client_experiment_check_enabled") .tag("experiment_name", experimentName) .tag("result", String.valueOf(enabled)) .register(this.config.getMeterRegistry()) .increment(); - this.eventDispatcher.publish(context, litmusExperiment, enabled, null); + if (config.isEnableClickStream()) { + this.eventDispatcher.publish(context, litmusExperiment, enabled, null); + } log.info("experiment_name: {}, result: {}", experimentName, enabled); return enabled; @@ -183,14 +179,13 @@ public class DefaultLitmus implements Litmus { Arrays.asList( new DefaultStrategy(), - new UserWithIdStrategy(new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(), - litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry())), + new UserWithIdStrategy(new HttpExperimentFetcher(litmusConfig)), - new DeviceWithIdStrategy(new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(), - litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry())), + new DeviceWithIdStrategy(new HttpExperimentFetcher(litmusConfig)), - new PhoneNumberStrategy(new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(), - litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry())), + new PhoneNumberStrategy(new HttpExperimentFetcher(litmusConfig)), + + new CustomParameterWithIdStrategy(new HttpExperimentFetcher(litmusConfig)), new FlexibleRolloutStrategy()); @@ -228,10 +223,13 @@ public class DefaultLitmus implements Litmus { ? VariantUtil.selectVariant(litmusExperiment, context, defaultValue) : defaultValue; - this.eventDispatcher.publish(context, litmusExperiment, enabled, variant); + if (config.isEnableClickStream()) { + this.eventDispatcher.publish(context, litmusExperiment, enabled, variant); + } + log.info("experiment_name: {}, result: {}", experimentName, variant.toString()); - Counter.builder("litmus_client_experiment_variant") + counterMetrics(config, "litmus_client_experiment_variant") .tag("experiment_name", experimentName) .tag("result", String.valueOf(enabled)) .tag("variant", variant.getName()) @@ -257,13 +255,9 @@ public class DefaultLitmus implements Litmus { * Emit litmus version to prometheus to track litmus-client version used by services */ private void trackVersion(LitmusConfig litmusConfig) { - Counter.builder("litmus_client_version") - .tag("vertical", litmusConfig.getVertical()) - .tag("app_name", litmusConfig.getAppName()) - .tag("version", "2.0.5-RELEASE") + counterMetrics(config, "litmus_client_version") .register(litmusConfig.getMeterRegistry()) .increment(); - } } diff --git a/litmus-client/src/main/java/com/navi/medici/strategy/CustomParameterWithIdStrategy.java b/litmus-client/src/main/java/com/navi/medici/strategy/CustomParameterWithIdStrategy.java new file mode 100644 index 0000000..4f2bf06 --- /dev/null +++ b/litmus-client/src/main/java/com/navi/medici/strategy/CustomParameterWithIdStrategy.java @@ -0,0 +1,66 @@ +package com.navi.medici.strategy; + +import com.navi.medici.client.HttpExperimentFetcher; +import com.navi.medici.context.LitmusContext; +import com.navi.medici.util.StrategyUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.Map; +import java.util.Optional; + +import static com.navi.medici.strategy.FlexibleRolloutStrategy.GROUP_ID; +import static com.navi.medici.strategy.FlexibleRolloutStrategy.PERCENTAGE; + +public class CustomParameterWithIdStrategy implements Strategy { + private static final String STRATEGY_NAME = "customWithId"; + + private static final String SEGMENT = "segment"; + + private static final String CUSTOM_PARAMETER_NAME = "customParameter"; + + private final HttpExperimentFetcher experimentFetcher; + + public CustomParameterWithIdStrategy(HttpExperimentFetcher experimentFetcher) { + this.experimentFetcher = experimentFetcher; + } + + + @Override + public String getName() { + return STRATEGY_NAME; + } + + @Override + public boolean isEnabled(Map parameters) { + return false; + } + + @Override + public boolean isEnabled(Map parameters, LitmusContext litmusContext) { + if (StringUtils.isBlank(parameters.get(PERCENTAGE))) { + return customWithIdSegmentCheck(parameters, litmusContext); + } else { + return segmentCheckWithRollout(parameters, litmusContext); + } + } + + private boolean customWithIdSegmentCheck(Map parameters, LitmusContext litmusContext) { + var customParameterId = litmusContext.getProperties().get(CUSTOM_PARAMETER_NAME); + var segmentName = parameters.get(SEGMENT); + var result = experimentFetcher.segmentIdExists(segmentName, customParameterId); + + return result.getData() != null && (Boolean) result.getData(); + } + + private boolean segmentCheckWithRollout(Map parameters, LitmusContext litmusContext) { + var customParameterId = litmusContext.getProperties().get(CUSTOM_PARAMETER_NAME); + var percentage = StrategyUtils.getPercentage(parameters.get(PERCENTAGE)); + var groupId = parameters.getOrDefault(GROUP_ID, ""); + + var norm = StrategyUtils.getNormalizedNumber(customParameterId, groupId); + + return Optional.of(customWithIdSegmentCheck(parameters, litmusContext)) + .map(r -> r && percentage > 0 && norm <= percentage) + .orElse(false); + } +} diff --git a/litmus-client/src/main/java/com/navi/medici/strategy/PhoneNumberStrategy.java b/litmus-client/src/main/java/com/navi/medici/strategy/PhoneNumberStrategy.java index 1754471..3444c6d 100644 --- a/litmus-client/src/main/java/com/navi/medici/strategy/PhoneNumberStrategy.java +++ b/litmus-client/src/main/java/com/navi/medici/strategy/PhoneNumberStrategy.java @@ -41,19 +41,19 @@ public class PhoneNumberStrategy implements Strategy { } private boolean phoneNumberSegmentCheck(Map parameters, LitmusContext litmusContext) { - var userId = litmusContext.getUserId().orElse(null); + var phoneNumber = litmusContext.getPhoneNumber().orElse(null); var segmentName = parameters.get(SEGMENT); - var result = experimentFetcher.segmentIdExists(segmentName, userId); + var result = experimentFetcher.segmentIdExists(segmentName, phoneNumber); return result.getData() != null && (Boolean) result.getData(); } private boolean segmentCheckWithRollout(Map parameters, LitmusContext litmusContext) { - var userId = litmusContext.getUserId().orElse(null); + var phoneNumber = litmusContext.getPhoneNumber().orElse(null); var percentage = StrategyUtils.getPercentage(parameters.get(PERCENTAGE)); var groupId = parameters.getOrDefault(GROUP_ID, ""); - var norm = StrategyUtils.getNormalizedNumber(userId, groupId); + var norm = StrategyUtils.getNormalizedNumber(phoneNumber, groupId); return Optional.of(phoneNumberSegmentCheck(parameters, litmusContext)) .map(r -> r && percentage > 0 && norm <= percentage) diff --git a/litmus-client/src/main/java/com/navi/medici/util/LitmusProperties.java b/litmus-client/src/main/java/com/navi/medici/util/LitmusProperties.java new file mode 100644 index 0000000..aac31cb --- /dev/null +++ b/litmus-client/src/main/java/com/navi/medici/util/LitmusProperties.java @@ -0,0 +1,23 @@ +package com.navi.medici.util; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public class LitmusProperties { + static Properties appProperties; + + static { + try (InputStream is = LitmusProperties.class.getClassLoader().getResourceAsStream("app.properties")) { + appProperties = new Properties(); + appProperties.load(is); + } catch (IOException ioException) { + appProperties = new Properties(); + appProperties.setProperty("litmus.client.version", "0.0.0-default"); + } + } + + public static String getProperty(String propName) { + return appProperties.getProperty(propName); + } +} diff --git a/litmus-client/src/main/java/com/navi/medici/util/MetricsUtils.java b/litmus-client/src/main/java/com/navi/medici/util/MetricsUtils.java new file mode 100644 index 0000000..4049ab7 --- /dev/null +++ b/litmus-client/src/main/java/com/navi/medici/util/MetricsUtils.java @@ -0,0 +1,13 @@ +package com.navi.medici.util; + +import com.navi.medici.config.LitmusConfig; +import io.micrometer.core.instrument.Counter; + +public class MetricsUtils { + public static Counter.Builder counterMetrics(LitmusConfig litmusConfig, String name) { + return Counter.builder(name) + .tag("vertical", litmusConfig.getVertical()) + .tag("app_name", litmusConfig.getAppName()) + .tag("litmus_client_version", litmusConfig.getLitmusClientVersion()); + } +} diff --git a/litmus-client/src/main/resources/META-INF/LITMUS-CLIENT.MF b/litmus-client/src/main/resources/META-INF/LITMUS-CLIENT.MF deleted file mode 100644 index 3a41cea..0000000 --- a/litmus-client/src/main/resources/META-INF/LITMUS-CLIENT.MF +++ /dev/null @@ -1 +0,0 @@ -Implementation-Version: 2.0.5-RELEASE diff --git a/litmus-client/src/main/resources/app.properties b/litmus-client/src/main/resources/app.properties new file mode 100644 index 0000000..6907184 --- /dev/null +++ b/litmus-client/src/main/resources/app.properties @@ -0,0 +1 @@ +litmus.client.version=2.0.6-RELEASE \ No newline at end of file diff --git a/litmus-client/src/test/java/com/navi/medici/client/ClickStreamClientTest.java b/litmus-client/src/test/java/com/navi/medici/client/ClickStreamClientTest.java index 4389b55..051a26f 100644 --- a/litmus-client/src/test/java/com/navi/medici/client/ClickStreamClientTest.java +++ b/litmus-client/src/test/java/com/navi/medici/client/ClickStreamClientTest.java @@ -53,8 +53,7 @@ public class ClickStreamClientTest extends WireMockRules { .build(); var clickStreamPayload = clickStreamPayload(); - client = new ClickStreamClient(litmusConfig.getClickStreamAPI(), litmusConfig.getAppName(), - litmusConfig.getVertical(), litmusConfig.getMeterRegistry()); + client = new ClickStreamClient(litmusConfig); wireMockRule.stubFor(post("/events/json").withRequestBody(equalToJson(new ObjectMapper().writeValueAsString(clickStreamPayload))) .willReturn(aResponse() @@ -74,8 +73,7 @@ public class ClickStreamClientTest extends WireMockRules { .build(); var clickStreamPayload = clickStreamPayload(); - client = new ClickStreamClient(litmusConfig.getClickStreamAPI(), litmusConfig.getAppName(), - litmusConfig.getVertical(), litmusConfig.getMeterRegistry()); + client = new ClickStreamClient(litmusConfig); wireMockRule.stubFor(post("/events/json").withRequestBody(equalToJson(new ObjectMapper().writeValueAsString(clickStreamPayload))) .willReturn(aResponse() diff --git a/litmus-client/src/test/java/com/navi/medici/client/HttpExperimentFetcherTest.java b/litmus-client/src/test/java/com/navi/medici/client/HttpExperimentFetcherTest.java index 16d51d4..197d945 100644 --- a/litmus-client/src/test/java/com/navi/medici/client/HttpExperimentFetcherTest.java +++ b/litmus-client/src/test/java/com/navi/medici/client/HttpExperimentFetcherTest.java @@ -35,15 +35,14 @@ public class HttpExperimentFetcherTest extends WireMockRules { File file = new File(getClass().getClassLoader().getResource("unleash-repo-v1.json").toURI()); String response = TestUtils.fileToString(file); - wireMockRule.stubFor(get( "/litmus-core/v1/experiments?vertical=test-experiment&polling_time=20") + wireMockRule.stubFor(get( "/litmus-core/v1/experiments/vertical?vertical=test-experiment&polling_time=20") .willReturn(aResponse() .withHeader("Content-Type", "application/json") .withStatus(200) .withBody(response))); - httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(), - litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry()); + httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig); var litmusResponse = httpExperimentFetcher.fetchExperiments("test-experiment", 20L ); assertEquals(litmusResponse.getExperimentCollection().getLitmusExperiments().size(), 3); @@ -61,13 +60,12 @@ public class HttpExperimentFetcherTest extends WireMockRules { .litmusAPI("http://localhost:" + wireMockRule.port() + "/litmus-core/v1") .build(); - stubFor(get("/litmus-core/v1/experiments?vertical=test-experiment&polling_time=20") + stubFor(get("/litmus-core/v1/experiments/vertical?vertical=test-experiment&polling_time=20") .willReturn(aResponse() .withHeader("Content-Type", "application/json") .withStatus(304))); - httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(), - litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry()); + httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig); var litmusResponse = httpExperimentFetcher.fetchExperiments("test-experiment", 20L ); assertEquals(litmusResponse.getExperimentCollection().getLitmusExperiments().size(), 0); @@ -85,18 +83,17 @@ public class HttpExperimentFetcherTest extends WireMockRules { .litmusAPI("http://localhost:" + wireMockRule.port() + "/litmus-core/v1") .build(); - stubFor(get("/litmus-core/v1/experiments?vertical=test-experiment&polling_time=20") + stubFor(get("/litmus-core/v1/experiments/vertical?vertical=test-experiment&polling_time=20") .willReturn(aResponse() .withHeader("Content-Type", "application/json") .withStatus(500))); - httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(), - litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry()); + httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig); var litmusResponse = httpExperimentFetcher.fetchExperiments("test-experiment", 20L ); assertEquals(litmusResponse.getExperimentCollection().getLitmusExperiments().size(), 0); - assertEquals(litmusResponse.getHttpStatusCode(), 500); - assertEquals(litmusResponse.getStatus(), Status.UNAVAILABLE); + assertEquals(500, litmusResponse.getHttpStatusCode()); + assertEquals(Status.UNAVAILABLE, litmusResponse.getStatus()); } @Test @@ -120,8 +117,7 @@ public class HttpExperimentFetcherTest extends WireMockRules { .withStatus(200) .withBody(response))); - httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(), - litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry()); + httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig); var result = httpExperimentFetcher.segmentIdExists(segmentName, id); assertTrue(result.getData()); @@ -144,8 +140,7 @@ public class HttpExperimentFetcherTest extends WireMockRules { .willReturn(aResponse() .withStatus(200))); - httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(), - litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry()); + httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig); Exception e = assertThrows(LitmusException.class, () -> httpExperimentFetcher.segmentIdExists(segmentName, id) diff --git a/litmus-client/src/test/java/com/navi/medici/event/EventDispatcherTest.java b/litmus-client/src/test/java/com/navi/medici/event/EventDispatcherTest.java index b961199..44fa41a 100644 --- a/litmus-client/src/test/java/com/navi/medici/event/EventDispatcherTest.java +++ b/litmus-client/src/test/java/com/navi/medici/event/EventDispatcherTest.java @@ -15,6 +15,8 @@ import com.navi.medici.context.LitmusContext; import com.navi.medici.enums.ExperimentType; import com.navi.medici.request.v1.LitmusExperiment; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executors; + import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -36,6 +38,7 @@ public class EventDispatcherTest { @Test public void testEventDispatchWithoutClickStreamPayload() { + when(litmusConfig.getExecutorService()).thenReturn(Executors.newFixedThreadPool(1)); LitmusContext litmusContext = LitmusContext.builder() .appName("test-app") .userId("test-user-id") @@ -58,7 +61,7 @@ public class EventDispatcherTest { @Test public void testEventDispatchWithClickStreamPayload() { - + when(litmusConfig.getExecutorService()).thenReturn(Executors.newFixedThreadPool(1)); LitmusContext litmusContext = buildLitmusContext(); LitmusExperiment litmusExperiment = LitmusExperiment.builder() diff --git a/litmus-client/src/test/java/com/navi/medici/litmus/DefaultLitmusTest.java b/litmus-client/src/test/java/com/navi/medici/litmus/DefaultLitmusTest.java index d1382cc..6a6296d 100644 --- a/litmus-client/src/test/java/com/navi/medici/litmus/DefaultLitmusTest.java +++ b/litmus-client/src/test/java/com/navi/medici/litmus/DefaultLitmusTest.java @@ -3,8 +3,12 @@ package com.navi.medici.litmus; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import com.navi.medici.context.LitmusContext; @@ -71,7 +75,7 @@ public class DefaultLitmusTest { .deviceId("test-device-id") .build()); var result = litmus.isEnabled("experiment-1"); - assertTrue(result); + assertFalse(result); } @Test @@ -156,6 +160,8 @@ public class DefaultLitmusTest { public void testExperimentPresentWithStrategy100RolloutVariant() { var litmusConfigBuilder = TestUtils.buildLitmusConfig(); litmusConfigBuilder.litmusContextProvider(litmusContextProvider); + litmusConfigBuilder.enableClickStream(true); + litmus = new DefaultLitmus(litmusConfigBuilder.build(), litmusExperimentRepository); when(litmusExperimentRepository.getLitmusExperiment(anyString())).thenReturn(LitmusExperiment.builder() @@ -184,4 +190,38 @@ public class DefaultLitmusTest { assertTrue(result.isEnabled()); assertEquals(result.getName(), "variant-1"); } + + @Test + public void testClickStreamKillSwitch() { + var litmusConfigBuilder = TestUtils.buildLitmusConfig(); + litmusConfigBuilder.litmusContextProvider(litmusContextProvider); + litmus = new DefaultLitmus(litmusConfigBuilder.build(), litmusExperimentRepository); + + when(litmusExperimentRepository.getLitmusExperiment(anyString())).thenReturn(LitmusExperiment.builder() + .name("experiment-1") + .enabled(Boolean.TRUE) + .vertical("PL") + .experimentId("test-experiment-id") + .type(ExperimentType.EXPERIMENT) + .strategies(List.of(ActivationStrategy.builder() + .name("flexibleRollout") + .parameters(Map.of("rollout", "100", "stickiness", "userId", "groupId", "test-group-id")) + .build())) + .variants(List.of(VariantDefinition.builder() + .name("variant-1") + .weight(100) + .stickiness("userId") + .overrides(List.of()) + .build())) + .build()); + + when(litmusContextProvider.getContext()).thenReturn(LitmusContext.builder() + .userId("test-user-id") + .deviceId("test-device-id") + .build()); + var result = litmus.getVariant("experiment-1"); + assertTrue(result.isEnabled()); + assertEquals(result.getName(), "variant-1"); + verify(eventDispatcher, times(0)).publish(any(), any(), any(), any()); + } } \ No newline at end of file diff --git a/litmus-client/src/test/java/com/navi/medici/repository/LitmusExperimentRepositoryTest.java b/litmus-client/src/test/java/com/navi/medici/repository/LitmusExperimentRepositoryTest.java index 8bf0ec2..63a81f3 100644 --- a/litmus-client/src/test/java/com/navi/medici/repository/LitmusExperimentRepositoryTest.java +++ b/litmus-client/src/test/java/com/navi/medici/repository/LitmusExperimentRepositoryTest.java @@ -46,8 +46,7 @@ public class LitmusExperimentRepositoryTest { public void noBackUpAndNoRepositoryAvailable() { LitmusConfig litmusConfig = TestUtils.buildLitmusConfig().build(); - ExperimentFetcher experimentFetcher = new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(), - litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry()); + ExperimentFetcher experimentFetcher = new HttpExperimentFetcher(litmusConfig); ExperimentBackupHandler experimentBackupHandler = new ExperimentBackupHandlerFile(litmusConfig); LitmusExperimentRepository litmusExperimentRepository = new LitmusExperimentRepository(litmusConfig, experimentFetcher, experimentBackupHandler); @@ -63,8 +62,7 @@ public class LitmusExperimentRepositoryTest { ExperimentBackupHandler experimentBackupHandler = mock(ExperimentBackupHandlerFile.class); when(experimentBackupHandler.read()).thenReturn(new LitmusExperimentCollection(Collections.emptyList(), 1)); - ExperimentFetcher experimentFetcher = new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(), - litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry()); + ExperimentFetcher experimentFetcher = new HttpExperimentFetcher(litmusConfig); LitmusScheduledExecutor litmusScheduledExecutor = mock(LitmusScheduledExecutor.class); @@ -141,12 +139,12 @@ public class LitmusExperimentRepositoryTest { LitmusExperimentRepository experimentRepository = new LitmusExperimentRepository(config, executor, experimentFetcher, experimentBackupHandler); verify(executor).setInterval(runnableArgumentCaptor.capture(), anyLong(), anyLong()); - verify(experimentFetcher, times(0)).fetchExperiments(anyString(), anyLong()); + verify(experimentFetcher, times(1)).fetchExperiments(anyString(), anyLong()); runnableArgumentCaptor.getValue().run(); verify(experimentBackupHandler, times(1)).read(); - verify(experimentFetcher, times(1)).fetchExperiments(anyString(), anyLong()); + verify(experimentFetcher, times(2)).fetchExperiments(anyString(), anyLong()); assertTrue(experimentRepository.getLitmusExperiment("experiment-name1").isEnabled()); } diff --git a/litmus-client/src/test/java/com/navi/medici/strategy/DeviceWithIdStrategyTest.java b/litmus-client/src/test/java/com/navi/medici/strategy/DeviceWithIdStrategyTest.java index 9096284..cf38dbb 100644 --- a/litmus-client/src/test/java/com/navi/medici/strategy/DeviceWithIdStrategyTest.java +++ b/litmus-client/src/test/java/com/navi/medici/strategy/DeviceWithIdStrategyTest.java @@ -21,10 +21,15 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class DeviceWithIdStrategyTest { + + @Spy + ObjectMapper objectMapper; + @Mock HttpExperimentFetcher httpExperimentFetcher; @@ -39,7 +44,7 @@ public class DeviceWithIdStrategyTest { @Test public void testWithoutContext() throws Exception { String parameters = " {\"groupId\": \"new-home-page-group-id\", \"rollout\": \"100\", \"segment\": \"test-segment\"}"; - HashMap params = new ObjectMapper().readValue(parameters, HashMap.class); + HashMap params = objectMapper.readValue(parameters, HashMap.class); assertFalse(deviceWithIdStrategy.isEnabled(params)); } @@ -47,7 +52,7 @@ public class DeviceWithIdStrategyTest { @Test public void testStrategyWithRollout() throws Exception { String parameters = " {\"groupId\": \"new-home-page-group-id\", \"rollout\": \"100\", \"segment\": \"test-segment\"}"; - HashMap params = new ObjectMapper().readValue(parameters, HashMap.class); + HashMap params = objectMapper.readValue(parameters, HashMap.class); var context = TestUtils.buildLitmusContext(); when(httpExperimentFetcher.segmentIdExists(anyString(), anyString())) @@ -60,7 +65,7 @@ public class DeviceWithIdStrategyTest { @Test public void testStrategyWithoutRollout() throws Exception { String parameters = " {\"groupId\": \"new-home-page-group-id\", \"segment\": \"test-segment\"}"; - HashMap params = new ObjectMapper().readValue(parameters, HashMap.class); + HashMap params = objectMapper.readValue(parameters, HashMap.class); var context = TestUtils.buildLitmusContext(); when(httpExperimentFetcher.segmentIdExists(anyString(), anyString())) diff --git a/litmus-client/src/test/java/com/navi/medici/utils/TestUtils.java b/litmus-client/src/test/java/com/navi/medici/utils/TestUtils.java index 2a3934e..8d65987 100644 --- a/litmus-client/src/test/java/com/navi/medici/utils/TestUtils.java +++ b/litmus-client/src/test/java/com/navi/medici/utils/TestUtils.java @@ -15,7 +15,8 @@ public class TestUtils { .clickStreamAPI("http://localhost") .vertical("PL") .appName("test-app") - .litmusAPI("http://localhost:8080/litmus-core/v1"); + .litmusAPI("http://localhost:8080/litmus-core/v1") + .synchronousFetchOnInitialisation(true); } public static LitmusContext buildLitmusContext() { diff --git a/litmus-core/pom.xml b/litmus-core/pom.xml index 4888f08..22644b2 100644 --- a/litmus-core/pom.xml +++ b/litmus-core/pom.xml @@ -5,11 +5,11 @@ litmus com.navi.medici - 2.0.5-RELEASE + 2.0.6-RELEASE litmus-core - 2.0.5-RELEASE + 2.0.6-RELEASE jar litmus-core @@ -31,25 +31,25 @@ com.navi.medici litmus-model - 2.0.5-RELEASE + 2.0.6-RELEASE com.navi.medici litmus-db - 2.0.5-RELEASE + 2.0.6-RELEASE com.navi.medici litmus-cache - 2.0.5-RELEASE + 2.0.6-RELEASE com.navi.medici litmus-util - 2.0.5-RELEASE + 2.0.6-RELEASE diff --git a/litmus-core/src/main/java/com/navi/medici/controller/v1/ExperimentController.java b/litmus-core/src/main/java/com/navi/medici/controller/v1/ExperimentController.java index 91fd008..48eb983 100644 --- a/litmus-core/src/main/java/com/navi/medici/controller/v1/ExperimentController.java +++ b/litmus-core/src/main/java/com/navi/medici/controller/v1/ExperimentController.java @@ -1,6 +1,5 @@ package com.navi.medici.controller.v1; -import com.navi.medici.entity.ExperimentEntity; import com.navi.medici.request.v1.LitmusExperiment; import com.navi.medici.request.v1.LitmusExperimentStrategyUpdate; import com.navi.medici.request.v1.VerticalUpdateRequest; diff --git a/litmus-db/pom.xml b/litmus-db/pom.xml index 0ca6445..82a8aa3 100644 --- a/litmus-db/pom.xml +++ b/litmus-db/pom.xml @@ -4,11 +4,11 @@ litmus com.navi.medici - 2.0.5-RELEASE + 2.0.6-RELEASE litmus-db - 2.0.5-RELEASE + 2.0.6-RELEASE jar litmus-db @@ -27,7 +27,7 @@ com.navi.medici litmus-model - 2.0.5-RELEASE + 2.0.6-RELEASE diff --git a/litmus-liquibase/pom.xml b/litmus-liquibase/pom.xml index 7ad59f9..82bd2aa 100644 --- a/litmus-liquibase/pom.xml +++ b/litmus-liquibase/pom.xml @@ -4,11 +4,11 @@ litmus com.navi.medici - 2.0.5-RELEASE + 2.0.6-RELEASE litmus-liquibase - 2.0.5-RELEASE + 2.0.6-RELEASE jar litmus-liquibase diff --git a/litmus-mock/pom.xml b/litmus-mock/pom.xml index 5da41b7..fabc50d 100644 --- a/litmus-mock/pom.xml +++ b/litmus-mock/pom.xml @@ -4,11 +4,11 @@ litmus com.navi.medici - 2.0.5-RELEASE + 2.0.6-RELEASE litmus-mock - 2.0.5-RELEASE + 2.0.6-RELEASE jar litmus-mock @@ -16,13 +16,13 @@ com.navi.medici litmus-model - 2.0.5-RELEASE + 2.0.6-RELEASE com.navi.medici litmus-client - 2.0.5-RELEASE + 2.0.6-RELEASE diff --git a/litmus-mock/src/main/java/com/navi/medici/container/CustomLitmusContextProvider.java b/litmus-mock/src/main/java/com/navi/medici/container/CustomLitmusContextProvider.java index 2863875..4e4648b 100644 --- a/litmus-mock/src/main/java/com/navi/medici/container/CustomLitmusContextProvider.java +++ b/litmus-mock/src/main/java/com/navi/medici/container/CustomLitmusContextProvider.java @@ -15,9 +15,9 @@ public class CustomLitmusContextProvider implements LitmusContextProvider { @Override public LitmusContext getContext() { return LitmusContext.builder() - .userId(new Random().nextInt() + "") - .deviceId(new Random().nextInt() + "") - .clickStreamPayload("{\"app\":{\"name\":\"NaviDebug\",\"version\":\"77\",\"version_name\":\"1.9.3-cug-1-debug\"},\"client_ts\":\"1633768839907\",\"device\":{\"advertising_id\":\"8835d2b0-5615-412e-b133-8f8dc28e228e\",\"device_id\":\"9a14136215e76324\",\"manufacturer\":\"vivo\",\"model\":\"V2040\",\"os\":\"Android\",\"os_version\":\"30\"},\"events\":[{\"event_name\":\"splash\",\"timestamp\":1633768835058},{\"event_name\":\"home_activity\",\"timestamp\":1633768839791},{\"event_name\":\"home\",\"timestamp\":1633768839860},{\"event_name\":\"full_page_loader_shown\",\"timestamp\":1633768839868}],\"location\":{\"latitude\":\"null\",\"longitude\":\"null\"},\"network\":{\"carrier\":\"\",\"type\":\"Wifi\"},\"source\":\"SyncTimer\",\"user\":{}}") + .addProperty("loanOfferReferenceId", "873a0877-51a7-4acf-96f6-66eb6ac80652") +// .deviceId(new Random().nextInt() + "") +// .clickStreamPayload("{\"app\":{\"name\":\"NaviDebug\",\"version\":\"77\",\"version_name\":\"1.9.3-cug-1-debug\"},\"client_ts\":\"1633768839907\",\"device\":{\"advertising_id\":\"8835d2b0-5615-412e-b133-8f8dc28e228e\",\"device_id\":\"9a14136215e76324\",\"manufacturer\":\"vivo\",\"model\":\"V2040\",\"os\":\"Android\",\"os_version\":\"30\"},\"events\":[{\"event_name\":\"splash\",\"timestamp\":1633768835058},{\"event_name\":\"home_activity\",\"timestamp\":1633768839791},{\"event_name\":\"home\",\"timestamp\":1633768839860},{\"event_name\":\"full_page_loader_shown\",\"timestamp\":1633768839868}],\"location\":{\"latitude\":\"null\",\"longitude\":\"null\"},\"network\":{\"carrier\":\"\",\"type\":\"Wifi\"},\"source\":\"SyncTimer\",\"user\":{}}") .build(); } } \ No newline at end of file diff --git a/litmus-mock/src/main/java/com/navi/medici/container/MockContainer.java b/litmus-mock/src/main/java/com/navi/medici/container/MockContainer.java index 72f3a6c..c3b728f 100644 --- a/litmus-mock/src/main/java/com/navi/medici/container/MockContainer.java +++ b/litmus-mock/src/main/java/com/navi/medici/container/MockContainer.java @@ -18,7 +18,7 @@ public class MockContainer { .instanceId("test-instance") .litmusContextProvider(new CustomLitmusContextProvider()) .clickStreamAPI("https://dev-janus.np.navi-tech.in/events/json") - .vertical("PL") + .vertical("SA") .meterRegistry(meterRegistry) .synchronousFetchOnInitialisation(true) .build(); diff --git a/litmus-model/pom.xml b/litmus-model/pom.xml index 875d8c4..9091c36 100644 --- a/litmus-model/pom.xml +++ b/litmus-model/pom.xml @@ -5,11 +5,11 @@ litmus com.navi.medici - 2.0.5-RELEASE + 2.0.6-RELEASE litmus-model - 2.0.5-RELEASE + 2.0.6-RELEASE jar litmus-model diff --git a/litmus-proxy/pom.xml b/litmus-proxy/pom.xml index bb1da7a..5b111f0 100644 --- a/litmus-proxy/pom.xml +++ b/litmus-proxy/pom.xml @@ -4,11 +4,11 @@ litmus com.navi.medici - 2.0.5-RELEASE + 2.0.6-RELEASE litmus-proxy - 2.0.5-RELEASE + 2.0.6-RELEASE jar litmus-proxy @@ -17,19 +17,19 @@ com.navi.medici litmus-model - 2.0.5-RELEASE + 2.0.6-RELEASE com.navi.medici litmus-client - 2.0.5-RELEASE + 2.0.6-RELEASE com.navi.medici litmus-util - 2.0.5-RELEASE + 2.0.6-RELEASE diff --git a/litmus-util/pom.xml b/litmus-util/pom.xml index fe790ef..b03018f 100644 --- a/litmus-util/pom.xml +++ b/litmus-util/pom.xml @@ -4,11 +4,11 @@ litmus com.navi.medici - 2.0.5-RELEASE + 2.0.6-RELEASE litmus-util - 2.0.5-RELEASE + 2.0.6-RELEASE litmus-util diff --git a/pom.xml b/pom.xml index de8c0a9..85c70c9 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.navi.medici litmus - 2.0.5-RELEASE + 2.0.6-RELEASE pom litmus