Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incubating WebSocketNetworkTransport #5362

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions gradle/libraries.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ rx-java3 = "3.1.6"
sqldelight = "2.0.1"
truth = "1.1.3"
moshix = "0.14.1"
node-ws = "8.14.2"

[libraries]
android-plugin = { group = "com.android.tools.build", name = "gradle", version.ref = "android-plugin" }
Expand Down Expand Up @@ -74,6 +75,7 @@ apollo-normalizedcache-sqlite-incubating = { group = "com.apollographql.apollo3"
apollo-rx2-support-java = { group = "com.apollographql.apollo3", name = "apollo-rx2-support-java", version.ref = "apollo" }
apollo-plugin = { group = "com.apollographql.apollo3", name = "apollo-gradle-plugin", version.ref = "apollo" }
apollo-runtime = { group = "com.apollographql.apollo3", name = "apollo-runtime", version.ref = "apollo" }
apollo-websocket-network-transport-incubating = { group = "com.apollographql.apollo3", name = "apollo-websocket-network-transport-incubating", version.ref = "apollo" }
apollo-compiler = { group = "com.apollographql.apollo3", name = "apollo-compiler", version.ref = "apollo" }
apollo-execution = { group = "com.apollographql.apollo3", name = "apollo-execution-incubating", version.ref = "apollo" }
# Used by the apollo-tooling project which uses a published version of Apollo
Expand Down
5 changes: 5 additions & 0 deletions kotlin-js-store-2.0/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,11 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==

[email protected]:
version "8.14.2"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f"
integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==

[email protected]:
version "8.5.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f"
Expand Down
5 changes: 5 additions & 0 deletions libraries/apollo-api/api/apollo-api.api
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,11 @@ public final class com/apollographql/apollo3/exception/ApolloParseException : co
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
}

public final class com/apollographql/apollo3/exception/ApolloRetryException : com/apollographql/apollo3/exception/ApolloException {
public fun <init> (JLjava/lang/Throwable;)V
public final fun getAttempt ()J
}

public final class com/apollographql/apollo3/exception/ApolloWebSocketClosedException : com/apollographql/apollo3/exception/ApolloException {
public fun <init> (ILjava/lang/String;Ljava/lang/Throwable;)V
public synthetic fun <init> (ILjava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,10 @@ class ApolloCompositeException : ApolloException {

class AutoPersistedQueriesNotSupported : ApolloException(message = "The server does not support auto persisted queries")
class MissingValueException : ApolloException(message = "The optional doesn't have a value")

/**
* An operation should be retried.
*
* @property attempt the number of times the operation has already been attempted without success
*/
class ApolloRetryException(val attempt: Long, cause: Throwable) : ApolloException("The operation should be retried", cause)
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ internal class MockServerImpl(
}

is ConnectionClosed -> {
println("Connection Closed (${e.message})")
// Nothing, ignore those
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import kotlinx.coroutines.flow.map
import okio.Buffer
import okio.ByteString
import okio.ByteString.Companion.toByteString
import okio.IOException

internal suspend fun readFrames(reader: Reader, onMessage: (WebSocketMessage) -> Unit) {
val currentMessage = Buffer()
Expand All @@ -19,6 +20,17 @@ internal suspend fun readFrames(reader: Reader, onMessage: (WebSocketMessage) ->
}

while (true) {
/**
* Check if the client closed the connection
*/
if (reader.buffer.size == 0L) {
try {
reader.fillBuffer()
} catch (e: IOException) {
throw ConnectionClosed(e)
}
}

require(2)

var b = reader.buffer.readByte().toInt()
Expand Down
9 changes: 0 additions & 9 deletions libraries/apollo-runtime/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,3 @@ kotlin {
}
}

tasks.register("iOSSimTest") {
dependsOn("iosSimTestBinaries")
doLast {
val binary = kotlin.targets.getByName<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>("iosSim").binaries.getTest("DEBUG").outputFile
exec {
commandLine = listOf("xcrun", "simctl", "spawn", "iPhone 8", binary.absolutePath)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,6 @@ actual class DefaultWebSocketEngine : WebSocketEngine {
}

/*
* The function below works due to ktor being used for the HTTP engine
* and how ktor imports ws, if this changes, ws would need to be added
* as a direct dependency.
*
* The following applies for lines below
* Copyright 2014-2019 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Some lines have been added/modified from the original source (https://github.com/ktorio/ktor/blob/f723638afd4d36024c390c5b79108b53ab513943/ktor-client/ktor-client-core/js/src/io/ktor/client/engine/js/JsClientEngine.kt#L62)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
public final class com/apollographql/apollo3/network/websocket/AppSyncWsProtocol : com/apollographql/apollo3/network/websocket/WsProtocol {
public static final field Companion Lcom/apollographql/apollo3/network/websocket/AppSyncWsProtocol$Companion;
public fun <init> ()V
public fun <init> (Lkotlin/jvm/functions/Function1;)V
public synthetic fun <init> (Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun connectionInit (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun getAuthorization ()Lkotlin/jvm/functions/Function1;
public fun getName ()Ljava/lang/String;
public fun operationStart (Lcom/apollographql/apollo3/api/ApolloRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun operationStop (Lcom/apollographql/apollo3/api/ApolloRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun parseServerMessage (Ljava/lang/String;)Lcom/apollographql/apollo3/network/websocket/ServerMessage;
public fun ping (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun pong (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class com/apollographql/apollo3/network/websocket/AppSyncWsProtocol$Companion {
public final fun buildUrl (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Ljava/lang/String;
public static synthetic fun buildUrl$default (Lcom/apollographql/apollo3/network/websocket/AppSyncWsProtocol$Companion;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;ILjava/lang/Object;)Ljava/lang/String;
}

public final class com/apollographql/apollo3/network/websocket/AppSyncWsProtocol$Factory : com/apollographql/apollo3/network/websocket/WsProtocol$Factory {
public fun <init> ()V
public final fun authorization (Lkotlin/jvm/functions/Function1;)Lcom/apollographql/apollo3/network/websocket/AppSyncWsProtocol$Factory;
public fun build ()Lcom/apollographql/apollo3/network/websocket/WsProtocol;
}

public abstract interface class com/apollographql/apollo3/network/websocket/ClientMessage {
}

public final class com/apollographql/apollo3/network/websocket/CompleteServerMessage : com/apollographql/apollo3/network/websocket/ServerMessage {
public fun <init> (Ljava/lang/String;)V
public final fun getId ()Ljava/lang/String;
}

public final class com/apollographql/apollo3/network/websocket/ConnectionAckServerMessage : com/apollographql/apollo3/network/websocket/ServerMessage {
public static final field INSTANCE Lcom/apollographql/apollo3/network/websocket/ConnectionAckServerMessage;
}

public final class com/apollographql/apollo3/network/websocket/ConnectionErrorServerMessage : com/apollographql/apollo3/network/websocket/ServerMessage {
public fun <init> (Ljava/lang/Object;)V
public final fun getPayload ()Ljava/lang/Object;
}

public final class com/apollographql/apollo3/network/websocket/ConnectionKeepAliveServerMessage : com/apollographql/apollo3/network/websocket/ServerMessage {
public static final field INSTANCE Lcom/apollographql/apollo3/network/websocket/ConnectionKeepAliveServerMessage;
}

public final class com/apollographql/apollo3/network/websocket/DataClientMessage : com/apollographql/apollo3/network/websocket/ClientMessage {
public fun <init> ([B)V
public final fun getData ()[B
}

public final class com/apollographql/apollo3/network/websocket/GeneralErrorServerMessage : com/apollographql/apollo3/network/websocket/ServerMessage {
public fun <init> (Ljava/lang/Exception;)V
public final fun getException ()Ljava/lang/Exception;
}

public final class com/apollographql/apollo3/network/websocket/GraphQLWsProtocol : com/apollographql/apollo3/network/websocket/WsProtocol {
public synthetic fun <init> (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun connectionInit (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun getConnectionParams ()Lkotlin/jvm/functions/Function1;
public fun getName ()Ljava/lang/String;
public fun operationStart (Lcom/apollographql/apollo3/api/ApolloRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun operationStop (Lcom/apollographql/apollo3/api/ApolloRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun parseServerMessage (Ljava/lang/String;)Lcom/apollographql/apollo3/network/websocket/ServerMessage;
public fun ping (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun pong (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class com/apollographql/apollo3/network/websocket/GraphQLWsProtocol$Factory : com/apollographql/apollo3/network/websocket/WsProtocol$Factory {
public fun <init> ()V
public fun build ()Lcom/apollographql/apollo3/network/websocket/WsProtocol;
public final fun connectionParams (Lkotlin/jvm/functions/Function1;)Lcom/apollographql/apollo3/network/websocket/GraphQLWsProtocol$Factory;
}

public final class com/apollographql/apollo3/network/websocket/JvmWebSocketEngine : com/apollographql/apollo3/network/websocket/WebSocketEngine {
public fun <init> (Lokhttp3/OkHttpClient;)V
public fun newWebSocket (Ljava/lang/String;Ljava/util/List;Lcom/apollographql/apollo3/network/websocket/WebSocketListener;)Lcom/apollographql/apollo3/network/websocket/WebSocket;
}

public final class com/apollographql/apollo3/network/websocket/OperationErrorServerMessage : com/apollographql/apollo3/network/websocket/ServerMessage {
public fun <init> (Ljava/lang/String;Ljava/lang/Object;)V
public final fun getId ()Ljava/lang/String;
public final fun getPayload ()Ljava/lang/Object;
}

public final class com/apollographql/apollo3/network/websocket/ParseErrorServerMessage : com/apollographql/apollo3/network/websocket/ServerMessage {
public fun <init> (Ljava/lang/String;)V
public final fun getErrorMessage ()Ljava/lang/String;
}

public final class com/apollographql/apollo3/network/websocket/PingServerMessage : com/apollographql/apollo3/network/websocket/ServerMessage {
public static final field INSTANCE Lcom/apollographql/apollo3/network/websocket/PingServerMessage;
}

public final class com/apollographql/apollo3/network/websocket/PongServerMessage : com/apollographql/apollo3/network/websocket/ServerMessage {
public static final field INSTANCE Lcom/apollographql/apollo3/network/websocket/PongServerMessage;
}

public final class com/apollographql/apollo3/network/websocket/ResponseServerMessage : com/apollographql/apollo3/network/websocket/ServerMessage {
public fun <init> (Ljava/lang/String;Ljava/lang/Object;Z)V
public final fun getComplete ()Z
public final fun getId ()Ljava/lang/String;
public final fun getResponse ()Ljava/lang/Object;
}

public abstract interface class com/apollographql/apollo3/network/websocket/ServerMessage {
}

public final class com/apollographql/apollo3/network/websocket/SubscriptionWsProtocol : com/apollographql/apollo3/network/websocket/WsProtocol {
public synthetic fun <init> (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun connectionInit (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun getConnectionParams ()Lkotlin/jvm/functions/Function1;
public fun getName ()Ljava/lang/String;
public fun operationStart (Lcom/apollographql/apollo3/api/ApolloRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun operationStop (Lcom/apollographql/apollo3/api/ApolloRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun parseServerMessage (Ljava/lang/String;)Lcom/apollographql/apollo3/network/websocket/ServerMessage;
public fun ping (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun pong (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class com/apollographql/apollo3/network/websocket/SubscriptionWsProtocol$Factory : com/apollographql/apollo3/network/websocket/WsProtocol$Factory {
public fun <init> ()V
public fun <init> (J)V
public fun <init> (JLkotlin/jvm/functions/Function1;)V
public fun <init> (JLkotlin/jvm/functions/Function1;Lcom/apollographql/apollo3/network/ws/WsFrameType;)V
public synthetic fun <init> (JLkotlin/jvm/functions/Function1;Lcom/apollographql/apollo3/network/ws/WsFrameType;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lkotlin/jvm/functions/Function1;)V
public synthetic fun <init> (Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun build ()Lcom/apollographql/apollo3/network/websocket/WsProtocol;
}

public final class com/apollographql/apollo3/network/websocket/TextClientMessage : com/apollographql/apollo3/network/websocket/ClientMessage {
public fun <init> (Ljava/lang/String;)V
public final fun getText ()Ljava/lang/String;
}

public abstract interface class com/apollographql/apollo3/network/websocket/WebSocket {
public abstract fun close (ILjava/lang/String;)V
public abstract fun connect ()V
public abstract fun send (Ljava/lang/String;)V
public abstract fun send ([B)V
}

public abstract interface class com/apollographql/apollo3/network/websocket/WebSocketEngine {
public abstract fun newWebSocket (Ljava/lang/String;Ljava/util/List;Lcom/apollographql/apollo3/network/websocket/WebSocketListener;)Lcom/apollographql/apollo3/network/websocket/WebSocket;
public static synthetic fun newWebSocket$default (Lcom/apollographql/apollo3/network/websocket/WebSocketEngine;Ljava/lang/String;Ljava/util/List;Lcom/apollographql/apollo3/network/websocket/WebSocketListener;ILjava/lang/Object;)Lcom/apollographql/apollo3/network/websocket/WebSocket;
}

public final class com/apollographql/apollo3/network/websocket/WebSocketEngine_jvmKt {
public static final fun WebSocketEngine ()Lcom/apollographql/apollo3/network/websocket/WebSocketEngine;
}

public abstract interface class com/apollographql/apollo3/network/websocket/WebSocketListener {
public abstract fun onClosed (Ljava/lang/Integer;Ljava/lang/String;)V
public abstract fun onError (Ljava/lang/Throwable;)V
public abstract fun onMessage (Ljava/lang/String;)V
public abstract fun onMessage ([B)V
public abstract fun onOpen ()V
}

public final class com/apollographql/apollo3/network/websocket/WebSocketNetworkTransport : com/apollographql/apollo3/network/NetworkTransport {
public synthetic fun <init> (Lkotlin/jvm/functions/Function1;Ljava/util/List;Lcom/apollographql/apollo3/network/websocket/WebSocketEngine;JLcom/apollographql/apollo3/network/websocket/WsProtocol$Factory;Lkotlin/jvm/functions/Function3;JJZLkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun closeConnection (Ljava/lang/Throwable;)V
public fun dispose ()V
public fun execute (Lcom/apollographql/apollo3/api/ApolloRequest;)Lkotlinx/coroutines/flow/Flow;
public final fun getAttempt ()J
public final fun getSubscriptionCount ()Lkotlinx/coroutines/flow/MutableStateFlow;
public final fun setAttempt (J)V
}

public final class com/apollographql/apollo3/network/websocket/WebSocketNetworkTransport$Builder {
public fun <init> ()V
public final fun addHeader (Ljava/lang/String;Ljava/lang/String;)Lcom/apollographql/apollo3/network/websocket/WebSocketNetworkTransport$Builder;
public final fun build ()Lcom/apollographql/apollo3/network/websocket/WebSocketNetworkTransport;
public final fun connectionAcknowledgeTimeoutMillis (J)Lcom/apollographql/apollo3/network/websocket/WebSocketNetworkTransport$Builder;
public final fun enableReopen (Z)Lcom/apollographql/apollo3/network/websocket/WebSocketNetworkTransport$Builder;
public final fun headers (Ljava/util/List;)Lcom/apollographql/apollo3/network/websocket/WebSocketNetworkTransport$Builder;
public final fun idleTimeoutMillis (J)Lcom/apollographql/apollo3/network/websocket/WebSocketNetworkTransport$Builder;
public final fun pingIntervalMillis (J)Lcom/apollographql/apollo3/network/websocket/WebSocketNetworkTransport$Builder;
public final fun protocol (Lcom/apollographql/apollo3/network/websocket/WsProtocol$Factory;)Lcom/apollographql/apollo3/network/websocket/WebSocketNetworkTransport$Builder;
public final fun reopenWhen (Lkotlin/jvm/functions/Function3;)Lcom/apollographql/apollo3/network/websocket/WebSocketNetworkTransport$Builder;
public final fun serverUrl (Ljava/lang/String;)Lcom/apollographql/apollo3/network/websocket/WebSocketNetworkTransport$Builder;
public final fun serverUrl (Lkotlin/jvm/functions/Function1;)Lcom/apollographql/apollo3/network/websocket/WebSocketNetworkTransport$Builder;
public final fun webSocketEngine (Lcom/apollographql/apollo3/network/websocket/WebSocketEngine;)Lcom/apollographql/apollo3/network/websocket/WebSocketNetworkTransport$Builder;
public final fun wsProtocolFactory (Lcom/apollographql/apollo3/network/websocket/WsProtocol$Factory;)Lcom/apollographql/apollo3/network/websocket/WebSocketNetworkTransport$Builder;
}

public abstract interface class com/apollographql/apollo3/network/websocket/WebSocketNetworkTransport$Event {
}

public abstract interface class com/apollographql/apollo3/network/websocket/WsProtocol {
public abstract fun connectionInit (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun getName ()Ljava/lang/String;
public abstract fun operationStart (Lcom/apollographql/apollo3/api/ApolloRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun operationStop (Lcom/apollographql/apollo3/api/ApolloRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun parseServerMessage (Ljava/lang/String;)Lcom/apollographql/apollo3/network/websocket/ServerMessage;
public abstract fun ping (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun pong (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public abstract interface class com/apollographql/apollo3/network/websocket/WsProtocol$Factory {
public abstract fun build ()Lcom/apollographql/apollo3/network/websocket/WsProtocol;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
plugins {
id("org.jetbrains.kotlin.multiplatform")
}

apolloLibrary(
javaModuleName = "com.apollographql.apollo3.network.websocket",
withLinux = false
)

kotlin {
sourceSets {
findByName("commonMain")?.apply {
dependencies {
api(project(":apollo-runtime"))
api(project(":apollo-mpp-utils"))
api(libs.atomicfu)
}
}

findByName("commonTest")?.apply {
dependencies {
implementation(project(":apollo-mockserver"))
implementation(project(":apollo-testing-support")) {
because("runTest")
}
}
}

findByName("jsMain")?.apply {
dependencies {
/**
* WebSocket implementation for node
*/
api(npm("ws", libs.versions.node.ws.get()))
/**
* Kotlin Node declarations
*
* The situation is a bit weird because jsMain has both browser and node dependencies but
* there is not much we can do about it
* See https://youtrack.jetbrains.com/issue/KT-47038
*/
implementation(libs.kotlin.node)
}
}
}
}
Loading
Loading