Skip to content

feat: Add ReadFrom parsing support to ConfigurationOptions for AZ Affinity #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

jbrinkman
Copy link
Collaborator

Summary

This PR implements comprehensive ReadFrom parsing support in ConfigurationOptions to enable AZ (Availability Zone) affinity configuration through connection strings and programmatic configuration. This addresses issue #26 by providing a complete implementation of ReadFrom strategy parsing, validation, and serialization.

Changes Made

Core Implementation

  • ReadFrom Parsing: Added support for parsing readFrom and az parameters from connection strings
  • Strategy Validation: Implemented comprehensive validation for ReadFromStrategy and AZ parameter combinations
  • Serialization Support: Added ToString formatting for ReadFrom configurations with round-trip integrity
  • Property Validation: Enhanced ReadFrom property setter with cross-validation logic
  • Error Handling: Comprehensive error messages and validation throughout the pipeline

Supported ReadFrom Strategies

  • Primary - Always read from primary nodes
  • PreferReplica - Prefer replica nodes, fallback to primary
  • AzAffinity - Prefer replicas in the same AZ, with fallback
  • AzAffinityReplicasAndPrimary - Prefer nodes in the same AZ (replicas first, then primary), with fallback

Connection String Examples

localhost:6379,readFrom=Primary
localhost:6379,readFrom=PreferReplica  
localhost:6379,readFrom=AzAffinity,az=us-east-1a
localhost:6379,readFrom=AzAffinityReplicasAndPrimary,az=eu-west-1b

Test Coverage

  • 992 lines of comprehensive end-to-end integration tests
  • 48 test cases covering complete configuration pipeline
  • Connection string parsing to FFI layer verification
  • Error handling and validation scenarios
  • Round-trip serialization integrity
  • Backward compatibility with legacy configurations
  • Performance testing with concurrent connections
  • Both standalone and cluster client scenarios

Technical Details

Implementation Approach

  1. Connection String Parsing: Extended DoParse method to handle readFrom and az parameters
  2. Validation Logic: Implemented ValidateAndSetReadFrom with comprehensive strategy/AZ validation
  3. Serialization: Added FormatReadFrom method for ToString output with proper formatting
  4. Property Validation: Enhanced ReadFrom property setter with immediate validation
  5. Error Propagation: Ensured validation errors propagate correctly through the entire pipeline

Validation Rules

  • Primary and PreferReplica strategies cannot have AZ parameters
  • AzAffinity and AzAffinityReplicasAndPrimary strategies require non-empty AZ parameters
  • Case-insensitive parsing for ReadFrom strategy values
  • Comprehensive error messages for all validation scenarios

Backward Compatibility

  • Existing configurations without ReadFrom continue to work unchanged
  • Default behavior preserved when no ReadFrom is specified
  • Legacy connection strings remain fully functional

Testing

All tests pass including:

  • ✅ 48 new end-to-end integration tests
  • ✅ Existing unit tests for ConfigurationOptions parsing
  • ✅ Existing unit tests for ReadFrom property validation
  • ✅ Integration tests for ConnectionMultiplexer ReadFrom mapping

Closes

Closes #26

Checklist

  • Implementation follows existing code patterns and conventions
  • Comprehensive test coverage with end-to-end integration tests
  • Backward compatibility maintained
  • Error handling and validation implemented
  • Documentation through comprehensive test examples
  • All existing tests continue to pass
  • DCO signoff included in all commits

@jbrinkman jbrinkman requested a review from a team as a code owner August 13, 2025 14:51
@jbrinkman jbrinkman force-pushed the jbrinkman/az-affinity-configurationoptions-support branch from e0d1212 to ae81ad5 Compare August 13, 2025 15:50
};

// Use property setter to ensure validation
cloned.ReadFrom = readFrom;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not to set as other fields set?

Comment on lines +95 to +96
private string? tempAz; // Temporary storage for AZ during parsing
private ReadFromStrategy? tempReadFromStrategy; // Temporary storage for ReadFrom strategy during parsing
Copy link
Collaborator

Choose a reason for hiding this comment

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

If those need for parsing only - create them in the parsing method.

};
}

private static void ValidateReadFromConfiguration(ReadFrom readFromConfig)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This method repeats ValidateAndSetReadFrom. Can you remove duplicates or re-use the code?

// Test that AZ affinity settings are properly passed to the Rust core
// by creating connections with different AZ values and verifying they work

var azValues = new[] { "us-east-1a", "us-west-2b", "eu-central-1c", "ap-south-1d" };
Copy link
Collaborator

Choose a reason for hiding this comment

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

You are testing different names of az. It is an overkill. If client works with a random AZ name - it works.
If you still want to keep this test - parametrize it.


var connectionTasks = new List<Task<(ConnectionMultiplexer Connection, ReadFromStrategy Strategy, string? Az)>>();

var configurations = new[]
Copy link
Collaborator

Choose a reason for hiding this comment

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

a. parametrize
b. I already seen this test above

Copy link
Collaborator

Choose a reason for hiding this comment

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

There are a lot of repeating tests which do nothing.
There is no test which validates that client reaches server nodes in the configured AZ and doesn't reach in others.

Probably, create this test and delete all others - you'll save time on refactoring.

Comment on lines +320 to +344
[Theory]
[InlineData("us-east-1a")]
[InlineData("eu-west-1b")]
[InlineData("ap-south-1c")]
[InlineData("ca-central-1")]
public void ToString_WithAzAffinityStrategy_IncludesCorrectAzFormat(string azValue)
{
// Arrange
var options = new ConfigurationOptions();
options.ReadFrom = new ReadFrom(ReadFromStrategy.AzAffinity, azValue);

// Act
var result = options.ToString();

// Assert
Assert.Contains("readFrom=AzAffinity", result);
Assert.Contains($"az={azValue}", result);
}

[Theory]
[InlineData("us-west-2a")]
[InlineData("eu-central-1b")]
[InlineData("ap-northeast-1c")]
public void ToString_WithAzAffinityReplicasAndPrimaryStrategy_IncludesCorrectAzFormat(string azValue)
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

It is enough to test with 1 random string.

Copy link
Collaborator

Choose a reason for hiding this comment

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

A lot of repeating tests...

- Implement ParseReadFromStrategy method to convert string values to ReadFromStrategy enum
- Add validation for ReadFrom strategy and AZ parameter combinations
- Extend DoParse method to handle readFrom and az parameters from connection strings
- Add comprehensive error handling with descriptive messages
- Support case-insensitive parsing for all ReadFrom strategies
- Extend ToString method to include ReadFrom and AZ in connection strings
- Add comprehensive unit tests covering all parsing scenarios
- Reorganize private fields to follow C# analyzer rules

Addresses task 1 of GitHub issue #26
Satisfies requirements: 1.1, 1.2, 1.5, 1.6, 4.1, 4.2, 4.3, 4.4, 4.5

Signed-off-by: jbrinkman <[email protected]>
- Add FormatReadFrom method to convert ReadFrom struct to string representation
- Extract FormatReadFromStrategy method as proper private method
- Refactor ToString method to use new FormatReadFrom method
- Ensure proper formatting for all ReadFromStrategy values
- Maintain backward compatibility with existing ToString format

Addresses task 2 of AZ affinity support implementation

Signed-off-by: jbrinkman <[email protected]>
…parameters

- Add readFrom case to the switch statement in DoParse method
- Add az case to the switch statement in DoParse method
- Implement proper parsing logic that creates ReadFrom struct from parsed values
- Add validation during parsing to catch invalid combinations early
- Support case-insensitive parsing of ReadFrom strategy values
- Validate AZ parameter combinations with ReadFrom strategies

Addresses task 4 from AZ affinity support specification

Signed-off-by: jbrinkman <[email protected]>
- Add ConnectionMultiplexerReadFromMappingTests.cs with 12 test cases
- Verify ReadFrom configuration mapping from ConfigurationOptions to ClientConfigurationBuilder
- Test all ReadFromStrategy values (Primary, PreferReplica, AzAffinity, AzAffinityReplicasAndPrimary)
- Verify null ReadFrom handling for backward compatibility
- Test both standalone and cluster client configurations
- Confirm end-to-end flow from ConfigurationOptions to ConnectionConfig

Addresses task 5: Verify ConnectionMultiplexer ReadFrom mapping
Requirements: 3.1, 3.2, 3.4, 6.1

Signed-off-by: jbrinkman <[email protected]>
…serialization

- Add ToString output tests for each ReadFromStrategy value
- Add round-trip parsing tests (Parse → ToString → Parse)
- Add backward compatibility tests with existing configuration strings
- Add proper AZ formatting tests in ToString output
- Covers requirements 5.1-5.5 and 6.2-6.3 from AZ affinity support spec

All 57 tests pass, ensuring proper serialization and deserialization
of ReadFrom configurations while maintaining backward compatibility.

Signed-off-by: jbrinkman <[email protected]>
…property validation

- Add ReadFrom property setter validation tests for all strategies
- Add Clone method ReadFrom preservation tests with comprehensive scenarios
- Add null ReadFrom handling and default behavior tests
- Add cross-validation tests between ReadFromStrategy and AZ parameters
- Ensure proper error handling for invalid configurations
- Verify independence of cloned instances
- Test complex configuration scenarios with ReadFrom

Addresses requirements 2.1, 2.2, 2.3, 2.4, 2.5, and 6.4 from AZ affinity support spec

Signed-off-by: jbrinkman <[email protected]>
…rom configuration

- Add ReadFromEndToEndIntegrationTests with 48 test cases covering complete pipeline
- Test connection string to FFI layer flow for all ReadFromStrategy values
- Test ConfigurationOptions programmatic configuration flow
- Test error handling throughout the complete configuration pipeline
- Test round-trip serialization (Parse → ToString → Parse) integrity
- Test backward compatibility with legacy configurations
- Test performance scenarios with concurrent connections
- Test FFI layer integration to verify configuration reaches Rust core
- Verify AZ affinity settings are properly passed to the Rust core
- Cover both standalone and cluster client scenarios
- Fix test case for invalid ReadFrom strategy to avoid parsing ambiguity

Implements task 12 from AZ Affinity support implementation plan.
Requirements covered: 3.1, 3.2, 3.3, 3.4, 3.5

Signed-off-by: jbrinkman <[email protected]>
@jbrinkman jbrinkman force-pushed the jbrinkman/az-affinity-configurationoptions-support branch from ae81ad5 to 353265e Compare August 13, 2025 18:37
…iplexer

- Updated exception message assertion in ConfigurationOptionsReadFromTests to be case insensitive.
- Replaced reflection-based method invocation with direct calls to CreateClientConfigBuilder in ConnectionMultiplexerReadFromMappingTests for better readability and performance.
- Added new tests to verify ReadFrom configuration flows correctly to ConnectionConfig for both standalone and cluster configurations.
- Removed unnecessary reflection helper method to streamline the test code.
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.

Complete AZ Affinity and ReadFrom Strategy Support in ConfigurationOptions
2 participants