Akhil/optimise backend v2 - #220
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…port, EOF newline) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Decorator-based caching layer with versioned per-user keys, XFetch on aggregates, fail-open + per-namespace rollout flag. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
25 task-by-task TDD plan with full code, exact paths, commit boundaries. Covers foundation (deps, config, client, decorator, lifespan, slowapi), route caches per namespace, integration tests, load test, ops docs. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Implements the core cache read path: @cached decorator with user/global scope, version-based invalidation, XFetch probabilistic refresh, and fail-open safety via _safe(). Adds bump_version, cache_invalidate, and get_or_set helpers. All imports are lazy to support Python 3.9 test env where config.py uses 3.10+ union syntax. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Wires Redis open_redis() and close_redis() into FastAPI lifespan with fail-open behavior. App boots successfully when REDIS_URL is unset. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds integration tests using testcontainers to verify cache decorator, bump_version, and cross-user isolation against a real Redis container. Tests gracefully skip if Docker is unavailable with clear messaging. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Decorate list_bookmarks, get_bookmark, and list_folders with @cached(ns="bookmarks", ttl=120, scope="user") and make uid keyword-only. Add await bump_version(ns="bookmarks", uid=uid) to all write paths: create/update/delete/move/import/clear_all for bookmarks and create/update/delete for folders. Update all call sites in api.py and internal snapshot() to pass uid=uid as keyword argument. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Wrap CollectionItem in React.memo with custom arePropsEqual comparator that compares item.id, item.name, item.type, level, and all callbacks - Add useCallback to openAddFolderDialog and openRenameCollectionDialog to provide stable callback references for memoization - Add test to verify CollectionItem is exported as memoized component This prevents unnecessary re-renders of CollectionItem components when parent state changes but item props remain the same, improving performance in collection trees with many items. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Decorate list_tasks, get_task_stats, export_tasks, get_task, list_projects with @cached(ns="tasks", ttl=60, scope="user"); bump version on every write (create, update, status toggle, delete, import, project CRUD). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace shallow $$typeof check with direct comparator function tests. Now verifies that memo skips re-renders on identical props and triggers on changed item id, handler refs, or level. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Memoize the visibleHistory slice computation and add a 200ms debounce to the search input to avoid filter recomputation on every keystroke while keeping the search input responsive. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Wrap RequestPanel export with React.memo to prevent unnecessary re-renders when parent re-renders with stable props - Extract inline handler lambdas (setMethod, setUrl) into useCallback at top of ApiClient to ensure stable references across renders - Deps for useCallback: [activeTabId, tabs] covers closure access via updateActiveTab Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wrap updateActiveTab in useCallback with deps [activeTabId], then have handleMethodChange and handleUrlChange depend only on updateActiveTab instead of [activeTabId, tabs]. This prevents re-creation of handlers on every state mutation, allowing React.memo on RequestPanel to hold. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Offloads JSON.stringify(JSON.parse(...)) to a dedicated Web Worker for application/json responses so large payloads do not block the main thread. Falls back synchronously for non-JSON content types and when the worker is not yet ready (SSR / pre-mount). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Decorate `resolve_short_url` with @cached(ns="url_shortener_resolve", ttl=600, scope="global", strategy="xfetch") - Decorate `list_my_short_urls` with @cached(ns="url_shortener_owner", ttl=120, scope="user") - Invalidate resolve cache key on create/update/delete via cache_invalidate + _resolve_key helper - Bump url_shortener_owner version on create/update/delete via bump_version - Update api.py call sites to use renamed service functions with keyword args Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add get_top_tools and get_activity_buckets as global-scoped aggregate read functions decorated with @cached(ns="analytics_aggregate", ttl=300, scope="global", strategy="xfetch"). Expose both via new GET /analytics/top-tools and GET /analytics/activity-buckets endpoints in api.py. Per-user get_dashboard_analytics remains undecorated.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Move tabs/activeTabId state, localStorage effects, and all tab handlers out of ApiClient into TabsProvider with split useTabs/useTabsActions contexts. ApiClient now wraps ApiClientInner in <TabsProvider>. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…for append Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…unsound TS) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CollectionsProvider wraps useCollections() once; CollectionsSidebar reads state/actions via useCollectionsState()/useCollectionsActions() instead of receiving 9 collection-related props. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tes; misc review fixes
C1: analytics/services.py:83 — positional get_task_stats(uid) → keyword get_task_stats(uid=uid)
C2: users_repo.py — add bump_version(ns="auth_user", uid=uid) after every Mongo write in
update_user_profile, complete_onboarding, set_master_vault, set_backup_codes,
mark_backup_code_used, set_refresh_token_hash, clear_refresh_token_hash; skip no-op
early-return path in update_user_profile
I1: auth/services.py — move _fetch_user_doc_cached to module scope with @cached decorator
so the decorator factory runs once at import time, not per call
I2: api_client/services.py — add bump_version(ns="api_client", uid=uid) at end of
trim_history (after delete completes; early-return path skips bump correctly)
I4: test_cache_integration.py — add missing second list_bookmarks(uid="u1") call after
bump so calls["n"] == 3 assertion matches the test's intended trace
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…activeEnvId source Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…khil/mydevtools into akhil/optimise-backend-v2
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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.
No description provided.