Skip to content

Commit abc50d7

Browse files
authored
Merge pull request #1171 from aciidb0mb3r/repo-update
[Resolver] Save the prefetched containers to avoid duplicate lookups
2 parents bbac385 + d424f36 commit abc50d7

File tree

4 files changed

+58
-24
lines changed

4 files changed

+58
-24
lines changed

Sources/PackageGraph/DependencyResolver.swift

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,11 @@ public protocol PackageContainerProvider {
230230
associatedtype Container: PackageContainer
231231

232232
/// Get the container for a particular identifier asynchronously.
233-
func getContainer(for identifier: Container.Identifier, completion: @escaping (Result<Container, AnyError>) -> Void)
233+
func getContainer(
234+
for identifier: Container.Identifier,
235+
skipUpdate: Bool,
236+
completion: @escaping (Result<Container, AnyError>) -> Void
237+
)
234238
}
235239

236240
/// An individual constraint onto a container.
@@ -1039,10 +1043,7 @@ public class DependencyResolver<
10391043

10401044
// Never prefetch when running in incomplete mode.
10411045
if !isInIncompleteMode && isPrefetchingEnabled {
1042-
// Ask all of these containers upfront to do async cloning.
1043-
for constraint in constraints {
1044-
provider.getContainer(for: constraint.identifier) { _ in }
1045-
}
1046+
prefetch(containers: constraints.map({ $0.identifier }))
10461047
}
10471048

10481049
// Update the active constraint set to include all active constraints.
@@ -1137,7 +1138,16 @@ public class DependencyResolver<
11371138
// MARK: Container Management
11381139

11391140
/// The active set of managed containers.
1140-
public private(set) var containers: [Identifier: Container] = [:]
1141+
public var containers: [Identifier: Container] {
1142+
return containersLock.withLock {
1143+
_containers
1144+
}
1145+
}
1146+
private var containersLock = Lock()
1147+
private var _containers: [Identifier: Container] = [:]
1148+
1149+
/// The set of containers requested so far.
1150+
private var requestedContainers: Set<Identifier> = []
11411151

11421152
/// Get the container for the given identifier, loading it if necessary.
11431153
private func getContainer(for identifier: Identifier) throws -> Container {
@@ -1152,15 +1162,40 @@ public class DependencyResolver<
11521162

11531163
/// Add a managed container.
11541164
private func addContainer(for identifier: Identifier) throws -> Container {
1155-
assert(!containers.keys.contains(identifier))
11561165
// Get the container synchronously from provider.
1157-
let container = try await { provider.getContainer(for: identifier, completion: $0) }
1158-
containers[identifier] = container
1166+
let skipUpdate = requestedContainers.contains(identifier)
1167+
requestedContainers.insert(identifier)
1168+
let container = try await { provider.getContainer(for: identifier, skipUpdate: skipUpdate, completion: $0) }
1169+
1170+
return set(container, for: identifier)
1171+
}
11591172

1160-
// Inform the delegate we are considering a new container.
1161-
delegate.added(container: identifier)
1173+
/// Starts prefetching the given containers.
1174+
private func prefetch(containers identifiers: [Identifier]) {
11621175

1163-
return container
1176+
// Prefetch the containers which are missing.
1177+
for identifier in identifiers where !requestedContainers.contains(identifier) {
1178+
requestedContainers.insert(identifier)
1179+
provider.getContainer(for: identifier, skipUpdate: false) {
1180+
// We ignore the errors here and expect them to be caught later.
1181+
guard case .success(let container) = $0 else { return }
1182+
self.set(container, for: identifier)
1183+
}
1184+
}
1185+
}
1186+
1187+
/// Set the container for the given identifier to containers store.
1188+
///
1189+
/// If the container is already present, it is not inserted again and the old
1190+
/// copy is returned.
1191+
@discardableResult
1192+
private func set(_ container: Container, for identifier: Identifier) -> Container {
1193+
return containersLock.withLock {
1194+
if let container = _containers[identifier] { return container }
1195+
self._containers[identifier] = container
1196+
self.delegate.added(container: identifier)
1197+
return container
1198+
}
11641199
}
11651200
}
11661201

Sources/PackageGraph/RepositoryPackageContainerProvider.swift

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,6 @@ public class RepositoryPackageContainerProvider: PackageContainerProvider {
5050
self.toolsVersionLoader = toolsVersionLoader
5151
}
5252

53-
public func getContainer(
54-
for identifier: Container.Identifier,
55-
completion: @escaping (Result<Container, AnyError>) -> Void
56-
) {
57-
getContainer(for: identifier, skipUpdate: false, completion: completion)
58-
}
59-
6053
public func getContainer(
6154
for identifier: Container.Identifier,
6255
skipUpdate: Bool,

Sources/SourceControl/RepositoryManager.swift

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,7 @@ public class RepositoryManager {
244244
return handle
245245
})
246246

247-
case .pending:
248-
precondition(false, "This should never have been called")
249-
return
250-
251-
case .uninitialized, .error:
247+
case .pending, .uninitialized, .error:
252248
// Change the state to pending.
253249
handle.status = .pending
254250
let repositoryPath = self.path.appending(handle.subpath)

Sources/TestSupport/MockDependencyResolver.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ extension PackageContainerConstraint where T == String {
5858
}
5959
}
6060

61+
extension PackageContainerProvider {
62+
public func getContainer(
63+
for identifier: Container.Identifier,
64+
completion: @escaping (Result<Container, AnyError>) -> Void
65+
) {
66+
getContainer(for: identifier, skipUpdate: false, completion: completion)
67+
}
68+
}
69+
6170
public enum MockLoadingError: Error {
6271
case unknownModule
6372
}
@@ -159,6 +168,7 @@ public struct MockPackagesProvider: PackageContainerProvider {
159168

160169
public func getContainer(
161170
for identifier: Container.Identifier,
171+
skipUpdate: Bool,
162172
completion: @escaping (Result<Container, AnyError>
163173
) -> Void) {
164174
DispatchQueue.global().async {

0 commit comments

Comments
 (0)