72 lines
2.7 KiB
Swift
72 lines
2.7 KiB
Swift
//
|
|
// Copyright 2026 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import Foundation
|
|
import SignalServiceKit
|
|
|
|
/// Handles fetching and parsing remote megaphones and release notes.
|
|
public class RemoteReleaseNotesFetchingManager {
|
|
private let remoteReleaseNotesService: any RemoteReleaseNotesServiceProtocol
|
|
private let remoteMegaphoneFetcher: RemoteMegaphoneFetcher
|
|
private let remoteAnnouncementFetcher: RemoteAnnouncementFetcher
|
|
|
|
init(
|
|
db: DB,
|
|
remoteReleaseNotesService: any RemoteReleaseNotesServiceProtocol,
|
|
) {
|
|
self.remoteReleaseNotesService = remoteReleaseNotesService
|
|
|
|
self.remoteMegaphoneFetcher = RemoteMegaphoneFetcher(
|
|
db: db,
|
|
remoteReleaseNotesService: remoteReleaseNotesService,
|
|
)
|
|
self.remoteAnnouncementFetcher = RemoteAnnouncementFetcher(
|
|
db: db,
|
|
remoteReleaseNotesService: remoteReleaseNotesService,
|
|
)
|
|
}
|
|
|
|
/// Fetch all remote release notes currently on the service and persist them
|
|
/// locally. Removes any locally-persisted remote release notes that are no
|
|
/// longer available remotely.
|
|
func syncRemoteReleaseNotes() async throws {
|
|
Logger.info("Beginning remote release notes fetch.")
|
|
|
|
let (megaphoneManifests, announcementManifests) = try await fetchManifests()
|
|
|
|
let megaphoneResult = await Result {
|
|
try await remoteMegaphoneFetcher.run(manifests: megaphoneManifests)
|
|
}
|
|
|
|
if case .failure(let error) = megaphoneResult {
|
|
Logger.error("megaphone fetch failed: \(error)")
|
|
}
|
|
|
|
if BuildFlags.ReleaseNotesChannel.announcementFetch {
|
|
let announcementResult = await Result {
|
|
try await remoteAnnouncementFetcher.run(manifests: announcementManifests)
|
|
}
|
|
if case .failure(let error) = announcementResult {
|
|
Logger.error("announcement fetch failed: \(error)")
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Fetch the manifests for the currently-active remote megaphones.
|
|
/// Manifests contain metadata about a megaphone, such as when it should be
|
|
/// shown and what actions it should expose. They do not contain any
|
|
/// user-visible content, such as strings.
|
|
private func fetchManifests() async throws -> ([RemoteMegaphoneModel.Manifest], [RemoteAnnouncementModel.Manifest]) {
|
|
return try await Retry.performWithBackoff(
|
|
maxAttempts: 3,
|
|
isRetryable: { $0.isNetworkFailureOrTimeout || $0.is5xxServiceResponse },
|
|
block: {
|
|
Logger.info("Fetching remote release notes manifests")
|
|
return try await remoteReleaseNotesService.fetchManifests()
|
|
},
|
|
)
|
|
}
|
|
}
|