Skip to content

LDClient.init doesn't really return a Future that will complete with the latest feature flag values #143

@JinW-Airwallex

Description

@JinW-Airwallex

Is this a support request?
No

Describe the bug
I'm not sure if I misunderstand this but the doc about LDClient.init says: The result is a Future which will complete once the client has been initialized with the latest feature flag values.. However, it looks like even if I turn off the device's WiFi and let the network requests fail, calling get() on the returned Future will still succeed without any exception. Where is the so called latest feature flag values?

The goal I'm trying to achieve is to block users from accessing the app before we successfully load the feature flags from LD. But that doesn't seem to be supported by the SDK or am I missing something here?

What's more, let's just assume the network issue is temporary, it's actually impossible for app to retry the connection proactively because LDClient.init is only allowed to be called once as mentioned in #108! And the only other option is setOnline on the returned client which unfortunately doesn't have a callback or anything to notify the results.

To reproduce

  1. Turn off WiFi and call LDClient.init.
  2. Call get() on the returned Future.
  3. Check the Logcat and also monitor the pass of the get() without throwing.
  4. The allFlags() on the LDClient will return an empty map.

Expected behavior
If the device is offline and the LDConfig specifies offline to be false, an exception should be thrown upon calling get() on the Future returned from LDClient.init.

Logs

2021-11-12 16:41:19.270 15942-16193/com.airwallex.internal W/DiagnosticEventProcessor: Unhandled exception in LaunchDarkly client attempting to connect to URI: https://mobile.launchdarkly.com/mobile/events/diagnostic
    java.net.UnknownHostException: Unable to resolve host "mobile.launchdarkly.com": No address associated with hostname
        at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:124)
        at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:103)
        at java.net.InetAddress.getAllByName(InetAddress.java:1152)
        at okhttp3.Dns$Companion$DnsSystem.lookup(Dns.kt:49)
        at okhttp3.internal.connection.RouteSelector.resetNextInetSocketAddress(RouteSelector.kt:164)
        at okhttp3.internal.connection.RouteSelector.nextProxy(RouteSelector.kt:129)
        at okhttp3.internal.connection.RouteSelector.next(RouteSelector.kt:71)
        at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:205)
        at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
        at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
        at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
        at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)
        at com.launchdarkly.sdk.android.DiagnosticEventProcessor.sendDiagnosticEventSync(DiagnosticEventProcessor.java:129)
        at com.launchdarkly.sdk.android.DiagnosticEventProcessor.lambda$sendDiagnosticEventAsync$0$com-launchdarkly-sdk-android-DiagnosticEventProcessor(DiagnosticEventProcessor.java:116)
        at com.launchdarkly.sdk.android.DiagnosticEventProcessor$$ExternalSyntheticLambda1.run(Unknown Source:4)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)

SDK version
3.1.1

Language version, developer tools
Android, Kotlin

OS/platform
Android API 30

Additional context

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions