Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
💥 This pull request now has conflicts. Could you fix it @mcalhoun? 🙏 |
|
Important Cloud Posse Engineering Team Review RequiredThis pull request modifies files that require Cloud Posse's review. Please be patient, and a core maintainer will review your changes. To expedite this process, reach out to us on Slack in the |
e0eb984 to
fd28158
Compare
📝 WalkthroughWalkthroughThis pull request introduces Redis as a new store type by adding the necessary Redis and Rendezvous hashing dependencies in the Changes
Sequence Diagram(s)sequenceDiagram
participant C as Client
participant RS as RedisStore
participant RC as Redis Client
C->>RS: Request Get/Set operation with parameters
RS->>RS: Compute full key (using getKey)
RS->>RC: Execute Redis command (Get/Set)
RC-->>RS: Return result/status
RS->>C: Return processed result or error
Possibly related PRs
Suggested labels
Suggested reviewers
✨ Finishing Touches
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (6)
pkg/store/redis_store.go (2)
90-121: Handle missing keys explicitly.
When a key is missing in Redis,Getreturns an error. Consider distinguishing theredis.Nilerror to returnnilor a more explicit "not found" message rather than a generic failure.Here is a sample snippet:
jsonData, err := s.redisClient.Get(ctx, paramName).Result() if err == redis.Nil { - return nil, fmt.Errorf("failed to get key: %v", err) + return nil, nil // or a custom 'not found' error } else if err != nil { return nil, fmt.Errorf("failed to get key: %v", err) }
123-151: Assess context handling strategy.
Usingcontext.Background()for each call is acceptable for small-scale usage. However, you might consider passing a context from the caller to handle cancellation and timeouts more granularly.pkg/store/store.go (1)
15-15: Fix the typo in the comment.
"containts" should be "contains."-// then it splits the component if it containts a "/" +// then it splits the component if it contains a "/"pkg/store/redis_store_test.go (2)
35-72: Consider enhancing test assertions.The test is well-structured, but consider adding assertions for:
- The mock call count to verify the exact number of Redis operations
- The actual key format to ensure proper key construction
// Assert assert.NoError(t, err) assert.Equal(t, expectedValue, result) +mockClient.AssertNumberOfCalls(t, "Get", 1) +assert.Equal(t, "repo/testprefix/mystack/mycomponent/mykey", fullKey) mockClient.AssertExpectations(t)
107-142: Consider testing with non-zero expiration.The test currently only validates with zero expiration. Consider adding test cases with:
- Positive expiration duration
- Different expiration values
func TestRedisStore_Set_Success(t *testing.T) { + testCases := []struct { + name string + expiration time.Duration + }{ + {"NoExpiration", 0}, + {"WithExpiration", time.Hour}, + {"ShortExpiration", time.Minute}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { // Existing test code but use tc.expiration + }) + } }website/docs/core-concepts/projects/configuration/stores.mdx (1)
131-182: Consider enhancing Redis documentation.While the documentation is clear, consider adding:
- Example of using Redis with authentication
- Example of using custom stacks_delimiter
- Best practices for key naming conventions
Add these examples:
# Example with authentication stores: prod/redis: type: redis options: url: redis://:password@redis.example.com:6379 # Example with custom delimiter stores: stage/redis: type: redis options: stacks_delimiter: "/" url: redis://localhost:6379
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
go.sumis excluded by!**/*.sum
📒 Files selected for processing (6)
go.mod(2 hunks)pkg/store/redis_store.go(1 hunks)pkg/store/redis_store_test.go(1 hunks)pkg/store/registry.go(2 hunks)pkg/store/store.go(2 hunks)website/docs/core-concepts/projects/configuration/stores.mdx(3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: Build (windows-latest, windows)
- GitHub Check: Summary
🔇 Additional comments (6)
pkg/store/registry.go (1)
37-48: Looks good!
The new "redis" case follows the same pattern as other stores. Great approach for consistency.pkg/store/redis_store_test.go (4)
14-33: Well-structured mock implementation!The mock implementation follows best practices using testify/mock, and the ptr helper function is clean and focused.
74-105: Solid error handling test!The test properly validates the not found scenario using redis.Nil and includes appropriate error message checks.
144-172: Excellent negative test case!Good choice using a channel to trigger JSON marshal error, as it's a reliable way to generate the error condition.
174-243: Comprehensive error scenario coverage!Both tests effectively validate error handling for:
- JSON unmarshal errors with invalid JSON
- Key generation errors with nil prefix
go.mod (1)
49-49: Consider updating go-redis version.The current version (v9.7.0) is older. Consider updating to the latest stable version for potential bug fixes and improvements.
Run this script to check the latest version:
Also applies to: 132-132
9336949 to
7494ec7
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (5)
pkg/store/store.go (1)
18-30: Consider adding input validation.The function could benefit from validating input parameters to prevent potential issues with empty or malformed inputs.
func getKey(prefix string, stackDelimiter string, stack string, component string, key string, finalDelimiter string) (string, error) { + if stackDelimiter == "" { + return "", fmt.Errorf("stack delimiter cannot be empty") + } + if finalDelimiter == "" { + return "", fmt.Errorf("final delimiter cannot be empty") + } stackParts := strings.Split(stack, stackDelimiter)pkg/store/redis_store.go (2)
36-51: Consider adding connection timeout.The Redis connection options could benefit from a configurable timeout to prevent hanging in case of network issues.
func getRedisOptions(options *RedisStoreOptions) (*redis.Options, error) { if options.URL != nil { opts, err := redis.ParseURL(*options.URL) if err != nil { return &redis.Options{}, fmt.Errorf("failed to parse redis url: %v", err) } + // Add default timeouts + opts.DialTimeout = 5 * time.Second + opts.ReadTimeout = 3 * time.Second + opts.WriteTimeout = 3 * time.Second return opts, nil }
89-120: Consider adding Redis key existence check.The Get method could benefit from explicitly checking if the key exists before attempting to retrieve it.
ctx := context.Background() + exists, err := s.redisClient.Exists(ctx, paramName).Result() + if err != nil { + return nil, fmt.Errorf("failed to check key existence: %v", err) + } + if exists == 0 { + return nil, fmt.Errorf("key not found: %s", paramName) + } jsonData, err := s.redisClient.Get(ctx, paramName).Result()pkg/store/redis_store_test.go (1)
35-71: Consider adding timeout test cases.The success test could benefit from additional cases testing timeout scenarios.
+func TestRedisStore_Get_Timeout(t *testing.T) { + mockClient := new(MockRedisClient) + store, err := NewRedisStore(RedisStoreOptions{ + Prefix: ptr("testprefix"), + StackDelimiter: ptr("/"), + URL: ptr("redis://localhost:6379"), + }) + assert.NoError(t, err) + + redisStore, ok := store.(*RedisStore) + assert.True(t, ok) + redisStore.redisClient = mockClient + + // Simulate timeout + mockClient.On("Get", context.Background(), mock.Anything).Return("", redis.ErrConnDone) + + result, err := redisStore.Get("stack", "component", "key") + assert.Error(t, err) + assert.Nil(t, result) + assert.Contains(t, err.Error(), "failed to get key") +}website/docs/core-concepts/projects/configuration/stores.mdx (1)
131-182: Consider adding Redis configuration best practices.The Redis documentation would benefit from a section on recommended configurations and best practices.
Add a section on Redis best practices:
#### Best Practices - Use a prefix to namespace your keys and prevent conflicts - Consider using SSL/TLS for production environments - Set appropriate timeouts for your environment - Use strong passwords in production - Consider implementing key expiration policies
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
go.sumis excluded by!**/*.sum
📒 Files selected for processing (6)
go.mod(2 hunks)pkg/store/redis_store.go(1 hunks)pkg/store/redis_store_test.go(1 hunks)pkg/store/registry.go(2 hunks)pkg/store/store.go(2 hunks)website/docs/core-concepts/projects/configuration/stores.mdx(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- pkg/store/registry.go
- go.mod
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: Build (windows-latest, windows)
- GitHub Check: Summary
🔇 Additional comments (3)
pkg/store/store.go (1)
14-18: LGTM! Well-documented function.The function comments clearly explain the key generation process and its components.
pkg/store/redis_store.go (1)
14-18: LGTM! Clean struct definition.The RedisStore struct has all necessary fields for Redis operations.
pkg/store/redis_store_test.go (1)
14-29: LGTM! Well-structured mock implementation.The MockRedisClient properly implements the RedisClient interface with clean mock handling.
7494ec7 to
ecae929
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
website/docs/core-concepts/projects/configuration/stores.mdx (2)
137-139: Add secure Redis URL example.The example shows an insecure Redis URL. Consider adding a secure example.
Add secure URL example:
options: - url: redis://localhost:6379 + url: rediss://username:password@host:6379/0
180-181: Enhance Redis authentication documentation.The authentication section could be more detailed about security best practices.
Add security recommendations:
- Use TLS (rediss://) in production
- Avoid embedding credentials in URLs, use environment variables instead
- Set appropriate Redis ACLs
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
go.sumis excluded by!**/*.sum
📒 Files selected for processing (6)
go.mod(2 hunks)pkg/store/redis_store.go(1 hunks)pkg/store/redis_store_test.go(1 hunks)pkg/store/registry.go(2 hunks)pkg/store/store.go(2 hunks)website/docs/core-concepts/projects/configuration/stores.mdx(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- pkg/store/registry.go
- go.mod
- pkg/store/redis_store_test.go
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: Build (windows-latest, windows)
- GitHub Check: Summary
|
These changes were released in v1.159.0. |
* add redis store * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

what
why
references
Summary by CodeRabbit