From 2cf1c1cd3ab118d11e219318c2ae7a1ee573e444 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 3 Oct 2024 23:30:19 +0200 Subject: [PATCH] support none/gzip in C# sdk --- src/Compression.cs | 9 ++++ .../ClientApi/CompressableQueryUpdate.cs | 3 +- src/SpacetimeDBClient.cs | 48 ++++++++++++------- src/WebSocket.cs | 4 +- 4 files changed, 43 insertions(+), 21 deletions(-) create mode 100644 src/Compression.cs diff --git a/src/Compression.cs b/src/Compression.cs new file mode 100644 index 0000000..8f630f9 --- /dev/null +++ b/src/Compression.cs @@ -0,0 +1,9 @@ +namespace SpacetimeDB +{ + public enum Compression + { + None, + Brotli, + Gzip, + } +} diff --git a/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs b/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs index af397a5..1af6fd2 100644 --- a/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs +++ b/src/SpacetimeDB/ClientApi/CompressableQueryUpdate.cs @@ -12,6 +12,7 @@ namespace SpacetimeDB.ClientApi [SpacetimeDB.Type] public partial record CompressableQueryUpdate : SpacetimeDB.TaggedEnum<( SpacetimeDB.ClientApi.QueryUpdate Uncompressed, - byte[] Brotli + byte[] Brotli, + byte[] Gzip )>; } diff --git a/src/SpacetimeDBClient.cs b/src/SpacetimeDBClient.cs index 5ba858f..de6c7d5 100644 --- a/src/SpacetimeDBClient.cs +++ b/src/SpacetimeDBClient.cs @@ -22,6 +22,7 @@ public sealed class DbConnectionBuilder string? uri; string? nameOrAddress; string? token; + Compression? compression; public DbConnection Build() { @@ -33,7 +34,7 @@ public DbConnection Build() { throw new InvalidOperationException("Building DbConnection with a null nameOrAddress. Call WithModuleName() first."); } - conn.Connect(token, uri, nameOrAddress); + conn.Connect(token, uri, nameOrAddress, compression ?? Compression.Brotli); #if UNITY_5_3_OR_NEWER SpacetimeDBNetworkManager.ActiveConnections.Add(conn); #endif @@ -58,6 +59,12 @@ public DbConnectionBuilder WithCredentials(in (Identity i return this; } + public DbConnectionBuilder WithCompression(Compression compression) + { + this.compression = compression; + return this; + } + public DbConnectionBuilder OnConnect(Action cb) { conn.onConnect += (identity, token) => cb.Invoke(conn, identity, token); @@ -205,6 +212,17 @@ enum CompressionAlgos : byte { None = 0, Brotli = 1, + Gzip = 2, + } + + private static BinaryReader BrotliReader(Stream stream) + { + return new BinaryReader(new BrotliStream(stream, CompressionMode.Decompress)); + } + + private static BinaryReader GzipReader(Stream stream) + { + return new BinaryReader(new GZipStream(stream, CompressionMode.Decompress)); } private static ServerMessage DecompressDecodeMessage(byte[] bytes) @@ -217,16 +235,11 @@ private static ServerMessage DecompressDecodeMessage(byte[] bytes) switch (compression) { case CompressionAlgos.None: - { - using var binaryReader = new BinaryReader(stream); - return new ServerMessage.BSATN().Read(binaryReader); - } + return new ServerMessage.BSATN().Read(new BinaryReader(stream)); case CompressionAlgos.Brotli: - { - using var decompressedStream = new BrotliStream(stream, CompressionMode.Decompress); - using var binaryReader = new BinaryReader(decompressedStream); - return new ServerMessage.BSATN().Read(binaryReader); - } + return new ServerMessage.BSATN().Read(BrotliReader(stream)); + case CompressionAlgos.Gzip: + return new ServerMessage.BSATN().Read(GzipReader(stream)); default: throw new InvalidOperationException("Unknown compression type"); } @@ -240,12 +253,11 @@ private static QueryUpdate DecompressDecodeQueryUpdate(CompressableQueryUpdate u return qu; case CompressableQueryUpdate.Brotli(var bytes): - { - using var stream = new MemoryStream(bytes); - using var decompressedStream = new BrotliStream(stream, CompressionMode.Decompress); - using var binaryReader = new BinaryReader(decompressedStream); - return new QueryUpdate.BSATN().Read(binaryReader); - } + return new QueryUpdate.BSATN().Read(BrotliReader(new MemoryStream(bytes))); + + case CompressableQueryUpdate.Gzip(var bytes): + return new QueryUpdate.BSATN().Read(GzipReader(new MemoryStream(bytes))); + default: throw new InvalidOperationException(); } @@ -575,7 +587,7 @@ public void Disconnect() /// /// URI of the SpacetimeDB server (ex: https://testnet.spacetimedb.com) /// The name or address of the database to connect to - internal void Connect(string? token, string uri, string addressOrName) + internal void Connect(string? token, string uri, string addressOrName, Compression compression) { isClosing = false; @@ -593,7 +605,7 @@ internal void Connect(string? token, string uri, string addressOrName) { try { - await webSocket.Connect(token, uri, addressOrName, Address); + await webSocket.Connect(token, uri, addressOrName, Address, compression); } catch (Exception e) { diff --git a/src/WebSocket.cs b/src/WebSocket.cs index cd22c26..dd0dae7 100644 --- a/src/WebSocket.cs +++ b/src/WebSocket.cs @@ -50,9 +50,9 @@ public WebSocket(ConnectOptions options) public bool IsConnected { get { return Ws != null && Ws.State == WebSocketState.Open; } } - public async Task Connect(string? auth, string host, string nameOrAddress, Address clientAddress) + public async Task Connect(string? auth, string host, string nameOrAddress, Address clientAddress, Compression compression) { - var url = new Uri($"{host}/database/subscribe/{nameOrAddress}?client_address={clientAddress}"); + var url = new Uri($"{host}/database/subscribe/{nameOrAddress}?client_address={clientAddress}&compression={nameof(compression)}"); Ws.Options.AddSubProtocol(_options.Protocol); var source = new CancellationTokenSource(10000);