Queuer
Queuer is a queue manager, built on top of OperationQueue and Dispatch (aka GCD).
Install / Use
/learn @FabrizioBrancati/QueuerREADME
Queuer
Features
Queuer is a queue manager, built on top of OperationQueue and Dispatch (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:
- [x] Works on all Swift compatible platforms (even Linux)
- [x] Easy to use
- [x] Well documented (100% documented)
- [x] Well tested (100% of code coverage)
- [x] Create an operation block
- [x] Create a single operation
- [x] Create chained operations
- [x] Manage a centralized queue
- [x] Create unlimited queue
- [x] Declare how many concurrent operation a queue can handle
- [x] Create semaphores
- [x] Create and handle schedules
- [x] Automatically or manually retry an operation
- [ ] Throttling between each automatic operation retry
Requirements
| 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+ | ✅ |
Installing
See Requirements section to check Swift, Queuer, and OS versions.
In your Package.swift Swift Package Manager manifest, add the following dependency to your dependencies 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"),
]
),
Usage
- 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
Shared Queuer
Queuer offers a shared instance that you can use to add operations to a centralized queue:
Queuer.shared.addOperation(operation)
Custom Queue
You can also create a custom queue:
let queue = Queuer(name: "MyCustomQueue")
You can even create a queue by defining the maxConcurrentOperationCount and the qualityOfService properties:
let queue = Queuer(name: "MyCustomQueue", maxConcurrentOperationCount: Int.max, qualityOfService: .default)
Create an Operation Block
You have three methods to add an Operation block.
-
Directly on the
queue(orQueuer.shared):queue.addOperation { /// Your task here } -
Creating a
ConcurrentOperationwith a block:let concurrentOperation = ConcurrentOperation { _ in /// Your task here } queue.addOperation(concurrentOperation)
[!NOTE] We will see how
ConcurrentOperationworks later.
Chained Operations
Chained Operations are Operations that add a dependency each other.
They follow the given array order, for example: [A, B, C] = A -> B -> C -> completionBlock.
let concurrentOperationA = ConcurrentOperation { _ in
/// Your task A here
}
let concurrentOperationB = ConcurrentOperation { _ in
/// Your task B here
}
queue.addChainedOperations([concurrentOperationA, concurrentOperationB]) {
/// Your completion task here
}
You can also add a completionHandler after the queue creation with:
queue.addCompletionHandler {
/// Your completion task here
}
Group Operations
Group Operations are Operations that handles a group of Operations with a completion handler.
Allows the execution of a block of Operations 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 a Chained Opetation.
let groupOperationA = GroupOperation(
[
ConcurrentOperation { _ in
/// Your task A here
},
ConcurrentOperation { _ in
/// Your task B here
}
]
)
let concurrentOperationC = 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.
Queue States
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 calling
pause()you will not be sure that everyOperationwill be paused. If theOperationis already started it will not be on pause until it's a customOperationthat overridespause()function.
-
Resume a queue:
queue.resume()
[!WARNING] To have a complete
pauseandresumestates you must create a customOperationthat overridespause()andresume()function.
-
Wait until all
Operations are finished:queue.waitUntilAllOperationsAreFinished()
[!IMPORTANT] This function means that the queue will blocks the current thread until all
Operations are finished.
Synchronous Queue
Setting the maxConcurrentOperationCount property of a queue to 1 will make you sure that only one task at a time will be executed.
Asynchronous Operation
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 custom ConcurrentOperation by subclassing it.
You must override execute() function and call the finish(success:) function inside it, when the task has finished its job to notify the queue.
For convenience it has an init function with a completion block:
let concurrentOperation = ConcurrentOperation { _ in
/// Your task here
}
concurrentOperation.addToQueue(queue)
Automatically Retry an Operation
An Operation 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 the success property to false. With success to false the Operation will retry until reaches maximumRetries property value. To let the Operation know when everything is ok, you must set success to true.
With currentAttempt you can know at which attempt the Operation is.
let concurrentOperation = ConcurrentOperation { operation in
/// Your task here
if /* Successful */ {
operation.success = true
} else {
operation.success = false
}
}
Manually Retry an Operation
You can manually retry an Operation when you think that the execution will be successful.
An Operation 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 the manualRetry property to true, you must do this outside of the execution closure. You must also set success to true or false to let the Operation know when is everything ok, like the automatic retry feature.
To let the Operation retry your execution closure, you have to call the retry() function. Be sure to call it at least maximumRetries times, it is not
