Skip to content
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

fix tag deletion issue #11

Merged
merged 12 commits into from
Jan 8, 2025
Merged

fix tag deletion issue #11

merged 12 commits into from
Jan 8, 2025

Conversation

mdaliyan
Copy link
Owner

@mdaliyan mdaliyan commented Jan 8, 2025

Changelog

  • add some bullet points

Code Quality Assurance

  • All tests pass locally.
  • All tests pass in CI.
  • Coverage is above 90%.
  • All exposed functions, interfaces, and types have documentation.
  • Run benchmarks again if there is functionality change.

Summary by CodeRabbit

  • New Features

    • Added GetByTag method to retrieve cache entries by tag.
    • Introduced new functionality for tag-based entry retrieval.
  • Bug Fixes

    • Improved concurrency control and mutex management.
    • Enhanced thread safety in cache operations.
  • Tests

    • Added new test cases for tag-based retrieval.
    • Updated test helper functions for better error reporting.
  • Refactor

    • Simplified method signatures.
    • Improved code clarity and resource management.

@mdaliyan mdaliyan self-assigned this Jan 8, 2025
Copy link

coderabbitai bot commented Jan 8, 2025

Warning

Rate limit exceeded

@mdaliyan has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 14 minutes and 48 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 810616c and 9cb3c78.

📒 Files selected for processing (1)
  • .github/workflows/test.yml (2 hunks)

Walkthrough

The pull request introduces enhancements to the icache package, focusing on tag-based entry retrieval and improved concurrency management. A new GetByTag method is added to the Pot interface, allowing retrieval of entries associated with specific tags. The changes span multiple files, including icache.go, pot.go, shard.go, and tags.go, with modifications to mutex handling, method signatures, and entry management. Additionally, several tests are updated to validate the new functionality and improve test clarity.

Changes

File Changes
icache.go Added GetByTag method to Pot interface
pot.go - Added GetByTag method to pot type
- Improved mutex management with defer statements
- Refactored entry retrieval and tag management
shard.go - Simplified method return types
- Added defer statements for mutex unlocking
- Renamed DropEntry parameter from keys to key
tags.go - Retained sync.RWMutex
- Replaced drop with dropTagIfNoOtherEntriesExist
- Added getEntriesWithTags method
icache_test.go - Updated tests for tag-based retrieval
- Modified existing test cases
internal_test.go - Removed init function
- Added t.Helper() to assertion functions

Sequence Diagram

sequenceDiagram
    participant Client
    participant Pot
    participant Shard
    participant Tags
    
    Client->>Pot: GetByTag("B")
    Pot->>Shard: GetEntry
    Shard-->>Pot: Return entries
    Pot->>Tags: getEntriesWithTags
    Tags-->>Pot: Return matching entries
    Pot-->>Client: Return entries or error
Loading

Poem

🐰 In the cache of code so bright,
Tags now dance with pure delight!
Mutex locks, they softly sway,
Entries found without delay.
A rabbit's cache, now swift and clean! 🏃‍♂️🔍


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?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (3)
shard.go (1)

60-65: Unnecessary assignment before deletion in DropEntry

In the DropEntry method, setting s.entries[key] = nil before deleting the key from the map is unnecessary.

You can simplify the code by removing the assignment:

 func (s *shard[T]) DropEntry(key uint64) {
 	s.rw.Lock()
 	defer s.rw.Unlock()
-	s.entries[key] = nil
 	delete(s.entries, key)
 }
icache.go (1)

40-41: Fix documentation typos and improve clarity

The documentation comment has typos and could be clearer:

-// Get restores ann T entries previously stored with the given tag
+// GetByTag retrieves all entries previously stored with the given tag
.github/workflows/test.yml (1)

Line range hint 17-17: Consider updating minimum Go version requirement

The test matrix includes Go 1.18.1 which is quite old. Given the new features and improvements in newer versions, consider:

  1. Updating the minimum supported version to at least 1.19 or 1.20
  2. Documenting the minimum required Go version in the README
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dbfbf17 and cb6e9d4.

📒 Files selected for processing (5)
  • .github/workflows/test.yml (1 hunks)
  • icache.go (1 hunks)
  • pot.go (6 hunks)
  • shard.go (3 hunks)
  • tags.go (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (16)
  • GitHub Check: lint-and-test (1.22.3, windows-latest)
  • GitHub Check: lint-and-test (1.22.3, macos-latest)
  • GitHub Check: lint-and-test (1.22.3, ubuntu-latest)
  • GitHub Check: lint-and-test (1.21.10, windows-latest)
  • GitHub Check: lint-and-test (1.21.10, macos-latest)
  • GitHub Check: lint-and-test (1.21.10, ubuntu-latest)
  • GitHub Check: lint-and-test (1.20.14, windows-latest)
  • GitHub Check: lint-and-test (1.20.14, macos-latest)
  • GitHub Check: lint-and-test (1.20.14, ubuntu-latest)
  • GitHub Check: lint-and-test (1.19.13, windows-latest)
  • GitHub Check: lint-and-test (1.19.13, macos-latest)
  • GitHub Check: lint-and-test (1.19.13, ubuntu-latest)
  • GitHub Check: lint-and-test (1.18.1, windows-latest)
  • GitHub Check: lint-and-test (1.18.1, macos-latest)
  • GitHub Check: lint-and-test (1.18.1, ubuntu-latest)
  • GitHub Check: coverage
🔇 Additional comments (2)
pot.go (1)

101-107: Ensure thread safety when accessing entries from GetByTag

The GetByTag method retrieves entries using p.tags.getEntriesWithTags, which may return entries that could be modified concurrently.

Confirm that the entries returned by GetByTag are accessed safely. You may need to lock the entries or return copies to prevent concurrent modification issues.

.github/workflows/test.yml (1)

12-12: Verify the need for 'test' branch in workflow triggers

Adding the 'test' branch to PR triggers seems unusual. Typically, feature branches or development branches are used for testing before merging to master/main. Consider if this aligns with your branching strategy.

Run this script to check the branch usage patterns:

✅ Verification successful

'test' branch in workflow triggers appears intentional

The workflow configuration shows a well-structured branch strategy where:

  • Feature development occurs in feature/* branches
  • Pull requests can target master, v1, or test branches
  • Direct pushes to master are explicitly disabled

The inclusion of the test branch alongside master and v1 in PR triggers appears to be part of a deliberate branch protection strategy.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check branch usage patterns in the repository
git branch -r | grep -E 'test|feature|dev' | sort
git log --format="%H %d %s" --graph --all | grep -E 'test|feature|dev'

Length of output: 51


Script:

#!/bin/bash
# Check workflow configurations and branch patterns
fd -e yml -e yaml . .github/workflows/ --exec cat {}
cat .github/workflows/test.yml

Length of output: 2953

tags.go Outdated Show resolved Hide resolved
tags.go Outdated Show resolved Hide resolved
pot.go Show resolved Hide resolved
pot.go Show resolved Hide resolved
shard.go Outdated Show resolved Hide resolved
icache.go Outdated Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
pot.go (1)

177-200: Optimize expired entries handling

The current implementation has potential issues:

  1. Unnecessary allocation of expiredEntries slice
  2. Double iteration over expired entries

Consider this more efficient approach:

 func (p *pot[T]) dropExpiredEntries(at time.Time) {
     now := at.UnixNano()
     p.windowRW.Lock()
     defer p.windowRW.Unlock()
 
     var expiredWindows int
-    var expiredEntries entrySlice[T]
     for _, entry := range p.window {
         if entry == nil {
             expiredWindows++
             continue
         }
         entry.rw.Lock()
         if now < entry.expiresAt {
             entry.rw.Unlock()
             break
         }
         entry.deleted = true
-        expiredEntries = append(expiredEntries, entry)
+        p.dropEntry(entry)
         expiredWindows++
         entry.rw.Unlock()
     }
-    if len(expiredEntries) > 0 {
+    if expiredWindows > 0 {
         p.window = append(entrySlice[T]{}, p.window[expiredWindows:]...)
-        for _, e := range expiredEntries {
-            p.dropEntry(e)
-        }
     }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb6e9d4 and 12459d7.

📒 Files selected for processing (3)
  • icache_test.go (1 hunks)
  • pot.go (5 hunks)
  • shard.go (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • shard.go
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: lint-and-test (1.20.14, windows-latest)
🔇 Additional comments (1)
pot.go (1)

55-56: Verify proper mutex ordering to prevent deadlocks

The addition of deferred mutex unlocks is good, but we need to ensure proper mutex ordering when multiple locks are acquired.

Let's verify the mutex acquisition order across the codebase:

Also applies to: 63-65, 70-71, 77-87, 110-112, 129-131, 155-160, 164-165

✅ Verification successful

Mutex ordering is correct and safe

The codebase follows a consistent lock hierarchy (pot -> entry) with proper deferred unlocks, preventing potential deadlocks.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential deadlock scenarios by analyzing mutex lock ordering

# Look for methods that acquire multiple locks
rg -A 5 'Lock|RLock' --type go

# Look for nested mutex operations
ast-grep --pattern 'Lock() {
  $$$
  Lock()
  $$$
}'

Length of output: 2969

icache_test.go Outdated Show resolved Hide resolved
pot.go Show resolved Hide resolved
pot.go Outdated Show resolved Hide resolved
pot.go Outdated Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
pot.go (2)

132-134: ⚠️ Potential issue

Race condition in tags.add still needs attention.

While the pot-level locking is good, there's still a potential race condition in p.tags.add(e) as mentioned in the past review.

Ensure that the add method in the tags struct properly synchronizes access to t.pairs.


158-163: ⚠️ Potential issue

Race condition in getEntriesWithTags still needs attention.

While the pot-level locking is good, there's still a potential race condition in getEntriesWithTags as mentioned in the past review.

Ensure that getEntriesWithTags is thread-safe by adding proper synchronization when accessing t.pairs.

🧹 Nitpick comments (1)
internal_test.go (1)

Line range hint 74-86: Consider enhancing the failAssertion function

Two suggestions to improve error reporting:

  1. Add t.Helper() to failAssertion as it's also a helper function
  2. Use string formatting for better error messages

Here's the suggested implementation:

 func failAssertion(t *testing.T, not bool, expected, actual interface{}, msg ...string) {
+    t.Helper()
     if len(msg) != 0 {
-        fmt.Println("assertion: ", msg)
+        fmt.Printf("assertion: %v\n", msg)
     }
-    if not {
-        fmt.Print("not expected:")
-    } else {
-        fmt.Print("expected:")
-    }
-    fmt.Printf("%v\n", expected)
-    fmt.Printf("actual: %v\n", actual)
+    expectation := "expected"
+    if not {
+        expectation = "not expected"
+    }
+    fmt.Printf("%s: %v\nactual: %v\n", expectation, expected, actual)
     t.Fail()
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 12459d7 and 53dc521.

📒 Files selected for processing (5)
  • icache.go (1 hunks)
  • icache_test.go (1 hunks)
  • internal_test.go (1 hunks)
  • pot.go (4 hunks)
  • shard.go (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • icache.go
  • icache_test.go
  • shard.go
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: lint-and-test (1.22.3, windows-latest)
  • GitHub Check: lint-and-test (1.20.14, windows-latest)
🔇 Additional comments (9)
internal_test.go (3)

27-27: Great addition of t.Helper()!

Adding t.Helper() improves test failure reporting by showing the actual test line number instead of the helper function, making it easier to debug failed tests.


34-34: Consistent implementation across all assertion functions!

The addition of t.Helper() has been consistently applied to all assertion functions, which is great for maintaining a uniform approach to test failure reporting.

Also applies to: 41-41, 46-46, 51-51, 56-56, 61-61, 68-68


Line range hint 1-86: Verify impact of removing random seed initialization

The removal of the init() function that seeded the random number generator could affect tests that rely on randomness.

Let's verify if there are any tests depending on random number generation:

✅ Verification successful

Random seed initialization removal is safe

The random number generator is only used in benchmarks to simulate workload by generating random test data and accessing it randomly. Since benchmarks don't make assertions on random values, the default seed (1) provided by math/rand is sufficient.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of math/rand or crypto/rand in test files
echo "Searching for random number usage in tests..."
rg -t go --glob '*_test.go' 'rand\.'

Length of output: 288


Script:

#!/bin/bash
# Check the content of benchmark_test.go
echo "Content of benchmark_test.go:"
cat benchmark_test.go

Length of output: 1146

pot.go (6)

54-55: LGTM! Good improvement in mutex handling.

Adding defer for mutex unlock is a good practice as it ensures the mutex is always released, even in case of panics.


62-87: Well-structured concurrent access patterns!

Good improvements:

  1. Using RLock for read-only operations
  2. Proper defer usage for unlocks
  3. Entry-level locking in ExpireTime
  4. Abstraction of entry retrieval logic

113-128: LGTM! Good concurrent access handling.

The method correctly handles:

  • Pot-level read locking
  • Entry-level read locking
  • Proper cleanup of deleted entries

180-204: LGTM! Good improvements in expired entries handling.

The changes improve efficiency by:

  1. Using proper synchronization
  2. Optimizing the expired entries cleanup process
  3. Maintaining proper locking order

209-211: LGTM! Good cleanup of tag management.

The changes improve the tag cleanup process and remove the ineffective nil assignment as suggested in the past review.


101-110: 🛠️ Refactor suggestion

Add entry-level locking to prevent races.

While the pot-level RLock is good, the returned entries should be protected against concurrent modifications.

Apply this diff:

 func (p *pot[T]) GetByTag(tag string) ([]*entry[T], error) {
     p.windowRW.RLock()
     defer p.windowRW.RUnlock()
 
     entries := p.tags.getEntriesWithTags(tagKeyGen(tag)...)
+    // Lock entries to prevent races
+    for _, e := range entries {
+        e.rw.RLock()
+        if e.deleted {
+            e.rw.RUnlock()
+            continue
+        }
+        // Caller must unlock entries after use
+    }
     if len(entries) == 0 {
         return nil, ErrNotFound
     }
     return entries, nil
 }

Likely invalid or redundant comment.

@mdaliyan
Copy link
Owner Author

mdaliyan commented Jan 8, 2025

@coderabbitai full review

Copy link

coderabbitai bot commented Jan 8, 2025

✅ Actions performed

Full review triggered.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
shard.go (1)

34-38: ⚠️ Potential issue

Possible nil pointer dereference in EntryExists method

In the EntryExists method, after retrieving the entry e, there is a potential for a nil pointer dereference if e is nil. Accessing e.deleted when e is nil would cause a panic.

Apply this diff to fix the issue:

 func (s *shard[T]) EntryExists(key uint64) bool {
 	s.rw.RLock()
 	defer s.rw.RUnlock()
 	e, ok := s.entries[key]
+	if !ok || e == nil {
+		return false
+	}
 	return !e.deleted
 }

This ensures that you only access e.deleted if e is not nil.

🧹 Nitpick comments (4)
internal_test.go (1)

Line range hint 74-85: Add t.Helper() to failAssertion function

For consistency with other helper functions and improved error reporting, consider adding t.Helper() to the failAssertion function as well.

 func failAssertion(t *testing.T, not bool, expected, actual interface{}, msg ...string) {
+    t.Helper()
     if len(msg) != 0 {
         fmt.Println("assertion: ", msg)
     }
tags.go (1)

9-9: [Nitpick] Suggest aligning struct fields for readability

For improved readability, consider aligning the struct fields in tags[T].

Apply this diff:

 type tags[T any] struct {
 	rw    sync.RWMutex
 	pairs map[uint64]entries[T]
 }
icache.go (1)

40-42: Enhance method documentation for GetByTag

While the documentation covers the error case, it would be helpful to add:

  • A brief description of what constitutes a tag
  • Whether the order of returned entries is guaranteed
  • Whether the returned slice can be modified by the caller

Consider expanding the documentation like this:

-// GetByTag restores ann T entries previously stored with the given tag
-// returns ErrNotFound if there is no entries to return.
+// GetByTag returns all entries that were stored with the given tag.
+// The order of returned entries is not guaranteed.
+// Returns ErrNotFound if no entries exist with the given tag.
+// The returned slice can be safely modified by the caller.
pot.go (1)

186-205: Optimize memory usage in expired entries handling

The current implementation might hold onto memory longer than necessary:

  1. The expired entries slice creates an additional allocation
  2. The window slice copy could be more efficient

Consider this optimization:

-    var expiredEntries entrySlice[T]
+    expiredEntries := make([]*entry[T], 0, len(p.window))
     for _, entry := range p.window {
         if entry == nil {
             expiredWindows++
             continue
         }
         entry.rw.Lock()
         if now < entry.expiresAt {
             entry.rw.Unlock()
             break
         }
         entry.deleted = true
         expiredEntries = append(expiredEntries, entry)
         expiredWindows++
         entry.rw.Unlock()
     }
     if len(expiredEntries) > 0 {
-        p.window = append(entrySlice[T]{}, p.window[expiredWindows:]...)
+        if expiredWindows < len(p.window) {
+            p.window = p.window[expiredWindows:]
+            p.window = p.window[:len(p.window):len(p.window)] // trim capacity
+        } else {
+            p.window = nil
+        }
         for _, e := range expiredEntries {
             p.dropEntry(e)
         }
     }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dbfbf17 and 5129deb.

📒 Files selected for processing (6)
  • icache.go (1 hunks)
  • icache_test.go (1 hunks)
  • internal_test.go (1 hunks)
  • pot.go (4 hunks)
  • shard.go (3 hunks)
  • tags.go (2 hunks)
🔇 Additional comments (11)
internal_test.go (1)

27-27: Great addition of t.Helper() calls!

Adding t.Helper() to all assertion functions is a good practice. It improves test failure reporting by ensuring that error messages point to the test file line number rather than the helper function implementation.

Also applies to: 34-34, 41-41, 46-46, 51-51, 56-56, 61-61, 68-68

tags.go (2)

19-20: Proper synchronization in add method

The add method now correctly acquires a write lock on t.rw before modifying t.pairs. This ensures thread-safe operation when adding entries with their associated tags.


47-65: Verify locking order to prevent potential deadlocks

In getEntriesWithTags, you acquire a read lock on t.rw and then, within the loop, acquire read locks on e.rw. Ensure that elsewhere in the code, there are no instances where e.rw is locked before t.rw, as this could lead to a deadlock due to inconsistent lock ordering.

Consider reviewing the codebase to confirm that all locks are acquired in a consistent order.

shard.go (2)

28-31: Proper use of read lock in Len method

The Len method now correctly uses a read lock with defer to ensure thread-safe access to s.entries.


53-54: Proper synchronization in SetEntry method

The SetEntry method now acquires a write lock before modifying s.entries, ensuring thread safety when setting entries.

icache_test.go (4)

91-99: Test data consistency corrected in multiple by tag sub-test

The test case now correctly sets the item with key "3" and value newItem("3"), ensuring consistency between the key and the item's ID. This addresses the previous inconsistency where the item's ID did not match its key.


98-99: Additional assertion improves test coverage

Adding assertIsTrue(t, p.Exists("3")) after dropping tags enhances the test by verifying that the item with key "3" still exists as expected.


100-106: Verification of GetByTag after tag drop

The added assertions check the behavior of GetByTag after tags have been dropped, ensuring that the method returns the correct items and errors. This strengthens the test suite by validating the tag-based retrieval functionality.


110-131: Addition of TestGetByTags function enhances test suite

The new TestGetByTags function effectively tests the GetByTag method, verifying correct retrieval of items by tags and proper error handling when querying a non-existent tag. This addition improves the overall test coverage for tag-based operations.

pot.go (2)

53-54: LGTM! Improved thread safety

Good addition of defer for mutex unlock, ensuring the lock is always released even if the method panics.


212-214: LGTM! Improved tag cleanup

Good implementation of tag cleanup that removes tags only when no other entries exist.

tags.go Show resolved Hide resolved
pot.go Show resolved Hide resolved
@mdaliyan
Copy link
Owner Author

mdaliyan commented Jan 8, 2025

https://github.com/coderabbitai full review

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
pot.go (2)

78-88: Consider using time.UnixNano for consistent precision.

The conversion between UnixNano (used in Set) and Unix (used here) might lead to precision loss.

-    ti := time.Unix(e.expiresAt, 0)
+    ti := time.Unix(0, e.expiresAt)

193-212: Optimize slice operations in dropExpiredEntries.

Consider pre-allocating the new slice with the correct capacity to avoid potential reallocation.

     if expiredWindows > 0 {
-        p.window = append(entrySlice[T]{}, p.window[expiredWindows:]...)
+        remaining := len(p.window) - expiredWindows
+        newWindow := make(entrySlice[T], remaining)
+        copy(newWindow, p.window[expiredWindows:])
+        p.window = newWindow
     }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5129deb and 2b5593b.

📒 Files selected for processing (5)
  • icache.go (1 hunks)
  • icache_test.go (1 hunks)
  • internal_test.go (1 hunks)
  • pot.go (4 hunks)
  • shard.go (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • icache_test.go
  • icache.go
  • shard.go
  • internal_test.go
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: lint-and-test (1.20.14, windows-latest)
🔇 Additional comments (6)
pot.go (6)

53-54: LGTM! Good use of deferred mutex unlock.

The addition of defer for mutex unlock is a good practice that ensures proper cleanup even in case of panics.


61-63: LGTM! Good addition of read locks for thread safety.

The addition of RLock protection for read-only operations is correct and necessary for concurrent access safety.

Also applies to: 68-74, 78-88


125-127: LGTM! Consistent use of read lock.

The addition of RLock protection is correct and maintains consistency with other read operations.


144-147: LGTM! Race condition fixed.

The addition of proper Lock protection fixes the previously identified race condition in the Set method.


171-176: LGTM! Thread safety improved.

The addition of proper Lock protection fixes the previously identified race condition in the DropTags method.


218-220: LGTM! Good memory management.

The addition of tag cleanup logic helps prevent memory leaks by removing unused tags.

pot.go Outdated Show resolved Hide resolved
@mdaliyan mdaliyan changed the title test fix tag deletion issue Jan 8, 2025
@mdaliyan
Copy link
Owner Author

mdaliyan commented Jan 8, 2025

https://github.com/coderabbitai full review

@mdaliyan mdaliyan merged commit e0f61c4 into master Jan 8, 2025
18 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Jan 8, 2025
5 tasks
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.

1 participant