Skip to content

Instantly share code, notes, and snippets.

@nicholascross
Last active December 8, 2016 21:15
Show Gist options
  • Save nicholascross/4c2c9ffaeb3f4e4d2bbd3e6f16e5ea08 to your computer and use it in GitHub Desktop.
Save nicholascross/4c2c9ffaeb3f4e4d2bbd3e6f16e5ea08 to your computer and use it in GitHub Desktop.
//
// CoalesceOperation.swift
// RequestCoalesce
//
// Created by Nicholas Cross on 4/12/2016.
// Copyright © 2016 Nicholas Cross. All rights reserved.
//
import Foundation
public class CoalesceGroup {
private var coalesceGroup: DispatchGroup
private var coalesceQueue: DispatchQueue
init() {
self.coalesceGroup = DispatchGroup()
self.coalesceQueue = DispatchQueue(label: "OperationQueue")
}
public func performAsync(coalesce coalesceable: Coalesceable, withForceRefresh forceRefresh: Bool = false, completed: @escaping ()->()) {
DispatchQueue.global(qos: .background).async {
self.perform(coalesce: coalesceable, withForceRefresh: forceRefresh, completed: completed)
}
}
public func perform(coalesce coalesceable: Coalesceable, withForceRefresh forceRefresh: Bool = false, completed: @escaping ()->()) {
guard !forceRefresh else {
self._perform(coalesce: coalesceable, withForceRefresh: true, completed: completed)
return
}
self.coalesceQueue.async {
self._perform(coalesce: coalesceable, completed: completed)
}
}
private func _perform(coalesce coalesceable: Coalesceable, withForceRefresh forceRefresh: Bool = false, completed: @escaping ()->()) {
if (!forceRefresh) {
self.coalesceGroup.wait()
}
self.coalesceGroup.enter()
self.coalesceGroup.notify(queue: DispatchQueue.global(qos: .background), execute: completed)
if !coalesceable.isCached || forceRefresh {
coalesceable.performOperation() {
DispatchQueue.global(qos: .background).async {
self.coalesceGroup.leave()
}
}
}
else {
self.coalesceGroup.leave()
}
}
}
public protocol Coalesceable {
var isCached: Bool {get}
func performOperation(complete: @escaping ()->())
}

Request coalescing

Queue up async requests for the same resource and retrieving first from a remote source and any queued requests from a cache

Load from cache if possible

  • Dispatch async background queue
    • Dispatch group wait
      • Dipsatch group enter
      • Fetch from cache
      • Else load from url
      • Dispatch group leave

Force reload

  • Dipsatch group enter
  • Load from url
  • Dispatch group leave
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment