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 {
final class RequestManagerPriorityContext {
var resourceCounters: [String: Int] = [:]
var resourceCounters: [String: Bag<Int>] = [:]
}
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 value = self.priorityContext.resourceCounters[resourceId] ?? 0
self.priorityContext.resourceCounters[resourceId] = value + 1
let counters: Bag<Int>
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 {
guard let `self` = self else {
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
let lhsPriority = lhs.resourceId.flatMap { id in
if let counters = self.priorityContext.resourceCounters[id], counters > 0 {
return true
if let counters = self.priorityContext.resourceCounters[id] {
return counters.copyItems().max() ?? 0
} else {
return false
return 0
}
} ?? false
} ?? 0
let rhsPriority = rhs.resourceId.flatMap { id in
if let counters = self.priorityContext.resourceCounters[id], counters > 0 {
return true
if let counters = self.priorityContext.resourceCounters[id] {
return counters.copyItems().max() ?? 0
} else {
return false
return 0
}
} ?? false
} ?? 0
if lhsPriority != rhsPriority {
if lhsPriority {
return true
} else {
return false
}
return lhsPriority > rhsPriority
}
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()
self.context.with { context in
disposable.set(context.pushPriority(resourceId: resourceId))
disposable.set(context.pushPriority(resourceId: resourceId, priority: priority))
}
return disposable
}

View File

@ -400,8 +400,8 @@ public extension TelegramEngine {
preconditionFailure()
}
public func pushPriorityDownload(resourceId: String) -> Disposable {
return self.account.network.multiplexedRequestManager.pushPriority(resourceId: resourceId)
public func pushPriorityDownload(resourceId: String, priority: Int = 1) -> Disposable {
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 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 {
case let .image(image):
@ -1523,6 +1540,7 @@ public func waitUntilStoryMediaPreloaded(context: AccountContext, peerId: Engine
return ActionDisposable {
statusDisposable.dispose()
loadDisposable.dispose()
fetchPriorityDisposable?.dispose()
}
}
}