Implement the PostgreSQL Streaming Replication Protocol#3281
Implement the PostgreSQL Streaming Replication Protocol#3281Brar merged 56 commits intonpgsql:mainfrom
Conversation
This type was added in PostgreSQL 9.4 and we didn't handle it yet. While a type handler and a specific type isnt't strictly necessary for the implementation of replication in Npgsql it will probably be useful once people start using the replication feature and want to query their database regading replication related information like pg_replication_slots.
There was a very old ToDo-comment in the code because TimestampHandler and TimestampTzHandler were passing values through NpgsqlDateTime in order to convert them from/to the backend representation. For Replication we need to convert timestamps in a completely separate part of the codebase so we change it now and benefit from it multiple times.
|
@ Reviewers: Please don't bother investigating failing tests for now. I know about their flakiness and I expect to remove/disable most of them in the course of the review process. Also I'll add one additional commit to stop the timers when cancelling (it was on my todo-list but somehow I forgot it last night). |
roji
left a comment
There was a problem hiding this comment.
Here's a first partial round - I've gone through about half the files (I think), and it looks great. I've made lots of comments, but marked certain ones as IMPORTANT - anything without that can probably be ignored for now (up to you).
You should probably add yourself to CODEOWNERS for the appropriate paths 🤣
src/Npgsql/Replication/Logical/Protocol/NpgsqlLogicalReplicationConnectionExtensions.cs
Outdated
Show resolved
Hide resolved
src/Npgsql/Replication/Logical/Protocol/NpgsqlLogicalReplicationConnectionExtensions.cs
Outdated
Show resolved
Hide resolved
src/Npgsql/Replication/Logical/Protocol/NpgsqlLogicalReplicationConnectionExtensions.cs
Outdated
Show resolved
Hide resolved
src/Npgsql/Replication/Logical/Protocol/NpgsqlLogicalReplicationConnectionExtensions.cs
Outdated
Show resolved
Hide resolved
src/Npgsql/Replication/Logical/Protocol/NpgsqlLogicalReplicationConnectionExtensions.cs
Outdated
Show resolved
Hide resolved
…onConnectionExtensions.cs
If wal_sender_timeout is more than 3 seconds. We don't want this test to inexplicably hang for 60s (by default).
src/Npgsql/Replication/Logical/Protocol/NpgsqlLogicalReplicationConnectionExtensions.cs
Outdated
Show resolved
Hide resolved
src/Npgsql/Replication/Logical/Protocol/NpgsqlLogicalReplicationConnectionExtensions.cs
Outdated
Show resolved
Hide resolved
src/Npgsql/Replication/Logical/Internal/NpgsqlLogicalReplicationConnectionExtensions.cs
Outdated
Show resolved
Hide resolved
src/Npgsql/Replication/TestDecoding/NpgsqlTestDecodingPluginOptions.cs
Outdated
Show resolved
Hide resolved
src/Npgsql/Replication/Internal/LogicalReplicationConnectionExtensions.cs
Show resolved
Hide resolved
This reverts commit 3be4e28.
Also just DRY a bit
|
From my side, we're very close to merging this for 5.0. Some notes:
|
Previous commit was a test cleanup
| async ValueTask<string> ReadLong(string s) | ||
| { | ||
| var builder = new StringBuilder(s); | ||
| bool complete; | ||
| do | ||
| { | ||
| await ReadMore(async, cancellationToken); | ||
| complete = ReadFromBuffer(out s); | ||
| builder.Append(s); | ||
| } | ||
| while (!complete); | ||
|
|
||
| return builder.ToString(); | ||
| } |
There was a problem hiding this comment.
Maybe a bit late, but I think this code will fail if the split is in the middle of a unicode character that uses more than 1 byte to represent. Better Ensure the max length of a string is already present in the buffer (as it was previously), or create a temporary byte buffer with all the data which you then convert to a string in one go using the encoding.
There was a problem hiding this comment.
You're technically right... However, note that this is for reading null-terminated strings, which AFAIK are only used for certain short ASCII control strings, rather than actual user data - so I doubt there's a real bug here. But you can open a new issue to at least have it tracked.
BTW if we do want to preemptively fix this, then rather than entirely buffering the strings them in a temporary buffer, we can use System.Text.Decoder to incrementally load more chunks a decode. Note that we haven't even done this optimization for actual user strings (which are probably much more important, see TextHandler.ReadLong).
There was a problem hiding this comment.
At least in the replication protocol they are used for user data as well, for example table names, which can contain non-ascii characters.
I don't see why System.Text.Decoder would be anything better. It gives you some chars on every iteration. These chars are temporary anyway and must then be made into a string, after which the previously buffered chars are discarded. But generally a char[] takes up more memory than the corresponding byte[] in UTF8, so I think it's better to just buffer everything as bytes. The encoder can then convert these to a string in-place, with no extra temporary space.
There was a problem hiding this comment.
You're right... IIRC that's why I didn't do it in TextHandler either.
Open an issue for us to fix this?
Closes #1520