This commit is contained in:
Marcos Rodriguez Velez 2024-12-12 23:38:41 -04:00
parent ed8b8e32ae
commit 2ee82f8dc9
4 changed files with 80 additions and 54 deletions

View File

@ -85,5 +85,16 @@ extension MarketAPI {
return marketDataEntry
}
static func fetchMarketData(currency: String, completion: @escaping (Result<MarketData, Error>) -> ()) {
Task {
do {
let marketData = try await fetchMarketData(currency: currency)
completion(.success(marketData))
} catch {
completion(.failure(error))
}
}
}
}

View File

@ -30,42 +30,46 @@ struct MarketWidgetProvider: TimelineProvider {
let currentDate = Date()
var entries: [MarketWidgetEntry] = []
var marketDataEntry = MarketWidgetEntry(date: currentDate, marketData: MarketData(nextBlock: "...", sats: "...", price: "...", rate: 0))
entries.append(marketDataEntry) // Initial entry with no data
let marketDataEntry = MarketWidgetEntry(date: currentDate, marketData: MarketData(nextBlock: "...", sats: "...", price: "...", rate: 0))
entries.append(marketDataEntry) // Initial placeholder entry
Task {
let userPreferredCurrency = Currency.getUserPreferredCurrency()
let entry = await fetchMarketDataWithRetry(currency: userPreferredCurrency, retries: 3)
let userPreferredCurrency = Currency.getUserPreferredCurrency()
fetchMarketDataWithRetry(currency: userPreferredCurrency, retries: 3) { marketData in
let entry = MarketWidgetEntry(date: Date(), marketData: marketData)
entries.append(entry)
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
private func fetchMarketDataWithRetry(currency: String, retries: Int) async -> MarketWidgetEntry {
var marketData = MarketData(nextBlock: "...", sats: "...", price: "...", rate: 0)
private func fetchMarketDataWithRetry(currency: String, retries: Int, completion: @escaping (MarketData) -> ()) {
var attempt = 0
for attempt in 0..<retries {
do {
print("Attempt \(attempt + 1) to fetch market data.")
let fetchedData = try await fetchMarketData(currency: currency)
marketData = fetchedData
print("Successfully fetched market data on attempt \(attempt + 1).")
break
} catch {
print("Fetch market data failed (attempt \(attempt + 1)): \(error.localizedDescription)")
try? await Task.sleep(nanoseconds: UInt64(2 * 1_000_000_000)) // Wait 2 seconds before retrying
func attemptFetch() {
attempt += 1
print("Attempt \(attempt) to fetch market data.")
MarketAPI.fetchMarketData(currency: currency) { result in
switch result {
case .success(let marketData):
print("Successfully fetched market data on attempt \(attempt).")
completion(marketData)
case .failure(let error):
print("Fetch market data failed (attempt \(attempt)): \(error.localizedDescription)")
if attempt < retries {
DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
attemptFetch()
}
} else {
print("Failed to fetch market data after \(retries) attempts.")
let fallbackData = MarketData(nextBlock: "...", sats: "...", price: "...", rate: 0)
completion(fallbackData)
}
}
}
}
let marketDataEntry = MarketWidgetEntry(date: Date(), marketData: marketData)
return marketDataEntry
}
private func fetchMarketData(currency: String) async throws -> MarketData {
let marketData = try await MarketAPI.fetchMarketData(currency: currency)
return marketData
attemptFetch()
}
}

View File

@ -30,7 +30,7 @@ struct MarketView: View {
HStack(alignment: .center, spacing: 0, content: {
Text("Sats/\(Currency.getUserPreferredCurrency())").bold().lineLimit(1).font(Font.system(size:11, weight: .medium, design: .default)).foregroundColor(.textColor)
Spacer()
Text(marketData.sats == "..." ? "..." : marketData.sats).padding(EdgeInsets(top: 2, leading: 4, bottom: 2, trailing: 4)).lineLimit(1).minimumScaleFactor(0.1).foregroundColor(.widgetBackground).font(Font.system(size:11, weight: .semibold, design: .default)).background(Color(red: 0.97, green: 0.21, blue: 0.38)).overlay(
Text( marketData.sats).padding(EdgeInsets(top: 2, leading: 4, bottom: 2, trailing: 4)).lineLimit(1).minimumScaleFactor(0.1).foregroundColor(.widgetBackground).font(Font.system(size:11, weight: .semibold, design: .default)).background(Color(red: 0.97, green: 0.21, blue: 0.38)).overlay(
RoundedRectangle(cornerRadius: 4.0)
.stroke(Color.containerRed, lineWidth: 4.0))
})
@ -38,7 +38,7 @@ struct MarketView: View {
HStack(alignment: .center, spacing: 0, content: {
Text("Price").bold().lineLimit(1).font(Font.system(size:11, weight: . medium, design: .default)).foregroundColor(.textColor)
Spacer()
Text(marketData.price == "..." ? "..." : marketData.price).padding(EdgeInsets(top: 2, leading: 4, bottom: 2, trailing: 4)).lineLimit(1).minimumScaleFactor(0.1).foregroundColor(.widgetBackground).font(Font.system(size:11, weight: .semibold, design: .default)).background(Color(red: 0.29, green: 0.86, blue: 0.73)).overlay(
Text( marketData.price).padding(EdgeInsets(top: 2, leading: 4, bottom: 2, trailing: 4)).lineLimit(1).minimumScaleFactor(0.1).foregroundColor(.widgetBackground).font(Font.system(size:11, weight: .semibold, design: .default)).background(Color(red: 0.29, green: 0.86, blue: 0.73)).overlay(
RoundedRectangle(cornerRadius:4.0)
.stroke(Color.containerGreen, lineWidth: 4.0))
})

View File

@ -48,43 +48,54 @@ struct WalletInformationAndMarketWidgetProvider: TimelineProvider {
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
} else {
Task {
let userPreferredCurrency = Currency.getUserPreferredCurrency()
let allwalletsBalance = WalletData(balance: UserDefaultsGroup.getAllWalletsBalance(), latestTransactionTime: UserDefaultsGroup.getAllWalletsLatestTransactionTime())
let userPreferredCurrency = Currency.getUserPreferredCurrency()
let allWalletsBalance = WalletData(balance: UserDefaultsGroup.getAllWalletsBalance(), latestTransactionTime: UserDefaultsGroup.getAllWalletsLatestTransactionTime())
var retryCount = 0
let maxRetries = 3
var success = false
fetchMarketDataWithRetry(currency: userPreferredCurrency, retries: 3) { marketData in
let entry = WalletInformationAndMarketWidgetEntry(date: Date(), marketData: marketData, allWalletsBalance: allWalletsBalance)
Task {
await entryStore.setLastSuccessfulEntry(entry)
entries.append(entry)
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
}
}
while retryCount < maxRetries && !success {
do {
print("Fetching market data for currency: \(userPreferredCurrency)")
let result = try await MarketAPI.fetchMarketData(currency: userPreferredCurrency)
let entry = WalletInformationAndMarketWidgetEntry(date: Date(), marketData: result, allWalletsBalance: allwalletsBalance)
await entryStore.setLastSuccessfulEntry(entry)
entries.append(entry)
success = true
} catch {
retryCount += 1
print("Error fetching market data: \(error.localizedDescription). Retry \(retryCount)/\(maxRetries)")
if retryCount == maxRetries {
print("Max retries reached. Blacklisting server.")
private func fetchMarketDataWithRetry(currency: String, retries: Int, completion: @escaping (MarketData) -> ()) {
var attempt = 0
func attemptFetch() {
attempt += 1
print("Attempt \(attempt) to fetch market data.")
MarketAPI.fetchMarketData(currency: currency) { result in
switch result {
case .success(let marketData):
print("Successfully fetched market data on attempt \(attempt).")
completion(marketData)
case .failure(let error):
print("Error fetching market data: \(error.localizedDescription). Retry \(attempt)/\(retries)")
if attempt < retries {
DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
attemptFetch()
}
} else {
print("Max retries reached.")
Task {
if let lastEntry = await entryStore.getLastSuccessfulEntry() {
print("Using last successful entry.")
entries.append(lastEntry)
completion(lastEntry.marketData)
} else {
print("Using placeholder entry as fallback.")
entries.append(WalletInformationAndMarketWidgetEntry.placeholder)
completion(WalletInformationAndMarketWidgetEntry.placeholder.marketData)
}
}
}
}
let timeline = Timeline(entries: entries, policy: .atEnd)
print("Submitting timeline with \(entries.count) entries.")
completion(timeline)
}
}
attemptFetch()
}
}