fix(web): free a build slot before waking its waiters and filter paths once
- commit
- 570c3c01936f4e32209888090e68f1ae210f5bd1
- author
- brice · · 2026-10-12 05:22 UTC
- parent
- ff596dd
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +3 -5
M internal/adapters/ermitegit/convert.go +2 -4
| @@ -408,15 +408,13 @@ func (w *pathWalker) walk(tree git.ObjectID) error { | |||
| 408 | 408 | } | |
| 409 | 409 | ||
| 410 | 410 | // add lists the file name of the current directory, and says whether the walk | |
| 411 | - | // goes on. A path that is not addressable is not written to a chunk. | |
| 411 | + | // goes on. PathList.Add filters the paths that are not addressable; their | |
| 412 | + | // bytes stay in the chunk, which is rare enough not to matter. | |
| 412 | 413 | func (w *pathWalker) add(name []byte) bool { | |
| 413 | 414 | mark := len(w.prefix) | |
| 414 | 415 | w.prefix = append(w.prefix, name...) | |
| 415 | 416 | path := w.prefix | |
| 416 | 417 | w.prefix = w.prefix[:mark] | |
| 417 | - | if !domain.IsAddressablePathBytes(path) { | |
| 418 | - | return true | |
| 419 | - | } | |
| 420 | 418 | if w.chunk.Cap()-w.chunk.Len() < len(path) { | |
| 421 | 419 | w.chunk = strings.Builder{} | |
| 422 | 420 | w.chunk.Grow(max(pathChunk, len(path))) | |
| @@ -408,15 +408,13 @@ func (w *pathWalker) walk(tree git.ObjectID) error { | |||||
| 408 | } | 408 | } | ||
| 409 | 409 | ||||
| 410 | // add lists the file name of the current directory, and says whether the walk | 410 | // add lists the file name of the current directory, and says whether the walk | ||
| 411 | - | // goes on. A path that is not addressable is not written to a chunk. | 411 | + | // goes on. PathList.Add filters the paths that are not addressable; their |
| 412 | + | // bytes stay in the chunk, which is rare enough not to matter. | |||
| 412 | func (w *pathWalker) add(name []byte) bool { | 413 | func (w *pathWalker) add(name []byte) bool { | ||
| 413 | mark := len(w.prefix) | 414 | mark := len(w.prefix) | ||
| 414 | w.prefix = append(w.prefix, name...) | 415 | w.prefix = append(w.prefix, name...) | ||
| 415 | path := w.prefix | 416 | path := w.prefix | ||
| 416 | w.prefix = w.prefix[:mark] | 417 | w.prefix = w.prefix[:mark] | ||
| 417 | - | if !domain.IsAddressablePathBytes(path) { | |||
| 418 | - | return true | |||
| 419 | - | } | |||
| 420 | if w.chunk.Cap()-w.chunk.Len() < len(path) { | 418 | if w.chunk.Cap()-w.chunk.Len() < len(path) { | ||
| 421 | w.chunk = strings.Builder{} | 419 | w.chunk = strings.Builder{} | ||
| 422 | w.chunk.Grow(max(pathChunk, len(path))) | 420 | w.chunk.Grow(max(pathChunk, len(path))) | ||
M internal/adapters/web/pathcache.go +1 -1
| @@ -173,7 +173,6 @@ func (c *pathCache) joinOrStart(ctx context.Context, key, id string, build func( | |||
| 173 | 173 | // nobody above this goroutine could recover it and it would end the process. | |
| 174 | 174 | func (c *pathCache) run(ctx context.Context, key, id string, f *pathBuild, build func() ([]byte, error)) { | |
| 175 | 175 | defer func() { | |
| 176 | - | defer func() { <-c.slots }() | |
| 177 | 176 | if r := recover(); r != nil { | |
| 178 | 177 | f.body, f.err = nil, errBuildPanicked | |
| 179 | 178 | zerowrap.Ctx(ctx).Error().Interface("panic", r).Str("stack", string(debug.Stack())).Msg("path list build panicked") | |
| @@ -191,5 +190,6 @@ func (c *pathCache) finish(key, id string, f *pathBuild) { | |||
| 191 | 190 | c.putLocked(id, f.body) | |
| 192 | 191 | } | |
| 193 | 192 | c.mu.Unlock() | |
| 193 | + | <-c.slots // free before the waiters wake: one of them may start the next build | |
| 194 | 194 | close(f.done) | |
| 195 | 195 | } | |
| @@ -173,7 +173,6 @@ func (c *pathCache) joinOrStart(ctx context.Context, key, id string, build func( | |||||
| 173 | // nobody above this goroutine could recover it and it would end the process. | 173 | // nobody above this goroutine could recover it and it would end the process. | ||
| 174 | func (c *pathCache) run(ctx context.Context, key, id string, f *pathBuild, build func() ([]byte, error)) { | 174 | func (c *pathCache) run(ctx context.Context, key, id string, f *pathBuild, build func() ([]byte, error)) { | ||
| 175 | defer func() { | 175 | defer func() { | ||
| 176 | - | defer func() { <-c.slots }() | |||
| 177 | if r := recover(); r != nil { | 176 | if r := recover(); r != nil { | ||
| 178 | f.body, f.err = nil, errBuildPanicked | 177 | f.body, f.err = nil, errBuildPanicked | ||
| 179 | zerowrap.Ctx(ctx).Error().Interface("panic", r).Str("stack", string(debug.Stack())).Msg("path list build panicked") | 178 | zerowrap.Ctx(ctx).Error().Interface("panic", r).Str("stack", string(debug.Stack())).Msg("path list build panicked") | ||
| @@ -191,5 +190,6 @@ func (c *pathCache) finish(key, id string, f *pathBuild) { | |||||
| 191 | c.putLocked(id, f.body) | 190 | c.putLocked(id, f.body) | ||
| 192 | } | 191 | } | ||
| 193 | c.mu.Unlock() | 192 | c.mu.Unlock() | ||
| 193 | + | <-c.slots // free before the waiters wake: one of them may start the next build | |||
| 194 | close(f.done) | 194 | close(f.done) | ||
| 195 | } | 195 | } | ||