Skip to content

Commit

Permalink
add Large Scale Change Demo
Browse files Browse the repository at this point in the history
  • Loading branch information
NoahHsu committed Dec 19, 2023
1 parent caa781d commit 48e64ba
Show file tree
Hide file tree
Showing 13 changed files with 279 additions and 6 deletions.
2 changes: 1 addition & 1 deletion client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ dependencies {
implementation 'io.github.openfeign:feign-jackson'
implementation 'org.springframework.boot:spring-boot-starter-hateoas'

implementation 'dev.openfeature:sdk:1.5.0'
api 'dev.openfeature:sdk:1.5.0'

runtimeOnly 'org.springframework.boot:spring-boot-starter-webflux'

Expand Down
1 change: 0 additions & 1 deletion demo/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ dependencies {

implementation "org.springframework.boot:spring-boot-starter"
implementation project(":client")
implementation 'dev.openfeature:sdk:1.5.0'

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import dev.openfeature.sdk.Client;
import lombok.extern.slf4j.Slf4j;
import org.example.open.feature.openflagr.client.FeatureToggleApiProvider;
import org.example.open.feature.openflagr.demo.lsc.LargeScaleChangeDemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
Expand All @@ -21,6 +22,9 @@ public class DemoApp implements CommandLineRunner {
@Autowired
private ConfigurableApplicationContext context;

@Autowired
private LargeScaleChangeDemo largeScaleChangeDemo;

public static void main(String[] args) {
log.info("STARTING THE APPLICATION");
SpringApplication.run(DemoApp.class, args);
Expand Down Expand Up @@ -50,6 +54,8 @@ public void run(String... args) throws Exception {
OpenFeatureCanaryDemo.iteration(client, 500, iterationCount);
case "S" -> // Shadow
OpenFeatureShadowDemo.iteration(client, 100, iterationCount);
case "L" -> // Large-Scale Change
largeScaleChangeDemo.iteration(50);
default -> isNext = "N";
}

Expand All @@ -69,5 +75,6 @@ private static void printInstruction() {
System.out.println("B for Blue/Green");
System.out.println("C for Canary");
System.out.println("S for Shadow");
System.out.println("L for Large Scale Change");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class DemoHelper {

private static final String RESET = "\033[0m";
private static final String GREEN = "\033[0:32m";
private static final String BLUE = "\033[0;34m";
private static final String PURPLE = "\033[0;35m";
public static final String RESET = "\033[0m";
public static final String GREEN = "\033[0:32m";
public static final String BLUE = "\033[0;34m";
public static final String PURPLE = "\033[0;35m";

public static void printStartIteration(int iterationCount) {
printStartIteration(iterationCount, "");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.example.open.feature.openflagr.demo.lsc;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class FooService {

private final VendorServiceFactory vendorServiceFactory;

public String step1(RequestModel request) {
VendorService vendorService = vendorServiceFactory.findTargetVendor(request);
try {
return vendorService.step1() + " -> ";
} catch (Exception e) {
return "X -> ";
}
}

public String step2(RequestModel request) {
VendorService vendorService = vendorServiceFactory.findTargetVendor(request);
try {
return vendorService.step2() + " -> ";
} catch (Exception e) {
return "X -> ";
}
}

public String step3(RequestModel request) {
VendorService vendorService = vendorServiceFactory.findTargetVendor(request);
try {
return vendorService.step3();
} catch (Exception e) {
return "X";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.example.open.feature.openflagr.demo.lsc;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class LargeScaleChangeDemo {
public static final String FLAG_KEY = "lsc";
public static final String USER_ID_KEY = "userId";

private final FooService fooService;

public void iteration(int times) {
// release toggle for non-prepared feature
// permission toggle for tester to test
// operation toggle for canary release

int i = 1;
while (i <= times) {
RequestModel request = getRequestModel(i);
System.out.print(i + "\t:");
// step1
System.out.print(fooService.step1(request));

// step2
System.out.print(fooService.step2(request));

// step3
System.out.print(fooService.step3(request));
if (i % 5 == 0) {
System.out.println();
} else {
System.out.print("\t\t");
}
i++;
}


}

private static RequestModel getRequestModel(int i) {
return new RequestModel(
String.valueOf(i),
getA(i));
}

private static LevelName getA(int i) {
if (i %10 == 0) return LevelName.VIP;
return LevelName.NORMAL;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.example.open.feature.openflagr.demo.lsc;

public enum LevelName {
NORMAL, VIP;

public boolean isNormal() {
return this == NORMAL;
}

public boolean isVip() {
return this == VIP;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.example.open.feature.openflagr.demo.lsc;

public record RequestModel(String userId, LevelName vendor) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.example.open.feature.openflagr.demo.lsc;

import dev.openfeature.sdk.Client;
import dev.openfeature.sdk.MutableContext;
import lombok.RequiredArgsConstructor;
import org.example.open.feature.openflagr.client.FeatureToggleApiProvider;
import org.springframework.stereotype.Service;

import static org.example.open.feature.openflagr.demo.DemoHelper.BLUE;
import static org.example.open.feature.openflagr.demo.DemoHelper.RESET;
import static org.example.open.feature.openflagr.demo.lsc.LargeScaleChangeDemo.FLAG_KEY;
import static org.example.open.feature.openflagr.demo.lsc.LargeScaleChangeDemo.USER_ID_KEY;

@Service
@RequiredArgsConstructor
public class VendorAV1ServiceImpl implements VendorService {

private final FeatureToggleApiProvider featureToggleApiProvider;

@Override
public boolean accept(RequestModel request) {
Client client = featureToggleApiProvider.getFlagrApiClient();
MutableContext evaluationContext = new MutableContext(request.userId());
evaluationContext.add(USER_ID_KEY, request.userId());

boolean isToggleOn = client.getBooleanValue(FLAG_KEY, false, evaluationContext);

return !isToggleOn && request.vendor().isNormal();
}

@Override
public String step1() {
return BLUE + "A1" + RESET;
}

@Override
public String step2() {
return BLUE + "A2" + RESET;
}

@Override
public String step3() {
return BLUE + "A3" + RESET;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.example.open.feature.openflagr.demo.lsc;

import dev.openfeature.sdk.Client;
import dev.openfeature.sdk.MutableContext;
import lombok.RequiredArgsConstructor;
import org.example.open.feature.openflagr.client.FeatureToggleApiProvider;
import org.springframework.stereotype.Service;

import static org.example.open.feature.openflagr.demo.DemoHelper.GREEN;
import static org.example.open.feature.openflagr.demo.DemoHelper.RESET;
import static org.example.open.feature.openflagr.demo.lsc.LargeScaleChangeDemo.FLAG_KEY;
import static org.example.open.feature.openflagr.demo.lsc.LargeScaleChangeDemo.USER_ID_KEY;

@Service
@RequiredArgsConstructor
public class VendorBV1ServiceImpl implements VendorService {

private final FeatureToggleApiProvider featureToggleApiProvider;

@Override
public boolean accept(RequestModel request) {
Client client = featureToggleApiProvider.getFlagrApiClient();
MutableContext evaluationContext = new MutableContext(request.userId());
evaluationContext.add(USER_ID_KEY, request.userId());

boolean isToggleOn = client.getBooleanValue(FLAG_KEY, false, evaluationContext);

return isToggleOn && request.vendor().isNormal();
}

@Override
public String step1() {
return GREEN + "B1" + RESET;
}

@Override
public String step2() {
// throw new UnsupportedOperationException("not implements yes");
return GREEN + "B2" + RESET;
}

@Override
public String step3() {
// throw new UnsupportedOperationException("not implements yes");
return GREEN + "B3" + RESET;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.example.open.feature.openflagr.demo.lsc;

import org.springframework.stereotype.Service;

import static org.example.open.feature.openflagr.demo.DemoHelper.*;

@Service
public class VendorSV1ServiceImpl implements VendorService{
@Override
public boolean accept(RequestModel request) {
return request.vendor().isVip();
}

@Override
public String step1() {
return PURPLE + "S1" + RESET;
}

@Override
public String step2() {
return PURPLE + "S2" + RESET;
}

@Override
public String step3() {
return PURPLE + "S3" + RESET;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.example.open.feature.openflagr.demo.lsc;

public interface VendorService {

boolean accept(RequestModel request);

String step1();

String step2();

String step3();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.example.open.feature.openflagr.demo.lsc;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor
public class VendorServiceFactory {

private final List<VendorService> vendorServices;

VendorService findTargetVendor(RequestModel request) {
for (VendorService strategy : vendorServices) {
if (strategy.accept(request)) {
return strategy;
}
}
throw new RuntimeException("no match strategy");
}

}

0 comments on commit 48e64ba

Please sign in to comment.