-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Feature/real time flags (#5) * Compiles and test, need to add some tests then get it into a sample app * Should be testing but not getting the errors through Fuse so can't run into the logic * Probably gone as far as I can with 2.x fuel, let's try the 3.x * Move to Retrofit - seems to be going well so far, test runs * Tidying up, setTrait test not working * All the tests are passing so will finish the retrofit migration * Updated some of the logic and added setTraits * Checkpoint commit before trying generic converter * Generics working fine * All passing for flags and such with the new generic caching * Mostly swapped to Retrofit, now need to do the analytics * Analytics now over to retrofit * Add caching for the getFlags endpoint * Get rid of the last of Fuel * Another clear-out and all working fine on the tests * Now using Retrofit cache, remove the old stuff * Now just using HTTP caching * Delete the old caching logic * Finishing off, should be done for defaults and caching * Remove unneeded todo * Remove some more code * Still just playing around with it * Move cache configuration to its own data class * Tidy up the cache config and the tests * Update the comments * Now covers the caching tests * Tidy up some more of the tests * Some more tidying up * Default to caching disabled * Last few PR comments * Split the read and write timeout for HTTP * Initial basic implementation, let's try to get things hooked up to the server * Seems to be generally working * Checkpoint commit, seems to be generally working now just need to get the flags on update * Checkpoint commit before making the changes OK'd by Matthew to move the update clock into the event service * Ensure that the event source just reconnects if it loses the connection * Events and timers now all hooked-up and working in the manual integration test * Got the integration test working * Tidy everything up and move sensitive data to environment variables * Add a new test to cover the event stream going through a reconnect cycle * Added test for the live stream of flags, tidied up the imports and various thing, changed the logic a bit for when we need to do updates from events * Update FlagsmithClient/src/test/java/com/flagsmith/RealTimeUpdatesIntegrationTests.kt Co-authored-by: Matthew Elwell <[email protected]> * Update environment variables in the github actions * Add some error checking on the environment variables so it's a bit more obvious what's going on if we don't configure properly * Noddy change to get the tests to run again * Try printing out unsuccessful responses in the integration tests * Push more more non-empty checks --------- Co-authored-by: Matthew Elwell <[email protected]>
- Loading branch information
1 parent
9aab12d
commit 18ccc05
Showing
13 changed files
with
492 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
FlagsmithClient/src/main/java/com/flagsmith/entities/FeatureStatePutBody.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package com.flagsmith.entities | ||
|
||
internal data class FeatureStatePutBody ( | ||
val enabled: Boolean, | ||
val feature_state_value: Any? | ||
) |
7 changes: 7 additions & 0 deletions
7
FlagsmithClient/src/main/java/com/flagsmith/entities/FlagEvent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.flagsmith.entities | ||
|
||
import com.google.gson.annotations.SerializedName | ||
|
||
internal data class FlagEvent ( | ||
@SerializedName(value = "updated_at") val updatedAt: Double | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithEventService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package com.flagsmith.internal | ||
|
||
import android.util.Log | ||
import com.flagsmith.entities.FlagEvent | ||
import com.google.gson.Gson | ||
import kotlinx.coroutines.flow.MutableStateFlow | ||
import okhttp3.OkHttpClient | ||
import okhttp3.Request | ||
import okhttp3.Response | ||
import okhttp3.sse.EventSource | ||
import okhttp3.sse.EventSourceListener | ||
import okhttp3.sse.EventSources | ||
import java.util.concurrent.TimeUnit | ||
|
||
internal class FlagsmithEventService constructor( | ||
private val eventSourceUrl: String?, | ||
private val environmentKey: String, | ||
private val updates: (Result<FlagEvent>) -> Unit | ||
) { | ||
private val defaultEventSourceHost = "https://realtime.flagsmith.com/" | ||
|
||
private val sseClient = OkHttpClient.Builder() | ||
.addInterceptor(FlagsmithRetrofitService.envKeyInterceptor(environmentKey)) | ||
.connectTimeout(6, TimeUnit.SECONDS) | ||
.readTimeout(10, TimeUnit.MINUTES) | ||
.writeTimeout(10, TimeUnit.MINUTES) | ||
.build() | ||
|
||
private val defaultEventSourceUrl: String = defaultEventSourceHost + "sse/environments/" + environmentKey + "/stream" | ||
|
||
private val sseRequest = Request.Builder() | ||
.url(eventSourceUrl ?: defaultEventSourceUrl) | ||
.header("Accept", "application/json") | ||
.addHeader("Accept", "text/event-stream") | ||
.build() | ||
|
||
private var currentEventSource: EventSource? = null | ||
|
||
var sseEventsFlow = MutableStateFlow(FlagEvent(updatedAt = 0.0)) | ||
private set | ||
|
||
private val sseEventSourceListener = object : EventSourceListener() { | ||
override fun onClosed(eventSource: EventSource) { | ||
super.onClosed(eventSource) | ||
Log.d(TAG, "onClosed: $eventSource") | ||
|
||
// This isn't uncommon and is the nature of HTTP requests, so just reconnect | ||
initEventSource() | ||
} | ||
|
||
override fun onEvent(eventSource: EventSource, id: String?, type: String?, data: String) { | ||
super.onEvent(eventSource, id, type, data) | ||
Log.d(TAG, "onEvent: $data") | ||
if (type != null && type == "environment_updated" && data.isNotEmpty()) { | ||
val flagEvent = Gson().fromJson(data, FlagEvent::class.java) | ||
sseEventsFlow.tryEmit(flagEvent) | ||
updates(Result.success(flagEvent)) | ||
} | ||
} | ||
|
||
override fun onFailure(eventSource: EventSource, t: Throwable?, response: Response?) { | ||
super.onFailure(eventSource, t, response) | ||
t?.printStackTrace() | ||
Log.d(TAG, "onFailure: ${t?.message}") | ||
if (t != null) | ||
updates(Result.failure(t)) | ||
else | ||
updates(Result.failure(Throwable("Unknown error"))) | ||
} | ||
|
||
override fun onOpen(eventSource: EventSource, response: Response) { | ||
super.onOpen(eventSource, response) | ||
Log.d(TAG, "onOpen: $eventSource") | ||
} | ||
} | ||
|
||
init { | ||
initEventSource() | ||
} | ||
|
||
private fun initEventSource() { | ||
currentEventSource?.cancel() | ||
currentEventSource = EventSources.createFactory(sseClient) | ||
.newEventSource(request = sseRequest, listener = sseEventSourceListener) | ||
} | ||
|
||
companion object { | ||
private const val TAG = "FlagsmithEventService" | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
FlagsmithClient/src/main/java/com/flagsmith/internal/FlagsmithEventTimeTracker.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package com.flagsmith.internal | ||
|
||
/// | ||
internal interface FlagsmithEventTimeTracker { | ||
var lastSeenAt: Double | ||
} |
Oops, something went wrong.