Skip to content

Commit

Permalink
feat: non boolean feature support
Browse files Browse the repository at this point in the history
  • Loading branch information
ptitFicus committed Oct 30, 2024
1 parent 98bcc86 commit d0ad130
Show file tree
Hide file tree
Showing 29 changed files with 1,826 additions and 175 deletions.
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@


<dependencies>
<dependency>
<groupId>dev.openfeature</groupId>
<artifactId>sdk</artifactId>
<version>1.10.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
Expand Down
190 changes: 190 additions & 0 deletions pom.xml.versionsBackup
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fr.maif</groupId>
<artifactId>izanami-client</artifactId>
<version>2.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>${project.groupId}:${project.artifactId}</name>
<description>Java client for Izanami in version &gt; 2</description>
<url>https://github.com/MAIF/izanami</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<maven-jar-plugin.version>3.3.0</maven-jar-plugin.version>
<junit-jupiter-engine.version>5.8.2</junit-jupiter-engine.version>
<hamcrest-all.version>1.3</hamcrest-all.version>
</properties>

<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>


<scm>
<connection>scm:git:[email protected]:MAIF/izanami-java-client.git</connection>
<developerConnection>scm:git:[email protected]:MAIF/izanami-java-client.git</developerConnection>
<url>https://github.com/MAIF/izanami-java-client/tree/main</url>
<tag>v2.0.0-beta1</tag>
</scm>

<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2</url>
</repository>
</distributionManagement>


<developers>
<developer>
<name>Benjamin Cavy</name>
<email>[email protected]</email>
<organization>MAIF</organization>
<organizationUrl>https://www.maif.fr/</organizationUrl>
</developer>
</developers>

<build>
<finalName>izanami-java-client</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<doclint>all,-missing</doclint>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>3.0.1</version>
<configuration>
<tagNameFormat>v@{project.version}</tagNameFormat>
</configuration>
</plugin>
</plugins>
</build>

<profiles>
<profile>
<id>ci-cd</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>


<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.14</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.16.0</version>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>2.16.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.16.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.16.0</version>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>4.2.1</version>
</dependency>

<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.24.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit-jupiter-engine.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock</artifactId>
<version>3.3.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
19 changes: 19 additions & 0 deletions src/main/java/fr/maif/ClientConfiguration.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package fr.maif;

import fr.maif.features.values.BooleanCastStrategy;
import fr.maif.http.IzanamiHttpClient;
import fr.maif.requests.IzanamiConnectionInformation;

Expand All @@ -12,7 +13,24 @@ public class ClientConfiguration {
public final FeatureCacheConfiguration cacheConfiguration;
public final IzanamiHttpClient httpClient;
public final Duration callTimeout;
public final BooleanCastStrategy castStrategy;
public ClientConfiguration(
IzanamiConnectionInformation connectionInformation,
FeatureClientErrorStrategy errorStrategy,
FeatureCacheConfiguration cacheConfiguration,
IzanamiHttpClient httpClient,
Duration callTimeout,
BooleanCastStrategy castStrategy
) {
this.connectionInformation = connectionInformation;
this.errorStrategy = errorStrategy;
this.cacheConfiguration = cacheConfiguration;
this.httpClient = httpClient;
this.callTimeout = callTimeout;
this.castStrategy = castStrategy;
}

@Deprecated
public ClientConfiguration(
IzanamiConnectionInformation connectionInformation,
FeatureClientErrorStrategy errorStrategy,
Expand All @@ -25,5 +43,6 @@ public ClientConfiguration(
this.cacheConfiguration = cacheConfiguration;
this.httpClient = httpClient;
this.callTimeout = callTimeout;
this.castStrategy = BooleanCastStrategy.LAX;
}
}
80 changes: 73 additions & 7 deletions src/main/java/fr/maif/FeatureClientErrorStrategy.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import java.util.concurrent.CompletableFuture;
import java.util.function.Function;

import java.math.BigDecimal;
/**
* Strategy to use when one feature activation status can't be fetched or computed locally.
* Izanami handle errors as follows :
Expand All @@ -27,7 +27,11 @@
public abstract class FeatureClientErrorStrategy<T extends FeatureClientErrorStrategy<T>> {
public boolean lastKnownFallbackAllowed = true;


public abstract CompletableFuture<Boolean> handleError(IzanamiError error);
public abstract CompletableFuture<String> handleErrorForString(IzanamiError error);
public abstract CompletableFuture<BigDecimal> handleErrorForNumber(IzanamiError error);


/**
*
Expand All @@ -39,7 +43,6 @@ public T fallbackOnLastKnownStrategy(boolean shouldUseLastKnownStrategy) {
return (T) this;
}


public static NullValueStrategy nullValueStrategy() {
return new NullValueStrategy();
}
Expand All @@ -57,58 +60,121 @@ public static FailStrategy failStrategy() {
* @param defaultValue default value to use as activation status
* @return an error strategy that use provided value as activation status
*/
@Deprecated
public static DefaultValueStrategy defaultValueStrategy(boolean defaultValue) {
return new DefaultValueStrategy(defaultValue);
return new DefaultValueStrategy(defaultValue, null, null);
}

public static DefaultValueStrategy defaultValueStrategy(boolean defaultValue, String defaultValueForString, BigDecimal defaultValueForNumber) {
return new DefaultValueStrategy(defaultValue, defaultValueForString, defaultValueForNumber);
}

/**
*
* @param callback function that will be called to compute feature activation status
* @return an error strategy that calls provided callback to compute activation status
*/
@Deprecated
public static CallbackStrategy callbackStrategy(
Function<IzanamiError, CompletableFuture<Boolean>> callback
) {
return new CallbackStrategy(callback);
return new CallbackStrategy(callback, (error) -> CompletableFuture.completedFuture(null), (error) -> CompletableFuture.completedFuture(null));
}

public static CallbackStrategy callbackStrategy(
Function<IzanamiError, CompletableFuture<Boolean>> callback,
Function<IzanamiError, CompletableFuture<String>> callbackForString,
Function<IzanamiError, CompletableFuture<BigDecimal>> callbackForNumber
) {
return new CallbackStrategy(callback, callbackForString, callbackForNumber);
}

public static class NullValueStrategy extends FeatureClientErrorStrategy<NullValueStrategy> {
@Override
public CompletableFuture<Boolean> handleError(IzanamiError error) {
return CompletableFuture.completedFuture(null);
}

@Override
public CompletableFuture<String> handleErrorForString(IzanamiError error) {
return CompletableFuture.completedFuture(null);
}

@Override
public CompletableFuture<BigDecimal> handleErrorForNumber(IzanamiError error) {
return CompletableFuture.completedFuture(null);
}
}

public static class FailStrategy extends FeatureClientErrorStrategy<FailStrategy> {
@Override
public CompletableFuture<Boolean> handleError(IzanamiError error) {
return CompletableFuture.failedFuture(new IzanamiException(error.message));
}

@Override
public CompletableFuture<String> handleErrorForString(IzanamiError error) {
return CompletableFuture.failedFuture(new IzanamiException(error.message));
}

@Override
public CompletableFuture<BigDecimal> handleErrorForNumber(IzanamiError error) {
return CompletableFuture.failedFuture(new IzanamiException(error.message));
}
}

public static class DefaultValueStrategy extends FeatureClientErrorStrategy<DefaultValueStrategy> {
public final boolean value;
public final String valueForString;
public final BigDecimal valueForNumber;

public DefaultValueStrategy(boolean value) {
public DefaultValueStrategy(boolean value, String valueForString, BigDecimal valueForNumber) {
this.value = value;
this.valueForString = valueForString;
this.valueForNumber = valueForNumber;
}

@Override
public CompletableFuture<Boolean> handleError(IzanamiError error) {
return CompletableFuture.completedFuture(value);
}

@Override
public CompletableFuture<String> handleErrorForString(IzanamiError error) {
return CompletableFuture.completedFuture(valueForString);
}

@Override
public CompletableFuture<BigDecimal> handleErrorForNumber(IzanamiError error) {
return CompletableFuture.completedFuture(valueForNumber);
}
}

public static class CallbackStrategy extends FeatureClientErrorStrategy<CallbackStrategy> {
private Function<IzanamiError, CompletableFuture<Boolean>> callback;
public CallbackStrategy(Function<IzanamiError, CompletableFuture<Boolean>> callback) {
private final Function<IzanamiError, CompletableFuture<Boolean>> callback;
private final Function<IzanamiError, CompletableFuture<String>> callbackForString;
private final Function<IzanamiError, CompletableFuture<BigDecimal>> callbackForNumber;

public CallbackStrategy(Function<IzanamiError, CompletableFuture<Boolean>> callback, Function<IzanamiError, CompletableFuture<String>> callbackForString, Function<IzanamiError, CompletableFuture<BigDecimal>> callbackForNumber) {
this.callback = callback;
this.callbackForString = callbackForString;
this.callbackForNumber = callbackForNumber;
}

@Override
public CompletableFuture<Boolean> handleError(IzanamiError error) {
return callback.apply(error);
}

@Override
public CompletableFuture<String> handleErrorForString(IzanamiError error) {
return callbackForString.apply(error);
}

@Override
public CompletableFuture<BigDecimal> handleErrorForNumber(IzanamiError error) {
return callbackForNumber.apply(error);
}
}

}
Loading

0 comments on commit d0ad130

Please sign in to comment.