feat(BA-5837): ValkeyCache for AppConfigFragment merged-view reads#11298
Draft
jopemachine wants to merge 7 commits intoBA-5832from
Draft
feat(BA-5837): ValkeyCache for AppConfigFragment merged-view reads#11298jopemachine wants to merge 7 commits intoBA-5832from
jopemachine wants to merge 7 commits intoBA-5832from
Conversation
This was referenced Apr 25, 2026
feat(BA-5814): AppConfigPolicy foundation (data / repository / service / adapter, bulk-aware)
#11266
Draft
jopemachine
commented
Apr 26, 2026
Member
Author
|
Please add unit tests |
3 tasks
47394e2 to
d039712
Compare
…ew reads Re-introduces a Valkey-backed cache layer for the merged AppConfig view, replacing the cache source that was dropped together with the legacy `app_configs` table in #11265 (BA-5822). The hot path — `AppConfigFragmentRepository.app_config(user_id, name)` — is the WebUI bootstrap loop (BEP-1052 §6) and was previously a DB hit per request. Mirrors the legacy `AppConfigCacheSource` shape on top of the `(user, name)`-keyed merged view: - `cache_source/cache_source.py`: - `get_merged_config(user_id, name)` cache-aside read keyed by `app_config:merged:{user_id}:{name}` - `set_merged_config(merged, domain_name=...)` writes the deep-merged payload + indexes the cache key in `app_config:user_keys:{user_id}` and the user in `app_config:domain_users:{domain_name}` so invalidation runs without `SCAN` - `invalidate_for_scope(scope_type, scope_id)`: - `USER`: drop the user's per-name set - `DOMAIN` / `DOMAIN_USER_DEFAULTS`: cascade through every member of the domain user set - `PUBLIC`: rely on TTL (broad invalidation TBD) - `invalidate_for_user(user_id)` convenience for self-service writes - `db_source.user_domain_name(user_id)` single-column lookup so the cache layer can tag merged-view entries with their owning domain - `AppConfigFragmentRepository.app_config(...)` is now cache-aside (cache hit returns the cached payload + fresh DB fragments; cache miss writes through) - `AppConfigFragmentAdminRepository.{create,update,purge}` invalidate the affected scope after the DB write - `repositories.py` builds the cache source from `args.valkey_stat_client` and threads it into both repos - All cache calls pass through `suppress_with_log` — cache failures log a warning and fall through to the DB
…Cache surface Carry the stack-wide `bulk_create_my` / `bulk_update_my` → `my_bulk_create` / `my_bulk_update` rename through the cache_source module added by this PR, plus the GQL / adapter / DTO touchpoints that the rebase resolved with `-X theirs` (which kept stale identifiers). Also strip the residual `BEP-1052 §X` references from the cache_source docstring and the merged-view repository docstring. Only the news fragments retain the BEP wording. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…attern The Valkey cache wrapper added in this PR re-introduced the `(key, spec)` and `(key)` signatures on `db_source.update` / `db_source.purge`. Switch the cache-aware admin_repository over to the Updater/Purger pattern from BA-5827 while keeping the merged- view cache-invalidation hooks intact. Also rename the residual `extra_config` / `extraConfig` references in the GQL types and schema dump to `config` for consistency with the column rename. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The lookup is a single-column fetch helper (not an entity getter), so the explicit `get_` prefix matches sister DB-source helpers and reads naturally at the call site. Update the only caller in `AppConfigFragmentRepository.app_config` accordingly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: octodog <mu001@lablup.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📚 Stacked PRs
This PR is part of a 10-PR stack delivering BEP-1052. Merge in order:
chore(BA-5822): drop legacy AppConfig layerfeat(BA-5814): AppConfigPolicy foundationfeat(BA-5815): AppConfigPolicy GraphQLfeat(BA-5844): AppConfigPolicy REST v2feat(BA-5827): AppConfigFragment foundationfeat(BA-5836): AppConfigFragment service verticalfeat(BA-5829): AppConfigFragment + AppConfig GraphQLfeat(BA-5830): AppConfigFragment + AppConfig REST v2feat(BA-5832): AppConfig v2 SDK + CLIfeat(BA-5837): ValkeyCache for AppConfigFragment merged-view reads← you are hereCI on intermediate PRs may show test churn since each one only lands a slice of the new layer. The full picture is guaranteed to build at the tip (#11298).
Closes #11297.
Summary
Re-introduces a Valkey-backed cache layer for the BEP-1052 merged
AppConfigview, replacing the cache source that was dropped togetherwith the legacy
app_configstable in #11265 (BA-5822). The hot path—
AppConfigFragmentRepository.app_config(user_id, name)— is theWebUI bootstrap loop (BEP-1052 §6) and was previously a DB hit per
request.
What's in here
repositories/app_config_fragment/cache_source/cache_source.py:get_merged_config(user_id, name)cache-aside read keyed byapp_config:merged:{user_id}:{name}set_merged_config(merged, domain_name=...)writes the deep-mergedpayload + indexes the key in
app_config:user_keys:{user_id}andthe user in
app_config:domain_users:{domain_name}so invalidationruns without
SCANinvalidate_for_scope(scope_type, scope_id):USER: drop the user's per-name setDOMAIN/DOMAIN_USER_DEFAULTS: cascade through every memberof the domain user set
PUBLIC: rely on TTL (broad invalidation TBD)db_source.user_domain_name(user_id)lookup so the cache layer cantag merged-view entries with their owning domain.
AppConfigFragmentRepository.app_config(...)is now cache-aside(hit → cached payload + fresh DB fragments; miss → DB read +
write-through).
AppConfigFragmentAdminRepository.{create,update,purge}invalidatethe affected scope after each DB write.
repositories.pybuilds the cache source fromargs.valkey_stat_clientand threads it into both repos.suppress_with_logso cache failureslog a warning and fall through to the DB.
Stack
Test plan
./bai:app-config my-get themepopulates cache.my-getreturns the same payload.my app-config bulk-updateinvalidates → nextmy-getreturns theupdated payload.
pants checkclean on the touched files.📚 Documentation preview 📚: https://sorna--11298.org.readthedocs.build/en/11298/
📚 Documentation preview 📚: https://sorna-ko--11298.org.readthedocs.build/ko/11298/