fix(datastore): log previously-silent empty-preset/recent reads (#614)

readPresetsLocked's os.IsNotExist branch and GetRecents' equivalent
branch silently returned an empty result with no log line at all,
unlike their sibling 0-byte/malformed-XML branches which already log.
When a reporter's speaker got served an empty preset list at reboot
despite an intact on-disk Presets.xml, there was no durable record of
it anywhere except a live capture at the exact moment.

Also log the per-device preset count going into every /full response
in CreateAccountDevice, distinguishing a disk read that came back
empty from one where source-mapping silently dropped presets
afterward.

Diagnostic only, no behavior change - the actual trigger for the
empty response is still open.
This commit is contained in:
Tobias Gesellchen
2026-08-21 08:59:36 +02:00
parent 21043d542a
commit 790a20d49b
2 changed files with 11 additions and 0 deletions
+4
View File
@@ -956,6 +956,8 @@ func (ds *DataStore) readPresetsLocked(account, device string) ([]models.Service
data, err := ds.rootReadFile(path)
if err != nil {
if os.IsNotExist(err) {
log.Printf("[Datastore] readPresetsLocked: no Presets.xml at %s — reporting no presets", sanitizeLog(path))
return []models.ServicePreset{}, false, nil
}
@@ -1299,6 +1301,8 @@ func (ds *DataStore) GetRecents(account, device string) ([]models.ServiceRecent,
data, err := ds.rootReadFile(path)
if err != nil {
if os.IsNotExist(err) {
log.Printf("[Datastore] GetRecents: no Recents.xml at %s — reporting no recents", sanitizeLog(path))
return []models.ServiceRecent{}, nil
}
+7
View File
@@ -752,6 +752,13 @@ func CreateAccountDevice(ds *datastore.DataStore, account, deviceID string) (mod
device.Presets = mapPresetsToFullResponse(presets, sources)
device.Recents = mapRecentsToFullResponse(recents, sources)
if len(device.Presets) != len(presets) {
log.Printf("[Marge] /full: device %s — read %d preset(s) from disk, embedding %d after source mapping",
sanitizeLog(deviceID), len(presets), len(device.Presets))
} else {
log.Printf("[Marge] /full: device %s — embedding %d preset(s)", sanitizeLog(deviceID), len(device.Presets))
}
return device, nil
}