Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Make RepoAccessCache a singleton#1426

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation

Copy link
Contributor

CopilotAI commentedNov 18, 2025
edited
Loading

Closes: #[issue_number]

Description

TheRepoAccessCache was being instantiated multiple times across the application, leading to inconsistent configuration (TTL, logger) and redundant initialization overhead.

Changes

  • Singleton implementation: AddedGetInstance() withsync.Once for thread-safe lazy initialization. Production code now uses a single shared cache instance.
  • Test isolation preserved: KeptNewRepoAccessCache() to create independent instances for parallel tests, avoiding test interference.
  • Simplified cache naming: All instances now use a shared "repo-access-cache" name. The singleton pattern ensures only one instance exists in production, while test instances share the underlying cache2go table but maintain independence through separate struct instances with different clients and configurations.

Usage

// Production: singleton instancecache:=lockdown.GetInstance(gqlClient,lockdown.WithTTL(5*time.Minute))// Testing: independent instancescache1:=lockdown.NewRepoAccessCache(mockClient1)cache2:=lockdown.NewRepoAccessCache(mockClient2)// Different instance// Testing: reset singleton between tests if neededlockdown.ResetInstance()

Tradeoffs

  • GetInstance() ignores client/options on subsequent calls. First initialization wins. This is standard singleton behavior but could surprise callers expecting reconfiguration.
  • ResetInstance() is unsafe if cache is in use. Documented for test-only usage.
  • All cache instances (singleton and test instances) share the same underlying cache2go table. This is acceptable because the singleton ensures one instance in production, and test instances maintain independence through separate struct configurations and mock clients.

Created from VS Code via theGitHub Pull Request extension.

Original prompt

Make RepoAccessCache a singleton

Created from VS Code via theGitHub Pull Request extension.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn moreCopilot coding agent tips in the docs.

CopilotAIand others added2 commitsNovember 18, 2025 09:55
Co-authored-by: JoannaaKL <67866556+JoannaaKL@users.noreply.github.com>
Co-authored-by: JoannaaKL <67866556+JoannaaKL@users.noreply.github.com>
CopilotAI changed the title[WIP] Make RepoAccessCache a singletonMake RepoAccessCache a singletonNov 18, 2025
CopilotAI requested a review fromJoannaaKLNovember 18, 2025 10:00
Copilot finished work on behalf ofJoannaaKLNovember 18, 2025 10:00
@JoannaaKLJoannaaKL marked this pull request as ready for reviewNovember 18, 2025 10:02
@JoannaaKLJoannaaKL requested a review froma team as acode ownerNovember 18, 2025 10:02
CopilotAI review requested due to automatic review settingsNovember 18, 2025 10:02
@JoannaaKL
Copy link
Contributor

@copilot Remove cacheIDCounter, we don't need it

Copilot finished reviewing on behalf ofJoannaaKLNovember 18, 2025 10:05
Copy link
Contributor

CopilotAI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements a singleton pattern forRepoAccessCache to ensure consistent configuration across the application and fixes a bug in cache table naming. The implementation usessync.Once for thread-safe lazy initialization while preserving the ability to create independent instances for testing.

  • AddsGetInstance() for singleton access with lazy initialization
  • Fixes cache table naming bug by using atomic counter instead of hardcoded string
  • KeepsNewRepoAccessCache() for test isolation in parallel tests

Reviewed Changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 3 comments.

FileDescription
pkg/lockdown/lockdown.goImplements singleton pattern with GetInstance(), ResetInstance(), and refactors cache creation into shared helper. Fixes cache naming with atomic counter
pkg/lockdown/lockdown_test.goAdds comprehensive tests for singleton behavior, reset functionality, and independent instance creation
internal/ghmcp/server.goUpdates production code to use GetInstance() instead of NewRepoAccessCache()
go.sumRemoves unused indirect dependency entries (appears to be from go mod tidy)

instance.cache.Flush()
}
instance=nil
instanceOnce= sync.Once{}

Choose a reason for hiding this comment

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

Resettingsync.Once by reassigning it doesn't work as intended. Thesync.Once type contains unexported state that tracks whetherDo() has been called. Simply reassigninginstanceOnce = sync.Once{} creates a newsync.Once, but it doesn't atomically coordinate with concurrent goroutines that might be executing or about to executeGetInstance().

This creates multiple race conditions:

  1. A goroutine could read the oldinstanceOnce value and be in the middle of executing itsDo() function whileResetInstance() replaces it
  2. The reassignment ofinstanceOnce itself is not atomic with respect to reads inGetInstance()

For a proper reset in tests, consider using a build tag or test-only code path, or accept thatResetInstance() is fundamentally unsafe for concurrent use and document this limitation more prominently (e.g., "MUST NOT be called concurrently with GetInstance()").

Copilot uses AI. Check for mistakes.
funcGetInstance(client*githubv4.Client,opts...RepoAccessOption)*RepoAccessCache {
instanceOnce.Do(func() {
instance=newRepoAccessCache(client,opts...)
})

Choose a reason for hiding this comment

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

TheinstanceMu mutex is declared but not used inGetInstance(). Whilesync.Once provides thread-safe initialization, there's no synchronization betweenGetInstance() readinginstance (line 66) andResetInstance() writing to it (line 78).

This creates a data race: concurrent calls toGetInstance() andResetInstance() will race on theinstance variable. To fix this,GetInstance() should acquireinstanceMu.RLock() before returning the instance to synchronize withResetInstance()'s write lock.

Suggested change
})
})
instanceMu.RLock()
deferinstanceMu.RUnlock()

Copilot uses AI. Check for mistakes.
}

// newRepoAccessCache creates a new cache instance. This is a private helper function
// used by GetInstance.

Choose a reason for hiding this comment

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

The comment states this is "used by GetInstance" but it's also called byNewRepoAccessCache() (line 89). The comment should be updated to reflect that this is a shared helper used by both the singleton and non-singleton constructors.

Suggested change
// used by GetInstance.
// used bybothGetInstance (singleton constructor) and NewRepoAccessCache (non-singleton constructor).

Copilot uses AI. Check for mistakes.
Co-authored-by: JoannaaKL <67866556+JoannaaKL@users.noreply.github.com>
Copy link
ContributorAuthor

@copilot Remove cacheIDCounter, we don't need it

Removed cacheIDCounter in commit11c7159. The singleton implementation now uses a shared "repo-access-cache" name for all instances.

Copilot finished work on behalf ofJoannaaKLNovember 18, 2025 10:13
@JoannaaKLJoannaaKL merged commit5bba60a intolockdown-mode-more-toolsNov 18, 2025
@JoannaaKLJoannaaKL deleted the copilot/make-repoaccesscache-singleton branchNovember 18, 2025 10:15
JoannaaKL added a commit that referenced this pull requestNov 21, 2025
* Apply lockdown mode to issues and pull requests* Add cache* Unlock in defer* Add muesli/cache2go* [WIP] Replace custom cache in lockdown.go with cache2go struct (#1425)* Initial plan* Replace custom cache with cache2go library- Added github.com/muesli/cache2go dependency- Replaced custom map-based cache with cache2go.CacheTable- Removed manual timer management (scheduleExpiry, ensureEntry methods)- Removed timer field from repoAccessCacheEntry struct- Updated GetRepoAccessInfo to use cache2go's Value() and Add() methods- Updated SetTTL to flush and re-add entries with new TTL- Used unique cache names per instance to avoid test interference- All existing tests pass with the new implementationCo-authored-by: JoannaaKL <67866556+JoannaaKL@users.noreply.github.com>* Final verification completeCo-authored-by: JoannaaKL <67866556+JoannaaKL@users.noreply.github.com>---------Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>Co-authored-by: JoannaaKL <67866556+JoannaaKL@users.noreply.github.com>* Use muesli for cache* Make RepoAccessCache a singleton (#1426)* Initial plan* Implement RepoAccessCache as a singleton patternCo-authored-by: JoannaaKL <67866556+JoannaaKL@users.noreply.github.com>* Complete singleton implementation and verificationCo-authored-by: JoannaaKL <67866556+JoannaaKL@users.noreply.github.com>* Remove cacheIDCounter as requestedCo-authored-by: JoannaaKL <67866556+JoannaaKL@users.noreply.github.com>---------Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>Co-authored-by: JoannaaKL <67866556+JoannaaKL@users.noreply.github.com>* Update mutexes* .* Reuse cache* .* .* Fix logic after vibe coding* Update docs* .* Refactoring to make the code pretty* Hide lockdown logic behind shouldFilter function* .* Tests---------Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

Copilot code reviewCopilotCopilot left review comments

@JoannaaKLJoannaaKLAwaiting requested review from JoannaaKL

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

2 participants

@JoannaaKL

[8]ページ先頭

©2009-2025 Movatter.jp