{"action":"opened","issue":{"url":"https://api.github.com/repos/mxcl/PromiseKit/issues/878","repository_url":"https://api.github.com/repos/mxcl/PromiseKit","labels_url":"https://api.github.com/repos/mxcl/PromiseKit/issues/878/labels{/name}","comments_url":"https://api.github.com/repos/mxcl/PromiseKit/issues/878/comments","events_url":"https://api.github.com/repos/mxcl/PromiseKit/issues/878/events","html_url":"https://github.com/mxcl/PromiseKit/issues/878","id":332656804,"node_id":"MDU6SXNzdWUzMzI2NTY4MDQ=","number":878,"title":"DispatchQueues should be generalized","user":{"login":"GarthSnyder","id":443181,"node_id":"MDQ6VXNlcjQ0MzE4MQ==","avatar_url":"https://avatars3.githubusercontent.com/u/443181?v=4","gravatar_id":"","url":"https://api.github.com/users/GarthSnyder","html_url":"https://github.com/GarthSnyder","followers_url":"https://api.github.com/users/GarthSnyder/followers","following_url":"https://api.github.com/users/GarthSnyder/following{/other_user}","gists_url":"https://api.github.com/users/GarthSnyder/gists{/gist_id}","starred_url":"https://api.github.com/users/GarthSnyder/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GarthSnyder/subscriptions","organizations_url":"https://api.github.com/users/GarthSnyder/orgs","repos_url":"https://api.github.com/users/GarthSnyder/repos","events_url":"https://api.github.com/users/GarthSnyder/events{/privacy}","received_events_url":"https://api.github.com/users/GarthSnyder/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-06-15T06:10:41Z","updated_at":"2018-06-15T06:10:41Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"I've been converting a project from RxSwift to PromiseKit, and it's going really well. I know these aren't regarded as competitive substitutes, but it has been a bit surprising to see how much cleaner some of the code gets.\r\n\r\nThe one thing that I'm feeling some regret about letting go of is RxSwift's `Scheduler` abstraction. Not because it's the world's most elegant API (though it's fine), but because it introduces a layer of abstraction between the Foundation-level facilities and the kit-level facilities. This separation is important because _you can't actually subclass_ `DispatchQueue`: it's a C language system that's intimately intertwined with the compiler and runtime. If you want different dispatch behavior in PromiseKit, you're pretty much stuck, as far as I can tell. (Good thing it's easy to intermix manual GCD blocks with PromiseKit-managed blocks!)\r\n\r\nI'll cite some specific use cases below, but just to get to the point: it would be nice if PromiseKit's `on` arguments accepted something like a `DispatchProtocol` object instead of an object-type-specific `DispatchQueue`. It's fine if the protocol mirrors the existing `DispatchQueue` API - I just want to be able to roll my own.\r\n\r\nIt looks like it would be a pretty straightforward change. I'd send it in as PR, except that I can imagine some strong potential objections to the basic idea. So I thought it would be better to get a temperature reading first. The main drawback is that `DispatchProtocol` becomes visible in the public API. I imagine most people's initial reaction would be something like \"WTF is a `DispatchProtocol`?\" Calling it something like `DispatchQueueProtocol` would perhaps clarify, but that's an awfully long name. Something like `Scheduler` is clear and succinct, but it obscures the fact that these objects really are just `DispatchQueue`s in 99% of cases.\r\n\r\nI have three use cases in the current project. One is a concurrency-limited queue. You can submit as many blocks as you like, but only N will be allowed to execute concurrently. The rest have to wait until a slot opens up. This is great for cases where you need to, e.g., read 100 XML feeds, but you know that `URLSession` will start acting up if you just fire them all off at once. At the same time, it's perfectly reasonable to queue up 100 blocks in a `DispatchQueue`, so you can get away with no queueing code at all outside of a generic concurrency-limited queue implementation.\r\n\r\nThe second case is rate-limited scheduling, where one of the external APIs limits the number of network requests that can be made in a given period of time. If you go over the limit, you get a significant punishment such as a 5-minute timeout, so it's worthwhile to obey the limit stringently. It's really easy to implement this in terms of `DispatchQueue`s, but again, you need some way to interpose your own layer.\r\n\r\nThe last case is plain old Core Data. If I understand the architecture correctly, `perform` and `performAndWait` are just thin wrappers around dispatch queues. Nevertheless, they are the designated interface and you are supposed to use them instead of trying to get your hands on the underlying `DispatchQueue`. It would be really nice to be able to write, e.g., `done(on: myCoreDataMOC) {...}` and just have it use `perform*` behind the scenes.\r\n\r\nThoughts?"}}
{"actor":{"display_login":"GarthSnyder"}}