Repository: apollographql/apollo-kotlin
Pull request #6119 (2024-08-13 14:07:51)

[runtime] Change NetworkMonitor to expose a StateFlow directly
Closes https://github.com/apollographql/apollo-kotlin/issues/6115

The previous interface was based on what `ApolloClient` needs but it prevented using `NetworkMonitor` for other use cases. This PR allows to use `NetworkMonitor` in a more generic way. 

This is obviously 200% breaking. If anyone implements their own `NetworkMonitor`, they'll need to update but hopefully it's not too hard (and the symbol is `@ApolloExperimental` in all cases).


Patch:
diff --git a/docs/source/advanced/network-connectivity.mdx b/docs/source/advanced/network-connectivity.mdx
index d15ec7a42f..6109a8b20b 100644
--- a/docs/source/advanced/network-connectivity.mdx
+++ b/docs/source/advanced/network-connectivity.mdx
@@ -27,6 +27,9 @@ val apolloClient = ApolloClient.Builder()
     .serverUrl("https://example.com/graphql")
     .retryOnErrorInterceptor(RetryOnErrorInterceptor(networkMonitor))
     .build()
+
+// once you're done with your `ApolloClient`
+networkMonitor.close()
 ```
 
 ### `failFastIfOffline`
diff --git a/intellij-plugin/README.md b/intellij-plugin/README.md
index 1cc4ae2db5..c05991d033 100644
--- a/intellij-plugin/README.md
+++ b/intellij-plugin/README.md
@@ -29,8 +29,8 @@ This plugin for Android Studio and IntelliJ helps you work with the
 
 The plugin is supported on:
 
-- IntelliJ 2023.2 and above
-- Android Studio 2023.2 (Iguana) and above
+- IntelliJ 2024.1 and above
+- Android Studio 2024.1 (Koala) and above
 
 ## Installation instructions
 
diff --git a/intellij-plugin/gradle.properties b/intellij-plugin/gradle.properties
index c9e15ef984..c792590e92 100644
--- a/intellij-plugin/gradle.properties
+++ b/intellij-plugin/gradle.properties
@@ -9,22 +9,22 @@ pluginRepositoryUrl=https://github.com/apollographql/apollo-kotlin
 # XXX Do update the supported versions in the README.md, and in docs/source/testing/android-studio-plugin.mdx file when updating these values!
 # See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
 # for insight into build numbers and IntelliJ Platform versions.
-pluginSinceBuild=232
-# This can be kept empty to mean no upper bound, but it's recommended to set it to whatever was tested
-pluginUntilBuild=241.*
+pluginSinceBuild=241
+# Upper bound: it's mandatory set it, and the plugin must be tested with this version
+pluginUntilBuild=242.*
 # IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
 platformType=IC
-# Corresponds to AS Iguana 2023.2.1 -> https://plugins.jetbrains.com/docs/intellij/android-studio-releases-list.html
+# Corresponds to AS Koala 2024.1.1 Patch 1 -> https://plugins.jetbrains.com/docs/intellij/android-studio-releases-list.html
 # and https://developer.android.com/studio/archive (more up to date)
 # See also https://plugins.jetbrains.com/docs/intellij/android-studio.html
-platformVersion=2023.2.5
-
+platformVersion=2024.1.4
 
 # Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
+platformBundledPlugins=com.intellij.java, org.jetbrains.kotlin, com.intellij.gradle, org.toml.lang
 # To find the version of a plugin relative to the platform version, see the plugin's page on the Marketplace,
-# e.g. for the toml plugin: https://plugins.jetbrains.com/plugin/8195-toml/versions/stable
-platformBundledPlugins=com.intellij.java, org.jetbrains.kotlin, com.intellij.gradle, org.jetbrains.android, org.toml.lang
-platformPlugins=com.intellij.lang.jsgraphql:4.0.2
+# e.g. for the GraphQL plugin: https://plugins.jetbrains.com/plugin/8097-graphql/versions/stable
+# Note: to run wih AS 2024.1.1, use org.jetbrains.android:241.14494.17
+platformPlugins=com.intellij.lang.jsgraphql:241.14494.150, org.jetbrains.android:241.17011.79
 
 # Opt-out flag for bundling Kotlin standard library.
 # See https://plugins.jetbrains.com/docs/intellij/kotlin.html#kotlin-standard-library for details.
diff --git a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/refactoring/migration/v3tov4/item/EncloseInService.kt b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/refactoring/migration/v3tov4/item/EncloseInService.kt
index 7ee582a5cc..79526be726 100644
--- a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/refactoring/migration/v3tov4/item/EncloseInService.kt
+++ b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/refactoring/migration/v3tov4/item/EncloseInService.kt
@@ -12,7 +12,6 @@ import com.apollographql.ijplugin.util.lambdaBlockExpression
 import com.intellij.openapi.project.Project
 import com.intellij.psi.PsiMigration
 import com.intellij.psi.search.GlobalSearchScope
-import org.jetbrains.kotlin.psi.KtBlockExpression
 import org.jetbrains.kotlin.psi.KtCallExpression
 import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
 import org.jetbrains.kotlin.psi.KtExpression
@@ -34,7 +33,7 @@ object EncloseInService : MigrationItem() {
             val statements = blockExpression.statements
             // If there's already a service call, we can't automatically refactor
             if (statements.none { it.isMethodCall("service") }) {
-              usages.add(blockExpression.toMigrationItemUsageInfo())
+              usages.add(expression.toMigrationItemUsageInfo())
             }
           }
         }
@@ -71,20 +70,24 @@ object EncloseInService : MigrationItem() {
   }
 
   override fun performRefactoring(project: Project, migration: PsiMigration, usage: MigrationItemUsageInfo) {
-    val blockExpression = usage.element as KtBlockExpression
+    val apolloCallExpression = usage.element as KtCallExpression
+    val blockExpression = apolloCallExpression.lambdaBlockExpression()!!
     val nonServiceStatements = blockExpression.statements.filter { !it.isApolloServiceExpression() }
     val nonServiceStatementsText = nonServiceStatements.map { it.text }
     nonServiceStatements.forEach { it.delete() }
-    val ktFactory = KtPsiFactory(project)
-    val newBlockExpression = ktFactory.createEmptyBody()
-    for (statement in nonServiceStatementsText) {
-      newBlockExpression.add(ktFactory.createNewLine())
-      newBlockExpression.add(ktFactory.createExpression(statement))
+    val replacementExpression = buildString {
+      append("apollo {\n")
+      for (it in nonServiceStatementsText) {
+        append("$it\n")
+      }
+      append("service(\"service\") {\n")
+      append(blockExpression.text)
+      append("\n}\n")
+      append("}")
     }
-    newBlockExpression.add(ktFactory.createNewLine())
-    newBlockExpression.add(ktFactory.createExpression("service(\"service\") {\n${blockExpression.text}\n}"))
-    newBlockExpression.lBrace?.delete()
-    newBlockExpression.rBrace?.delete()
-    blockExpression.replace(newBlockExpression)
+    val ktFactory = KtPsiFactory(project)
+    val newApolloCallExpression = ktFactory.createExpression(replacementExpression)
+    apolloCallExpression.parent.addAfter(newApolloCallExpression, apolloCallExpression)
+    apolloCallExpression.delete()
   }
 }
diff --git a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/interceptor/RetryOnErrorInterceptor.kt b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/interceptor/RetryOnErrorInterceptor.kt
index b257a58577..9ed47b5350 100644
--- a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/interceptor/RetryOnErrorInterceptor.kt
+++ b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/interceptor/RetryOnErrorInterceptor.kt
@@ -8,6 +8,7 @@ import com.apollographql.apollo.exception.ApolloException
 import com.apollographql.apollo.exception.ApolloNetworkException
 import com.apollographql.apollo.exception.OfflineException
 import com.apollographql.apollo.network.NetworkMonitor
+import com.apollographql.apollo.network.waitForNetwork
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.emitAll
@@ -60,7 +61,7 @@ private class DefaultRetryOnErrorInterceptorImpl(private val networkMonitor: Net
     val downStream = chain.proceed(request)
 
     return flow {
-          if (failFastIfOffline && networkMonitor?.isOnline() == false) {
+          if (failFastIfOffline && networkMonitor?.isOnline?.value == false) {
             emit((ApolloResponse.Builder(request.operation, request.requestUuid).exception(OfflineApolloException).build()))
           } else {
             emitAll(downStream)
diff --git a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/network/NetworkMonitor.kt b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/network/NetworkMonitor.kt
index c6f184b97d..8555cef708 100644
--- a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/network/NetworkMonitor.kt
+++ b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/network/NetworkMonitor.kt
@@ -5,11 +5,14 @@ package com.apollographql.apollo.network
 
 import com.apollographql.apollo.annotations.ApolloExperimental
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.mapNotNull
 import kotlinx.coroutines.flow.takeWhile
 import okio.Closeable
+import kotlin.js.JsName
 import kotlin.jvm.JvmMultifileClass
 import kotlin.jvm.JvmName
 
@@ -20,35 +23,35 @@ import kotlin.jvm.JvmName
 @ApolloExperimental
 interface NetworkMonitor : Closeable {
   /**
-   * The current state of the network
+   * Emits the current network state. May emit null during initialization
+   * when the current state is not known yet.
    */
-  suspend fun isOnline(): Boolean
+  val isOnline: StateFlow<Boolean?>
+}
 
-  /**
-   * Waits until [isOnline] is true
-   */
-  suspend fun waitForNetwork()
+internal suspend fun NetworkMonitor.waitForNetwork() {
+  isOnline.takeWhile { it != true }.collect()
 }
 
+/**
+ * @param networkObserverFactory a factory for a [NetworkObserver]. [networkObserverFactory] is called from a
+ * background thread.
+ */
 internal class DefaultNetworkMonitor(private val networkObserverFactory: () -> NetworkObserver) : NetworkMonitor, NetworkObserver.Listener {
   private val _isOnline: MutableStateFlow<Boolean?> = MutableStateFlow(null)
 
+  override val isOnline: StateFlow<Boolean?>
+    get() {
+      networkObserver
+      return _isOnline.asStateFlow()
+    }
+
   private val networkObserver by lazy {
     networkObserverFactory().also {
       it.setListener(this)
     }
   }
 
-  override suspend fun isOnline(): Boolean {
-    networkObserver
-    return _isOnline.mapNotNull { it }.first()
-  }
-
-  override suspend fun waitForNetwork() {
-    networkObserver
-    _isOnline.takeWhile { it != true }.collect()
-  }
-
   override fun close() {
     networkObserver.close()
   }


Test patch:
diff --git a/docs/source/testing/android-studio-plugin.mdx b/docs/source/testing/android-studio-plugin.mdx
index 3e8f662457..74457a9de1 100644
--- a/docs/source/testing/android-studio-plugin.mdx
+++ b/docs/source/testing/android-studio-plugin.mdx
@@ -11,8 +11,8 @@ The plugin is available on the JetBrains plugin repository. To install it from t
 
 At the time of writing, the plugin is supported on:
 
-- IntelliJ 2023.2 and above
-- Android Studio 2023.2 (Iguana) and above
+- IntelliJ 2024.1 and above
+- Android Studio 2024.1 (Koala) and above
 
 Please check the [plugin page](https://plugins.jetbrains.com/plugin/20645-apollo-graphql) for up to date information.
 
diff --git a/intellij-plugin/src/test/kotlin/com/apollographql/ijplugin/ApolloTestCase.kt b/intellij-plugin/src/test/kotlin/com/apollographql/ijplugin/ApolloTestCase.kt
index d654b35971..34a4744a27 100644
--- a/intellij-plugin/src/test/kotlin/com/apollographql/ijplugin/ApolloTestCase.kt
+++ b/intellij-plugin/src/test/kotlin/com/apollographql/ijplugin/ApolloTestCase.kt
@@ -19,6 +19,7 @@ import com.intellij.testFramework.PsiTestUtil
 import com.intellij.testFramework.TestDataPath
 import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor
 import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
+import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
 import com.intellij.util.ui.UIUtil
 import junit.framework.AssertionFailedError
 import org.jetbrains.kotlin.idea.KotlinLanguage
@@ -60,6 +61,7 @@ abstract class ApolloTestCase : LightJavaCodeInsightFixtureTestCase() {
     val codeStyleSettings = CodeStyle.getSettings(project)
     val kotlinSettings = codeStyleSettings.getCommonSettings(KotlinLanguage.INSTANCE)
     kotlinSettings.indentOptions!!.INDENT_SIZE = 2
+    kotlinSettings.WRAP_LONG_LINES = false
     val graphQLSettings = codeStyleSettings.getCommonSettings(GraphQLLanguage.INSTANCE)
     graphQLSettings.indentOptions!!.INDENT_SIZE = 2
 
@@ -108,6 +110,7 @@ abstract class ApolloTestCase : LightJavaCodeInsightFixtureTestCase() {
 
   protected fun doHighlighting(): List<HighlightInfo> {
     // Hack: sometimes doHighlighting fails with "AssertionError: PSI/document/model changes are not allowed during highlighting"
+    (myFixture as? CodeInsightTestFixtureImpl)?.canChangeDocumentDuringHighlighting(true)
     // Wait a bit for project to settle and try again
     return attempt(3) { myFixture.doHighlighting() }
   }
diff --git a/intellij-plugin/src/test/kotlin/com/apollographql/ijplugin/inspection/ApolloGraphQLConfigFilePresentInspectionTest.kt b/intellij-plugin/src/test/kotlin/com/apollographql/ijplugin/inspection/ApolloGraphQLConfigFilePresentInspectionTest.kt
index bfc3c6a5d5..d91014121c 100644
--- a/intellij-plugin/src/test/kotlin/com/apollographql/ijplugin/inspection/ApolloGraphQLConfigFilePresentInspectionTest.kt
+++ b/intellij-plugin/src/test/kotlin/com/apollographql/ijplugin/inspection/ApolloGraphQLConfigFilePresentInspectionTest.kt
@@ -21,6 +21,7 @@ class ApolloGraphQLConfigFilePresentInspectionTest : ApolloTestCase() {
   @Test
   fun testGraphqlConfigPresenceError() {
     myFixture.configureByFile("graphql.config.yml")
-    checkHighlighting()
+    assertTrue(doHighlighting().any { it.description == "The Apollo plugin retrieves the GraphQL configuration from Gradle and doesn't use the GraphQL config file" })
+//    checkHighlighting()
   }
 }
diff --git a/intellij-plugin/src/test/testData/inspection/graphql.config.yml b/intellij-plugin/src/test/testData/inspection/graphql.config.yml
index d7c1710398..14be07d2f1 100644
--- a/intellij-plugin/src/test/testData/inspection/graphql.config.yml
+++ b/intellij-plugin/src/test/testData/inspection/graphql.config.yml
@@ -1,4 +1,3 @@
-<warning descr="The Apollo plugin retrieves the GraphQL configuration from Gradle and doesn't use the GraphQL config file" textAttributesKey="WARNING_ATTRIBUTES"><warning descr="The Apollo plugin retrieves the GraphQL configuration from Gradle and doesn't use the GraphQL config file" textAttributesKey="WARNING_ATTRIBUTES">
 projects:
   main:
     schema: src/main/graphql/schema.graphqls
@@ -7,5 +6,3 @@ projects:
       endpoints:
         main: "https://apollo-fullstack-tutorial.herokuapp.com/graphql"
       apollo-key: ${APOLLO_KEY}
-
-</warning></warning>
\ No newline at end of file
diff --git a/intellij-plugin/src/test/testData/migration/compat-to-operationbased/reworkInlineFragmentFields_after.kt b/intellij-plugin/src/test/testData/migration/compat-to-operationbased/reworkInlineFragmentFields_after.kt
index 35b4fa92da..02f491a91f 100644
--- a/intellij-plugin/src/test/testData/migration/compat-to-operationbased/reworkInlineFragmentFields_after.kt
+++ b/intellij-plugin/src/test/testData/migration/compat-to-operationbased/reworkInlineFragmentFields_after.kt
@@ -32,13 +32,13 @@ public class FruitListQuery() : Query<FruitListQuery.Data> {
   )
 
   public data class List(
-          public val __typename: String,
-          public val id: String,
-          /**
+    public val __typename: String,
+    public val id: String,
+    /**
        * Synthetic field for inline fragment on Cherry
        */
       public val asCherry: OnCherry?,
-          /**
+    /**
        * Synthetic field for inline fragment on Apple
        */
       public val asApple: OnApple?,
@@ -51,14 +51,14 @@ public class FruitListQuery() : Query<FruitListQuery.Data> {
   )
 
   public data class AsApple(
-          public val __typename: String,
-          public val id: String,
-          public val color: String,
-          /**
+    public val __typename: String,
+    public val id: String,
+    public val color: String,
+    /**
        * Synthetic field for inline fragment on Golden
        */
       public val asGolden: OnGolden?,
-          /**
+    /**
        * Synthetic field for inline fragment on Granny
        */
       public val asGranny: OnGranny?,
diff --git a/intellij-plugin/src/test/testData/migration/v2-to-v3/addCustomTypeAdapter_after.kt b/intellij-plugin/src/test/testData/migration/v2-to-v3/addCustomTypeAdapter_after.kt
index 8f444a5712..c8e14da44a 100644
--- a/intellij-plugin/src/test/testData/migration/v2-to-v3/addCustomTypeAdapter_after.kt
+++ b/intellij-plugin/src/test/testData/migration/v2-to-v3/addCustomTypeAdapter_after.kt
@@ -21,10 +21,10 @@ enum class CustomType : ScalarType {
 
 suspend fun main() {
   val apolloClient = ApolloClient.Builder()
-          // TODO: Use addCustomScalarAdapter instead. See https://www.apollographql.com/docs/kotlin/migration/3.0/#custom-scalar-adapters
-          .addCustomTypeAdapter(DateTime.type, DateTimeAdapter())
-          // TODO: Use addCustomScalarAdapter instead. See https://www.apollographql.com/docs/kotlin/migration/3.0/#custom-scalar-adapters
-          .addCustomTypeAdapter(Url.type, UrlAdapter())
+    // TODO: Use addCustomScalarAdapter instead. See https://www.apollographql.com/docs/kotlin/migration/3.0/#custom-scalar-adapters
+    .addCustomTypeAdapter(DateTime.type, DateTimeAdapter())
+    // TODO: Use addCustomScalarAdapter instead. See https://www.apollographql.com/docs/kotlin/migration/3.0/#custom-scalar-adapters
+    .addCustomTypeAdapter(Url.type, UrlAdapter())
     .build()
 }
 
diff --git a/intellij-plugin/src/test/testData/migration/v2-to-v3/inMemoryNormalizedCache_after.kt b/intellij-plugin/src/test/testData/migration/v2-to-v3/inMemoryNormalizedCache_after.kt
index 5eb4a7046f..8d995a882f 100644
--- a/intellij-plugin/src/test/testData/migration/v2-to-v3/inMemoryNormalizedCache_after.kt
+++ b/intellij-plugin/src/test/testData/migration/v2-to-v3/inMemoryNormalizedCache_after.kt
@@ -20,8 +20,10 @@ suspend fun main() {
 
   val cacheFactory1 = MemoryCacheFactory(maxSizeBytes = 10 * 1024 * 1024)
   val cacheFactory2 = MemoryCacheFactory(maxSizeBytes = 10 * 1024 * 1024)
-  val cacheFactory3 = MemoryCacheFactory(maxSizeBytes = 10 * 1024 * 1024, expireAfterMillis = TimeUnit.MILLISECONDS.toMillis(10))
-  val cacheFactory4 = MemoryCacheFactory(maxSizeBytes = 10 * 1024 * 1024, expireAfterMillis = TimeUnit.MILLISECONDS.toMillis(10))
+  val cacheFactory3 =
+    MemoryCacheFactory(maxSizeBytes = 10 * 1024 * 1024, expireAfterMillis = TimeUnit.MILLISECONDS.toMillis(10))
+  val cacheFactory4 =
+    MemoryCacheFactory(maxSizeBytes = 10 * 1024 * 1024, expireAfterMillis = TimeUnit.MILLISECONDS.toMillis(10))
   val cacheFactory5 = MemoryCacheFactory(expireAfterMillis = TimeUnit.HOURS.toMillis(10))
 
   val apolloClient = ApolloClient.Builder()
diff --git a/intellij-plugin/src/test/testData/migration/v3-to-v4/multiModule_after.gradle.kts b/intellij-plugin/src/test/testData/migration/v3-to-v4/multiModule_after.gradle.kts
index 1299405b33..59c8b287ee 100644
--- a/intellij-plugin/src/test/testData/migration/v3-to-v4/multiModule_after.gradle.kts
+++ b/intellij-plugin/src/test/testData/migration/v3-to-v4/multiModule_after.gradle.kts
@@ -5,19 +5,19 @@ dependencies {
 apollo {
   service("service1") {
     packageName.set("com.example.service1")
-    dependsOn(project(":schema"))
+ dependsOn(project(":schema"))
   }
 
   service("service2") {
     packageName.set("com.example.service2")
-    dependsOn(project(":schema"))
+ dependsOn(project(":schema"))
   }
 }
 
 
 apollo {
-  service("service") {
-    packageName.set("com.example.service1")
-    dependsOn(project(":schema"))
-  }
+service("service") {
+packageName.set("com.example.service1")
+ dependsOn(project(":schema"))
+}
 }
diff --git a/libraries/apollo-runtime/src/commonTest/kotlin/test/network/NetworkMonitorTest.kt b/libraries/apollo-runtime/src/commonTest/kotlin/test/network/NetworkMonitorTest.kt
index c0b6fc84e7..363c2db27b 100644
--- a/libraries/apollo-runtime/src/commonTest/kotlin/test/network/NetworkMonitorTest.kt
+++ b/libraries/apollo-runtime/src/commonTest/kotlin/test/network/NetworkMonitorTest.kt
@@ -13,11 +13,14 @@ import com.apollographql.mockserver.MockServer
 import com.apollographql.mockserver.assertNoRequest
 import com.apollographql.mockserver.enqueueString
 import com.apollographql.apollo.network.NetworkMonitor
+import com.apollographql.apollo.network.waitForNetwork
 import test.FooQuery
 import com.apollographql.apollo.testing.internal.runTest
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.emitAll
 import kotlinx.coroutines.flow.first
@@ -91,15 +94,10 @@ class NetworkMonitorTest {
 class FakeNetworkMonitor: NetworkMonitor {
   val _isOnline = MutableStateFlow(false)
 
-  override fun close() {}
-
-  override suspend fun waitForNetwork() {
-    _isOnline.takeWhile { !it }.collect()
-  }
+  override val isOnline: StateFlow<Boolean?>
+    get() = _isOnline.asStateFlow()
 
-  override suspend fun isOnline(): Boolean {
-    return _isOnline.mapNotNull { it }.first()
-  }
+  override fun close() {}
 }
 
 class NetworkMonitorInterceptor(private val networkMonitor: NetworkMonitor): ApolloInterceptor {