Skip to content

Commit

Permalink
Merge pull request #183 from nova-wallet/2.4.4-to-main
Browse files Browse the repository at this point in the history
Fix MaxNominations constant missing in runtime
  • Loading branch information
ERussel authored Mar 1, 2022
2 parents 8a0ccf8 + e561cf4 commit 2bdc11f
Show file tree
Hide file tree
Showing 25 changed files with 518 additions and 101 deletions.
78 changes: 47 additions & 31 deletions novawallet.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,5 @@
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}
Binary file not shown.
Binary file not shown.
58 changes: 58 additions & 0 deletions novawallet/Common/Operation/AsyncClosureOperation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import Foundation
import RobinHood

final class AsyncClosureOperation<ResultType>: BaseOperation<ResultType> {
let operationClosure: (@escaping (Result<ResultType, Error>?) -> Void) throws -> Void
let cancelationClosure: () -> Void

private var mutex: DispatchSemaphore?

public init(
cancelationClosure: @escaping () -> Void,
operationClosure: @escaping (@escaping (Result<ResultType, Error>?) -> Void) throws -> Void
) {
self.cancelationClosure = cancelationClosure
self.operationClosure = operationClosure
}

override public func main() {
super.main()

if isCancelled {
return
}

if result != nil {
return
}

mutex = DispatchSemaphore(value: 0)

do {
var closureResult: Result<ResultType, Error>?

try operationClosure { [weak self] operationResult in
closureResult = operationResult

self?.mutex?.signal()
}

if let result = closureResult {
self.result = result
} else {
mutex?.wait()

result = closureResult
}

} catch {
result = .failure(error)
}
}

override func cancel() {
super.cancel()

cancelationClosure()
}
}
28 changes: 24 additions & 4 deletions novawallet/Common/Operation/StorageDecodingOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,11 @@ final class StorageConstantOperation<T: Decodable>: BaseOperation<T>, ConstantDe

let path: ConstantCodingPath

init(path: ConstantCodingPath) {
let fallbackValue: T?

init(path: ConstantCodingPath, fallbackValue: T? = nil) {
self.path = path
self.fallbackValue = fallbackValue

super.init()
}
Expand All @@ -260,7 +263,14 @@ final class StorageConstantOperation<T: Decodable>: BaseOperation<T>, ConstantDe
let item: T = try decode(at: path, codingFactory: factory).map(to: T.self)
result = .success(item)
} catch {
result = .failure(error)
if
let storageError = error as? StorageDecodingOperationError,
storageError == .invalidStoragePath,
let fallbackValue = fallbackValue {
result = .success(fallbackValue)
} else {
result = .failure(error)
}
}
}
}
Expand All @@ -270,8 +280,11 @@ final class PrimitiveConstantOperation<T: LosslessStringConvertible & Equatable>

let path: ConstantCodingPath

init(path: ConstantCodingPath) {
let fallbackValue: T?

init(path: ConstantCodingPath, fallbackValue: T? = nil) {
self.path = path
self.fallbackValue = fallbackValue

super.init()
}
Expand All @@ -296,7 +309,14 @@ final class PrimitiveConstantOperation<T: LosslessStringConvertible & Equatable>
.map(to: StringScaleMapper<T>.self)
result = .success(item.value)
} catch {
result = .failure(error)
if
let storageError = error as? StorageDecodingOperationError,
storageError == .invalidStoragePath,
let fallbackValue = fallbackValue {
result = .success(fallbackValue)
} else {
result = .failure(error)
}
}
}
}
40 changes: 38 additions & 2 deletions novawallet/Common/Protocols/RuntimeConstantFetching.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ protocol RuntimeConstantFetching {
for path: ConstantCodingPath,
runtimeCodingService: RuntimeCodingServiceProtocol,
operationManager: OperationManagerProtocol,
fallbackValue: T?,
closure: @escaping (Result<T, Error>) -> Void
) -> CancellableCall

func fetchCompoundConstant<T: Decodable>(
for path: ConstantCodingPath,
runtimeCodingService: RuntimeCodingServiceProtocol,
operationManager: OperationManagerProtocol,
fallbackValue: T?,
closure: @escaping (Result<T, Error>) -> Void
) -> CancellableCall
}
Expand All @@ -24,9 +26,42 @@ extension RuntimeConstantFetching {
runtimeCodingService: RuntimeCodingServiceProtocol,
operationManager: OperationManagerProtocol,
closure: @escaping (Result<T, Error>) -> Void
) -> CancellableCall {
fetchConstant(
for: path,
runtimeCodingService: runtimeCodingService,
operationManager: operationManager,
fallbackValue: nil,
closure: closure
)
}

@discardableResult
func fetchCompoundConstant<T: Decodable>(
for path: ConstantCodingPath,
runtimeCodingService: RuntimeCodingServiceProtocol,
operationManager: OperationManagerProtocol,
closure: @escaping (Result<T, Error>) -> Void
) -> CancellableCall {
fetchCompoundConstant(
for: path,
runtimeCodingService: runtimeCodingService,
operationManager: operationManager,
fallbackValue: nil,
closure: closure
)
}

@discardableResult
func fetchConstant<T: LosslessStringConvertible & Equatable>(
for path: ConstantCodingPath,
runtimeCodingService: RuntimeCodingServiceProtocol,
operationManager: OperationManagerProtocol,
fallbackValue: T?,
closure: @escaping (Result<T, Error>) -> Void
) -> CancellableCall {
let codingFactoryOperation = runtimeCodingService.fetchCoderFactoryOperation()
let constOperation = PrimitiveConstantOperation<T>(path: path)
let constOperation = PrimitiveConstantOperation<T>(path: path, fallbackValue: fallbackValue)
constOperation.configurationBlock = {
do {
constOperation.codingFactory = try codingFactoryOperation.extractNoCancellableResultData()
Expand Down Expand Up @@ -57,10 +92,11 @@ extension RuntimeConstantFetching {
for path: ConstantCodingPath,
runtimeCodingService: RuntimeCodingServiceProtocol,
operationManager: OperationManagerProtocol,
fallbackValue: T?,
closure: @escaping (Result<T, Error>) -> Void
) -> CancellableCall {
let codingFactoryOperation = runtimeCodingService.fetchCoderFactoryOperation()
let constOperation = StorageConstantOperation<T>(path: path)
let constOperation = StorageConstantOperation<T>(path: path, fallbackValue: fallbackValue)
constOperation.configurationBlock = {
do {
constOperation.codingFactory = try codingFactoryOperation.extractNoCancellableResultData()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ final class RuntimeProvider {
let logger: LoggerProtocol?

private(set) var snapshot: RuntimeSnapshot?
private(set) var pendingRequests: [PendingRequest] = []
private(set) var pendingRequests: [UUID: PendingRequest] = [:]
private(set) var currentWrapper: CompoundOperationWrapper<RuntimeSnapshot?>?
private var mutex = NSLock()

Expand Down Expand Up @@ -104,15 +104,30 @@ final class RuntimeProvider {
}
}

private func cancelRequest(for requestId: UUID) {
mutex.lock()

defer {
mutex.unlock()
}

let maybePendingRequest = pendingRequests[requestId]
pendingRequests[requestId] = nil

if let pendingRequest = maybePendingRequest {
deliver(snapshot: nil, to: pendingRequest)
}
}

private func resolveRequests() {
guard !pendingRequests.isEmpty else {
return
}

let requests = pendingRequests
pendingRequests = []
pendingRequests = [:]

requests.forEach { deliver(snapshot: snapshot, to: $0) }
requests.forEach { deliver(snapshot: snapshot, to: $0.value) }
}

private func deliver(snapshot: RuntimeSnapshot?, to request: PendingRequest) {
Expand All @@ -131,6 +146,7 @@ final class RuntimeProvider {
}

private func fetchCoderFactory(
assigning requestId: UUID,
runCompletionIn queue: DispatchQueue?,
executing closure: @escaping (RuntimeCoderFactoryProtocol?) -> Void
) {
Expand All @@ -145,28 +161,27 @@ final class RuntimeProvider {
if let snapshot = snapshot {
deliver(snapshot: snapshot, to: request)
} else {
pendingRequests.append(request)
pendingRequests[requestId] = request
}
}

func fetchCoderFactoryOperation() -> BaseOperation<RuntimeCoderFactoryProtocol> {
ClosureOperation { [weak self] in
var fetchedFactory: RuntimeCoderFactoryProtocol?

let semaphore = DispatchSemaphore(value: 0)

self?.fetchCoderFactory(runCompletionIn: nil) { factory in
fetchedFactory = factory
semaphore.signal()
let requestId = UUID()

return AsyncClosureOperation(cancelationClosure: { [weak self] in
self?.cancelRequest(for: requestId)
}) { [weak self] responseClosure in
if let strongSelf = self {
strongSelf.fetchCoderFactory(assigning: requestId, runCompletionIn: nil) { maybeFactory in
if let factory = maybeFactory {
responseClosure(.success(factory))
} else {
responseClosure(nil)
}
}
} else {
responseClosure(.failure(RuntimeProviderError.providerUnavailable))
}

semaphore.wait()

guard let factory = fetchedFactory else {
throw RuntimeProviderError.providerUnavailable
}

return factory
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,17 @@ final class MortalEraOperationFactory {

guard
let bestNumber = BigUInt.fromHexString(bestHeader.number),
let finalizedNumber = BigUInt.fromHexString(finalizedHeader.number),
bestNumber >= finalizedNumber else {
let finalizedNumber = BigUInt.fromHexString(finalizedHeader.number) else {
throw BaseOperationError.unexpectedDependentResult
}

let blockNumber = bestNumber - finalizedNumber > Self.maxFinalityLag ? bestNumber : finalizedNumber
if bestNumber >= finalizedNumber {
let blockNumber = bestNumber - finalizedNumber > Self.maxFinalityLag ? bestNumber : finalizedNumber

return BlockNumber(blockNumber)
return BlockNumber(blockNumber)
} else {
return BlockNumber(finalizedNumber)
}
}

mapOperation.addDependency(finalizedHeaderWrapper.targetOperation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ final class PayoutValidatorsForNominatorFactory {
{
query {
eraValidatorInfos(
orderBy: ERA_DESC,
filter:{
\(eraFilter)
others:{contains:[{who:\"\(accountAddress)\"}]}
Expand Down
2 changes: 1 addition & 1 deletion novawallet/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
Expand Down
Loading

0 comments on commit 2bdc11f

Please sign in to comment.