@@ -3,10 +3,10 @@ import Foundation
3
3
4
4
/// A service that synchronizes attachments between local and remote storage.
5
5
///
6
- /// This actor watches for changes to active attachments and performs queued
6
+ /// This watches for changes to active attachments and performs queued
7
7
/// download, upload, and delete operations. Syncs can be triggered manually,
8
8
/// periodically, or based on database changes.
9
- actor SyncingService {
9
+ public class SyncingService {
10
10
private let remoteStorage : RemoteStorageAdapter
11
11
private let localStorage : LocalStorageAdapter
12
12
private let attachmentsService : AttachmentService
@@ -17,6 +17,7 @@ actor SyncingService {
17
17
private let syncTriggerSubject = PassthroughSubject < Void , Never > ( )
18
18
private var periodicSyncTimer : Timer ?
19
19
private var syncTask : Task < Void , Never > ?
20
+ private let lock : LockActor
20
21
let logger : any LoggerProtocol
21
22
22
23
let logTag = " AttachmentSync "
@@ -47,32 +48,32 @@ actor SyncingService {
47
48
self . errorHandler = errorHandler
48
49
self . syncThrottle = syncThrottle
49
50
self . logger = logger
50
- closed = false
51
+ self . closed = false
52
+ self . lock = LockActor ( )
51
53
}
52
54
53
55
/// Starts periodic syncing of attachments.
54
56
///
55
57
/// - Parameter period: The time interval in seconds between each sync.
56
58
public func startSync( period: TimeInterval ) async throws {
57
- try guardClosed ( )
58
-
59
- // Close any active sync operations
60
- try await stopSync ( )
59
+ try await lock. withLock {
60
+ try guardClosed ( )
61
61
62
- setupSyncFlow ( )
62
+ // Close any active sync operations
63
+ try await _stopSync ( )
63
64
64
- periodicSyncTimer = Timer . scheduledTimer (
65
- withTimeInterval: period,
66
- repeats: true
67
- ) { [ weak self] _ in
68
- guard let self = self else { return }
69
- Task { try ? await self . triggerSync ( ) }
65
+ setupSyncFlow ( period: period)
70
66
}
71
67
}
72
68
73
69
public func stopSync( ) async throws {
74
- try guardClosed ( )
70
+ try await lock. withLock {
71
+ try guardClosed ( )
72
+ try await _stopSync ( )
73
+ }
74
+ }
75
75
76
+ private func _stopSync( ) async throws {
76
77
if let timer = periodicSyncTimer {
77
78
timer. invalidate ( )
78
79
periodicSyncTimer = nil
@@ -92,10 +93,12 @@ actor SyncingService {
92
93
93
94
/// Cleans up internal resources and cancels any ongoing syncing.
94
95
func close( ) async throws {
95
- try guardClosed ( )
96
+ try await lock. withLock {
97
+ try guardClosed ( )
96
98
97
- try await stopSync ( )
98
- closed = true
99
+ try await _stopSync ( )
100
+ closed = true
101
+ }
99
102
}
100
103
101
104
/// Triggers a sync operation. Can be called manually.
@@ -141,13 +144,13 @@ actor SyncingService {
141
144
}
142
145
143
146
/// Sets up the main attachment syncing pipeline and starts watching for changes.
144
- private func setupSyncFlow( ) {
147
+ private func setupSyncFlow( period : TimeInterval ) {
145
148
syncTask = Task {
146
149
do {
147
150
try await withThrowingTaskGroup ( of: Void . self) { group in
148
151
// Handle sync trigger events
149
152
group. addTask {
150
- let syncTrigger = await self . createSyncTrigger ( )
153
+ let syncTrigger = self . createSyncTrigger ( )
151
154
152
155
for await _ in syncTrigger {
153
156
try Task . checkCancellation ( )
@@ -162,12 +165,20 @@ actor SyncingService {
162
165
163
166
// Watch attachment records. Trigger a sync on change
164
167
group. addTask {
165
- for try await _ in try await self . attachmentsService. watchActiveAttachments ( ) {
168
+ for try await _ in try self . attachmentsService. watchActiveAttachments ( ) {
166
169
self . syncTriggerSubject. send ( ( ) )
167
170
try Task . checkCancellation ( )
168
171
}
169
172
}
170
173
174
+ group. addTask {
175
+ let delay = UInt64 ( period * 1_000_000_000 )
176
+ while !Task. isCancelled {
177
+ try await Task . sleep ( nanoseconds: delay)
178
+ try await self . triggerSync ( )
179
+ }
180
+ }
181
+
171
182
// Wait for any task to complete
172
183
try await group. next ( )
173
184
}
0 commit comments