{"id":27859863,"url":"https://github.com/ponyboy47/taskkit","last_synced_at":"2025-05-04T17:11:45.562Z","repository":{"id":63920341,"uuid":"132639370","full_name":"Ponyboy47/TaskKit","owner":"Ponyboy47","description":"Swift replacement for Operation and OperationQueue","archived":false,"fork":false,"pushed_at":"2019-03-27T20:23:05.000Z","size":81,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-28T01:21:12.696Z","etag":null,"topics":["operation","operationqueue","queue","swift","swift4","task","tasks"],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Ponyboy47.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-05-08T16:58:37.000Z","updated_at":"2024-03-20T11:12:27.000Z","dependencies_parsed_at":"2023-01-14T14:00:30.385Z","dependency_job_id":null,"html_url":"https://github.com/Ponyboy47/TaskKit","commit_stats":null,"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ponyboy47%2FTaskKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ponyboy47%2FTaskKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ponyboy47%2FTaskKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ponyboy47%2FTaskKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ponyboy47","download_url":"https://codeload.github.com/Ponyboy47/TaskKit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252369013,"owners_count":21736878,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["operation","operationqueue","queue","swift","swift4","task","tasks"],"created_at":"2025-05-04T17:11:44.959Z","updated_at":"2025-05-04T17:11:45.549Z","avatar_url":"https://github.com/Ponyboy47.png","language":"Swift","readme":"# TaskKit AKA \"Task It\"\n\nThis framework is my attempt at replacing the Standard Library's [OperationQueue](https://developer.apple.com/documentation/foundation/operationqueue) \u0026 [Operation](https://developer.apple.com/documentation/foundation/operation) classes.\u003cbr /\u003e\nI've ran into a number of issues when using an `OperationQueue` in the past, like when it can't handle more than 100 `Operation`s and freezes indefinitely (at least on Linux), as well as a number of other intricacies that I found frustrating or just down right annoying.\u003cbr /\u003e\nSo I built this! I tried to make it equally thread-safe with similar APIs, but more protocol oriented than the Standard Library counterpart.\n\n## Installation (SPM)\nAdd this to your Package.swift\n```swift\n.package(url: \"https://github.com/Ponyboy47/TaskKit.git\", from: \"0.6.0\")\n```\nSupports Swift 4.x (Including 4.2)\n\n## The Task Protocols\nThe basis of TaskKit is (you guessed it) Tasks.\n\nThere are a number of Task protocols you can conform to:\n### Task\nThis is the base protocol that all the subsequent `*Task` protocols also conform to.\u003cbr /\u003e\nIn order to conform to any `Task` protocol, you must implement the following protocol requirements:\u003cbr /\u003e\n\n```swift\nvar state: TaskState { get set }\n```\nThis contains information about the current execution progress of the task and may also contain an array of log messages (you would have to add log messages in your object that conforms to `Task`).\u003cbr /\u003e\nIt is recomended that you begin by assigning this to `.ready`, otherwise, be sure that the `status.state` value is `.ready` before your task is added to the TaskQueue or else it will fail to execute.\u003cbr /\u003e\u003cbr /\u003e\n\n```swift\nvar priority: TaskPriority { get set }\n```\nA task's priority determines when it will be executed relative to other tasks in the queue.\u003cbr /\u003e\nHigh priority tasks are executed before lower priority tasks.\u003cbr /\u003e\u003cbr /\u003e\n\n```swift\nvar qos: DispatchQoS { get }\n```\nThis will be the [Quality of Service](https://developer.apple.com/documentation/dispatch/dispatchqos) that is used to execute your task.\u003cbr /\u003e\u003cbr /\u003e\n\n```swift\nfunc finish()\n```\nA function that will be executed when your task completes, regardless of whether or not it completed successfully.\u003cbr /\u003e\nCheck your task's state so that you can have different logic depending on whether it failed or succeeded.\u003cbr /\u003e\u003cbr /\u003e\n\n```swift\nfunc execute() -\u003e Bool\n```\nThis is the function that will be called to run your task.\u003cbr /\u003e\nThis function should return whether or not your task completed its execution successfully.\u003cbr /\u003e\u003cbr /\u003e\n\n### ConfigurableTask\nA `Task` that depends on some external source to configure itself properly (ie: a script to validate a configuration file before execution).\n\n```swift\nfunc configure() -\u003e Bool\n```\nThe function that must run successfully before your task can be executed.\u003cbr /\u003e\nThis function should return whether or not it configured your task properly.\u003cbr /\u003e\u003cbr /\u003e\n\n### PausableTask\nA `Task` that can be stopped mid-execution and resumed at a later time.\n\n```swift\nfunc pause() -\u003e Bool\n```\nThe function used to stop execution.\u003cbr /\u003e\nReturn whether or not your task's execution was successfully paused.\u003cbr /\u003e\u003cbr /\u003e\n\n```swift\nfunc resume() -\u003e Bool\n```\nThe function used to resume previously stopped execution.\u003cbr /\u003e\nReturn whether or not your task's execution was successfully resumed.\u003cbr /\u003e\u003cbr /\u003e\n\n### CancellableTask\nA `Task` that can be cancelled mid-execution, but cannot (or will not) be resumed at a later time.\n\n```swift\nfunc cancel()\n```\nThe function used to cancel execution.\u003cbr /\u003e\n\n### DependentTask\nA `Task` that cannot be executed until one or more other `Task`s have successfully been executed.\n\n```swift\nvar dependencies: [Task] { get set }\n```\nAn array of the tasks that must execute successfully before this task can begin its execution.\u003cbr /\u003e\u003cbr /\u003e\n\n```swift\nfunc finish(dependency: Task)\n```\nA function that is ran whenever a dependency finishes executing.\u003cbr /\u003e\nThe dependency that just completed is passed as the `dependency` parameter.\u003cbr /\u003e\u003cbr /\u003e\n\n## Basic Usage\n\nAfter you have at least one type conforming to any of the `Task` protocols, you can create a `TaskQueue` and add tasks to it:\n```swift\n// Create a queue (maxSimultaneous defaults to 1)\nlet queue = TaskQueue(name: \"com.example.taskqueue\", maxSimultaneous: 2)\n\n// Add a task to the queue\nqueue.add(task: myTask)\n\n// Start the queue's execution\nqueue.start()\n```\n\nIf you have a task with dependencies, then you don't need to add the dependencies to the task.\nThey'll automatically be ran before the task that they depend on is run.\n```swift\n// Add a dependency to your task\nmyTask.add(dependency: dependencyTask)\n\n// Add the base task to the queue\nqueue.add(task: myTask)\n\n// Start the queue\nqueue.start()\n```\n\n## Linked Queues\n\nSometimes, you might want to separate tasks into different queues even when the tasks in the separate queues may depend on each other.\nThis is where you may use a LinkedTaskQueue instead.\n```swift\n// Let's start with two queues:\n// 1. For moving media files\n// 2. For converting the media\nlet moveQueue = LinkedTaskQueue(name: \"com.example.linked.move\", maxSimultaneous: 5)\nlet conversionQueue = LinkedTaskQueue(name: \"com.example.linked.conversion\", linkedTo: moveQueue)\n\n// Add our move tasks\nmoveQueue.add(tasks: moveTasks)\n\n// One of the move tasks shouldn't happen until after it has been converted\nmoveTasks[0].add(dependency: conversionTask)\n\n// Add that conversion task to its queue\nconversionQueue.add(task: conversionTask)\n\n// Start both the queues\nmoveQueue.start()\nconversionQueue.start()\n```\nNOTE: Any dependency tasks must exist in one of the linked queues or there will be a fatal error\n\n## TODO\n\n- [ ] Investigate ARC best-practices and see if memory usage/performance/correctness can be improved\n  - https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html\n- [x] Investigate improved Hashable conformances\n  - https://developer.apple.com/documentation/swift/adopting_common_protocols\n\n## License\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fponyboy47%2Ftaskkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fponyboy47%2Ftaskkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fponyboy47%2Ftaskkit/lists"}