Skip to content

Commit 7e4a4c0

Browse files
committed
vk-1024-hybrid-router: added thread safety to NavigationRouter. Update route refresh callbacks to match outcome RouteResponse object.
1 parent 76b20ed commit 7e4a4c0

File tree

4 files changed

+68
-35
lines changed

4 files changed

+68
-35
lines changed

Sources/MapboxCoreNavigation/CacheHandlerFactory.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
import MapboxNavigationNative
33

4-
struct CacheHandlerFactory {
4+
enum CacheHandlerFactory {
55

66
private static var key: (TilesConfig, ConfigHandle, HistoryRecorderHandle?)? = nil
77
private static var cachedHandle: CacheHandle!

Sources/MapboxCoreNavigation/NavigationRouter.swift

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ public class NavigationRouter {
3535
}
3636

3737
public private(set) var activeRequests: [RequestId : RoutingRequest] = [:]
38-
public private(set) var source: RouterSource
39-
private var router: RouterInterface
40-
private var settings: NavigationSettings
38+
private let requestsLock = NSLock()
39+
public let source: RouterSource
40+
private let router: RouterInterface
41+
private let settings: NavigationSettings
4142

4243
public init(_ source: RouterSource = .hybrid, settings: NavigationSettings = .shared) {
4344
self.source = source
@@ -55,15 +56,28 @@ public class NavigationRouter {
5556
}
5657

5758
fileprivate func finish(request id: RequestId) {
59+
requestsLock.lock(); defer {
60+
requestsLock.unlock()
61+
}
62+
5863
router.cancelRequest(forToken: id)
5964
activeRequests[id] = nil
6065
print(">>> finished id: \(id)")
6166
}
6267

68+
func complete(requestId: RequestId, with result: @escaping () -> Void) {
69+
DispatchQueue.main.async {
70+
result()
71+
self.finish(request: requestId)
72+
}
73+
}
74+
75+
6376
public func doRequest<ResponseType: Codable>(options: DirectionsOptions,
6477
completion: @escaping (Result<ResponseType, DirectionsError>) -> Void) -> RequestId {
6578
let directionsUri = settings.directions.url(forCalculating: options).absoluteString
6679
var requestId: RequestId!
80+
requestsLock.lock()
6781
requestId = router.getRouteForDirectionsUri(directionsUri) { [weak self] (result, _) in // mind exposing response origin?
6882
guard let self = self else { return }
6983

@@ -75,22 +89,21 @@ public class NavigationRouter {
7589

7690
if let jsonData = data,
7791
let response = try? decoder.decode(ResponseType.self, from: jsonData) {
78-
DispatchQueue.main.async {
92+
self.complete(requestId: requestId) {
7993
completion(.success(response))
80-
self.finish(request: requestId)
8194
}
8295
} else {
83-
DispatchQueue.main.async {
96+
self.complete(requestId: requestId) {
8497
completion(.failure(.unknown(response: nil,
8598
underlying: result.error as? Error,
8699
code: nil,
87100
message: nil)))
88-
self.finish(request: requestId)
89101
}
90102
}
91103
}
92104
activeRequests[requestId] = .init(id: requestId,
93105
router: self)
106+
requestsLock.unlock()
94107
print(">>> started id: \(requestId)")
95108
return requestId
96109
}
@@ -116,9 +129,8 @@ public class NavigationRouter {
116129

117130
@discardableResult public func refreshRoute(indexedRouteResponse: IndexedRouteResponse,
118131
fromLegAtIndex startLegIndex: UInt32 = 0,
119-
completionHandler: @escaping Directions.RouteRefreshCompletionHandler) -> RequestId {
132+
completionHandler: @escaping Directions.RouteCompletionHandler) -> RequestId {
120133
guard case let .route(routeOptions) = indexedRouteResponse.routeResponse.options,
121-
let route = indexedRouteResponse.selectedRoute,
122134
let responseIdentifier = indexedRouteResponse.routeResponse.identifier else {
123135
preconditionFailure("Invalid route data passed for refreshing.")
124136
}
@@ -128,52 +140,73 @@ public class NavigationRouter {
128140

129141
let routeIndex = UInt32(indexedRouteResponse.routeIndex)
130142

131-
guard let routeData = try? encoder.encode(route),
143+
guard
144+
let routeData = try? encoder.encode(indexedRouteResponse.routeResponse),
132145
let routeJSONString = String(data: routeData, encoding: .utf8) else {
133146
preconditionFailure("Could not serialize route data for refreshing.")
134147
}
135148

136149
var requestId: RequestId!
137-
requestId = router.getRouteRefresh(for: RouteRefreshOptions(requestId: responseIdentifier,
138-
routeIndex: routeIndex,
139-
legIndex: startLegIndex),
150+
let refreshOptions = RouteRefreshOptions(requestId: responseIdentifier,
151+
routeIndex: routeIndex,
152+
legIndex: startLegIndex,
153+
routingProfile: routeOptions.profileIdentifier.nativeProfile)
154+
requestsLock.lock()
155+
requestId = router.getRouteRefresh(for: refreshOptions,
140156
route: routeJSONString) { [weak self] result, _ in
141157
guard let self = self else { return }
142158
// change to route deserialization
143159
do {
144160
let json = result.value as? String
145161
guard let data = json?.data(using: .utf8) else {
146-
DispatchQueue.main.async {
147-
completionHandler(self.settings.directions.credentials, .failure(.noData))
148-
self.finish(request: requestId)
162+
self.complete(requestId: requestId) {
163+
let session = (options: routeOptions as DirectionsOptions,
164+
credentials: self.settings.directions.credentials)
165+
completionHandler(session, .failure(.noData))
149166
}
150167
return
151168
}
152169
let decoder = JSONDecoder()
153-
decoder.userInfo = [
154-
.responseIdentifier: responseIdentifier,
155-
.routeIndex: routeIndex,
156-
.startLegIndex: startLegIndex,
157-
.credentials: self.settings.directions.credentials,
158-
]
170+
decoder.userInfo = [.options: routeOptions,
171+
.credentials: self.settings.directions.credentials]
159172

160-
let result = try decoder.decode(RouteRefreshResponse.self, from: data)
173+
let result = try decoder.decode(RouteResponse.self, from: data)
161174

162-
DispatchQueue.main.async {
163-
completionHandler(self.settings.directions.credentials, .success(result))
164-
self.finish(request: requestId)
175+
self.complete(requestId: requestId) {
176+
let session = (options: routeOptions as DirectionsOptions,
177+
credentials: self.settings.directions.credentials)
178+
completionHandler(session, .success(result))
165179
}
166180
} catch {
167-
DispatchQueue.main.async {
181+
self.complete(requestId: requestId) {
182+
let session = (options: routeOptions as DirectionsOptions,
183+
credentials: self.settings.directions.credentials)
168184
let bailError = DirectionsError(code: nil, message: nil, response: nil, underlyingError: error)
169-
completionHandler(self.settings.directions.credentials, .failure(bailError))
170-
self.finish(request: requestId)
185+
completionHandler(session, .failure(bailError))
171186
}
172187
}
173188
}
174189
activeRequests[requestId] = .init(id: requestId,
175190
router: self)
191+
requestsLock.unlock()
176192
print(">>> started refresh id: \(requestId)")
177193
return requestId
178194
}
179195
}
196+
197+
extension DirectionsProfileIdentifier {
198+
var nativeProfile: RoutingProfile {
199+
switch self {
200+
case .automobile:
201+
return .driving
202+
case .automobileAvoidingTraffic:
203+
return .drivingTraffic
204+
case .cycling:
205+
return .cycling
206+
case .walking:
207+
return .walking
208+
default:
209+
return .driving
210+
}
211+
}
212+
}

Sources/MapboxCoreNavigation/RouteProgress.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,10 +290,10 @@ open class RouteProgress: Codable {
290290
}
291291

292292
/**
293-
Updates the current route with attributes from the given skeletal route.
293+
Updates the current route with a refreshed one.
294294
*/
295-
public func refreshRoute(with refreshedRoute: RefreshedRoute, at location: CLLocation) {
296-
route.refreshLegAttributes(from: refreshedRoute)
295+
func refreshRoute(with refreshedRoute: Route, at location: CLLocation) {
296+
route = refreshedRoute
297297
currentLegProgress = RouteLegProgress(leg: route.legs[legIndex],
298298
stepIndex: currentLegProgress.stepIndex,
299299
spokenInstructionIndex: currentLegProgress.currentStepProgress.spokenInstructionIndex)

Sources/MapboxCoreNavigation/Router.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,8 @@ extension InternalRouter where Self: Router {
213213
guard case let .success(response) = result, let self = self else {
214214
return
215215
}
216-
217-
self.routeProgress.refreshRoute(with: response.route, at: location)
216+
self.indexedRouteResponse = .init(routeResponse: response, routeIndex: self.indexedRouteResponse.routeIndex)
217+
self.routeProgress.refreshRoute(with: self.indexedRouteResponse.selectedRoute!, at: location)
218218

219219
var userInfo = [RouteController.NotificationUserInfoKey: Any]()
220220
userInfo[.routeProgressKey] = self.routeProgress

0 commit comments

Comments
 (0)