Skip to content

fix: updating indexes in a more consistent manner#7575

Open
shawkins wants to merge 2 commits intofabric8io:mainfrom
shawkins:iss7265
Open

fix: updating indexes in a more consistent manner#7575
shawkins wants to merge 2 commits intofabric8io:mainfrom
shawkins:iss7265

Conversation

@shawkins
Copy link
Copy Markdown
Contributor

@shawkins shawkins commented Mar 19, 2026

closes: #7265

Description

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change
  • Chore (non-breaking change which doesn't affect codebase;
    test, version modification, documentation, etc.)

Checklist

  • Code contributed by me aligns with current project license: Apache 2.0
  • I Added CHANGELOG entry regarding this change
  • I have implemented unit tests to cover my changes
  • I have added/updated the javadocs and other documentation accordingly
  • No new bugs, code smells, etc. in SonarCloud report
  • I tested my code in Kubernetes
  • I tested my code in OpenShift

Copy link
Copy Markdown
Contributor

@csviri csviri left a comment

Choose a reason for hiding this comment

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

Not sure if following all the aspects but seems to solve the original issue.

Maybe could you elaborate the downside (if any) compared to alternative (ReadWriteLock version).

thank you!

});
} else {
values.computeIfAbsent(indexKey == null ? this : indexKey, k -> ConcurrentHashMap.newKeySet()).add(key);
values.compute(indexKey == null ? this : indexKey, (k, v) -> v == null ? new ConcurrentHashMap<>() : v).put(key,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The indexKey can be null?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, in some situations users want the ability to lookup by null appearently.

@shawkins
Copy link
Copy Markdown
Contributor Author

Maybe could you elaborate the downside (if any) compared to alternative (ReadWriteLock version).

The difference in the approaches comes down to CacheImpl.put. With a ReadWriteLock, a simultaneous read while put is called will block.

Here the read will not block, and you are not guarenteed to see the new index state of the item being put (at least not until the updateIndices call is finished).

In any other circumstance, the behavior is the same in the sense that if the cache update "happens before" the index read, then you get the same results. This is because if an item already exists in an index, there's no ephemal removal. And there's a consistency check that ensures if another revision of that resource already exists in the cache, that we won't inappropriately return something as belonging to the index. On a delete, the item will no longer be in the cache, and nothing will be returned for it.

@manusa
Copy link
Copy Markdown
Member

manusa commented Mar 31, 2026

After reviewing both approaches, I think this is the right direction. The lock-free read path is important for performance, and the optimistic consistency approach addresses the core issue from #7265 (items temporarily disappearing during same-key updates) without introducing read contention.

I've asked @Desel72 to scope down #7558 to just the concurrency reproducer test (CacheImplConcurrencyTest) landed as @Disabled. Once that's merged, this PR should re-enable the test and use it to validate the fix.

@shawkins could you bring this out of draft once we have the reproducer test to verify against?

closes: fabric8io#7265

Signed-off-by: Steve Hawkins <shawkins@redhat.com>
@shawkins shawkins marked this pull request as ready for review March 31, 2026 13:19
Desel72 pushed a commit to Desel72/kubernetes-client that referenced this pull request Apr 2, 2026
Revert ReadWriteLock changes to CacheImpl, ProcessorStore, and
ProcessorStoreTest. Remove CHANGELOG entry. Keep CacheImplConcurrencyTest
as a disabled reproducer for fabric8io#7265, to be enabled once fabric8io#7575 lands.
manusa pushed a commit that referenced this pull request Apr 2, 2026
…nconsistency (#7558)

* fix(informer): use ReadWriteLock in CacheImpl to prevent index read inconsistency

* fix: use specific import for ReentrantReadWriteLock in ProcessorStoreTest

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: refactor concurrency test to parameterized and add CHANGELOG entry

- Replaced two nearly-identical test methods with a single parameterized
  test using @valuesource and a shared helper method
- Added CHANGELOG entry for issue #7265

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: reduce PR to concurrency reproducer test with @disabled

Revert ReadWriteLock changes to CacheImpl, ProcessorStore, and
ProcessorStoreTest. Remove CHANGELOG entry. Keep CacheImplConcurrencyTest
as a disabled reproducer for #7265, to be enabled once #7575 lands.

* fix: assert thread completion in concurrency reproducer test

Check return values of doneLatch.await() and executor.awaitTermination()
so that a deadlock or hung thread fails the test instead of silently
passing.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

Temporal resource miss on Informer index

3 participants