fix(library): survive a music disk that is not mounted
ci / api / api (push) Successful in 29s
ci / db / db (push) Successful in 47s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 52s
release / release (версия и заметки) (push) Successful in 4s
release / android (APK в релиз) (push) Successful in 3m20s
ci / api / api (push) Successful in 29s
ci / db / db (push) Successful in 47s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 52s
release / release (версия и заметки) (push) Successful in 4s
release / android (APK в релиз) (push) Successful in 3m20s
On the test server the host music folder was not mounted, so every stream and fingerprint failed with no such file, and a scan of the empty folder would have marked the whole library missing and purged it after 30 days. - a scan of an empty source folder with known files aborts with a clear error - fingerprinting skips such a source with one warning instead of one per file - LIBRARY_HOST mounts use rslave, so a disk mounted after start shows up - update.sh refuses to deploy with an empty LIBRARY_HOST Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
421b1a3eb9
commit
3da82e902a
7 files changed
+66
-1
No files matched your search
@@ -198,6 +198,7 @@ func (fp *Fingerprinter) chromaprint() bool {
|
||||
func (fp *Fingerprinter) Run(ctx context.Context) {
|
||||
withFP := fp.chromaprint()
|
||||
roots := map[uuid.UUID]string{}
|
||||
unavailable := map[uuid.UUID]bool{} // каталог источника пуст или не открывается — диск не смонтирован
|
||||
var after uuid.UUID
|
||||
for ctx.Err() == nil {
|
||||
todo, err := fp.store.FilesToFingerprint(ctx, withFP, after, 200)
|
||||
@@ -213,6 +214,9 @@ func (fp *Fingerprinter) Run(ctx context.Context) {
|
||||
return
|
||||
}
|
||||
after = f.ID
|
||||
if unavailable[f.SourceID] {
|
||||
continue
|
||||
}
|
||||
root, ok := roots[f.SourceID]
|
||||
if !ok {
|
||||
if root, err = fp.rootOf(ctx, f.SourceID); err != nil {
|
||||
@@ -220,12 +224,31 @@ func (fp *Fingerprinter) Run(ctx context.Context) {
|
||||
continue
|
||||
}
|
||||
roots[f.SourceID] = root
|
||||
if empty, err := dirEmpty(root); empty || err != nil {
|
||||
fp.log.Warn("fingerprints: source folder is empty or unreadable, skipped — is the disk mounted?",
|
||||
"source_id", f.SourceID, "root", root, "err", err)
|
||||
unavailable[f.SourceID] = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
fp.process(ctx, f, filepath.Join(root, filepath.FromSlash(f.RelPath)), withFP)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func dirEmpty(dir string) (bool, error) {
|
||||
d, err := os.Open(dir)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer func() { _ = d.Close() }()
|
||||
names, err := d.Readdirnames(1)
|
||||
if errors.Is(err, io.EOF) {
|
||||
return true, nil
|
||||
}
|
||||
return len(names) == 0, err
|
||||
}
|
||||
|
||||
func (fp *Fingerprinter) process(ctx context.Context, f FingerprintTodo, abs string, withFP bool) {
|
||||
sum := f.SHA256
|
||||
if sum == nil {
|
||||
|
||||
Reference in new issue
Block a user