Skip to content

Commit 16a15e3

Browse files
author
Lucas Nelaupe
authored
Allow user to specify enqueue DispatchQueue to fix multi-thread enqueue crash (#403)
1 parent ab9f88f commit 16a15e3

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

Sources/SwiftQueue/JobBuilder.swift

-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@ public final class JobBuilder {
184184
assert(JSONSerialization.isValidJSONObject(info.params))
185185
info.constraints.append(PersisterConstraint(serializer: manager.params.serializer, persister: manager.params.persister))
186186
}
187-
188187
manager.enqueue(info: info)
189188
}
190189

Sources/SwiftQueue/SwiftQueueManager.swift

+23-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ public final class SwiftQueueManager {
6363
/// Schedule a job to the queue
6464
/// TODO Need to remove this method
6565
public func enqueue(info: JobInfo) {
66+
if let thread = params.enqueueThread {
67+
thread.sync(flags: .barrier) {
68+
enqueueInMainThread(info: info)
69+
}
70+
} else {
71+
enqueueInMainThread(info: info)
72+
}
73+
}
74+
75+
private func enqueueInMainThread(info: JobInfo) {
6676
let queue = getQueue(queueName: info.queueName)
6777
let job = queue.createHandler(type: info.type, params: info.params)
6878
let constraints = info.constraints
@@ -167,14 +177,17 @@ internal struct SqManagerParams {
167177

168178
var initInBackground: Bool
169179

180+
var enqueueThread: DispatchQueue?
181+
170182
init(jobCreator: JobCreator,
171183
queueCreator: QueueCreator,
172184
persister: JobPersister = UserDefaultsPersister(),
173185
serializer: JobInfoSerializer = DecodableSerializer(maker: DefaultConstraintMaker()),
174186
logger: SwiftQueueLogger = NoLogger.shared,
175187
listener: JobListener? = nil,
176188
initInBackground: Bool = false,
177-
dispatchQueue: DispatchQueue = DispatchQueue.global(qos: DispatchQoS.QoSClass.utility)
189+
dispatchQueue: DispatchQueue = DispatchQueue.global(qos: DispatchQoS.QoSClass.utility),
190+
enqueueThread: DispatchQueue? = nil
178191
) {
179192
self.jobCreator = jobCreator
180193
self.queueCreator = queueCreator
@@ -184,6 +197,7 @@ internal struct SqManagerParams {
184197
self.listener = listener
185198
self.initInBackground = initInBackground
186199
self.dispatchQueue = dispatchQueue
200+
self.enqueueThread = enqueueThread
187201
}
188202

189203
}
@@ -242,6 +256,14 @@ public final class SwiftQueueManagerBuilder {
242256
return self
243257
}
244258

259+
/// Use a single DispatchQueue to enqueue jobs
260+
/// This can solve crashes when calling 'enqueue' in a multi-thread environment
261+
public func set(enqueueDispatcher: DispatchQueue) -> Self {
262+
params.enqueueThread = enqueueDispatcher
263+
return self
264+
}
265+
266+
245267
/// Get an instance of `SwiftQueueManager`
246268
public func build() -> SwiftQueueManager {
247269
return SwiftQueueManager(params: params, isSuspended: isSuspended)

Tests/SwiftQueueTests/SwiftQueueManagerTests.swift

+25
Original file line numberDiff line numberDiff line change
@@ -305,4 +305,29 @@ class SwiftQueueManagerTests: XCTestCase {
305305
job.assertError(queueError: .canceled)
306306
}
307307

308+
func testConcurrentScheduling() {
309+
let (type, job) = (UUID().uuidString, TestJob())
310+
let creator = TestCreator([type: job])
311+
let persister = PersisterTracker(key: UUID().uuidString)
312+
let manager = SwiftQueueManagerBuilder(creator: creator)
313+
.set(isSuspended: true)
314+
.set(enqueueDispatcher: .main)
315+
.set(persister: persister).build()
316+
317+
318+
let concurrentQueue = DispatchQueue(label: "com.test.concurrent", attributes: .concurrent)
319+
for _ in 0..<10 {
320+
concurrentQueue.async {
321+
JobBuilder(type: type).parallel(queueName: UUID().uuidString).schedule(manager: manager)
322+
}
323+
}
324+
325+
for _ in 0..<10 {
326+
DispatchQueue(label: "com.test.concurrent", attributes: .concurrent).async {
327+
JobBuilder(type: type).parallel(queueName: UUID().uuidString).schedule(manager: manager)
328+
}
329+
}
330+
331+
}
332+
308333
}

0 commit comments

Comments
 (0)