Skip to content

Commit 83b9b96

Browse files
committed
fix(SimpleResolver): Function loadOrResolve should be atomically executed in the serial queue
1 parent f7724f3 commit 83b9b96

File tree

1 file changed

+36
-22
lines changed

1 file changed

+36
-22
lines changed

Sources/InfomaniakDI/SimpleResolver.swift

+36-22
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public final class SimpleResolver: SimpleResolvable, SimpleStorable, CustomDebug
6565
enum ErrorDomain: Error {
6666
case factoryMissing(identifier: String)
6767
case typeMissmatch(expected: String, got: String)
68+
case unknown
6869
}
6970

7071
/// One singleton to rule them all
@@ -99,36 +100,49 @@ public final class SimpleResolver: SimpleResolvable, SimpleStorable, CustomDebug
99100
resolver: SimpleResolvable) throws -> Service {
100101
let serviceIdentifier = buildIdentifier(type: type, forIdentifier: customIdentifier)
101102

102-
// load form store
103-
var fetchedService: Any?
103+
var resolvedService: Service?
104+
var resolveError: Error?
104105
queue.sync {
105-
fetchedService = store[serviceIdentifier]
106-
}
107-
if let service = fetchedService as? Service {
108-
return service
106+
do {
107+
resolvedService = try loadOrResolve(
108+
serviceIdentifier: serviceIdentifier,
109+
factoryParameters: factoryParameters,
110+
resolver: resolver
111+
)
112+
} catch {
113+
resolveError = error
114+
}
109115
}
110116

111-
// load service from factory
112-
var factory: Factoryable?
113-
queue.sync {
114-
factory = factories[serviceIdentifier]
115-
}
116-
guard let factory = factory else {
117-
throw ErrorDomain.factoryMissing(identifier: serviceIdentifier)
117+
guard let resolvedService else {
118+
guard let resolveError else {
119+
throw ErrorDomain.unknown
120+
}
121+
throw resolveError
118122
}
119123

120-
// Apply factory closure
121-
let builtType = try factory.build(factoryParameters: factoryParameters, resolver: resolver)
122-
guard let service = builtType as? Service else {
123-
throw ErrorDomain.typeMissmatch(expected: "\(Service.Type.self)", got: "\(builtType.self)")
124-
}
124+
return resolvedService
125+
}
126+
127+
private func loadOrResolve<Service>(serviceIdentifier: String,
128+
factoryParameters: [String: Any]?,
129+
resolver: SimpleResolvable) throws -> Service {
130+
if let fetchedObject = store[serviceIdentifier],
131+
let fetchedService = fetchedObject as? Service {
132+
return fetchedService
133+
} else {
134+
guard let factory = factories[serviceIdentifier] else {
135+
throw ErrorDomain.factoryMissing(identifier: serviceIdentifier)
136+
}
137+
138+
let builtType = try factory.build(factoryParameters: factoryParameters, resolver: resolver)
139+
guard let service = builtType as? Service else {
140+
throw ErrorDomain.typeMissmatch(expected: "\(Service.Type.self)", got: "\(builtType.self)")
141+
}
125142

126-
// keep in store built object for later
127-
queue.sync {
128143
store[serviceIdentifier] = service
144+
return service
129145
}
130-
131-
return service
132146
}
133147

134148
// MARK: internal

0 commit comments

Comments
 (0)