-
Notifications
You must be signed in to change notification settings - Fork 146
feat: implement hybrid cache architecture #1246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for endearing-brigadeiros-63f9d0 canceled.
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1246 +/- ##
==========================================
- Coverage 83.36% 83.27% -0.10%
==========================================
Files 70 73 +3
Lines 3005 3204 +199
Branches 499 545 +46
==========================================
+ Hits 2505 2668 +163
- Misses 397 427 +30
- Partials 103 109 +6 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
12b56bd to
734621c
Compare
Signed-off-by: Fabio Vincenzi <[email protected]>
…zi/git-proxy into feature/hybrid-cache
06kellyjac
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm looking forward to faster pulls!
Caches are a common place for logic or security problems so we may want added scrutiny and testing for this PR to be extra safe :)
Added some thoughts, not ran this locally just yet.
| if (process.env.NODE_ENV === 'test') { | ||
| // TEST: Full cleanup (bare cache + all working copies) | ||
| try { | ||
| if (fs.existsSync('./.remote')) { | ||
| fs.rmSync('./.remote', { recursive: true, force: true }); | ||
| step.log('Test environment: Full .remote directory cleaned'); | ||
| } else { | ||
| step.log('Test environment: .remote directory already clean'); | ||
| } | ||
| } catch (err) { | ||
| step.log(`Warning: Could not clean .remote directory: ${err}`); | ||
| } | ||
| } else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like a safer option that ensures what we're testing more closely matches prod would be to either do some separate cleanup as necessary in the tests, or adjust config to have a much lower max (or even 0) then we can see if CacheManager itself is doing the cleanup.
| // Sort repositories by last accessed (oldest first for removal) | ||
| const reposToEvaluate = [...stats.repositories].sort( | ||
| (a, b) => a.lastAccessed.getTime() - b.lastAccessed.getTime(), | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't remember if we can use toSorted yet. If we still cant a comment to use toSorted in the future would help to find this later :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should be available from node 20 so yes I'll use it
| return 0; | ||
| } | ||
|
|
||
| return Math.round(totalBytes / (1024 * 1024)); // Convert to MB |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| return Math.round(totalBytes / (1024 * 1024)); // Convert to MB | |
| return Math.ceil(totalBytes / (1024 * 1024)); // Convert to MB |
rounding down would hide some amount of KB up to 511KB. Not the end of the world but safest to always round up rather than be shortchanged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no conversion anymore since we are using bytes everywhere
jescalada
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a code review for now - I'll be testing the code later!
I was wondering if you could do some profiling to verify/document the speed improvements with this PR. Would be nice to try it out with massive repos (for example https://github.com/backstage/backstage which is >10GB) to see the difference.
I'll try to do some profiling soon as well 🙂
|
why on earth is backstage's repo 10GB? 😭 |
|
@06kellyjac It might be because of the tons of plugins that come with the repo (many of which have redundant components). Pulling with |
…zi/git-proxy into pr/fabiovincenzi/1246
jescalada
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did some manual testing and things seem to work great! When using the profiling script though, I had some issues with git clone hanging without any error messages on both the backend and the script execution.
I tried testing with Backstage which is massive and so hiccups like that are expected. However, we do want to make sure that even these large repos can get cloned correctly without fail, or at least give descriptive errors on fail.
|
|
||
| | Metric | Without Cache (main) | With Cache (PR) | Improvement | | ||
| | ------------------- | -------------------- | --------------- | -------------------- | | ||
| | **Cold Push** | 20.63s | 17.58s | 15% faster | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the Improvement column calculations might be incorrect 🤔 A push that took 20s and is now taking 6.68s is 20/6.68 = 2.99x faster.
I think it feels more impactful and easier to understand when formatting it as a multiplier (3x faster, etc.) rather than a percentage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right! The percentages were showing time reduction (66% of time saved) rather than the speedup multiplier. Updated to show it as a multiplier, which is much clearer and more impactful. Thanks!
benchmark-cache.sh
Outdated
|
|
||
| # Configuration | ||
| PROXY_URL="http://localhost:8000" | ||
| GITHUB_REPO="${1:-fabiovincenzi/open-webui}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: We might want to add an explicit error message when executing benchmark-cache.sh but the chosen repo is not added to the authorised list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just edited to show original errors everywhere
benchmark-cache.sh
Outdated
|
|
||
| # Configuration | ||
| PROXY_URL="http://localhost:8000" | ||
| GITHUB_REPO="${1:-fabiovincenzi/open-webui}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we could also throw an error if the user didn't provide their own repo in the arguments rather than defaulting to your fork?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I tought i removed all the references of my github, I just realized I didn't commit those
benchmark-cache.sh
Outdated
| echo "" | ||
|
|
||
| # Store results | ||
| echo "$push_number,$is_first,$CLONE_TIME,$PUSH_TIME,$TOTAL_TIME" >> results.csv |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should add the resulting .csvs to .gitignore? 🤔
benchmark-cache.sh
Outdated
| echo -e "${GREEN}✓ Cache cleared${NC}" | ||
| echo "" | ||
|
|
||
| measure_push() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think now the error handling shoud be much better, I'm sorry I didn't push latest changes
benchmark-cache.sh
Outdated
| START_CLONE=$(date +%s.%N) | ||
|
|
||
| rm -rf "$REPO_NAME" 2>/dev/null || true | ||
| git clone "$PROXY_REPO_URL" "$REPO_NAME" > clone.log 2>&1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we could output the clone status just to make sure things are going well for larger repos too?
| git clone "$PROXY_REPO_URL" "$REPO_NAME" > clone.log 2>&1 | |
| git clone "$PROXY_REPO_URL" "$REPO_NAME" 2>&1 | tee clone.log |

Issue: #1207
Summary
Two-tier cache system for faster git operations: persistent bare repos + ephemeral working copies.
Architecture
.remote/cache/- Shared bare repositories (persistent).remote/work/<push-id>/- Per-push working copies (temporary)Configuration
Add to
proxy.config.json:{ "cache": { "maxSizeGB": 2, "maxRepositories": 50, "cacheDir": "./.remote/cache" } }Security