From 05e5fed96bf6069bbcbbf494956d2aa59c0f1259 Mon Sep 17 00:00:00 2001 From: Nicky Bondarenko Date: Mon, 24 Jul 2023 16:28:38 +0200 Subject: [PATCH 1/3] update README.md --- README.md | 174 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 153 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index ac75e98..8032727 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,33 @@ -[![](https://jitpack.io/v/spotify/openfeature-kotlin-sdk.svg)](https://jitpack.io/#spotify/openfeature-kotlin-sdk) + +

+ + + + OpenFeature Logo + +

-# OpenFeature Kotlin SDK +

OpenFeature Kotlin SDKs

![Status](https://img.shields.io/badge/lifecycle-alpha-a0c3d2.svg) -What is OpenFeature? +## 👋 Hey there! Thanks for checking out the OpenFeature Kotlin SDK + +### What is OpenFeature? + [OpenFeature][openfeature-website] is an open standard that provides a vendor-agnostic, community-driven API for feature flagging that works with your favorite feature flag management tool. -Why standardize feature flags? -Standardizing feature flags unifies tools and vendors behind a common interface which avoids vendor lock-in at the code level. Additionally, it offers a framework for building extensions and integrations and allows providers to focus on their unique value proposition. +### Why standardize feature flags? -This Kotlin implementation of an OpenFeature SDK has been developed at Spotify, and currently made available and maintained within the Spotify Open Source Software organization. Part of our roadmap is for the OpenFeature community to evaluate this implementation and potentially include it in the existing ecosystem of [OpenFeature SDKs][openfeature-sdks]. +Standardizing feature flags unifies tools and vendors behind a common interface which avoids vendor lock-in at the code level. Additionally, it offers a framework for building extensions and integrations and allows providers to focus on their unique value proposition. -## Requirements +## 🔍 Requirements - The Android minSdk version supported is: `21`. Note that this library is intended to be used in a mobile context, and has not been evaluated for use in other type of applications (e.g. server applications). -## Usage - -### Adding the library dependency +## 📦 Installation The Android project must include `maven("https://jitpack.io")` in `settings.gradle`. @@ -37,22 +44,147 @@ api("com.github.spotify:openfeature-kotlin-sdk:[ANY_BRANCH]-SNAPSHOT") This will get a build from the head of the mentioned branch. -### Resolving a flag +## 🌟 Features + +- support for various backend [providers](https://openfeature.dev/docs/reference/concepts/provider) +- easy integration and extension via [hooks](https://openfeature.dev/docs/reference/concepts/hooks) +- bool, string, numeric, and object flag types +- [context-aware](https://openfeature.dev/docs/reference/concepts/evaluation-context) evaluation + +## 🚀 Usage + +```kotlin + // configure a provider and get client + OpenFeatureAPI.setProvider( + CustomProvider.initialise() + ) + val client = OpenFeatureAPI.getClient() + + // get a bool flag value + client.getBooleanValue("boolFlag", default = false) + + // get a bool flag value async + openFeatureClient + .toAsync() + .observeBooleanValue(key, default) + .collect { + // do something with boolean + } + + // get bool flag with compose + val myBoolProperty = openFeatureClient + .toAsync() + .observeBooleanValue(key, default) + .collectAsState() +``` + +### Context-aware evaluation + +Sometimes the value of a flag must take into account some dynamic criteria about the application or user, such as the user location, IP, email address, or the location of the server. +In OpenFeature, we refer to this as [`targeting`](https://openfeature.dev/specification/glossary#targeting). +If the flag system you're using supports targeting, you can provide the input data using the `EvaluationContext`. + + + +### Events + +Events allow you to react to state changes in the provider or underlying flag management system, such as flag definition changes, provider readiness, or error conditions. +Initialization events (`PROVIDER_READY` on success, `PROVIDER_ERROR` on failure) are dispatched for every provider. +Some providers support additional events, such as `PROVIDER_CONFIGURATION_CHANGED`. +Please refer to the documentation of the provider you're using to see what events are supported. + +```kotlin + // to listen to PROVIDER_READY event + CoroutineScope(Dispatchers.IO).launch { + awaitProviderReady() + // now provider is ready, read the properties + } +``` + +### Providers: + +To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency. +This can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/java-sdk-contrib) available under the OpenFeature organization. +Finally, you’ll then need to write the provider itself. +This can be accomplished by implementing the `Provider` interface exported by the OpenFeature SDK. + ```kotlin -import dev.openfeature.sdk.* +class NewProvider(override val hooks: List>, override val metadata: Metadata) : FeatureProvider { + override fun getBooleanEvaluation( + key: String, + defaultValue: Boolean, + context: EvaluationContext? + ): ProviderEvaluation { + // resolve a boolean flag value + } + + override fun getDoubleEvaluation( + key: String, + defaultValue: Double, + context: EvaluationContext? + ): ProviderEvaluation { + // resolve a double flag value + } + + override fun getIntegerEvaluation( + key: String, + defaultValue: Int, + context: EvaluationContext? + ): ProviderEvaluation { + // resolve an integer flag value + } + + override fun getObjectEvaluation( + key: String, + defaultValue: Value, + context: EvaluationContext? + ): ProviderEvaluation { + // resolve an object flag value + } + + override fun getStringEvaluation( + key: String, + defaultValue: String, + context: EvaluationContext? + ): ProviderEvaluation { + // resolve a string flag value + } + + override suspend fun initialize(initialContext: EvaluationContext?) { + // add context-aware provider initialisation + } + + override suspend fun onContextSet(oldContext: EvaluationContext?, newContext: EvaluationContext) { + // add necessary changes on context change + } -// Change NoOpProvider with your actual provider -OpenFeatureAPI.setProvider(NoOpProvider(), ImmutableContext()) -val flagValue = OpenFeatureAPI.getClient().getBooleanValue("boolFlag", false) +} ``` -Setting a new provider or setting a new evaluation context are asynchronous operations. The provider might execute I/O operations as part of these method calls (e.g. fetching flag evaluations from the backend and store them in a local cache). It's advised to not interact with the OpenFeature client until the `setProvider()` or `setEvaluationContext()` functions have returned successfully. -Please refer to our [documentation on static-context APIs](https://github.com/open-feature/spec/pull/171) for further information on how these APIs are structured for the use-case of mobile clients. +## ⭐️ Support the project + +- Give this repo a ⭐️! +- Follow us on social media: + - Twitter: [@openfeature](https://twitter.com/openfeature) + - LinkedIn: [OpenFeature](https://www.linkedin.com/company/openfeature/) +- Join us on [Slack](https://cloud-native.slack.com/archives/C0344AANLA1) +- For more check out our [community page](https://openfeature.dev/community/) + +## 🤝 Contributing + +Interested in contributing? Great, we'd love your help! To get started, take a look at the [CONTRIBUTING](CONTRIBUTING.md) guide. + +### Thanks to everyone that has already contributed + + + Pictures of the folks who have contributed to the project + + +Made with [contrib.rocks](https://contrib.rocks). -### Providers +## 📜 License -To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency. You’ll then need to write the provider itself. This can be accomplished by implementing the `FeatureProvider` interface exported by the OpenFeature SDK. +[Apache License 2.0](LICENSE) -[openfeature-website]: https://openfeature.dev -[openfeature-sdks]: https://openfeature.dev/docs/reference/technologies/ \ No newline at end of file +[openfeature-website]: https://openfeature.dev \ No newline at end of file From f6743d80818010396deeb50a7d7f3b6680402bb6 Mon Sep 17 00:00:00 2001 From: Nicky Bondarenko Date: Tue, 25 Jul 2023 15:05:11 +0200 Subject: [PATCH 2/3] update code snippets in README.md --- README.md | 48 +++++++++++++++++++----------------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 8032727..6d4ffc3 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ Note that this library is intended to be used in a mobile context, and has not b ## 📦 Installation +### Jitpack + The Android project must include `maven("https://jitpack.io")` in `settings.gradle`. You can now add the OpenFeature SDK dependency: @@ -44,6 +46,10 @@ api("com.github.spotify:openfeature-kotlin-sdk:[ANY_BRANCH]-SNAPSHOT") This will get a build from the head of the mentioned branch. +### Maven + +Installation via Maven Central is currently WIP + ## 🌟 Features - support for various backend [providers](https://openfeature.dev/docs/reference/concepts/provider) @@ -55,37 +61,21 @@ This will get a build from the head of the mentioned branch. ```kotlin // configure a provider and get client - OpenFeatureAPI.setProvider( - CustomProvider.initialise() - ) + OpenFeatureAPI.setProvider(customProvider) val client = OpenFeatureAPI.getClient() // get a bool flag value client.getBooleanValue("boolFlag", default = false) // get a bool flag value async - openFeatureClient - .toAsync() - .observeBooleanValue(key, default) - .collect { - // do something with boolean + coroutineScope.launch { + WithContext(Dispatchers.IO) { + client.awaitProviderReady() } - - // get bool flag with compose - val myBoolProperty = openFeatureClient - .toAsync() - .observeBooleanValue(key, default) - .collectAsState() + client.getBooleanValue("boolFlag", default = false) + } ``` -### Context-aware evaluation - -Sometimes the value of a flag must take into account some dynamic criteria about the application or user, such as the user location, IP, email address, or the location of the server. -In OpenFeature, we refer to this as [`targeting`](https://openfeature.dev/specification/glossary#targeting). -If the flag system you're using supports targeting, you can provide the input data using the `EvaluationContext`. - - - ### Events Events allow you to react to state changes in the provider or underlying flag management system, such as flag definition changes, provider readiness, or error conditions. @@ -94,11 +84,11 @@ Some providers support additional events, such as `PROVIDER_CONFIGURATION_CHANGE Please refer to the documentation of the provider you're using to see what events are supported. ```kotlin - // to listen to PROVIDER_READY event - CoroutineScope(Dispatchers.IO).launch { - awaitProviderReady() - // now provider is ready, read the properties - } + OpenFeatureAPI.eventsObserver() + .observe() + .collect { + // do something once the provider is ready + } ``` ### Providers: @@ -150,11 +140,11 @@ class NewProvider(override val hooks: List>, override val metadata: Meta // resolve a string flag value } - override suspend fun initialize(initialContext: EvaluationContext?) { + override fun initialize(initialContext: EvaluationContext?) { // add context-aware provider initialisation } - override suspend fun onContextSet(oldContext: EvaluationContext?, newContext: EvaluationContext) { + override fun onContextSet(oldContext: EvaluationContext?, newContext: EvaluationContext) { // add necessary changes on context change } From b9ae141fe3b6376d1e2cd2b499c07d7cd188888d Mon Sep 17 00:00:00 2001 From: Nicky Bondarenko Date: Tue, 25 Jul 2023 16:14:45 +0200 Subject: [PATCH 3/3] add a badge to README and remove wrong link --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6d4ffc3..7760f99 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@

OpenFeature Kotlin SDKs

-![Status](https://img.shields.io/badge/lifecycle-alpha-a0c3d2.svg) +![Status](https://img.shields.io/badge/lifecycle-alpha-a0c3d2.svg) [![](https://jitpack.io/v/spotify/openfeature-kotlin-sdk.svg)](https://jitpack.io/#spotify/openfeature-kotlin-sdk) ## 👋 Hey there! Thanks for checking out the OpenFeature Kotlin SDK @@ -94,7 +94,7 @@ Please refer to the documentation of the provider you're using to see what event ### Providers: To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency. -This can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/java-sdk-contrib) available under the OpenFeature organization. +This can be a new repository or included in the existing contrib repository available under the OpenFeature organization. Finally, you’ll then need to write the provider itself. This can be accomplished by implementing the `Provider` interface exported by the OpenFeature SDK.