Skip to content

Cache dependency version fetches per invocation#552

Open
bschwedler wants to merge 1 commit into
mainfrom
cache-dependency-fetches
Open

Cache dependency version fetches per invocation#552
bschwedler wants to merge 1 commit into
mainfrom
cache-dependency-fetches

Conversation

@bschwedler
Copy link
Copy Markdown
Contributor

@bschwedler bschwedler commented May 28, 2026

Closes #330

Memoize the requests-cache session factory and each dependency's _fetch_versions helper so backend init and JSON fetch+parse run exactly once per bakery invocation, instead of once per DependencyConstraint instance.

@bschwedler bschwedler requested a review from ianpittwood as a code owner May 28, 2026 14:37
Memoize the requests-cache session factory and each dependency's
_fetch_versions helper with functools.cache so the per-process backend
init and JSON fetch+parse happen exactly once regardless of how many
DependencyConstraint instances ask for them.

Previously each PythonDependencyConstraint, RDependencyConstraint, etc.
opened a fresh CachedSession and walked through the local HTTP cache on
every resolve_versions call, producing repeated "Initializing backend"
and "Cache directives" DEBUG lines and redundant parse work.

Closes #330
@bschwedler bschwedler force-pushed the cache-dependency-fetches branch from 92fdf16 to dcab125 Compare May 28, 2026 14:40
@github-actions
Copy link
Copy Markdown

Test Results

1 568 tests  ±0   1 568 ✅ ±0   8m 24s ⏱️ +34s
    1 suites ±0       0 💤 ±0 
    1 files   ±0       0 ❌ ±0 

Results for commit dcab125. ± Comparison against base commit f3b6b78.

Copy link
Copy Markdown

Copilot AI 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 reduces redundant dependency-version retrieval during a bakery invocation by memoizing the shared cached HTTP session and dependency version fetch helpers.

Changes:

  • Memoizes cached_session() so the requests-cache backend initializes once per process.
  • Converts dependency _fetch_versions helpers to cached static methods.
  • Clears the new caches in test fixtures so mocked sessions remain isolated per test.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
posit-bakery/posit_bakery/util.py Adds process-wide memoization for the cached requests session.
posit-bakery/posit_bakery/config/dependencies/python.py Memoizes Python version fetch/parse work.
posit-bakery/posit_bakery/config/dependencies/r.py Memoizes R version fetch/parse work.
posit-bakery/posit_bakery/config/dependencies/quarto.py Memoizes Quarto version fetches per prerelease mode.
posit-bakery/posit_bakery/config/dependencies/positron.py Memoizes Positron version fetch/parse work.
posit-bakery/test/config/conftest.py Clears memoized caches before request-mocking fixtures run.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +67 to +68
@cache
def cached_session() -> CachedSession:
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.

We shouldn't need to test core language functionality IMO. This isn't a complicated setup.

Comment on lines +74 to +82
return CachedSession(
cache_name="bakery_cache",
expire_after=3600,
backend="filesystem",
use_temp=True,
allowable_methods=["GET"],
allowable_codes=[200],
stale_if_error=True,
)
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.

I have a crazy idea: what if we cached this somehow as part of setup-bakery? Give it some sort of reasonable TTL and then recall the artifact it creates across all jobs in a workflow. That way we can resolve #304 and edge cases where new versions can crop up between build time and merge time.

Comment on lines +67 to +68
@cache
def cached_session() -> CachedSession:
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.

We shouldn't need to test core language functionality IMO. This isn't a complicated setup.


def _fetch_versions(self) -> list[DependencyVersion]:
@staticmethod
@cache
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.

roborev noted that the cached result can be mutated. We may want to note that or find a way to always return a copy.

@@ -92,6 +92,21 @@ def patch_testdata_response(url: str):

@pytest.fixture(scope="function")
def disable_requests_caching(mocker):
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.

Should this be autouse?

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.

Limit when we retrieve dependency versions

3 participants