Last active
September 14, 2020 22:25
-
-
Save descorp/8e8e403d0b626c542ff2f6bfdaace80a to your computer and use it in GitHub Desktop.
Lock + Timer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Our server is calling the external API using call_api that is doing the HTTP | |
| // call. The API provider charges us if we make more than 10 calls per second. | |
| // | |
| // How would you implement something that keeps us below the limit? | |
| //: [Previous](@previous) | |
| import Foundation | |
| import PlaygroundSupport | |
| var str = "Hello, playground" | |
| final class Proxy { | |
| private let limit: Int | |
| init(limit: Int) { | |
| self.limit = limit | |
| } | |
| private var isBusy = false | |
| private var counter: Int = 0 | |
| private var tasks: [DispatchWorkItem] = [] | |
| private var runner = DispatchQueue(label: UUID().uuidString, attributes: .concurrent) | |
| func process(_ caller: @escaping ()->()) { | |
| tasks.append(DispatchWorkItem() { caller() }) | |
| run() | |
| } | |
| private func run() { | |
| guard counter < limit else { return delay() } | |
| while !tasks.isEmpty, counter < limit { | |
| let task = tasks.removeFirst() | |
| counter += 1 | |
| runner.async(execute: task) | |
| } | |
| delay() | |
| } | |
| private func delay() { | |
| guard !isBusy else { return } | |
| self.isBusy = true | |
| runner.asyncAfter(deadline: .now() + .seconds(1), flags: .barrier) { [weak self] in | |
| guard let self = self else { return } | |
| self.counter = 0 | |
| self.isBusy = false | |
| if !self.tasks.isEmpty { self.run() } | |
| } | |
| } | |
| } | |
| let proxy = Proxy(limit: 10) | |
| for i in 0...99 { | |
| proxy.process { | |
| //DispatchQueue.main.async { | |
| print("\(i) : \(Date())") | |
| //} | |
| } | |
| } | |
| PlaygroundPage.current.needsIndefiniteExecution = true | |
| //: [Next](@next) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment