Commit bc167948 by Demid Merzlyakov

WdtWeatherSource refactoring.

parent eb04a35b
...@@ -22,6 +22,7 @@ public class WdtWeatherSource: WeatherSource { ...@@ -22,6 +22,7 @@ public class WdtWeatherSource: WeatherSource {
private let log = Logger(componentName: "WdtWeatherSource") private let log = Logger(componentName: "WdtWeatherSource")
private static let updateUrlMega = "https://1weather.onelouder.com/feeds/onelouder/mega.php" private static let updateUrlMega = "https://1weather.onelouder.com/feeds/onelouder/mega.php"
private static let updateUrlMicro = "https://1weather.onelouder.com/feeds/onelouder2/fm.php" private static let updateUrlMicro = "https://1weather.onelouder.com/feeds/onelouder2/fm.php"
private static let updateUrlHealth = "https://1weather.onelouder.com/feeds/onelouder/health.php"
/// This queue is needed to synchronize access to locationsBeingUpdated. Also, to make logging more clear. /// This queue is needed to synchronize access to locationsBeingUpdated. Also, to make logging more clear.
private let internalQueue: OperationQueue = { private let internalQueue: OperationQueue = {
...@@ -50,16 +51,13 @@ public class WdtWeatherSource: WeatherSource { ...@@ -50,16 +51,13 @@ public class WdtWeatherSource: WeatherSource {
} }
} }
/// This method should only be run from the internalQueue. private func buildURL(for location: Location, type: WeatherUpdateType, uvRequest: Bool) -> Result<URL, WdtWeatherSourceError> {
private func updateWeatherInternal(for location: Location, type: WeatherUpdateType, completion: @escaping WeatherSourceCompletion) {
guard !locationsBeingUpdated.contains(location) else {
completion(nil, WdtWeatherSourceError.alreadyBeingUpdated)
return
}
locationsBeingUpdated.insert(location)
var urlToUse = WdtWeatherSource.updateUrlMega var urlToUse = WdtWeatherSource.updateUrlMega
if type == .preferIncremental && location.lastWeatherUpdateDate != nil { if uvRequest {
log.debug("Start update (health) for \(location)")
urlToUse = WdtWeatherSource.updateUrlHealth
}
else if type == .preferIncremental && location.lastWeatherUpdateDate != nil {
urlToUse = WdtWeatherSource.updateUrlMicro urlToUse = WdtWeatherSource.updateUrlMicro
log.debug("Start update (incremental) for \(location)") log.debug("Start update (incremental) for \(location)")
} }
...@@ -71,12 +69,10 @@ public class WdtWeatherSource: WeatherSource { ...@@ -71,12 +69,10 @@ public class WdtWeatherSource: WeatherSource {
log.error("Couldn't create URLComponents from \(urlToUse)") log.error("Couldn't create URLComponents from \(urlToUse)")
assertionFailure("Should never happen. The URL should be correct.") assertionFailure("Should never happen. The URL should be correct.")
// Should never happen, but a lot of stuff that should never happen happens from time to time, so let's at least handle it gracefully in prod. // Should never happen, but a lot of stuff that should never happen happens from time to time, so let's at least handle it gracefully in prod.
completion(nil, WdtWeatherSourceError.badUrl) return .failure(.badUrl)
return
} }
var queryParameters = [String: String]() var queryParameters = [String: String]()
if let coordinates = location.coordinates { if let coordinates = location.coordinates {
queryParameters["LAT"] = String(format: "%.5f", coordinates.latitude) queryParameters["LAT"] = String(format: "%.5f", coordinates.latitude)
queryParameters["LON"] = String(format: "%.5f", coordinates.longitude) queryParameters["LON"] = String(format: "%.5f", coordinates.longitude)
...@@ -88,20 +84,28 @@ public class WdtWeatherSource: WeatherSource { ...@@ -88,20 +84,28 @@ public class WdtWeatherSource: WeatherSource {
queryParameters["COUNTRY"] = location.countryName queryParameters["COUNTRY"] = location.countryName
} }
guard !queryParameters.isEmpty else { guard !queryParameters.isEmpty else {
completion(nil, WdtWeatherSourceError.insufficientLocationInfo)
log.error("Not enough information about location.") log.error("Not enough information about location.")
return return .failure(.insufficientLocationInfo)
} }
queryParameters["UNITS"] = "all" queryParameters["UNITS"] = "all"
urlComponents.queryItems = queryParameters.map { URLQueryItem(name: $0, value: $1) } urlComponents.queryItems = queryParameters.map { URLQueryItem(name: $0, value: $1) }
guard let url = urlComponents.url else { guard let url = urlComponents.url else {
log.error("Couldn't create URL with params: \(queryParameters)") log.error("Couldn't create URL with params: \(queryParameters)")
completion(nil, WdtWeatherSourceError.badUrl) return .failure(.badUrl)
return
} }
log.debug("Network request (\(location)): \(url)") log.debug("Network request (\(location)): \(url)")
return .success(url)
}
/// This method should only be run from the internalQueue.
private func updateWeatherInternal(for location: Location, type: WeatherUpdateType, completion: @escaping WeatherSourceCompletion) {
let urlBuildResult = buildURL(for: location, type: type, uvRequest: false)
switch urlBuildResult {
case .failure(let error):
completion(nil, error)
return
case .success(let url):
let urlSession = URLSession.shared let urlSession = URLSession.shared
let dataTask = urlSession.dataTask(with: url) { [weak self] (data, reponse, error) in let dataTask = urlSession.dataTask(with: url) { [weak self] (data, reponse, error) in
guard let self = self else { return } guard let self = self else { return }
...@@ -128,6 +132,7 @@ public class WdtWeatherSource: WeatherSource { ...@@ -128,6 +132,7 @@ public class WdtWeatherSource: WeatherSource {
} }
dataTask.resume() dataTask.resume()
} }
}
private func applyChangesTo(location: Location, from locationResponse: WdtLocationResponse) throws -> Location? { private func applyChangesTo(location: Location, from locationResponse: WdtLocationResponse) throws -> Location? {
guard let wdtLocation = locationResponse.locations.first else { guard let wdtLocation = locationResponse.locations.first else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment