A Gleam WebSocket consumer for AT Protocol Jetstream events.

fix decompression algo for smaller frames ie delete commits

Changed files
+27 -13
src
+27 -13
src/goose_ws_ffi.erl
··· 145 145 DictPath = filename:join(PrivDir, "zstd_dictionary"), 146 146 case file:read_file(DictPath) of 147 147 {ok, DictData} -> 148 - %% Create decompression dictionary (returns reference directly) 148 + %% Create decompression context and dictionary 149 + DCtx = ezstd:create_decompression_context(1024 * 1024), 149 150 DDict = ezstd:create_ddict(DictData), 150 - {ok, DDict}; 151 + %% Select the dictionary for the decompression context 152 + ok = ezstd:select_ddict(DCtx, DDict), 153 + {ok, {DCtx, DDict}}; 151 154 {error, Err} -> 152 - io:format("Failed to read zstd dictionary: ~p~n", [Err]), 155 + io:format("Failed to load zstd dictionary: ~p~n", [Err]), 153 156 {error, Err} 154 157 end; 155 158 _ -> ··· 166 169 {gun_ws, _AnyConnPid, _AnyStreamRef, {binary, Binary}} -> 167 170 %% If compression is enabled, decompress the binary data 168 171 case {Compress, Decompressor} of 169 - {true, {ok, DDict}} -> 170 - try 171 - %% decompress_using_ddict returns the decompressed data directly 172 - Decompressed = ezstd:decompress_using_ddict(Binary, DDict), 173 - %% Ensure it's treated as a binary (not iolist) 174 - DecompressedBin = iolist_to_binary([Decompressed]), 175 - HandlerPid ! {ws_text, DecompressedBin} 176 - catch 177 - Error:Reason:_Stacktrace -> 178 - io:format("Decompression failed: ~p:~p~n", [Error, Reason]) 172 + {true, {ok, {DCtx, DDict}}} -> 173 + %% Try decompress_using_ddict first (works for frames with content size) 174 + case ezstd:decompress_using_ddict(Binary, DDict) of 175 + Result when is_binary(Result) -> 176 + HandlerPid ! {ws_text, Result}; 177 + Result when is_list(Result) -> 178 + HandlerPid ! {ws_text, iolist_to_binary(Result)}; 179 + {error, <<"failed to decompress: ZSTD_CONTENTSIZE_UNKNOWN">>} -> 180 + %% Frame doesn't have content size, use streaming with dictionary-loaded context 181 + case ezstd:decompress_streaming(DCtx, Binary) of 182 + StreamResult when is_binary(StreamResult) -> 183 + HandlerPid ! {ws_text, StreamResult}; 184 + StreamResult when is_list(StreamResult) -> 185 + HandlerPid ! {ws_text, iolist_to_binary(StreamResult)}; 186 + {error, _StreamReason} -> 187 + %% Skip frames that fail to decompress 188 + ok 189 + end; 190 + {error, _Reason} -> 191 + %% Skip frames that fail to decompress 192 + ok 179 193 end; 180 194 _ -> 181 195 %% No compression, ignore binary messages