Favoriten additiv abgleichen statt ersetzen; Upload-Timeout ist Einzelfehler
This commit is contained in:
@@ -293,19 +293,6 @@ class MeloCloudService {
|
||||
_pruefeStatus(antwort);
|
||||
}
|
||||
|
||||
/// Ersetzt die Favoriten am Server durch [cloudIds].
|
||||
Future<void> setzeFavoriten(List<String> cloudIds) async {
|
||||
_pruefeAnmeldung();
|
||||
final antwort = await _client
|
||||
.post(
|
||||
Uri.parse('$basisUrl/favorites'),
|
||||
headers: {..._kopf, 'Content-Type': 'application/json'},
|
||||
body: jsonEncode({'song_ids': cloudIds}),
|
||||
)
|
||||
.timeout(const Duration(seconds: 30));
|
||||
_pruefeStatus(antwort);
|
||||
}
|
||||
|
||||
/// Meldet Wiedergaben. Der Server nimmt höchstens 100 je Aufruf an und
|
||||
/// verwirft Doppelmeldungen desselben Titels innerhalb einer Stunde.
|
||||
Future<void> meldeVerlauf(List<CloudVerlauf> eintraege) async {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:drift/drift.dart' show Value;
|
||||
@@ -9,6 +10,7 @@ import 'package:uuid/uuid.dart';
|
||||
import '../library/database.dart';
|
||||
import 'media_store.dart';
|
||||
import 'melo_cloud_service.dart';
|
||||
import 'sync_merge.dart';
|
||||
|
||||
/// Was beim Abgleich mit welchen Titeln zu tun ist.
|
||||
///
|
||||
@@ -313,25 +315,77 @@ class SyncService extends ChangeNotifier {
|
||||
} on CloudException catch (e) {
|
||||
// Eine zu große oder abgelehnte Datei darf den Lauf nicht beenden.
|
||||
debugPrint('Upload „${song.title}“ übersprungen: ${e.message}');
|
||||
} on TimeoutException {
|
||||
// Der 120-s-Timeout (melo_cloud_service.dart:180) wirft
|
||||
// TimeoutException, nicht CloudException — ohne diesen Zweig riss ein
|
||||
// einziger hängender Upload den ganzen Lauf ab.
|
||||
debugPrint('Upload „${song.title}“: Zeitüberschreitung');
|
||||
}
|
||||
_erledigt++;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _gleicheFavoritenAb() async {
|
||||
/// Additiver Favoriten-Abgleich: gleicht in **beide** Richtungen an,
|
||||
/// entfernt aber in **keiner**.
|
||||
///
|
||||
/// Damit ist der alte Datenverlust-Bug strukturell unmöglich: es gibt
|
||||
/// keinen Codepfad mehr, der den Server-Stand ersetzen könnte. Der Preis
|
||||
/// ist bekannt und bewusst: ein Ent-Favorisieren propagiert nicht
|
||||
/// geräteübergreifend — hält ein zweites Gerät den Favoriten noch, bringt
|
||||
/// dessen nächster Abgleich ihn zurück.
|
||||
///
|
||||
/// Gibt `true` zurück, wenn die Phase vollständig durchlief.
|
||||
Future<bool> _gleicheFavoritenAb() async {
|
||||
_melde('Gleiche Favoriten ab …');
|
||||
|
||||
final Set<String> amServer;
|
||||
try {
|
||||
amServer = (await cloud.favoriten()).toSet();
|
||||
} catch (e) {
|
||||
// Ohne Server-Stand ist nichts zu tun. Blindes Pushen wäre harmlos,
|
||||
// aber nutzlos — die Phase wird übersprungen, der Lauf geht weiter.
|
||||
debugPrint('Favoriten-Abgleich übersprungen: $e');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grabsteine bleiben außen vor: favoriteSongIds() liefert auch Favoriten
|
||||
// getombsteter Titel, und die gehören nicht zurück auf den Server.
|
||||
final lokal = await db.allSongs();
|
||||
final cloudIdVon = {
|
||||
for (final s in lokal)
|
||||
if (s.cloudId != null) s.id: s.cloudId!,
|
||||
if (s.cloudId != null && !s.deleted) s.id: s.cloudId!,
|
||||
};
|
||||
final favoritenIds = await db.favoriteSongIds();
|
||||
final cloudFavoriten = [
|
||||
for (final id in favoritenIds)
|
||||
if (cloudIdVon[id] != null) cloudIdVon[id]!,
|
||||
];
|
||||
await cloud.setzeFavoriten(cloudFavoriten);
|
||||
final songIdVonCloudId = {
|
||||
for (final s in lokal)
|
||||
if (s.cloudId != null && !s.deleted) s.cloudId!: s.id,
|
||||
};
|
||||
final favoriten = (await db.favoriteSongIds()).toSet();
|
||||
|
||||
var vollstaendig = true;
|
||||
|
||||
for (final cloudId in zuPushendeFavoriten(
|
||||
lokaleFavoriten: favoriten,
|
||||
cloudIdVon: cloudIdVon,
|
||||
amServer: amServer,
|
||||
)) {
|
||||
try {
|
||||
await cloud.setzeFavorit(cloudId, true);
|
||||
} catch (e) {
|
||||
debugPrint('Favorit $cloudId nicht gemeldet: $e');
|
||||
vollstaendig = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (final songId in lokalZuSetzendeFavoriten(
|
||||
amServer: amServer,
|
||||
songIdVonCloudId: songIdVonCloudId,
|
||||
lokaleFavoriten: favoriten,
|
||||
)) {
|
||||
await db.setFavorite(songId, true);
|
||||
}
|
||||
|
||||
return vollstaendig;
|
||||
}
|
||||
|
||||
Future<void> _meldeVerlauf() async {
|
||||
|
||||
Reference in New Issue
Block a user