Kyu is persistent queue system written in Swift and inspired by Sidekiq.
I built the original version as a fire and forget way of handling the video and image uploads for Upshot.
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
# platform :osx, '10.11'
use_frameworks!
# Just the core, no UI
pod 'Kyu/Core', :git => 'TODO'
# Core lib + a basic UI for browsing workers and jobs
pod 'Kyu/iOS', :git => 'TODO'
Kyu is being used in production however I’ve set the current version to 0.9 as I’m not 100% happy with the API and will expect it to change.
First we need to create a Job.
class NewLineJob: KyuJobProtocol
{
static let filePathArgumentKey = "filePath"
func perform(arguments: [String : AnyObject]) -> KyuJobResult
{
guard let filePath = arguments[NewLineJob.filePathArgumentKey] as? String,
let fileHandle = NSFileHandle(forWritingAtPath: filePath) else
{
return KyuJobResult.fail
}
let stringToWrite = "Hello\n"
let stringToWriteData = stringToWrite.dataUsingEncoding(NSUTF8StringEncoding)!
fileHandle.seekToEndOfFile()
fileHandle.writeData(stringToWriteData)
fileHandle.closeFile()
return KyuJobResult.success
}
}
This Job will write a new line of text to a file.
Next, let’s initialize our Kyu.
do
{
self.kyu = try Kyu.configure({ (config) in
config.numberOfWorkers = 4
config.directoryURL = kyuDirectoryURL
config.job = NewLineJob()
config.maximumNumberOfRetries = 5
}
}
catch let error
{
// …
}
Wonderful, now let’s add a few jobs and try it out.
self.kyu.queueJob([NewLineJob.filePathArgumentKey:filePath])
self.kyu.queueJob([NewLineJob.filePathArgumentKey:filePath])
self.kyu.queueJob([NewLineJob.filePathArgumentKey:filePath])
BOOM! We’ve now queued 3 jobs 🎉
When initializing a Kyu object you can set the maximum number of retries.
Retries have an exponential backoff. This is crurently calculated with:
let retryTimeInterval = 30seconds * pow(numberOfRetries, 3)
do
{
self.kyu = try Kyu.configure({ (config) in
config.numberOfWorkers = 4
config.directoryURL = kyuDirectoryURL
config.job = NewLineJob()
config.maximumNumberOfRetries = 5
}
}
catch let error
{
// …
}
This means that after the 5th retry, the job will just be deleted.
By implementing the KyuDataSource
protocol you can have more control on whether the retry count is actually incremented.
When queing a job, you are returned an identifier. You can use this identifier to cancel a job.
let identifier = self.kyu.queueJob([NewLineJob.filePathArgumentKey:filePath])
do
{
try self.kyu.cancelJob(identifier)
}
catch KyuJobManagementError.JobNotFound
{
}
Kyu has a simple admin interface builtin. The aim is to make to provide some transparency to help with debugging.
To use the iOS admin UI, make sure you have the Kyu/iOS
pod
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
use_frameworks!
pod 'Kyu/iOS', :git => 'TODO'
All you need to do is present the KyuWorkersListViewController
view controller.
self.kyu = try! Kyu.configure { (config) -> () in
config.numberOfWorkers = 1
config.directoryURL = directoryURL
config.job = TestJob()
}
let kyuWorkersViewController = KyuWorkersListViewController(kyu: self.kyu)
let navigationController = UINavigationController(rootViewController: kyuWorkersViewController)
self.presentViewController(navigationController, animated: true, completion: nil)