- Notifications
You must be signed in to change notification settings - Fork48
Queuer is a queue manager, built on top of OperationQueue and Dispatch (aka GCD).
License
FabrizioBrancati/Queuer
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Queuer is a queue manager, built on top ofOperationQueue andDispatch (aka GCD). It allows you to create any asynchronous and synchronous task easily, all managed by a queue, with just a few lines.
Here is the list of all the features:
- Works on all Swift compatible platforms (even Linux)
- Easy to use
- Well documented (100% documented)
- Well tested (100% of code coverage)
- Create an operation block
- Create a single operation
- Create chained operations
- Manage a centralized queue
- Create unlimited queue
- Declare how many concurrent operation a queue can handle
- Create semaphores
- Create and handle schedules
- Automatically or manually retry an operation
- Throttling between each automatic operation retry
| Swift | Queuer | iOS | macOS | macCatalyst | tvOS | watchOS | visionOS | Linux |
|---|---|---|---|---|---|---|---|---|
| 3.1...3.2 | 1.0.0...1.1.0 | 8.0+ | 10.10+ | 9.0+ | 2.0+ | ✅ | ||
| 4.0 | 1.3.0 | 8.0+ | 10.10+ | 9.0+ | 2.0+ | ✅ | ||
| 4.1 | 1.3.1...1.3.2 | 8.0+ | 10.10+ | 9.0+ | 2.0+ | ✅ | ||
| 4.2 | 2.0.0...2.0.1 | 8.0+ | 10.10+ | 9.0+ | 3.0+ | ✅ | ||
| 5.0...5.10 | 2.1.0...2.2.0 | 8.0+ | 10.10+ | 9.0+ | 3.0+ | ✅ | ||
| 5.9...5.10 | 3.0.0 | 12.0+ | 10.13+ | 13.0+ | 12.0+ | 4.0+ | 1.0+ | ✅ |
SeeRequirements section to check Swift, Queuer, and OS versions.
In yourPackage.swift Swift Package Manager manifest, add the following dependency to yourdependencies argument:
.package(url:"https://github.com/FabrizioBrancati/Queuer.git", from:"3.0.0"),
Add the dependency to any targets you've declared in your manifest:
.target( name:"MyTarget", dependencies:[.product(name:"Queuer",package:"Queuer"),]),
- Shared Queuer
- Custom Queue
- Create an Operation Block
- Chained Operations
- Group Oprations
- Queue States
- Synchronous Queue
- Asynchronous Operation
- Automatically Retry an Operation
- Manually Retry an Operation
- Manually Finish an Operation
- Async Task in an Operation
- Scheduler
- Semaphore
Queuer offers a shared instance that you can use to add operations to a centralized queue:
Queuer.shared.addOperation(operation)
You can also create a custom queue:
letqueue=Queuer(name:"MyCustomQueue")
You can even create a queue by defining themaxConcurrentOperationCount and thequalityOfService properties:
letqueue=Queuer(name:"MyCustomQueue", maxConcurrentOperationCount:Int.max, qualityOfService:.default)
You have three methods to add anOperation block.
Directly on the
queue(orQueuer.shared):queue.addOperation{ /// Your task here}
Creating a
ConcurrentOperationwith a block:letconcurrentOperation=ConcurrentOperation{ _in /// Your task here}queue.addOperation(concurrentOperation)
Note
We will see howConcurrentOperation works later.
Chained Operations areOperations that add a dependency each other.
They follow the given array order, for example:[A, B, C] = A -> B -> C -> completionBlock.
letconcurrentOperationA=ConcurrentOperation{ _in /// Your task A here}letconcurrentOperationB=ConcurrentOperation{ _in /// Your task B here}queue.addChainedOperations([concurrentOperationA, concurrentOperationB]){ /// Your completion task here}
You can also add acompletionHandler after the queue creation with:
queue.addCompletionHandler{ /// Your completion task here}
Group Operations areOperations that handles a group ofOperations with a completion handler.
Allows the execution of a block ofOperations with a completion handler that will be called once all the operations are finished, for example:[A -> [[B & C & D] -> completionHandler] -> E] -> completionHandler.It should usually be used with aChained Opetation.
letgroupOperationA=GroupOperation([ConcurrentOperation{ _in /// Your task A here},ConcurrentOperation{ _in /// Your task B here}])letconcurrentOperationC=ConcurrentOperation{ _in /// Your task C here}queue.addChainedOperations([groupOperationA, concurrentOperationC]){ /// Your completion task here}
In this case the output will be the following one:[[A & B -> completionHandler] -> C] -> completionHandler.
There are a few method to handle the queue states.
Cancel all
Operations in a queue:queue.cancelAll()
Pause a queue:
queue.pause()
Warning
By callingpause() you will not be sure that everyOperation will be paused. If theOperation is already started it will not be on pause until it's a customOperation that overridespause() function.
Resume a queue:
queue.resume()
Warning
To have a completepause andresume states you must create a customOperation that overridespause() andresume() function.
Wait until all
Operations are finished:queue.waitUntilAllOperationsAreFinished()
Important
This function means that the queue will blocks the current thread until allOperations are finished.
Setting themaxConcurrentOperationCount property of a queue to1 will make you sure that only one task at a time will be executed.
ConcurrentOperation is a class created to be subclassed.It allows synchronous and asynchronous tasks, has a pause and resume states, can be easily added to a queue and can be created with a block.
You can create your customConcurrentOperation by subclassing it.
You must overrideexecute() function and call thefinish(success:) function inside it, when the task has finished its job to notify the queue.
For convenience it has aninit function with a completion block:
letconcurrentOperation=ConcurrentOperation{ _in /// Your task here}concurrentOperation.addToQueue(queue)
AnOperation is passed to every closure, with it you can set and handle the retry feature.
By default the retry feature is disabled, to enable it simply set thesuccess property tofalse. Withsuccess tofalse theOperation will retry until reachesmaximumRetries property value. To let theOperation know when everything is ok, you must setsuccess totrue.
WithcurrentAttempt you can know at which attempt theOperation is.
letconcurrentOperation=ConcurrentOperation{ operationin /// Your task hereif /* Successful */{ operation.success=true}else{ operation.success=false}}
You can manually retry anOperation when you think that the execution will be successful.
AnOperation is passed to every closure, with it you can set and handle the retry feature.
By default the manual retry feature is disabled, to enable it simply set themanualRetry property totrue, you must do this outside of the execution closure. You must also setsuccess totrue orfalse to let theOperation know when is everything ok, like the automatic retry feature.
To let theOperation retry your execution closure, you have to call theretry() function. Be sure to call it at leastmaximumRetries times, it is not a problem if you callretry() more times than is needed, your execution closure will not be executed more times than themaximumRetries value.
letconcurrentOperation=ConcurrentOperation{ operationin /// Your task hereif /* Successful */{ operation.success=true}else{ operation.success=false}}concurrentOperation.manualRetry=true/// Later on your codeconcurrentOperation.retry()
Caution
If theretry() function is not called, you may block the entire queue.
By default theOperation will finish its job when the execution closure is completed.
This means, if you have an asynchronous task insiede the closure, theOperation will finish before the task is completed.
If you want to finish it manually, you can set themanualFinish property totrue and call thefinish(success:) function when the task is completed.
Call thefinish(success:) function withsuccess parameter totrue orfalse to let theOperation know if the task was successful or not. If you don't explicitly set thesuccess parameter, it will be set totrue.
letconcurrentOperation=ConcurrentOperation{ operationin /// Your asynchonous task here}concurrentOperation.manualFinish=true/// Later on your code in your asynchronous taskconcurrentOperation.finish(success:true)
Caution
If you don't call thefinish(success:) function, your queue will be blocked and it will never ends.
If you want to use async/await tasks, you need to setmanualFinish totrue in order to be fully in control of theOperation lifecycle.
Note
Read more about manually finish anOperationhere.
letconcurrentOperation=ConcurrentOperation{ operationinTask{ /// Your asynchonous task here operation.finish(success:true) // or false} /// Your asynchonous task here}concurrentOperation.manualFinish=true
Caution
If you don't setmanualFinish totrue, yourOperation will finish before the async task is completed.
AScheduler is a struct that uses the GDC'sDispatchSourceTimer to create a timer that can execute functions with a specified interval and quality of service.
letschedule=Scheduler(deadline:.now(), repeating:.seconds(1)){ /// Your task here}
You can even create aScheduler without the handler and set it later:
varschedule=Scheduler(deadline:.now(), repeating:.seconds(1))schedule.setHandler{ /// Your task here}
Withtimer property you can access to allDispatchSourceTimer properties and functions, likecancel():
schedule.timer.cancel()
ASemaphore is a struct that uses the GCD'sDispatchSemaphore to create a semaphore on the function and wait until it finish its job.
Tip
Is recommend to use adefer { semaphore.continue() } right after theSemaphore creation andwait() call.
letsemaphore=Semaphore()semaphore.wait()defer{ semaphore.continue()}/// Your task here
You can even set a custom timeout, default is.distantFuture:
semaphore.wait(DispatchTime(uptimeNanoseconds:1_000_000_000))
It's more useful if used inside an asynchronous task:
letconcurrentOperation=ConcurrentOperation{ /// Your task here semaphore.continue()}concurrentOperation.addToQueue(queue)semaphore.wait()
To see what has changed in recent versions of Queuer, see theCHANGELOG.md file.
- If you need help, open an issue.
- If you found a bug, open an issue.
- If you have a feature request, open an issue.
- If you want to contribute, seeContributing section.
SeeCONTRIBUTING.md file.
Queuer is available under the MIT license. See theLICENSE file for more info.
About
Queuer is a queue manager, built on top of OperationQueue and Dispatch (aka GCD).
Topics
Resources
License
Contributing
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Uh oh!
There was an error while loading.Please reload this page.