Die Startseite holte ihre Reihen im Gänsemarsch
Die Weboberfläche holt alles, was auf der Startseite steht, in einem
einzigen `Promise.all` — und sie holt sogar mehr davon: Vorschlag und
saisonale Reihe kennt die App gar nicht. Trotzdem war sie spürbar
langsamer. Der Grund stand in einer Schleife:
for mediathek in mediatheken {
... await client.send(...)
}
Ein `await` im Schleifenrumpf heisst: Rundreise, warten, nächste
Rundreise. Bei vier Mediatheken viermal hintereinander, nachdem
„Fortsetzen" und „Als Nächstes" längst da waren. Dieselbe Schleife stand
in beiden Hintergründen, für Flaro wie für Jellyfin.
Jetzt laufen sie nebeneinander, in einer `TaskGroup`. Die Reihenfolge der
Mediatheken bleibt erhalten — nach den Antworten zu ordnen hiesse, dass
die Reihen nach jedem Start woanders stünden. Ein Actor steht dem nicht
im Weg: jede Anfrage gibt ihn beim Warten frei, genau wie die beiden
`async let` darüber es schon tun.
Nebenbei: ein Fehler bei einer Mediathek nimmt die anderen nicht mehr
mit. Eine Startseite mit drei von vier Reihen ist besser als keine.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
8397e042b8
commit
c5ab200846
@@ -86,38 +86,67 @@ public actor FlaroBackend: MediaBackend {
|
|||||||
// Einstellungen — „Gesehenes in Neuzugängen ausblenden" und
|
// Einstellungen — „Gesehenes in Neuzugängen ausblenden" und
|
||||||
// „Aufmacher nur aus Neuzugängen" —, und beide taten an einem
|
// „Aufmacher nur aus Neuzugängen" —, und beide taten an einem
|
||||||
// Flaro-Server deshalb nichts.
|
// Flaro-Server deshalb nichts.
|
||||||
for mediathek in mediatheken {
|
// **Nebeneinander, nicht nacheinander.**
|
||||||
let pfad = mediathek.kind == .show ? "/api/v1/series" : "/api/v1/movies"
|
//
|
||||||
let abfrage = [
|
// Hier stand eine Schleife mit `await` darin: bei vier Mediatheken
|
||||||
URLQueryItem(name: "library", value: mediathek.id),
|
// vier Rundreisen hintereinander, jede erst nach der vorigen. Die
|
||||||
URLQueryItem(name: "sort", value: "added"),
|
// Weboberfläche holt dieselben Reihen in einem `Promise.all` — und
|
||||||
URLQueryItem(name: "take", value: "24"),
|
// sie holt sogar mehr davon. Genau das war der Unterschied, den man
|
||||||
]
|
// der App ansah.
|
||||||
let titel: [MediaItem]
|
//
|
||||||
if mediathek.kind == .show {
|
// Ein Actor steht dem nicht im Weg: jede Anfrage gibt ihn beim
|
||||||
guard let seite = try? await client.send(
|
// Warten wieder frei, so wie die beiden darüber es schon tun.
|
||||||
FlaroRequest(path: pfad, query: abfrage),
|
let neuzugaenge = await withTaskGroup(of: (Int, MediaRowGroup?).self) { gruppe in
|
||||||
as: Wire.Page<Wire.Series>.self) else { continue }
|
for (platz, mediathek) in mediatheken.enumerated() {
|
||||||
titel = seite.items.map { $0.neutral() }
|
gruppe.addTask { (platz, await self.neuzugang(in: mediathek)) }
|
||||||
} else {
|
|
||||||
guard let seite = try? await client.send(
|
|
||||||
FlaroRequest(path: pfad, query: abfrage),
|
|
||||||
as: Wire.Page<Wire.Movie>.self) else { continue }
|
|
||||||
titel = seite.items.map { $0.neutral() }
|
|
||||||
}
|
}
|
||||||
guard !titel.isEmpty else { continue }
|
|
||||||
reihen.append(MediaRowGroup(
|
// **Die Reihenfolge der Mediatheken, nicht die der Antworten.**
|
||||||
id: "latest.\(mediathek.id)",
|
// Sonst stünden die Reihen nach jedem Start woanders — je
|
||||||
title: String(
|
// nachdem, welche Abfrage zuerst zurückkam.
|
||||||
localized: "flaro.row.latestIn \(mediathek.title)",
|
var gesammelt: [(Int, MediaRowGroup?)] = []
|
||||||
bundle: .module),
|
for await ergebnis in gruppe { gesammelt.append(ergebnis) }
|
||||||
libraryID: mediathek.id,
|
return gesammelt.sorted { $0.0 < $1.0 }.compactMap(\.1)
|
||||||
items: titel))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reihen.append(contentsOf: neuzugaenge)
|
||||||
return reihen
|
return reihen
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Die Reihe „Zuletzt hinzugefügt" einer Mediathek — oder nichts.
|
||||||
|
///
|
||||||
|
/// **Ein Fehler bei einer Mediathek nimmt nicht die anderen mit.** Die
|
||||||
|
/// Startseite mit drei von vier Reihen ist besser als gar keine.
|
||||||
|
private func neuzugang(in mediathek: MediaLibrary) async -> MediaRowGroup? {
|
||||||
|
let pfad = mediathek.kind == .show ? "/api/v1/series" : "/api/v1/movies"
|
||||||
|
let abfrage = [
|
||||||
|
URLQueryItem(name: "library", value: mediathek.id),
|
||||||
|
URLQueryItem(name: "sort", value: "added"),
|
||||||
|
URLQueryItem(name: "take", value: "24"),
|
||||||
|
]
|
||||||
|
|
||||||
|
let titel: [MediaItem]
|
||||||
|
if mediathek.kind == .show {
|
||||||
|
guard let seite = try? await client.send(
|
||||||
|
FlaroRequest(path: pfad, query: abfrage),
|
||||||
|
as: Wire.Page<Wire.Series>.self) else { return nil }
|
||||||
|
titel = seite.items.map { $0.neutral() }
|
||||||
|
} else {
|
||||||
|
guard let seite = try? await client.send(
|
||||||
|
FlaroRequest(path: pfad, query: abfrage),
|
||||||
|
as: Wire.Page<Wire.Movie>.self) else { return nil }
|
||||||
|
titel = seite.items.map { $0.neutral() }
|
||||||
|
}
|
||||||
|
|
||||||
|
guard !titel.isEmpty else { return nil }
|
||||||
|
|
||||||
|
return MediaRowGroup(
|
||||||
|
id: "latest.\(mediathek.id)",
|
||||||
|
title: String(localized: "flaro.row.latestIn \(mediathek.title)", bundle: .module),
|
||||||
|
libraryID: mediathek.id,
|
||||||
|
items: titel)
|
||||||
|
}
|
||||||
|
|
||||||
public func items(
|
public func items(
|
||||||
inLibrary library: MediaLibrary,
|
inLibrary library: MediaLibrary,
|
||||||
query: MediaQuery,
|
query: MediaQuery,
|
||||||
|
|||||||
@@ -130,19 +130,34 @@ public func isInLocalNetwork() async -> Bool {
|
|||||||
// sind zwei verschiedene Fragen — in einer gemeinsamen Reihe steht am
|
// sind zwei verschiedene Fragen — in einer gemeinsamen Reihe steht am
|
||||||
// Ende beides durcheinander, und wer nach einem Film sucht, blättert
|
// Ende beides durcheinander, und wer nach einem Film sucht, blättert
|
||||||
// an Folgen vorbei.
|
// an Folgen vorbei.
|
||||||
for library in libraries {
|
//
|
||||||
let items = try? await latestItems(limit: 20, inLibrary: library.id)
|
// **Nebeneinander, nicht nacheinander.** Hier stand ein `await` in
|
||||||
rows.append(MediaRowGroup(
|
// der Schleife: bei vier Mediatheken vier Rundreisen hintereinander.
|
||||||
id: "latest.\(library.id)",
|
// Die Reihenfolge der Mediatheken bleibt trotzdem erhalten — sonst
|
||||||
title: String(
|
// stünden die Reihen nach jedem Start woanders.
|
||||||
localized: "row.latestIn \(library.title)",
|
let latest = await withTaskGroup(of: (Int, MediaRowGroup).self) { group in
|
||||||
bundle: .module
|
for (place, library) in libraries.enumerated() {
|
||||||
),
|
group.addTask {
|
||||||
libraryID: library.id,
|
let items = try? await self.latestItems(limit: 20, inLibrary: library.id)
|
||||||
items: items ?? []
|
return (place, MediaRowGroup(
|
||||||
))
|
id: "latest.\(library.id)",
|
||||||
|
title: String(
|
||||||
|
localized: "row.latestIn \(library.title)",
|
||||||
|
bundle: .module
|
||||||
|
),
|
||||||
|
libraryID: library.id,
|
||||||
|
items: items ?? []
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var collected: [(Int, MediaRowGroup)] = []
|
||||||
|
for await result in group { collected.append(result) }
|
||||||
|
return collected.sorted { $0.0 < $1.0 }.map(\.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rows.append(contentsOf: latest)
|
||||||
|
|
||||||
rows.append(MediaRowGroup(
|
rows.append(MediaRowGroup(
|
||||||
id: "favourites",
|
id: "favourites",
|
||||||
title: String(localized: "row.favourites", bundle: .module),
|
title: String(localized: "row.favourites", bundle: .module),
|
||||||
|
|||||||
Reference in New Issue
Block a user