diff --git a/TODO.md b/TODO.md index e908746..63bb559 100644 --- a/TODO.md +++ b/TODO.md @@ -16,3 +16,26 @@ - ~fetch requested files from mirror~ - ~DB sync from mirror~ - ~Config file and import~ + +Looking at what you've built and what's left on your TODO, here's how I'd think about the "done" line for a capstone: + +**What you already have that's impressive:** +- Real concurrent systems work — singleflight, atomic ops, mutex +- Custom HTTP transport with timeout tuning +- Atomic file writes with the tmp-then-rename pattern +- Meaningful test suite with httptest, not just trivial unit tests +- Clean dependency injection, thoughtful package boundaries +- Config validation with proper error wrapping + +**What would make it a complete capstone story:** +- The streaming solution for large packages — this is your most interesting unsolved technical problem and directly demonstrates you understand the HTTP layer +- At least one more meaningful feature working end-to-end, either the refresh scheduling via systemd timer or the prefetch-on-refresh logic +- Actually deployed and serving your home network — "running in production" is a strong closer + +**What I'd leave out of the capstone scope:** +- The AUR builder — that's a whole second project honestly +- Chi middleware — nice but not substantive enough to matter + +The through-line you want to be able to tell is: *I built a caching reverse proxy from scratch in Go, handling concurrency, filesystem atomicity, and HTTP semantics correctly, and deployed it on real hardware.* You're close to being able to say that. The streaming piece and a working deployment are the remaining gaps. + +How far out is the capstone deadline? diff --git a/internal/cache/cache.go b/internal/cache/cache.go index d79407a..675e75c 100644 --- a/internal/cache/cache.go +++ b/internal/cache/cache.go @@ -78,8 +78,11 @@ func (e *UpstreamError) Error() string { func (c *Cache) fetch(pkgName string) error { // pkgName is relative to the localRoot // ie pkgName includes /{repo}/os/{arch}/ and the actual name linux-x.x.x.pkg.tar.zst + tempPkgName := pkgName + ".tmp" tempPkgPath := filepath.Join(c.cfg.cacheRoot, tempPkgName) //full tmp write path + + // final file name and path outPkg := filepath.Join(c.cfg.cacheRoot, pkgName) pkgURL := c.nextMirror() + pkgName @@ -95,6 +98,7 @@ func (c *Cache) fetch(pkgName string) error { return &UpstreamError{StatusCode: resp.StatusCode} } + // use a tmp file for the initial fetch in case it fails outFile, err := os.Create(tempPkgPath) if err != nil { return err @@ -107,6 +111,7 @@ func (c *Cache) fetch(pkgName string) error { return err } + // mv file to final location if err := os.Rename(tempPkgPath, outPkg); err != nil { os.Remove(tempPkgPath) return err