Created
May 27, 2020 18:55
-
-
Save kylehughes/83b185f8cc28f2ccd4ba5548440201d7 to your computer and use it in GitHub Desktop.
Batch Collector Implementation
This file contains 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
// | |
// Collector.swift | |
// InformationSuperhighway | |
// | |
// Created by Kyle Hughes on 2/26/20. | |
// Copyright © 2020 Kyle Hughes. All rights reserved. | |
// | |
final class Collector<Item> { | |
typealias FlushHandler = ([Item]) -> Void | |
private let collection: Atomic<[Item]> | |
private let flushHandler: FlushHandler | |
private let flushInterval: TimeInterval | |
private let flushHandlerQueue: DispatchQueue | |
private let flushQueue: DispatchQueue | |
private var flushTimer: Timer? | |
// MARK: Internal Initialization | |
init( | |
flushInterval: TimeInterval, | |
flushHandlerQueue: DispatchQueue = .global(qos: .default), | |
flushHandler: @escaping FlushHandler | |
) { | |
self.flushInterval = flushInterval | |
self.flushHandlerQueue = flushHandlerQueue | |
self.flushHandler = flushHandler | |
collection = Atomic([]) | |
flushQueue = DispatchQueue(label: "Collector.FlushQueue", qos: .userInitiated) | |
} | |
// MARK: Internal Instance Interface | |
func add(item: Item) { | |
collection.value.append(item) | |
} | |
func flush() { | |
flushQueue.async { | |
self.collection.modify { collection in | |
guard !collection.isEmpty else { | |
return | |
} | |
let capturedCollection = collection | |
collection.removeAll() | |
self.flushHandlerQueue.async { | |
self.flushHandler(capturedCollection) | |
} | |
} | |
} | |
} | |
func start() { | |
guard flushTimer == nil else { | |
return | |
} | |
flush() | |
flushTimer = .scheduledTimer( | |
timeInterval: flushInterval, | |
target: self, | |
selector: #selector(handleFlushTimerTrigger), | |
userInfo: nil, | |
repeats: true) | |
} | |
func stop() { | |
guard let flushTimer = flushTimer else { | |
return | |
} | |
flushTimer.invalidate() | |
self.flushTimer = nil | |
} | |
// MARK: Private Instance Interface | |
@objc private func handleFlushTimerTrigger() { | |
flush() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment