8
8
import Foundation
9
9
10
10
/// A helper for executing asynchronous work serially.
11
- public actor TaskQueue < Success> {
12
- private var previousTask : Task < Success , Error > ?
11
+ public class TaskQueue < Success> {
12
+ typealias Block = @Sendable ( ) async -> Void
13
+ private var streamContinuation : AsyncStream < Block > . Continuation !
13
14
14
- public init ( ) { }
15
+ public init ( ) {
16
+ let stream = AsyncStream < Block > . init { continuation in
17
+ streamContinuation = continuation
18
+ }
19
+
20
+ Task {
21
+ for await block in stream {
22
+ _ = await block ( )
23
+ }
24
+ }
25
+ }
26
+
27
+ deinit {
28
+ streamContinuation. finish ( )
29
+ }
15
30
16
31
/// Serializes asynchronous requests made from an async context
17
32
///
@@ -25,17 +40,31 @@ public actor TaskQueue<Success> {
25
40
/// TaskQueue serializes this work so that `doAsync1` is performed before `doAsync2`,
26
41
/// which is performed before `doAsync3`.
27
42
public func sync( block: @Sendable @escaping ( ) async throws -> Success ) async throws -> Success {
28
- let currentTask : Task < Success , Error > = Task { [ previousTask] in
29
- _ = await previousTask? . result
30
- return try await block ( )
43
+ try await withCheckedThrowingContinuation { continuation in
44
+ streamContinuation. yield {
45
+ do {
46
+ let value = try await block ( )
47
+ continuation. resume ( returning: value)
48
+ } catch {
49
+ continuation. resume ( throwing: error)
50
+ }
51
+ }
31
52
}
32
- previousTask = currentTask
33
- return try await currentTask. value
34
53
}
35
54
36
- public nonisolated func async ( block: @Sendable @escaping ( ) async throws -> Success ) rethrows {
37
- Task {
38
- try await sync ( block: block)
55
+ public func async ( block: @Sendable @escaping ( ) async throws -> Success ) {
56
+ streamContinuation. yield {
57
+ do {
58
+ _ = try await block ( )
59
+ } catch {
60
+ Self . log. warn ( " Failed to handle async task in TaskQueue< \( Success . self) > with error: \( error) " )
61
+ }
39
62
}
40
63
}
41
64
}
65
+
66
+ extension TaskQueue {
67
+ public static var log : Logger {
68
+ Amplify . Logging. logger ( forNamespace: String ( describing: self ) )
69
+ }
70
+ }
0 commit comments