Skip to content

Conversation

@bencoppock
Copy link

@bencoppock bencoppock commented Oct 25, 2025

Decoding binary-encoded payloads using Slipstream.Serializer.PhoenixSocketV2Serializer results in garbled values. Encoding seems correct, but the pattern match for decoding isn't properly accounting for a couple of ref-related values that Phoenix uses…

I've added a round trip test that ensures decoding a binary-encoded value returns the original value. I also added a round trip test for non-binary json encoding just for good measure (it wasn't broken).

These changes bring SlipStream's implementation in line with what I'm seeing In Phoenix itself:
https://github.com/phoenixframework/phoenix/blob/v1.8.1/lib/phoenix/socket/serializers/v2_json_serializer.ex#L124C8-L124C21

@bencoppock
Copy link
Author

I'm seeing that running mix bless on main results in the same code coverage failure as this PR (with the exact same coverage percentages).

Is that going to be a blocker for getting PRs merged? I don't mind circling back and seeing what I can do about those 3 missed lines, but it might be a few days before I get to it…

@the-mikedavis
Copy link
Collaborator

It looks like the CI is failing here because of a test case rather than coverage. I can reproduce the failure locally:

  1) test given a connection joined to a good topic a binary message may be received synchronously (Slipstream.SynchronicityTest)
     test/slipstream/synchronicity_test.exs:124
     match (=) failed
     The following variables were pinned:
       topic = "test:good"
       expected_payload = {:binary, <<2, 3>>}
     code:  assert {:ok, ^topic, "foo", ^expected_payload} = await_message(^topic, "foo", ^expected_payload)
     left:  {:ok, ^topic, "foo", ^expected_payload}
     right: {:error, :timeout}
     stacktrace:
       test/slipstream/synchronicity_test.exs:132: (test)

@bencoppock
Copy link
Author

It looks like the CI is failing here because of a test case rather than coverage. I can reproduce the failure locally:

Oh, you're totally right! Guess I didn't notice that test failure when I ran mix bless.

It's not obvious to me what the correct answer is here. I think my change makes sense, but I'm not super familiar with Phoenix Channels implementation (or SlipStream, for that matter).

Would you prefer I close this PR until I've got something more concrete to offer? Or leave it open for a bit in the hopes I find time to wrap my head around it shortly?

Encoding was correct, but the pattern match for decoding wasn't
properly accounting for a couple of values that Phoenix uses.

Added a round trip test for binary encoding to verify that encode/decode
returns the original value. Also added a round trip test for non-binary
json encoding for good measure (even though it wasn't broken).
@bencoppock bencoppock force-pushed the fix-broken-decode-binary branch from be6f551 to f5fd66f Compare October 29, 2025 17:16
Copy link
Collaborator

@the-mikedavis the-mikedavis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind leaving the PR open. Do you have steps to reproduce the problem you're seeing? The code on main looks correct to me so I'm not sure where the garbled values are coming from

end

defp decode_binary!(<<
@push::size(8),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the current implementation for decode_binary!/1 is correct: this clause is decoding binary pushes and the clause below is for replies. I would need to check the Phoenix code again but I think only the reply binary has the ref_size and ref parts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants