Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for Spanner queues by adding Send and Ack command types, updating the command builder and connection classes, and introducing queue-related test fixtures and integration tests. Feedback on the changes highlights syntax errors in the queue creation SQL statement, an integration test that defines commands but never executes or disposes of them, and a public field that should be private and readonly. Additionally, there is a copy-paste error in the XML documentation for CreateSendCommand, and a potential NullReferenceException in a SpannerCommand constructor because the null check on key is executed after the constructor initializer.
6fde46a to
d858058
Compare
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces support for Spanner Queues by adding Send and Ack commands, updating SpannerCommand and SpannerConnection to handle queue operations, and adding integration tests. The review feedback highlights several issues to address, including a syntax error from a trailing comma in the CREATE QUEUE DDL, a code smell from calling an abstract method in a constructor, timezone-related issues from using DateTime.Now instead of DateTime.UtcNow, hardcoded personal test configurations, a potential NullReferenceException when validating Payload, and various copy-paste errors in exception messages and XML documentation.
d858058 to
47daa5d
Compare
085d8cc to
e83cef5
Compare
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces support for Spanner queues by adding 'Send' and 'Ack' command types to SpannerCommand, along with corresponding integration tests and fixtures. The review feedback highlights several critical issues and improvement opportunities: a syntax error (trailing comma) in the queue creation DDL, synchronous blocking in the test fixture setup, a lack of validation for single-key constraints on Send and Ack commands, a potential runtime failure when validating inferred payload types, and missing property copies in the SpannerCommand copy constructor which would break cloning.
f2a5bc7 to
e848450
Compare
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces support for Spanner database queues by adding Send and Ack command types, along with corresponding connection helper methods, test fixtures, and unit/integration tests. However, there are critical issues in the implementation: the state checks validating that exactly one key is provided for Send and Ack mutations are inverted, which will cause runtime failures when valid inputs are provided. Additionally, a trailing comma in the CREATE QUEUE DDL statement in MutationsQueueFixture.cs will result in a syntax error at runtime.
69a5e27 to
90dd96d
Compare
|
@amanda-tarafa removing you to try cutting down noise until this is ready for review again |
1d43440 to
51a10db
Compare
51b22de to
5fa8509
Compare
amanda-tarafa
left a comment
There was a problem hiding this comment.
Only partially reviewed, but better to get the changes I request in before continuing. These are bound to change things further own.
| /// </summary> | ||
| /// <param name="databaseQueue">The name of the queue to send a message to. Must not be null.</param> | ||
| /// <param name="parameters">A collection of <see cref="SpannerParameter"/> that comprise | ||
| /// the message key and Payload. Requires a Payload and at least one non-payload parameter.</param> |
There was a problem hiding this comment.
Do we need to validate that the key is present? Even if it's required by Spanner, if there's nothing and we set it to nothing, then Spanner will fail.
And actually, we can do that for Payload as well, we attempt to extract payload, but if it's not there, we just set it to nothin and let Spanner fail.
Yes, I think this approach matches better our philosophy of keeping validations to a minimum client side. And when you make these changes, make sure to update this comment here to say something like "A collection of parameters that should contain the key elements and the payload."
And same for the other.
| internal static SpannerCommand ForSendCommand( | ||
| SpannerCommandTextBuilder commandTextBuilder, | ||
| SpannerConnection connection, | ||
| SpannerParameterCollection parameters, | ||
| SpannerTransaction transaction = null) => new(commandTextBuilder, connection, transaction, parameters); | ||
|
|
||
| internal static SpannerCommand ForAckCommand( | ||
| SpannerCommandTextBuilder commandTextBuilder, | ||
| SpannerConnection connection, | ||
| SpannerParameterCollection parameters, | ||
| SpannerTransaction transaction = null) => new(commandTextBuilder, connection, transaction, parameters); | ||
|
|
There was a problem hiding this comment.
Why do we add this layer here that we don't have for any of the other commands. Let's just use the SpannerCommand constructor anywhere when we create send and ack.
| /// Note: "Insert" and "Delete" are never treated as Send and Ack even when the | ||
| /// target table is internally a queue. |
There was a problem hiding this comment.
| /// Note: "Insert" and "Delete" are never treated as Send and Ack even when the | |
| /// target table is internally a queue. | |
| /// Note: `insert <name>` and `delete <name>` are always interpreted as insert and delete mutations, never as send or ack mutations. |
| /// <summary> | ||
| /// Optional configurations for Send mutations. | ||
| /// </summary> | ||
| public SendOptions SendOptions { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Optional configurations for Ack mutations. | ||
| /// </summary> | ||
| public AckOptions AckOptions { get; set; } | ||
|
|
There was a problem hiding this comment.
In docs, add a note, like the one we have in DirectedRead for instance, saying that these will be ignored for all other operations.
| /// Note: Insert and Delete are never treated as Send and Ack even when the | ||
| /// target table is internally a queue. |
There was a problem hiding this comment.
Same wording as in the other one.
| private const string SendCommand = "SEND"; | ||
| private const string AckCommand = "ACK"; |
There was a problem hiding this comment.
We are not parsing these, so why do we need these constants for? We cannot represent these as text, we should use the empty string for the text command here, similar to what we do for Read IIRC.
| /// <param name="queue">The name of the Spanner database queue for which messages will be acked. Must not be null.</param> | ||
| /// <returns>A <see cref="SpannerCommandTextBuilder"/> representing a <see cref="F:SpannerCommandType.Ack"/> Spanner command.</returns> | ||
| public static SpannerCommandTextBuilder CreateAckTextBuilder(string queue) => | ||
| CreateBuilderForTableDml(AckCommand, SpannerCommandType.Ack, queue); |
There was a problem hiding this comment.
I think you need to create a new method CreateBuilderForQueueMutation that only receives the type and the name of the queue. We need to add a new public property here called TargetQueue that's equivalent to TargetTable but only one of those can be set at any given time.
b/422231498
Suggested path for reviewing
SendandAckmethods inSpannerConnection.cs, and then look at the first test of QueueTests.cs` in the integration test project to see a basic usage.SpannerCommand.ExecutableCommandaround lines 400. This is the portion of code that packages theSendandAckmutations into the protobuf message wire typeCreateSendCommandpublic method down to the part that prepares the mutation protobuf types from aboveDMN until squash