-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Provides a contract for client applications to use a custom http/2 implementation. Roughly abstracted from our TypeScript grpc-web library, with a few rough edges taken off, and no external dependencies. Two integration tests are included, one which requires https (presently only possible with manual testing, see #6421), and one which pretends to contact the server but really responds to every request with a "success" response and no payload. No documentation required at this time, generated typescript includes details on the new APIs. Fixes #6404 Backport #6476
- Loading branch information
Showing
13 changed files
with
511 additions
and
52 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
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
74 changes: 74 additions & 0 deletions
74
web/client-api/src/main/java/io/deephaven/web/client/api/grpc/GrpcTransport.java
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,74 @@ | ||
// | ||
// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending | ||
// | ||
package io.deephaven.web.client.api.grpc; | ||
|
||
import com.vertispan.tsdefs.annotations.TsInterface; | ||
import elemental2.core.Uint8Array; | ||
import io.deephaven.javascript.proto.dhinternal.browserheaders.BrowserHeaders; | ||
import io.deephaven.javascript.proto.dhinternal.grpcweb.grpc.Transport; | ||
import jsinterop.annotations.JsIgnore; | ||
import jsinterop.annotations.JsType; | ||
import jsinterop.base.JsPropertyMap; | ||
|
||
/** | ||
* gRPC transport implementation. | ||
* | ||
*/ | ||
@JsType(namespace = "dh.grpc") | ||
@TsInterface | ||
public interface GrpcTransport { | ||
/** | ||
* Starts the stream, sending metadata to the server. | ||
* | ||
* @param metadata the headers to send the server when opening the connection | ||
*/ | ||
void start(JsPropertyMap<HeaderValueUnion> metadata); | ||
|
||
/** | ||
* Sends a message to the server. | ||
* | ||
* @param msgBytes bytes to send to the server | ||
*/ | ||
void sendMessage(Uint8Array msgBytes); | ||
|
||
/** | ||
* "Half close" the stream, signaling to the server that no more messages will be sent, but that the client is still | ||
* open to receiving messages. | ||
*/ | ||
void finishSend(); | ||
|
||
/** | ||
* End the stream, both notifying the server that no more messages will be sent nor received, and preventing the | ||
* client from receiving any more events. | ||
*/ | ||
void cancel(); | ||
|
||
/** | ||
* Helper to transform ts implementations to our own api. | ||
*/ | ||
@JsIgnore | ||
static GrpcTransport from(Transport tsTransport) { | ||
return new GrpcTransport() { | ||
@Override | ||
public void start(JsPropertyMap<HeaderValueUnion> metadata) { | ||
tsTransport.start(new BrowserHeaders(metadata)); | ||
} | ||
|
||
@Override | ||
public void sendMessage(Uint8Array msgBytes) { | ||
tsTransport.sendMessage(msgBytes); | ||
} | ||
|
||
@Override | ||
public void finishSend() { | ||
tsTransport.finishSend(); | ||
} | ||
|
||
@Override | ||
public void cancel() { | ||
tsTransport.cancel(); | ||
} | ||
}; | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
web/client-api/src/main/java/io/deephaven/web/client/api/grpc/GrpcTransportFactory.java
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,70 @@ | ||
// | ||
// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending | ||
// | ||
package io.deephaven.web.client.api.grpc; | ||
|
||
import com.vertispan.tsdefs.annotations.TsInterface; | ||
import elemental2.core.Uint8Array; | ||
import io.deephaven.javascript.proto.dhinternal.browserheaders.BrowserHeaders; | ||
import io.deephaven.javascript.proto.dhinternal.grpcweb.transports.transport.Transport; | ||
import io.deephaven.javascript.proto.dhinternal.grpcweb.transports.transport.TransportFactory; | ||
import jsinterop.annotations.JsOverlay; | ||
import jsinterop.annotations.JsProperty; | ||
import jsinterop.annotations.JsType; | ||
import jsinterop.base.Js; | ||
|
||
/** | ||
* Factory for creating gRPC transports. | ||
*/ | ||
@TsInterface | ||
@JsType(namespace = "dh.grpc", isNative = true) | ||
public interface GrpcTransportFactory { | ||
/** | ||
* Create a new transport instance. | ||
* | ||
* @param options options for creating the transport | ||
* @return a transport instance to use for gRPC communication | ||
*/ | ||
GrpcTransport create(GrpcTransportOptions options); | ||
|
||
/** | ||
* Return true to signal that created transports may have {@link GrpcTransport#sendMessage(Uint8Array)} called on it | ||
* more than once before {@link GrpcTransport#finishSend()} should be called. | ||
* | ||
* @return true to signal that the implementation can stream multiple messages, false otherwise indicating that | ||
* Open/Next gRPC calls should be used | ||
*/ | ||
@JsProperty | ||
boolean getSupportsClientStreaming(); | ||
|
||
/** | ||
* Adapt this factory to the transport factory used by the gRPC-web library. | ||
*/ | ||
@JsOverlay | ||
default TransportFactory adapt() { | ||
return options -> { | ||
GrpcTransport impl = create(GrpcTransportOptions.from(options)); | ||
return new Transport() { | ||
@Override | ||
public void cancel() { | ||
impl.cancel(); | ||
} | ||
|
||
@Override | ||
public void finishSend() { | ||
impl.finishSend(); | ||
} | ||
|
||
@Override | ||
public void sendMessage(Uint8Array msgBytes) { | ||
impl.sendMessage(msgBytes); | ||
} | ||
|
||
@Override | ||
public void start(BrowserHeaders metadata) { | ||
impl.start(Js.cast(metadata.headersMap)); | ||
} | ||
}; | ||
}; | ||
} | ||
} |
92 changes: 92 additions & 0 deletions
92
web/client-api/src/main/java/io/deephaven/web/client/api/grpc/GrpcTransportOptions.java
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,92 @@ | ||
// | ||
// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending | ||
// | ||
package io.deephaven.web.client.api.grpc; | ||
|
||
import com.vertispan.tsdefs.annotations.TsInterface; | ||
import elemental2.core.JsError; | ||
import elemental2.core.Uint8Array; | ||
import elemental2.dom.URL; | ||
import io.deephaven.javascript.proto.dhinternal.browserheaders.BrowserHeaders; | ||
import io.deephaven.javascript.proto.dhinternal.grpcweb.transports.transport.TransportOptions; | ||
import jsinterop.annotations.JsFunction; | ||
import jsinterop.annotations.JsIgnore; | ||
import jsinterop.annotations.JsNullable; | ||
import jsinterop.annotations.JsOptional; | ||
import jsinterop.annotations.JsType; | ||
import jsinterop.base.JsPropertyMap; | ||
|
||
/** | ||
* Options for creating a gRPC stream transport instance. | ||
*/ | ||
@TsInterface | ||
@JsType(namespace = "dh.grpc") | ||
public class GrpcTransportOptions { | ||
@JsFunction | ||
@FunctionalInterface | ||
public interface OnHeadersCallback { | ||
void onHeaders(JsPropertyMap<HeaderValueUnion> headers, int status); | ||
} | ||
|
||
@JsFunction | ||
@FunctionalInterface | ||
public interface OnChunkCallback { | ||
void onChunk(Uint8Array chunk); | ||
} | ||
|
||
@JsFunction | ||
@FunctionalInterface | ||
public interface OnEndCallback { | ||
void onEnd(@JsOptional @JsNullable JsError error); | ||
} | ||
|
||
/** | ||
* The gRPC method URL. | ||
*/ | ||
public URL url; | ||
|
||
/** | ||
* True to enable debug logging for this stream. | ||
*/ | ||
public boolean debug; | ||
|
||
/** | ||
* Callback for when headers and status are received. The headers are a map of header names to values, and the | ||
* status is the HTTP status code. If the connection could not be made, the status should be 0. | ||
*/ | ||
public OnHeadersCallback onHeaders; | ||
|
||
/** | ||
* Callback for when a chunk of data is received. | ||
*/ | ||
public OnChunkCallback onChunk; | ||
|
||
/** | ||
* Callback for when the stream ends, with an error instance if it can be provided. Note that the present | ||
* implementation does not consume errors, even if provided. | ||
*/ | ||
public OnEndCallback onEnd; | ||
|
||
/** | ||
* Internal copy of options, to be used for fallback. | ||
*/ | ||
@JsIgnore | ||
public TransportOptions originalOptions; | ||
|
||
/** | ||
* Convert a {@link TransportOptions} instance to a {@link GrpcTransportOptions} instance. | ||
*/ | ||
@JsIgnore | ||
public static GrpcTransportOptions from(TransportOptions options) { | ||
GrpcTransportOptions impl = new GrpcTransportOptions(); | ||
impl.url = new URL(options.getUrl()); | ||
impl.debug = options.isDebug(); | ||
impl.onHeaders = (headers, status) -> options.getOnHeaders().onInvoke(new BrowserHeaders(headers), status); | ||
impl.onChunk = p0 -> { | ||
// "false" because the underlying implementation doesn't rely on this anyway. | ||
options.getOnChunk().onInvoke(p0, false); | ||
}; | ||
impl.onEnd = options.getOnEnd()::onInvoke; | ||
return impl; | ||
} | ||
} |
Oops, something went wrong.