Repository navigation
Phase 1: read a whole message off a socket - #3
Merged
Merged
Conversation
The socket half of framing. decode_message/1 says :more when the buffer holds less than a message; this reads again until it does not, so nothing above this layer sees a partial read. The socket is reached through a Mysqlex.Transport behaviour rather than :gen_tcp directly. That is what makes the read loop testable: the test scripts a transport that delivers "hello" across three reads, splitting mid-header, which is exactly the case a real server produces under load and the case the 2018 code could not be made to exercise at all. Callbacks get added to the behaviour as the client needs them — recv/3 is all this slice uses.
A server that disconnects mid-message must not leave the read loop spinning. The error comes back to the caller, who decides whether the connection is still usable.
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #1, which it needs for
Mysqlex.Packet. GitHub will retarget this atmasteronce #1 merges.The socket half of framing.
decode_message/1returns:morewhen the buffer holds less than a message; this reads again until it doesn't, so no parser above this layer ever sees a partial read.What is here
Mysqlex.Transport— the behaviour the client reads through. One callback so far,recv/3; more get added as the client needs them.Mysqlex.Tcp— now declares the behaviour.Mysqlex.Client.recv_message/4— the read loop.Mysqlex.FakeTransportintest/support/— replays a scripted list of byte chunks.mix.exsgainselixirc_pathssotest/supportcompiles in the test environment.Why the behaviour
This is the seam that makes the rest of the protocol testable. The test that matters:
A message split across three reads, broken mid-header — the length in one read, the sequence id and part of the payload in the next, the remainder in a third. That is what a real server produces under load, and it is the case the 2018 code could not exercise at all, because the parser owned the socket.
The same seam is what will let the connection phase be tested without a database: capability negotiation, auth switches, the RSA path and TLS upgrade decisions are all branches that otherwise need specially configured live servers, which in practice means they never get tested.
Note on the buffer
recv_message/4takes a buffer in and handsrestback out, so the caller carries leftover bytes between messages rather than the transport holding hidden state. Appending withbuffer <> datarelies on the VM's binary append optimisation rather than an explicit iodata accumulator — worth revisiting if profiling ever says so.