diff --git a/libraries/apollo-runtime/src/appleMain/kotlin/com/apollographql/apollo3/network/ws/NSURLSessionWebSocketEngine.kt b/libraries/apollo-runtime/src/appleMain/kotlin/com/apollographql/apollo3/network/ws/NSURLSessionWebSocketEngine.kt index 3592a7e3435..fc32a283614 100644 --- a/libraries/apollo-runtime/src/appleMain/kotlin/com/apollographql/apollo3/network/ws/NSURLSessionWebSocketEngine.kt +++ b/libraries/apollo-runtime/src/appleMain/kotlin/com/apollographql/apollo3/network/ws/NSURLSessionWebSocketEngine.kt @@ -2,10 +2,10 @@ package com.apollographql.apollo3.network.ws import com.apollographql.apollo3.api.http.HttpHeader import com.apollographql.apollo3.exception.ApolloNetworkException -import com.apollographql.apollo3.internal.ChannelWrapper import com.apollographql.apollo3.network.toNSData import kotlinx.cinterop.convert import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.Channel import okio.ByteString import okio.toByteString @@ -61,7 +61,7 @@ actual class DefaultWebSocketEngine( setHTTPMethod("GET") } - val messageChannel = ChannelWrapper(Channel(Channel.UNLIMITED)) + val messageChannel = Channel(Channel.UNLIMITED) val isOpen = CompletableDeferred() val connectionListener = object : WebSocketConnectionListener { @@ -95,10 +95,11 @@ actual class DefaultWebSocketEngine( private class WebSocketConnectionImpl( val webSocket: NSURLSessionWebSocketTask, - val messageChannel: ChannelWrapper, + val messageChannel: Channel, ) : WebSocketConnection { init { - messageChannel.setInvokeOnClose { + @OptIn(ExperimentalCoroutinesApi::class) + messageChannel.invokeOnClose { webSocket.cancelWithCloseCode( closeCode = CLOSE_NORMAL.convert(), reason = null @@ -112,7 +113,8 @@ private class WebSocketConnectionImpl( } override fun send(data: ByteString) { - if (!messageChannel.isClosed) { + @OptIn(ExperimentalCoroutinesApi::class) + if (!messageChannel.isClosedForSend) { val message = NSURLSessionWebSocketMessage(data.toByteArray().toNSData()) val completionHandler = { error: NSError? -> if (error != null) handleError(error) @@ -122,7 +124,8 @@ private class WebSocketConnectionImpl( } override fun send(string: String) { - if (!messageChannel.isClosed) { + @OptIn(ExperimentalCoroutinesApi::class) + if (!messageChannel.isClosedForSend) { val message = NSURLSessionWebSocketMessage(string) val completionHandler = { error: NSError? -> if (error != null) handleError(error) diff --git a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/internal/ChannelWrapper.kt b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/internal/ChannelWrapper.kt deleted file mode 100644 index fbb7b516cb1..00000000000 --- a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/internal/ChannelWrapper.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.apollographql.apollo3.internal - -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.channels.Channel - -/** - * A wrapper for [Channel] that adds a method equivalent to [invokeOnClose], which is marked [ExperimentalCoroutinesApi]. - * There is a risk this API will be removed or changed in the future, which could break consumers of this library - that is why we use our - * own method. - * - * [Original source](https://github.com/Kotlin/kotlinx.coroutines/blob/version-1.5.2/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt#L286) - * - * TODO: remove when Channel.invokeOnClose is no longer marked ExperimentalCoroutinesApi. - */ -internal class ChannelWrapper(private val wrapped: Channel) : Channel by wrapped { - private var handler: ((cause: Throwable?) -> Unit)? = null - - var isClosed: Boolean = false - private set - - /** - * See [invokeOnClose]. - */ - fun setInvokeOnClose(handler: (cause: Throwable?) -> Unit) { - this.handler = handler - } - - override fun close(cause: Throwable?): Boolean { - isClosed = true - val closeAdded = wrapped.close(cause) - if (closeAdded) handler?.invoke(cause) - handler = null - return closeAdded - } -} diff --git a/libraries/apollo-runtime/src/jsMain/kotlin/com/apollographql/apollo3/network/ws/JsWebSocketEngine.kt b/libraries/apollo-runtime/src/jsMain/kotlin/com/apollographql/apollo3/network/ws/JsWebSocketEngine.kt index f3c292c19db..496817f3b1d 100644 --- a/libraries/apollo-runtime/src/jsMain/kotlin/com/apollographql/apollo3/network/ws/JsWebSocketEngine.kt +++ b/libraries/apollo-runtime/src/jsMain/kotlin/com/apollographql/apollo3/network/ws/JsWebSocketEngine.kt @@ -1,7 +1,6 @@ package com.apollographql.apollo3.network.ws import com.apollographql.apollo3.api.http.HttpHeader -import com.apollographql.apollo3.internal.ChannelWrapper import io.ktor.http.Headers import io.ktor.http.URLBuilder import io.ktor.http.URLProtocol @@ -34,7 +33,7 @@ actual class DefaultWebSocketEngine : WebSocketEngine { } }.build() val socket = createWebSocket(newUrl.toString(), Headers.build { headers.forEach { append(it.name, it.value) } }).awaitConnection() - val messageChannel = ChannelWrapper(Channel(Channel.UNLIMITED)) + val messageChannel = Channel(Channel.UNLIMITED) socket.onmessage = { messageEvent: MessageEvent -> val data = messageEvent.data if (data != null) { diff --git a/libraries/apollo-runtime/src/jvmMain/kotlin/com/apollographql/apollo3/network/ws/OkHttpWebSocketEngine.kt b/libraries/apollo-runtime/src/jvmMain/kotlin/com/apollographql/apollo3/network/ws/OkHttpWebSocketEngine.kt index 80563582a01..552a36c6593 100644 --- a/libraries/apollo-runtime/src/jvmMain/kotlin/com/apollographql/apollo3/network/ws/OkHttpWebSocketEngine.kt +++ b/libraries/apollo-runtime/src/jvmMain/kotlin/com/apollographql/apollo3/network/ws/OkHttpWebSocketEngine.kt @@ -2,9 +2,9 @@ package com.apollographql.apollo3.network.ws import com.apollographql.apollo3.api.http.HttpHeader import com.apollographql.apollo3.exception.ApolloWebSocketClosedException -import com.apollographql.apollo3.internal.ChannelWrapper import com.apollographql.apollo3.network.toOkHttpHeaders import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.Channel import okhttp3.OkHttpClient import okhttp3.Request @@ -25,7 +25,7 @@ actual class DefaultWebSocketEngine( url: String, headers: List, ): WebSocketConnection { - val messageChannel = ChannelWrapper(Channel(Channel.UNLIMITED)) + val messageChannel = Channel(Channel.UNLIMITED) val webSocketOpenResult = CompletableDeferred() //println("opening $url") @@ -71,7 +71,8 @@ actual class DefaultWebSocketEngine( webSocketOpenResult.await() - messageChannel.setInvokeOnClose { + @OptIn(ExperimentalCoroutinesApi::class) + messageChannel.invokeOnClose { // I think this is not necessary. The caller must call [WebSocketConnection.close] in all cases. // This should either trigger onClose or onFailure which should close the messageChannel //