reverting litmus client to java 11

Signed-off-by: chandresh pancholi <chandresh.pancholi@navi.com>
This commit is contained in:
chandresh pancholi
2021-11-13 03:01:57 +05:30
parent 0327b33038
commit 1cf5f4972e
6 changed files with 141 additions and 117 deletions

4
.gitignore vendored
View File

@@ -28,4 +28,6 @@ litmus-proxy/target
litmus-util/litmus-util.iml litmus-util/litmus-util.iml
litmus-util/target litmus-util/target
target target
log
.descriptions.json

View File

@@ -33,17 +33,25 @@ public class FlexibleRolloutStrategy implements Strategy {
} }
private Optional<String> resolveStickiness(String stickiness, LitmusContext context) { private Optional<String> resolveStickiness(String stickiness, LitmusContext context) {
return switch (stickiness) { switch (stickiness) {
case "userId" -> context.getUserId(); case "userId":
case "sessionId" -> context.getSessionId(); return context.getUserId();
case "deviceId" -> context.getDeviceId(); case "sessionId":
case "appVersionCode" -> context.getAppVersionCode(); return context.getSessionId();
case "osType" -> context.getOsType(); case "deviceId":
case "random" -> Optional.of(randomGenerator.get()); return context.getDeviceId();
case "default" -> Optional.of(context.getUserId() case "appVersionCode":
.orElse(context.getSessionId().orElse(this.randomGenerator.get()))); return context.getAppVersionCode();
default -> context.getByName(stickiness); case "osType":
}; return context.getOsType();
case "random":
return Optional.of(randomGenerator.get());
case "default":
return Optional.of(context.getUserId()
.orElse(context.getSessionId().orElse(this.randomGenerator.get())));
default:
return context.getByName(stickiness);
}
} }
@Override @Override

View File

@@ -12,104 +12,119 @@ import java.util.function.Predicate;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
public final class VariantUtil { public final class VariantUtil {
private VariantUtil() {}
private static Predicate<VariantOverride> overrideMatchesContext(LitmusContext context) { private VariantUtil() {
return (override) -> { }
Optional<String> contextValue;
switch (override.getContextName()) {
case "userId" -> contextValue = context.getUserId();
case "sessionId" -> contextValue = context.getSessionId();
case "remoteAddress" -> contextValue = context.getRemoteAddress();
case "appVersionCode" -> contextValue = context.getAppVersionCode();
case "osType" -> contextValue = context.getOsType();
case "deviceId" -> contextValue = context.getDeviceId();
default -> contextValue = Optional.ofNullable(context.getProperties().get(override.getContextName()));
}
return override.getValues().contains(contextValue.orElse(""));
};
}
private static Optional<VariantDefinition> getOverride( private static Predicate<VariantOverride> overrideMatchesContext(LitmusContext context) {
List<VariantDefinition> variants, LitmusContext context) { return (override) -> {
return variants.stream() Optional<String> contextValue;
.filter( switch (override.getContextName()) {
variant -> case "userId":
variant.getOverrides().stream() contextValue = context.getUserId();
.anyMatch(overrideMatchesContext(context))) break;
.findFirst(); case "sessionId":
} contextValue = context.getSessionId();
break;
private static String getIdentifier(LitmusContext context) { case "remoteAddress":
return context.getUserId() contextValue = context.getRemoteAddress();
.orElse( break;
context.getSessionId() case "appVersionCode":
.orElse( contextValue = context.getAppVersionCode();
context.getRemoteAddress() break;
.orElse(context.getAppVersionCode() case "osType":
.orElse(context.getOsType() contextValue = context.getOsType();
.orElse(context.getDeviceId() break;
.orElse(Double.toString(Math.random()))))) case "deviceId":
)); contextValue = context.getDeviceId();
} break;
default:
private static String randomString() { contextValue = Optional.ofNullable(context.getProperties().get(override.getContextName()));
int randSeed = new Random().nextInt(100000);
return "" + randSeed;
}
private static String getSeed(LitmusContext litmusContext, Optional<String> stickiness) {
return stickiness
.map(s -> litmusContext.getByName(s).orElse(randomString()))
.orElse(getIdentifier(litmusContext));
}
public static Variant selectVariant(LitmusExperiment litmusExperiment, LitmusContext context, Variant defaultVariant) {
if (litmusExperiment == null || StringUtils.isBlank(litmusExperiment.getVariants())) {
return defaultVariant;
}
List<VariantDefinition> variants = JacksonUtils.stringToListObject(litmusExperiment.getVariants(), VariantDefinition.class);
int totalWeight = variants.stream().mapToInt(VariantDefinition::getWeight).sum();
if (totalWeight == 0) {
return defaultVariant;
} }
return override.getValues().contains(contextValue.orElse(""));
};
}
Optional<VariantDefinition> variantOverride = getOverride(variants, context); private static Optional<VariantDefinition> getOverride(
if (variantOverride.isPresent()) { List<VariantDefinition> variants, LitmusContext context) {
var variantDefinition = variantOverride.get(); return variants.stream()
return Variant.builder() .filter(
.name(variantDefinition.getName()) variant ->
.payload(variantDefinition.getPayload()) variant.getOverrides().stream()
.enabled(true) .anyMatch(overrideMatchesContext(context)))
.stickiness(variantDefinition.getStickiness()) .findFirst();
.build(); }
}
Optional<String> customStickiness =
variants.stream()
.filter(f -> f.getStickiness() != null)
.map(VariantDefinition::getStickiness)
.findFirst();
int target =
StrategyUtils.getNormalizedNumber(
getSeed(context, customStickiness), litmusExperiment.getName(), totalWeight);
int counter = 0; private static String getIdentifier(LitmusContext context) {
for (final VariantDefinition definition : variants) { return context.getUserId()
if (definition.getWeight() != 0) { .orElse(
counter += definition.getWeight(); context.getSessionId()
if (counter >= target) { .orElse(
return Variant.builder() context.getRemoteAddress()
.name(definition.getName()) .orElse(context.getAppVersionCode()
.payload(definition.getPayload()) .orElse(context.getOsType()
.enabled(true) .orElse(context.getDeviceId()
.stickiness(definition.getStickiness()) .orElse(Double.toString(Math.random())))))
.build(); ));
} }
}
}
// Should not happen private static String randomString() {
int randSeed = new Random().nextInt(100000);
return "" + randSeed;
}
private static String getSeed(LitmusContext litmusContext, Optional<String> stickiness) {
return stickiness
.map(s -> litmusContext.getByName(s).orElse(randomString()))
.orElse(getIdentifier(litmusContext));
}
public static Variant selectVariant(LitmusExperiment litmusExperiment, LitmusContext context, Variant defaultVariant) {
if (litmusExperiment == null || StringUtils.isBlank(litmusExperiment.getVariants())) {
return defaultVariant;
}
List<VariantDefinition> variants = JacksonUtils.stringToListObject(litmusExperiment.getVariants(), VariantDefinition.class);
int totalWeight = variants.stream().mapToInt(VariantDefinition::getWeight).sum();
if (totalWeight == 0) {
return defaultVariant; return defaultVariant;
} }
Optional<VariantDefinition> variantOverride = getOverride(variants, context);
if (variantOverride.isPresent()) {
var variantDefinition = variantOverride.get();
return Variant.builder()
.name(variantDefinition.getName())
.payload(variantDefinition.getPayload())
.enabled(true)
.stickiness(variantDefinition.getStickiness())
.build();
}
Optional<String> customStickiness =
variants.stream()
.filter(f -> f.getStickiness() != null)
.map(VariantDefinition::getStickiness)
.findFirst();
int target =
StrategyUtils.getNormalizedNumber(
getSeed(context, customStickiness), litmusExperiment.getName(), totalWeight);
int counter = 0;
for (final VariantDefinition definition : variants) {
if (definition.getWeight() != 0) {
counter += definition.getWeight();
if (counter >= target) {
return Variant.builder()
.name(definition.getName())
.payload(definition.getPayload())
.enabled(true)
.stickiness(definition.getStickiness())
.build();
}
}
}
// Should not happen
return defaultVariant;
}
} }

View File

@@ -11,13 +11,11 @@ import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@Component @Component
@RequiredArgsConstructor public record LitmusProxyContainer(LitmusProxyConfig litmusProxyConfig) {
public class LitmusProxyContainer {
private final LitmusProxyConfig litmusProxyConfig;
@Bean @Bean
public Litmus litmus(RequestMetadata requestMetadata) { public Litmus litmus(RequestMetadata requestMetadata) {
var litmusConfig = LitmusConfig.builder() var litmusConfig = LitmusConfig.builder()
.litmusAPI(litmusProxyConfig.getLitmusEndpoint()) .litmusAPI(litmusProxyConfig.getLitmusEndpoint())
.appName("litmus-proxy") .appName("litmus-proxy")
.instanceId("test-instance") .instanceId("test-instance")

View File

@@ -12,10 +12,8 @@ import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
@RequestMapping("/v1/proxy") @RequestMapping("/v1/proxy")
@RequiredArgsConstructor
@Log4j2 @Log4j2
public class LitmusProxyController { public record LitmusProxyController(Litmus litmus) {
private final Litmus litmus;
@GetMapping(value = "/experiment", produces = MediaType.APPLICATION_JSON_VALUE) @GetMapping(value = "/experiment", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> fetch(@RequestParam("name") String experimentName) { public ResponseEntity<?> fetch(@RequestParam("name") String experimentName) {
@@ -24,4 +22,11 @@ public class LitmusProxyController {
return ResponseEntity.ok(result); return ResponseEntity.ok(result);
} }
@GetMapping(value = "/variant", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> fetchVariants(@RequestParam("name") String variantName) {
var variant = litmus.getVariant(variantName);
return ResponseEntity.ok(variant);
}
} }

View File

@@ -1,5 +1,6 @@
package com.navi.medici.provider; package com.navi.medici.provider;
import com.navi.medici.config.LitmusConfig;
import com.navi.medici.context.LitmusContext; import com.navi.medici.context.LitmusContext;
import com.navi.medici.interceptor.RequestMetadata; import com.navi.medici.interceptor.RequestMetadata;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
@@ -9,17 +10,12 @@ import org.springframework.web.context.annotation.RequestScope;
@Component @Component
@RequestScope @RequestScope
@Log4j2 @Log4j2
public class CustomLitmusProxyContextProvider implements LitmusContextProvider { public record CustomLitmusProxyContextProvider(RequestMetadata requestMetadata) implements LitmusContextProvider {
private final RequestMetadata requestMetadata;
public CustomLitmusProxyContextProvider(RequestMetadata requestMetadata) {
this.requestMetadata = requestMetadata;
}
@Override @Override
public LitmusContext getContext() { public LitmusContext getContext() {
return LitmusContext.builder() return LitmusContext.builder()
.userId(requestMetadata.customerId().orElseGet(() -> ""))
.clickStreamPayload(requestMetadata.getClickStreamData()) .clickStreamPayload(requestMetadata.getClickStreamData())
.appVersionCode(requestMetadata.getAppVersionCode().orElse("")) .appVersionCode(requestMetadata.getAppVersionCode().orElse(""))
.osType(requestMetadata.getOsVersion().orElse("")) .osType(requestMetadata.getOsVersion().orElse(""))