Poll sync cheaply and make the server deployable
Polling re-downloaded the whole store, photos included, every five
seconds. The app now checks a tiny version endpoint and only fetches the
payload when it actually moved, and the server gained request logging,
graceful shutdown, and self-hosting docs so it can run on a VPS instead
of only on localhost.
💘 Generated with Crush
Assisted-by: Crush:kimi-k3
This commit is contained in:
@@ -181,22 +181,34 @@ final class SyncService: ObservableObject {
|
||||
}
|
||||
|
||||
private func poll() {
|
||||
guard !isSyncing, let code, let url = endpoint("/api/sync/\(code)") else { return }
|
||||
guard !isSyncing, let code, let versionURL = endpoint("/api/sync/\(code)/version") else { return }
|
||||
Task {
|
||||
do {
|
||||
let (data, response) = try await URLSession.shared.data(from: url)
|
||||
if (response as? HTTPURLResponse)?.statusCode == 404 {
|
||||
// Cheap poll first: the full payload can be megabytes of
|
||||
// base64 images, so only download it when the version moved.
|
||||
let (versionData, versionResponse) = try await URLSession.shared.data(from: versionURL)
|
||||
if (versionResponse as? HTTPURLResponse)?.statusCode == 404 {
|
||||
lastError = "Sync group no longer exists on the server"
|
||||
return
|
||||
}
|
||||
guard let http = response as? HTTPURLResponse, http.statusCode == 200 else {
|
||||
syncLog("poll HTTP \((response as? HTTPURLResponse)?.statusCode ?? -1)")
|
||||
guard let versionHTTP = versionResponse as? HTTPURLResponse, versionHTTP.statusCode == 200 else {
|
||||
syncLog("poll HTTP \((versionResponse as? HTTPURLResponse)?.statusCode ?? -1)")
|
||||
return
|
||||
}
|
||||
let remoteVersion = try JSONDecoder().decode([String: Int64].self, from: versionData)["version"] ?? 0
|
||||
guard remoteVersion > lastVersion else {
|
||||
lastError = nil
|
||||
return
|
||||
}
|
||||
syncLog("poll remote v\(remoteVersion) local v\(lastVersion) — fetching payload")
|
||||
guard let payloadURL = endpoint("/api/sync/\(code)") else { return }
|
||||
let (data, response) = try await URLSession.shared.data(from: payloadURL)
|
||||
guard let http = response as? HTTPURLResponse, http.statusCode == 200 else { return }
|
||||
let remote = try JSONDecoder().decode(SyncGetResponse.self, from: data)
|
||||
syncLog("poll remote v\(remote.version) local v\(lastVersion)")
|
||||
if remote.version > lastVersion, let payload = remote.data {
|
||||
if let payload = remote.data {
|
||||
apply(payload, version: remote.version)
|
||||
} else {
|
||||
lastVersion = remote.version
|
||||
}
|
||||
lastError = nil
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user