11import Foundation
22
3- /// Context which performs actions on the attachment records
4- public final class AttachmentContext : Sendable {
5- // None of these class's methods mutate shared state directly
6- private let db : any PowerSyncDatabaseProtocol
7- private let tableName : String
8- private let logger : any LoggerProtocol
9- private let logTag = " AttachmentService "
10- private let maxArchivedCount : Int64
11-
12- /// Table used for storing attachments in the attachment queue.
13- private var table : String {
14- return tableName
15- }
16-
17- /// Initializes a new `AttachmentContext`.
18- public init (
19- db: PowerSyncDatabaseProtocol ,
20- tableName: String ,
21- logger: any LoggerProtocol ,
22- maxArchivedCount: Int64
23- ) {
24- self . db = db
25- self . tableName = tableName
26- self . logger = logger
27- self . maxArchivedCount = maxArchivedCount
28- }
3+ public protocol AttachmentContext : Sendable {
4+ var db : any PowerSyncDatabaseProtocol { get }
5+ var tableName : String { get }
6+ var logger : any LoggerProtocol { get }
7+ var maxArchivedCount : Int64 { get }
298
309 /// Deletes the attachment from the attachment queue.
31- public func deleteAttachment( id: String ) async throws {
10+ func deleteAttachment( id: String ) async throws
11+
12+ /// Sets the state of the attachment to ignored (archived).
13+ func ignoreAttachment( id: String ) async throws
14+
15+ /// Gets the attachment from the attachment queue using an ID.
16+ func getAttachment( id: String ) async throws -> Attachment ?
17+
18+ /// Saves the attachment to the attachment queue.
19+ func saveAttachment( attachment: Attachment ) async throws -> Attachment
20+
21+ /// Saves multiple attachments to the attachment queue.
22+ func saveAttachments( attachments: [ Attachment ] ) async throws
23+
24+ /// Gets all the IDs of attachments in the attachment queue.
25+ func getAttachmentIds( ) async throws -> [ String ]
26+
27+ /// Gets all attachments in the attachment queue.
28+ func getAttachments( ) async throws -> [ Attachment ]
29+
30+ /// Gets all active attachments that require an operation to be performed.
31+ func getActiveAttachments( ) async throws -> [ Attachment ]
32+
33+ /// Deletes attachments that have been archived.
34+ ///
35+ /// - Parameter callback: A callback invoked with the list of archived attachments before deletion.
36+ /// - Returns: `true` if all items have been deleted, `false` if there may be more archived items remaining.
37+ func deleteArchivedAttachments(
38+ callback: @Sendable @escaping ( [ Attachment] ) async throws -> Void
39+ ) async throws -> Bool
40+
41+ /// Clears the attachment queue.
42+ ///
43+ /// - Note: Currently only used for testing purposes.
44+ func clearQueue( ) async throws
45+ }
46+
47+ public extension AttachmentContext {
48+ func deleteAttachment( id: String ) async throws {
3249 _ = try await db. execute (
33- sql: " DELETE FROM \( table ) WHERE id = ? " ,
50+ sql: " DELETE FROM \( tableName ) WHERE id = ? " ,
3451 parameters: [ id]
3552 )
3653 }
3754
38- /// Sets the state of the attachment to ignored (archived).
39- public func ignoreAttachment( id: String ) async throws {
55+ func ignoreAttachment( id: String ) async throws {
4056 _ = try await db. execute (
41- sql: " UPDATE \( table ) SET state = ? WHERE id = ? " ,
57+ sql: " UPDATE \( tableName ) SET state = ? WHERE id = ? " ,
4258 parameters: [ AttachmentState . archived. rawValue, id]
4359 )
4460 }
4561
46- /// Gets the attachment from the attachment queue using an ID.
47- public func getAttachment( id: String ) async throws -> Attachment ? {
62+ func getAttachment( id: String ) async throws -> Attachment ? {
4863 return try await db. getOptional (
49- sql: " SELECT * FROM \( table ) WHERE id = ? " ,
64+ sql: " SELECT * FROM \( tableName ) WHERE id = ? " ,
5065 parameters: [ id]
5166 ) { cursor in
5267 try Attachment . fromCursor ( cursor)
5368 }
5469 }
5570
56- /// Saves the attachment to the attachment queue.
57- public func saveAttachment( attachment: Attachment ) async throws -> Attachment {
71+ func saveAttachment( attachment: Attachment ) async throws -> Attachment {
5872 return try await db. writeTransaction { ctx in
5973 try self . upsertAttachment ( attachment, context: ctx)
6074 }
6175 }
6276
63- /// Saves multiple attachments to the attachment queue.
64- public func saveAttachments( attachments: [ Attachment ] ) async throws {
77+ func saveAttachments( attachments: [ Attachment ] ) async throws {
6578 if attachments. isEmpty {
6679 return
6780 }
@@ -73,24 +86,22 @@ public final class AttachmentContext: Sendable {
7386 }
7487 }
7588
76- /// Gets all the IDs of attachments in the attachment queue.
77- public func getAttachmentIds( ) async throws -> [ String ] {
89+ func getAttachmentIds( ) async throws -> [ String ] {
7890 return try await db. getAll (
79- sql: " SELECT id FROM \( table ) WHERE id IS NOT NULL " ,
91+ sql: " SELECT id FROM \( tableName ) WHERE id IS NOT NULL " ,
8092 parameters: [ ]
8193 ) { cursor in
8294 try cursor. getString ( name: " id " )
8395 }
8496 }
8597
86- /// Gets all attachments in the attachment queue.
87- public func getAttachments( ) async throws -> [ Attachment ] {
98+ func getAttachments( ) async throws -> [ Attachment ] {
8899 return try await db. getAll (
89100 sql: """
90101 SELECT
91102 *
92103 FROM
93- \( table )
104+ \( tableName )
94105 WHERE
95106 id IS NOT NULL
96107 ORDER BY
@@ -102,14 +113,13 @@ public final class AttachmentContext: Sendable {
102113 }
103114 }
104115
105- /// Gets all active attachments that require an operation to be performed.
106- public func getActiveAttachments( ) async throws -> [ Attachment ] {
116+ func getActiveAttachments( ) async throws -> [ Attachment ] {
107117 return try await db. getAll (
108118 sql: """
109119 SELECT
110120 *
111121 FROM
112- \( table )
122+ \( tableName )
113123 WHERE
114124 state = ?
115125 OR state = ?
@@ -127,25 +137,18 @@ public final class AttachmentContext: Sendable {
127137 }
128138 }
129139
130- /// Clears the attachment queue.
131- ///
132- /// - Note: Currently only used for testing purposes.
133- public func clearQueue( ) async throws {
134- _ = try await db. execute ( " DELETE FROM \( table) " )
140+ func clearQueue( ) async throws {
141+ _ = try await db. execute ( " DELETE FROM \( tableName) " )
135142 }
136143
137- /// Deletes attachments that have been archived.
138- ///
139- /// - Parameter callback: A callback invoked with the list of archived attachments before deletion.
140- /// - Returns: `true` if all items have been deleted, `false` if there may be more archived items remaining.
141- public func deleteArchivedAttachments( callback: @Sendable @escaping ( [ Attachment] ) async throws -> Void ) async throws -> Bool {
144+ func deleteArchivedAttachments( callback: @Sendable @escaping ( [ Attachment] ) async throws -> Void ) async throws -> Bool {
142145 let limit = 1000
143146 let attachments = try await db. getAll (
144147 sql: """
145148 SELECT
146149 *
147150 FROM
148- \( table )
151+ \( tableName )
149152 WHERE
150153 state = ?
151154 ORDER BY
@@ -167,7 +170,7 @@ public final class AttachmentContext: Sendable {
167170 let idsString = String ( data: ids, encoding: . utf8) !
168171
169172 _ = try await db. execute (
170- sql: " DELETE FROM \( table ) WHERE id IN (SELECT value FROM json_each(?)); " ,
173+ sql: " DELETE FROM \( tableName ) WHERE id IN (SELECT value FROM json_each(?)); " ,
171174 parameters: [ idsString]
172175 )
173176
@@ -180,7 +183,7 @@ public final class AttachmentContext: Sendable {
180183 /// - attachment: The attachment to upsert.
181184 /// - context: The database transaction context.
182185 /// - Returns: The original attachment.
183- public func upsertAttachment(
186+ func upsertAttachment(
184187 _ attachment: Attachment ,
185188 context: ConnectionContext
186189 ) throws -> Attachment {
@@ -199,7 +202,7 @@ public final class AttachmentContext: Sendable {
199202 try context. execute (
200203 sql: """
201204 INSERT OR REPLACE INTO
202- \( table ) (id, timestamp, filename, local_uri, media_type, size, state, has_synced, meta_data)
205+ \( tableName ) (id, timestamp, filename, local_uri, media_type, size, state, has_synced, meta_data)
203206 VALUES
204207 (?, ?, ?, ?, ?, ?, ?, ?, ?)
205208 """ ,
@@ -212,10 +215,30 @@ public final class AttachmentContext: Sendable {
212215 updatedRecord. size,
213216 updatedRecord. state. rawValue,
214217 updatedRecord. hasSynced ?? 0 ,
215- updatedRecord. metaData,
218+ updatedRecord. metaData
216219 ]
217220 )
218221
219222 return attachment
220223 }
221224}
225+
226+ /// Context which performs actions on the attachment records
227+ public actor AttachmentContextImpl : AttachmentContext {
228+ public let db : any PowerSyncDatabaseProtocol
229+ public let tableName : String
230+ public let logger : any LoggerProtocol
231+ public let maxArchivedCount : Int64
232+
233+ public init (
234+ db: PowerSyncDatabaseProtocol ,
235+ tableName: String ,
236+ logger: any LoggerProtocol ,
237+ maxArchivedCount: Int64
238+ ) {
239+ self . db = db
240+ self . tableName = tableName
241+ self . logger = logger
242+ self . maxArchivedCount = maxArchivedCount
243+ }
244+ }
0 commit comments