feat(upload): extract upload subsystem + move sweep to scanner ticker (B16)

- internal/upload owns chunked-upload domain logic (fingerprint resume,
  part tmp+rename, assemble, session sweep) and the shared UniquePath
  helper used by both single-file and chunked completion paths
- handlers/uploads.go is now HTTP-only: bind params, call upload.U, map
  sentinel errors to the unchanged status/code/message contract
- B16: session sweep moved out of the UploadInit request path onto the
  scanner ticker via a Sweeper hook (upload.U satisfies it)
- unit tests for the package without PG/Redis; contract pinned by the
  existing handler integration tests (all green)
This commit is contained in:
2026-09-14 22:00:25 +08:00
parent 443f4acfa9
commit fbd5cd243d
10 changed files with 708 additions and 263 deletions
+4 -2
View File
@@ -18,6 +18,7 @@ import (
"booklib/internal/redispkg"
"booklib/internal/scanner"
"booklib/internal/store"
"booklib/internal/upload"
)
type H struct {
@@ -25,10 +26,11 @@ type H struct {
st *store.Store
rdb *redispkg.R
sc *scanner.Scanner
up *upload.U
}
func New(cfg *config.Config, st *store.Store, rdb *redispkg.R, sc *scanner.Scanner) *H {
return &H{cfg: cfg, st: st, rdb: rdb, sc: sc}
func New(cfg *config.Config, st *store.Store, rdb *redispkg.R, sc *scanner.Scanner, up *upload.U) *H {
return &H{cfg: cfg, st: st, rdb: rdb, sc: sc, up: up}
}
func err(c *gin.Context, status int, code, msg string) {