Skip to content

Add persistent sqlite3-backed API metadata cache#1815

Open
bendichter wants to merge 2 commits intomasterfrom
enh/api-cache
Open

Add persistent sqlite3-backed API metadata cache#1815
bendichter wants to merge 2 commits intomasterfrom
enh/api-cache

Conversation

@bendichter
Copy link
Member

Summary

  • Add APIMetadataCache class in dandi/apicache.py — a persistent sqlite3-backed cache for API metadata responses, keyed by (api_url, entity_type, entity_id) and validated against modified timestamps
  • Add cache: bool = False parameter to DandiAPIClient.__init__() to opt in to caching
  • Integrate cache into RemoteDandiset.get_raw_metadata() and BaseRemoteAsset.get_raw_metadata() — no extra API calls needed for staleness checks
  • Respects existing DANDI_CACHE env var ("ignore" disables, "clear" wipes)
  • Add module reference docs (apicache.rst), caching section in dandiapi.rst, and updated DEVELOPMENT.md

Test plan

  • python -m pytest dandi/tests/test_apicache.py -v — 8 unit tests covering miss, hit, staleness, update, clear, different entity types, DANDI_CACHE=ignore, and DANDI_CACHE=clear
  • pre-commit run --files dandi/apicache.py dandi/dandiapi.py dandi/tests/test_apicache.py — all checks pass
  • Manual: python -c "from dandi.dandiapi import DandiAPIClient; c = DandiAPIClient('https://api.dandiarchive.org/api', cache=True); ds = c.get_dandiset('000027'); print(ds.get_raw_metadata()['name'])" — run twice, second should be faster

🤖 Generated with Claude Code

Introduce opt-in caching for DandiAPIClient(cache=True) that persists
metadata responses to a local sqlite3 database, validated against
modified timestamps to avoid serving stale data without extra API calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bendichter bendichter added the minor Increment the minor version when merged label Feb 27, 2026
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@codecov
Copy link

codecov bot commented Feb 27, 2026

Codecov Report

❌ Patch coverage is 87.87879% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.14%. Comparing base (0fe497d) to head (f5a38de).

Files with missing lines Patch % Lines
dandi/dandiapi.py 56.25% 14 Missing ⚠️
dandi/apicache.py 95.83% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1815      +/-   ##
==========================================
+ Coverage   75.11%   75.14%   +0.02%     
==========================================
  Files          84       86       +2     
  Lines       11925    12050     +125     
==========================================
+ Hits         8958     9055      +97     
- Misses       2967     2995      +28     
Flag Coverage Δ
unittests 75.14% <87.87%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

``dandi.apicache``
==================

This module provides a persistent, sqlite3-backed cache for metadata returned
Copy link
Member

Choose a reason for hiding this comment

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

does it work ok on large ones like 000026? I just wonder that may be sqlite3 can quickly become inefficient for some uses. E.g. how large it would become after listing all dandisets and would it still perform ok? as should there be some per-dandiset cache may be instead?

except HTTP404Error:
raise NotFoundError(f"No such asset: {self}")
cache = self.client.cache
modified = self.modified.isoformat()
Copy link
Member

Choose a reason for hiding this comment

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

frankly I am not sure yet if we can rely on modified on per asset, see e.g. a random first hit

and we had touched on those prior in

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor Increment the minor version when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants