Skip to content

fix: initialize credentials before usage managers to resolve tier=None#121

Open
b3nw wants to merge 1 commit intoMirrowel:devfrom
b3nw:fix/tier-initialization-ordering
Open

fix: initialize credentials before usage managers to resolve tier=None#121
b3nw wants to merge 1 commit intoMirrowel:devfrom
b3nw:fix/tier-initialization-ordering

Conversation

@b3nw
Copy link
Contributor

@b3nw b3nw commented Feb 12, 2026

The _run() method was calling initialize_usage_managers() before _initialize_credentials(), so tier caches were empty when UsageManager read them. Swapping the order ensures project_tier_cache is populated before tiers are assigned to CredentialState objects.


Important

In background_refresher.py, _run() now initializes credentials before usage managers to ensure tier caches are populated, resolving an issue with empty tier caches.

  • Behavior:
    • In background_refresher.py, _run() now calls _initialize_credentials() before initialize_usage_managers() to ensure tier caches are populated before usage managers read them.
  • Comments:
    • Updated comments in _run() to reflect the new order of initialization steps.

This description was created by Ellipsis for daaf4d0. You can customize this summary. It will automatically update as commits are pushed.

The _run() method was calling initialize_usage_managers() before
_initialize_credentials(), so tier caches were empty when
UsageManager read them. Swapping the order ensures project_tier_cache
is populated before tiers are assigned to CredentialState objects.
@b3nw b3nw requested a review from Mirrowel as a code owner February 12, 2026 02:32
@mirrobot-agent
Copy link
Contributor

I'm starting my review of the initialization ordering fix in background_refresher.py. This looks like a targeted fix for the tier=None issue reported during startup. Examining the dependency chain now.

Copy link
Contributor

@mirrobot-agent mirrobot-agent bot left a comment

Choose a reason for hiding this comment

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

Overall Assessment

This PR successfully addresses a race condition in the initialization sequence of the BackgroundRefresher. By swapping the order of _initialize_credentials() and initialize_usage_managers(), it ensures that credential discovery (which populates the internal tier and project caches) happens before the usage managers are configured. This is a solid fix for the reported issue where tiers were being initialized as None.

Key Suggestions

The change is correct for the refresher's internal loop. However, I noticed that initialize_usage_managers() is also called explicitly in src/proxy_app/main.py and RotatingClient.__aenter__. Since that method has a guard preventing re-initialization, those early calls might still occur before discovery is finished. It would be worth verifying if those early calls can be removed or if the discovery logic should be moved higher up the chain.

Found During Review (Bonus)

While exploring the related logic, I spotted a minor redundant code block in src/rotator_library/providers/utilities/gemini_credential_manager.py. It appears there are two consecutive except Exception as e: blocks for the same try in the initialize_credentials method (around line 197). The second one is currently dead code and could be cleaned up.

This review was generated by an AI assistant.

Comment on lines +270 to +273
# Initialize credentials first to populate tier/project caches
await self._initialize_credentials()
# Then initialize usage managers which reads from those caches
await self._client.initialize_usage_managers()
Copy link
Contributor

Choose a reason for hiding this comment

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

This reordering correctly addresses the initialization dependency within the refresher loop. By calling _initialize_credentials() first, you ensure that the provider plugins have performed their discovery (populating the tier caches) before initialize_usage_managers() attempts to read that metadata.

One thing to note: RotatingClient.initialize_usage_managers() is also called in RotatingClient.__aenter__ and at line 606 of src/proxy_app/main.py. Because of the self._usage_initialized guard in that method, those early calls might still "win" and initialize the managers with None tiers before this background task reaches line 271.

To fully resolve this across the application, you might consider removing the early call in main.py or having initialize_usage_managers ensure that discovery has completed before proceeding.

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