Support arbitrary resource download priorities

This commit is contained in:
Ali 2023-08-01 01:18:34 +03:00
parent 6c647ba702
commit 069d5347dd
3 changed files with 53 additions and 24 deletions

View File

@ -92,7 +92,7 @@ struct NetworkResponseInfo {
private final class MultiplexedRequestManagerContext { private final class MultiplexedRequestManagerContext {
final class RequestManagerPriorityContext { final class RequestManagerPriorityContext {
var resourceCounters: [String: Int] = [:] var resourceCounters: [String: Bag<Int>] = [:]
} }
private let queue: Queue private let queue: Queue
@ -123,19 +123,34 @@ private final class MultiplexedRequestManagerContext {
} }
} }
func pushPriority(resourceId: String) -> Disposable { func pushPriority(resourceId: String, priority: Int) -> Disposable {
let queue = self.queue let queue = self.queue
let value = self.priorityContext.resourceCounters[resourceId] ?? 0 let counters: Bag<Int>
self.priorityContext.resourceCounters[resourceId] = value + 1 if let current = self.priorityContext.resourceCounters[resourceId] {
counters = current
} else {
counters = Bag()
self.priorityContext.resourceCounters[resourceId] = counters
}
return ActionDisposable { [weak self] in let index = counters.add(priority)
self.updateState()
return ActionDisposable { [weak self, weak counters] in
queue.async { queue.async {
guard let `self` = self else { guard let `self` = self else {
return return
} }
let value = self.priorityContext.resourceCounters[resourceId] ?? 0
self.priorityContext.resourceCounters[resourceId] = max(0, value - 1) if let current = self.priorityContext.resourceCounters[resourceId], current === counters {
current.remove(index)
if current.isEmpty {
self.priorityContext.resourceCounters.removeValue(forKey: resourceId)
}
self.updateState()
}
} }
} }
} }
@ -191,26 +206,22 @@ private final class MultiplexedRequestManagerContext {
for request in self.queuedRequests.sorted(by: { lhs, rhs in for request in self.queuedRequests.sorted(by: { lhs, rhs in
let lhsPriority = lhs.resourceId.flatMap { id in let lhsPriority = lhs.resourceId.flatMap { id in
if let counters = self.priorityContext.resourceCounters[id], counters > 0 { if let counters = self.priorityContext.resourceCounters[id] {
return true return counters.copyItems().max() ?? 0
} else { } else {
return false return 0
} }
} ?? false } ?? 0
let rhsPriority = rhs.resourceId.flatMap { id in let rhsPriority = rhs.resourceId.flatMap { id in
if let counters = self.priorityContext.resourceCounters[id], counters > 0 { if let counters = self.priorityContext.resourceCounters[id] {
return true return counters.copyItems().max() ?? 0
} else { } else {
return false return 0
} }
} ?? false } ?? 0
if lhsPriority != rhsPriority { if lhsPriority != rhsPriority {
if lhsPriority { return lhsPriority > rhsPriority
return true
} else {
return false
}
} }
return lhs.id < rhs.id return lhs.id < rhs.id
@ -335,10 +346,10 @@ final class MultiplexedRequestManager {
}) })
} }
func pushPriority(resourceId: String) -> Disposable { func pushPriority(resourceId: String, priority: Int) -> Disposable {
let disposable = MetaDisposable() let disposable = MetaDisposable()
self.context.with { context in self.context.with { context in
disposable.set(context.pushPriority(resourceId: resourceId)) disposable.set(context.pushPriority(resourceId: resourceId, priority: priority))
} }
return disposable return disposable
} }

View File

@ -400,8 +400,8 @@ public extension TelegramEngine {
preconditionFailure() preconditionFailure()
} }
public func pushPriorityDownload(resourceId: String) -> Disposable { public func pushPriorityDownload(resourceId: String, priority: Int = 1) -> Disposable {
return self.account.network.multiplexedRequestManager.pushPriority(resourceId: resourceId) return self.account.network.multiplexedRequestManager.pushPriority(resourceId: resourceId, priority: priority)
} }
} }
} }

View File

@ -1460,6 +1460,23 @@ public func waitUntilStoryMediaPreloaded(context: AccountContext, peerId: Engine
var statusSignals: [Signal<Never, NoError>] = [] var statusSignals: [Signal<Never, NoError>] = []
var loadSignals: [Signal<Never, NoError>] = [] var loadSignals: [Signal<Never, NoError>] = []
var fetchPriorityDisposable: Disposable?
var fetchPriorityResourceId: String?
switch storyItem.media {
case let .image(image):
if let representation = largestImageRepresentation(image.representations) {
fetchPriorityResourceId = representation.resource.id.stringRepresentation
}
case let .file(file):
fetchPriorityResourceId = file.resource.id.stringRepresentation
default:
break
}
if let fetchPriorityResourceId {
fetchPriorityDisposable = context.engine.resources.pushPriorityDownload(resourceId: fetchPriorityResourceId, priority: 2)
}
switch storyItem.media { switch storyItem.media {
case let .image(image): case let .image(image):
@ -1523,6 +1540,7 @@ public func waitUntilStoryMediaPreloaded(context: AccountContext, peerId: Engine
return ActionDisposable { return ActionDisposable {
statusDisposable.dispose() statusDisposable.dispose()
loadDisposable.dispose() loadDisposable.dispose()
fetchPriorityDisposable?.dispose()
} }
} }
} }