You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
After `initialize()` returns, `setProviderAndWait` waits for the provider’s `status` to move off `NotReady` and `Reconciling`. That is the provider’s contract to fulfill; the SDK does not time out. If a provider never updates `status` correctly, the call never completes. If you need a maximum wait time, wrap the call in your own `withTimeout` from `kotlinx.coroutines` (or similar) at the application level.
143
+
142
144
Asynchronous API that doesn't wait is also available. It's useful when you want to set a provider and continue with other tasks.
143
145
144
-
However, flag evaluations are only possible after the provider is Ready.
146
+
However, flag evaluations are only possible after the provider is `OpenFeatureStatus.Ready`. The built-in `NoOpProvider` reports `Ready` after initialization and returns default values for flags (a lightweight placeholder until you register a real provider).
145
147
146
148
```kotlin
147
149
OpenFeatureAPI.setProvider(MyProvider()) // can pass a dispatcher here
@@ -412,11 +414,17 @@ in an Android app.
412
414
413
415
### Develop a provider
414
416
415
-
To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency.
416
-
You’ll then need to write the provider by implementing the `FeatureProvider` interface exported by the OpenFeature SDK.
417
+
Providers are developed in dedicated projects that declare the OpenFeature SDK as a dependency. Each provider must implement the `StateManagingProvider` interface exported by the OpenFeature SDK.
418
+
419
+
The provider must keep `status` and `observe()` consistent: each time the provider transitions between `OpenFeatureStatus.NotReady`, `OpenFeatureStatus.Reconciling`, and `OpenFeatureStatus.Ready`, it must update `_status` and emit the corresponding `OpenFeatureProviderEvents` (for example, `OpenFeatureStatus.Reconciling` paired with `ProviderReconciling()`). The SDK derives `statusFlow` from `status`, and application-level handlers registered via `OpenFeatureAPI.observe()` receive the emitted events — inconsistency between the two will produce contradictory state to callers.
`FeatureProvider` is still supported although `StateManagingProvider` is preferred for new providers. It should be noted that `FeatureProvider` is a legacy behavior and will be removed in the next major version, due to its possible race condition in the presence of multi-threading.
506
+
482
507
> Built a new provider? [Let us know](https://github.com/open-feature/openfeature.dev/issues/new?assignees=&labels=provider&projects=&template=document-provider.yaml&title=%5BProvider%5D%3A+) so we can add it to the docs!
Copy file name to clipboardExpand all lines: kotlin-sdk/api/android/kotlin-sdk.api
+30-3Lines changed: 30 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -232,7 +232,7 @@ public final class dev/openfeature/kotlin/sdk/ImmutableStructure : dev/openfeatu
232
232
public fun keySet ()Ljava/util/Set;
233
233
}
234
234
235
-
public class dev/openfeature/kotlin/sdk/NoOpProvider : dev/openfeature/kotlin/sdk/FeatureProvider {
235
+
public class dev/openfeature/kotlin/sdk/NoOpProvider : dev/openfeature/kotlin/sdk/StateManagingProvider {
236
236
public fun <init> ()V
237
237
public fun <init> (Ljava/util/List;)V
238
238
public synthetic fun <init> (Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
@@ -242,6 +242,7 @@ public class dev/openfeature/kotlin/sdk/NoOpProvider : dev/openfeature/kotlin/sd
242
242
public fun getIntegerEvaluation (Ljava/lang/String;ILdev/openfeature/kotlin/sdk/EvaluationContext;)Ldev/openfeature/kotlin/sdk/ProviderEvaluation;
243
243
public fun getMetadata ()Ldev/openfeature/kotlin/sdk/ProviderMetadata;
244
244
public fun getObjectEvaluation (Ljava/lang/String;Ldev/openfeature/kotlin/sdk/Value;Ldev/openfeature/kotlin/sdk/EvaluationContext;)Ldev/openfeature/kotlin/sdk/ProviderEvaluation;
245
+
public fun getStatus ()Lkotlinx/coroutines/flow/StateFlow;
245
246
public fun getStringEvaluation (Ljava/lang/String;Ljava/lang/String;Ldev/openfeature/kotlin/sdk/EvaluationContext;)Ldev/openfeature/kotlin/sdk/ProviderEvaluation;
246
247
public fun initialize (Ldev/openfeature/kotlin/sdk/EvaluationContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
247
248
public fun observe ()Lkotlinx/coroutines/flow/Flow;
@@ -273,7 +274,7 @@ public final class dev/openfeature/kotlin/sdk/OpenFeatureAPI {
273
274
public final fun getHooks ()Ljava/util/List;
274
275
public final fun getProvider ()Ldev/openfeature/kotlin/sdk/FeatureProvider;
275
276
public final fun getProviderMetadata ()Ldev/openfeature/kotlin/sdk/ProviderMetadata;
276
-
public final fun getProvidersFlow ()Lkotlinx/coroutines/flow/MutableStateFlow;
277
+
public final fun getProvidersFlow ()Lkotlinx/coroutines/flow/StateFlow;
277
278
public final fun getStatus ()Ldev/openfeature/kotlin/sdk/OpenFeatureStatus;
278
279
public final fun getStatusFlow ()Lkotlinx/coroutines/flow/Flow;
279
280
public final fun setEvaluationContext (Ldev/openfeature/kotlin/sdk/EvaluationContext;Lkotlinx/coroutines/CoroutineDispatcher;)V
@@ -402,6 +403,18 @@ public final class dev/openfeature/kotlin/sdk/Reason : java/lang/Enum {
402
403
public static fun values ()[Ldev/openfeature/kotlin/sdk/Reason;
403
404
}
404
405
406
+
public abstract interface class dev/openfeature/kotlin/sdk/StateManagingProvider : dev/openfeature/kotlin/sdk/FeatureProvider {
407
+
public abstract fun getStatus ()Lkotlinx/coroutines/flow/StateFlow;
408
+
public abstract fun initialize (Ldev/openfeature/kotlin/sdk/EvaluationContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
409
+
public abstract fun observe ()Lkotlinx/coroutines/flow/Flow;
410
+
public abstract fun onContextSet (Ldev/openfeature/kotlin/sdk/EvaluationContext;Ldev/openfeature/kotlin/sdk/EvaluationContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
411
+
public abstract fun shutdown ()V
412
+
}
413
+
414
+
public final class dev/openfeature/kotlin/sdk/StateManagingProvider$DefaultImpls {
415
+
public static fun track (Ldev/openfeature/kotlin/sdk/StateManagingProvider;Ljava/lang/String;Ldev/openfeature/kotlin/sdk/EvaluationContext;Ldev/openfeature/kotlin/sdk/TrackingEventDetails;)V
416
+
}
417
+
405
418
public abstract interface class dev/openfeature/kotlin/sdk/Structure {
406
419
public abstract fun asMap ()Ljava/util/Map;
407
420
public abstract fun asObjectMap ()Ljava/util/Map;
@@ -709,6 +722,19 @@ public final class dev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$P
709
722
public fun toString ()Ljava/lang/String;
710
723
}
711
724
725
+
public final class dev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$ProviderReconciling : dev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents {
726
+
public fun <init> ()V
727
+
public fun <init> (Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$EventDetails;)V
728
+
public synthetic fun <init> (Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$EventDetails;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
729
+
public final fun component1 ()Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$EventDetails;
730
+
public final fun copy (Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$EventDetails;)Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$ProviderReconciling;
731
+
public static synthetic fun copy$default (Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$ProviderReconciling;Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$EventDetails;ILjava/lang/Object;)Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$ProviderReconciling;
732
+
public fun equals (Ljava/lang/Object;)Z
733
+
public fun getEventDetails ()Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$EventDetails;
734
+
public fun hashCode ()I
735
+
public fun toString ()Ljava/lang/String;
736
+
}
737
+
712
738
public final class dev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$ProviderStale : dev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents {
713
739
public fun <init> ()V
714
740
public fun <init> (Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$EventDetails;)V
@@ -872,7 +898,7 @@ public final class dev/openfeature/kotlin/sdk/multiprovider/FirstSuccessfulStrat
872
898
public fun evaluate (Ljava/util/List;Ljava/lang/String;Ljava/lang/Object;Ldev/openfeature/kotlin/sdk/EvaluationContext;Lkotlin/jvm/functions/Function4;)Ldev/openfeature/kotlin/sdk/ProviderEvaluation;
873
899
}
874
900
875
-
public final class dev/openfeature/kotlin/sdk/multiprovider/MultiProvider : dev/openfeature/kotlin/sdk/FeatureProvider {
901
+
public final class dev/openfeature/kotlin/sdk/multiprovider/MultiProvider : dev/openfeature/kotlin/sdk/StateManagingProvider {
876
902
public static final field Companion Ldev/openfeature/kotlin/sdk/multiprovider/MultiProvider$Companion;
877
903
public fun <init> (Ljava/util/List;Ldev/openfeature/kotlin/sdk/multiprovider/MultiProvider$Strategy;)V
878
904
public synthetic fun <init> (Ljava/util/List;Ldev/openfeature/kotlin/sdk/multiprovider/MultiProvider$Strategy;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
@@ -882,6 +908,7 @@ public final class dev/openfeature/kotlin/sdk/multiprovider/MultiProvider : dev/
882
908
public fun getIntegerEvaluation (Ljava/lang/String;ILdev/openfeature/kotlin/sdk/EvaluationContext;)Ldev/openfeature/kotlin/sdk/ProviderEvaluation;
883
909
public fun getMetadata ()Ldev/openfeature/kotlin/sdk/ProviderMetadata;
884
910
public fun getObjectEvaluation (Ljava/lang/String;Ldev/openfeature/kotlin/sdk/Value;Ldev/openfeature/kotlin/sdk/EvaluationContext;)Ldev/openfeature/kotlin/sdk/ProviderEvaluation;
911
+
public fun getStatus ()Lkotlinx/coroutines/flow/StateFlow;
885
912
public final fun getStatusFlow ()Lkotlinx/coroutines/flow/StateFlow;
886
913
public fun getStringEvaluation (Ljava/lang/String;Ljava/lang/String;Ldev/openfeature/kotlin/sdk/EvaluationContext;)Ldev/openfeature/kotlin/sdk/ProviderEvaluation;
887
914
public fun initialize (Ldev/openfeature/kotlin/sdk/EvaluationContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
Copy file name to clipboardExpand all lines: kotlin-sdk/api/jvm/kotlin-sdk.api
+30-3Lines changed: 30 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -232,7 +232,7 @@ public final class dev/openfeature/kotlin/sdk/ImmutableStructure : dev/openfeatu
232
232
public fun keySet ()Ljava/util/Set;
233
233
}
234
234
235
-
public class dev/openfeature/kotlin/sdk/NoOpProvider : dev/openfeature/kotlin/sdk/FeatureProvider {
235
+
public class dev/openfeature/kotlin/sdk/NoOpProvider : dev/openfeature/kotlin/sdk/StateManagingProvider {
236
236
public fun <init> ()V
237
237
public fun <init> (Ljava/util/List;)V
238
238
public synthetic fun <init> (Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
@@ -242,6 +242,7 @@ public class dev/openfeature/kotlin/sdk/NoOpProvider : dev/openfeature/kotlin/sd
242
242
public fun getIntegerEvaluation (Ljava/lang/String;ILdev/openfeature/kotlin/sdk/EvaluationContext;)Ldev/openfeature/kotlin/sdk/ProviderEvaluation;
243
243
public fun getMetadata ()Ldev/openfeature/kotlin/sdk/ProviderMetadata;
244
244
public fun getObjectEvaluation (Ljava/lang/String;Ldev/openfeature/kotlin/sdk/Value;Ldev/openfeature/kotlin/sdk/EvaluationContext;)Ldev/openfeature/kotlin/sdk/ProviderEvaluation;
245
+
public fun getStatus ()Lkotlinx/coroutines/flow/StateFlow;
245
246
public fun getStringEvaluation (Ljava/lang/String;Ljava/lang/String;Ldev/openfeature/kotlin/sdk/EvaluationContext;)Ldev/openfeature/kotlin/sdk/ProviderEvaluation;
246
247
public fun initialize (Ldev/openfeature/kotlin/sdk/EvaluationContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
247
248
public fun observe ()Lkotlinx/coroutines/flow/Flow;
@@ -273,7 +274,7 @@ public final class dev/openfeature/kotlin/sdk/OpenFeatureAPI {
273
274
public final fun getHooks ()Ljava/util/List;
274
275
public final fun getProvider ()Ldev/openfeature/kotlin/sdk/FeatureProvider;
275
276
public final fun getProviderMetadata ()Ldev/openfeature/kotlin/sdk/ProviderMetadata;
276
-
public final fun getProvidersFlow ()Lkotlinx/coroutines/flow/MutableStateFlow;
277
+
public final fun getProvidersFlow ()Lkotlinx/coroutines/flow/StateFlow;
277
278
public final fun getStatus ()Ldev/openfeature/kotlin/sdk/OpenFeatureStatus;
278
279
public final fun getStatusFlow ()Lkotlinx/coroutines/flow/Flow;
279
280
public final fun setEvaluationContext (Ldev/openfeature/kotlin/sdk/EvaluationContext;Lkotlinx/coroutines/CoroutineDispatcher;)V
@@ -402,6 +403,18 @@ public final class dev/openfeature/kotlin/sdk/Reason : java/lang/Enum {
402
403
public static fun values ()[Ldev/openfeature/kotlin/sdk/Reason;
403
404
}
404
405
406
+
public abstract interface class dev/openfeature/kotlin/sdk/StateManagingProvider : dev/openfeature/kotlin/sdk/FeatureProvider {
407
+
public abstract fun getStatus ()Lkotlinx/coroutines/flow/StateFlow;
408
+
public abstract fun initialize (Ldev/openfeature/kotlin/sdk/EvaluationContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
409
+
public abstract fun observe ()Lkotlinx/coroutines/flow/Flow;
410
+
public abstract fun onContextSet (Ldev/openfeature/kotlin/sdk/EvaluationContext;Ldev/openfeature/kotlin/sdk/EvaluationContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
411
+
public abstract fun shutdown ()V
412
+
}
413
+
414
+
public final class dev/openfeature/kotlin/sdk/StateManagingProvider$DefaultImpls {
415
+
public static fun track (Ldev/openfeature/kotlin/sdk/StateManagingProvider;Ljava/lang/String;Ldev/openfeature/kotlin/sdk/EvaluationContext;Ldev/openfeature/kotlin/sdk/TrackingEventDetails;)V
416
+
}
417
+
405
418
public abstract interface class dev/openfeature/kotlin/sdk/Structure {
406
419
public abstract fun asMap ()Ljava/util/Map;
407
420
public abstract fun asObjectMap ()Ljava/util/Map;
@@ -709,6 +722,19 @@ public final class dev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$P
709
722
public fun toString ()Ljava/lang/String;
710
723
}
711
724
725
+
public final class dev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$ProviderReconciling : dev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents {
726
+
public fun <init> ()V
727
+
public fun <init> (Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$EventDetails;)V
728
+
public synthetic fun <init> (Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$EventDetails;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
729
+
public final fun component1 ()Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$EventDetails;
730
+
public final fun copy (Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$EventDetails;)Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$ProviderReconciling;
731
+
public static synthetic fun copy$default (Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$ProviderReconciling;Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$EventDetails;ILjava/lang/Object;)Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$ProviderReconciling;
732
+
public fun equals (Ljava/lang/Object;)Z
733
+
public fun getEventDetails ()Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$EventDetails;
734
+
public fun hashCode ()I
735
+
public fun toString ()Ljava/lang/String;
736
+
}
737
+
712
738
public final class dev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$ProviderStale : dev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents {
713
739
public fun <init> ()V
714
740
public fun <init> (Ldev/openfeature/kotlin/sdk/events/OpenFeatureProviderEvents$EventDetails;)V
@@ -872,7 +898,7 @@ public final class dev/openfeature/kotlin/sdk/multiprovider/FirstSuccessfulStrat
872
898
public fun evaluate (Ljava/util/List;Ljava/lang/String;Ljava/lang/Object;Ldev/openfeature/kotlin/sdk/EvaluationContext;Lkotlin/jvm/functions/Function4;)Ldev/openfeature/kotlin/sdk/ProviderEvaluation;
873
899
}
874
900
875
-
public final class dev/openfeature/kotlin/sdk/multiprovider/MultiProvider : dev/openfeature/kotlin/sdk/FeatureProvider {
901
+
public final class dev/openfeature/kotlin/sdk/multiprovider/MultiProvider : dev/openfeature/kotlin/sdk/StateManagingProvider {
876
902
public static final field Companion Ldev/openfeature/kotlin/sdk/multiprovider/MultiProvider$Companion;
877
903
public fun <init> (Ljava/util/List;Ldev/openfeature/kotlin/sdk/multiprovider/MultiProvider$Strategy;)V
878
904
public synthetic fun <init> (Ljava/util/List;Ldev/openfeature/kotlin/sdk/multiprovider/MultiProvider$Strategy;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
@@ -882,6 +908,7 @@ public final class dev/openfeature/kotlin/sdk/multiprovider/MultiProvider : dev/
882
908
public fun getIntegerEvaluation (Ljava/lang/String;ILdev/openfeature/kotlin/sdk/EvaluationContext;)Ldev/openfeature/kotlin/sdk/ProviderEvaluation;
883
909
public fun getMetadata ()Ldev/openfeature/kotlin/sdk/ProviderMetadata;
884
910
public fun getObjectEvaluation (Ljava/lang/String;Ldev/openfeature/kotlin/sdk/Value;Ldev/openfeature/kotlin/sdk/EvaluationContext;)Ldev/openfeature/kotlin/sdk/ProviderEvaluation;
911
+
public fun getStatus ()Lkotlinx/coroutines/flow/StateFlow;
885
912
public final fun getStatusFlow ()Lkotlinx/coroutines/flow/StateFlow;
886
913
public fun getStringEvaluation (Ljava/lang/String;Ljava/lang/String;Ldev/openfeature/kotlin/sdk/EvaluationContext;)Ldev/openfeature/kotlin/sdk/ProviderEvaluation;
887
914
public fun initialize (Ldev/openfeature/kotlin/sdk/EvaluationContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
0 commit comments