If uploadFailed(for id: String)
, uploadSuccess()
and updateOnStart(_ id: String)
are called from the same thread (Thread 1 Main Thread) I understand that we wouldn't need a synchronized Queue. What if the the functions are called from different threads for each uploads. Where do I ensure there is synchronization? Will it be both the uploads and state or just the state?
enum FlowState {
case started(uploads: [String])
case submitted
case failed
}
class Session {
var state: FlowState
let syncQueue: DispatchQueue = .init(label: "Image Upload Sync Queue",
qos: .userInitiated,
attributes: [],
autoreleaseFrequency: .workItem)
init(state: FlowState) {
self.state = state
}
mutating func updateOnStart(_ id: String) {
guard case .started(var uploads) = state else {
return
}
uploads.append(id)
state = .started(uploads)
}
mutating func uploadFailed(for id: String) {
guard case .started(var uploads) = state else {
return
}
uploads.removeAll { $0 == id }
if uploads.isEmpty {
state = .failed
} else {
state = .started(uploads)
}
}
mutating func uploadSuccess() {
state = .submitted
}
}
Do we synchronize both the uploads
array operation and state like below?
syncQueue.sync {
uploads.append(id)
state = .started(uploads)
}
syncQueue.sync {
uploads.removeAll { $0 == id }
if uploads.isEmpty {
state = .failed
} else {
state = .started(uploads)
}
}
OR
syncQueue.sync {
state = .started(uploads)
}
syncQueue.sync {
if uploads.isEmpty {
state = .failed
} else {
state = .started(uploads)
}
}
A network call's completion handler can update Session
's state
property. The user for example selects 10 images and uploads it. Upon completion it could be a failure or a success. For every image that we upload, we cache the resouce id
and we remove it if uploads fails. When all the image upload fails, we update the status .failed
. We just care about one image being uploaded. When a single image is uploaded, we update the status to .submitted