Skip to content

Commit

Permalink
refactor: Remove BackgroundRealm for MailCoreRealmAccessor (#1414)
Browse files Browse the repository at this point in the history
  • Loading branch information
adrien-coye committed May 7, 2024
2 parents 71c5757 + 6a34ec5 commit bbe4d51
Show file tree
Hide file tree
Showing 17 changed files with 355 additions and 470 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,15 @@ public protocol AttachmentsManagerWorkable {
@MainActor func attachmentUploadTaskOrFinishedTask(for uuid: String) -> AttachmentUploadTask
}

/// Transactionable
extension AttachmentsManagerWorker: TransactionablePassthrough {}

// MARK: - AttachmentsManagerWorker

public final class AttachmentsManagerWorker {
weak var updateDelegate: AttachmentsContentUpdatable?

private let mailboxManager: MailboxManager
private let backgroundRealm: BackgroundRealm
private let draftLocalUUID: String

public let transactionExecutor: Transactionable
Expand Down Expand Up @@ -111,25 +113,22 @@ public final class AttachmentsManagerWorker {
}

public init(draftLocalUUID: String, mailboxManager: MailboxManager) {
backgroundRealm = BackgroundRealm(configuration: mailboxManager.realmConfiguration)
self.draftLocalUUID = draftLocalUUID
self.mailboxManager = mailboxManager
transactionExecutor = TransactionExecutor(realmAccessible: backgroundRealm)
let realmAccessor = MailCoreRealmAccessor(realmConfiguration: mailboxManager.realmConfiguration)
transactionExecutor = TransactionExecutor(realmAccessible: realmAccessor)
}

func addLocalAttachment(attachment: Attachment) async -> Attachment? {
attachmentUploadTasks[attachment.uuid] = await AttachmentUploadTask()

var detached: Attachment?
await backgroundRealm.execute { realm in
try? realm.write {
guard let draftInContext = realm.object(ofType: Draft.self, forPrimaryKey: self.draftLocalUUID) else {
return
}

draftInContext.attachments.append(attachment)
try? writeTransaction { writableRealm in
guard let draftInContext = writableRealm.object(ofType: Draft.self, forPrimaryKey: self.draftLocalUUID) else {
return
}

draftInContext.attachments.append(attachment)
detached = attachment.detached()
}

Expand Down Expand Up @@ -170,19 +169,17 @@ public final class AttachmentsManagerWorker {
attachmentUploadTasks.removeValue(forKey: oldAttachmentUUID)
}

await backgroundRealm.execute { realm in
try? realm.write {
guard let draftInContext = realm.object(ofType: Draft.self, forPrimaryKey: self.draftLocalUUID) else {
return
}

guard let liveOldAttachment = draftInContext.attachments.first(where: { $0.uuid == oldAttachmentUUID }) else {
return
}
try? writeTransaction { writableRealm in
guard let draftInContext = writableRealm.object(ofType: Draft.self, forPrimaryKey: self.draftLocalUUID) else {
return
}

// We need to update every field of the local attachment because embedded objects don't have a primary key
liveOldAttachment.update(with: newAttachment)
guard let liveOldAttachment = draftInContext.attachments.first(where: { $0.uuid == oldAttachmentUUID }) else {
return
}

// We need to update every field of the local attachment because embedded objects don't have a primary key
liveOldAttachment.update(with: newAttachment)
}

await updateDelegate?.contentWillChange()
Expand Down Expand Up @@ -348,18 +345,16 @@ extension AttachmentsManagerWorker: AttachmentsManagerWorkable {
}

public func removeAttachment(_ attachmentUUID: String) async {
await backgroundRealm.execute { realm in
try? realm.write {
guard let draftInContext = realm.object(ofType: Draft.self, forPrimaryKey: self.draftLocalUUID) else {
return
}

guard let liveAttachment = draftInContext.attachments.first(where: { $0.uuid == attachmentUUID }) else {
return
}
try? writeTransaction { writableRealm in
guard let draftInContext = writableRealm.object(ofType: Draft.self, forPrimaryKey: self.draftLocalUUID) else {
return
}

realm.delete(liveAttachment)
guard let liveAttachment = draftInContext.attachments.first(where: { $0.uuid == attachmentUUID }) else {
return
}

writableRealm.delete(liveAttachment)
}

await attachmentUploadTasks[attachmentUUID]?.task?.cancel()
Expand All @@ -384,31 +379,29 @@ extension AttachmentsManagerWorker: AttachmentsManagerWorkable {
let allSanitizedHtmlString = await allSanitizedHtml(in: htmlAttachments).joined(separator: "")

// Mutate Draft
await backgroundRealm.execute { realm in
try? realm.write {
guard let draftInContext = realm.object(ofType: Draft.self, forPrimaryKey: self.draftLocalUUID) else {
return
}

// Title if any usable
var modified = false
if draftInContext.subject.isEmpty,
!anyUsableTitle.isEmpty {
draftInContext.subject = anyUsableTitle
modified = true
}
try? writeTransaction { writableRealm in
guard let draftInContext = writableRealm.object(ofType: Draft.self, forPrimaryKey: self.draftLocalUUID) else {
return
}

if !allSanitizedHtmlString.isEmpty {
draftInContext.body = allSanitizedHtmlString + draftInContext.body
modified = true
}
// Title if any usable
var modified = false
if draftInContext.subject.isEmpty,
!anyUsableTitle.isEmpty {
draftInContext.subject = anyUsableTitle
modified = true
}

guard modified else {
return
}
if !allSanitizedHtmlString.isEmpty {
draftInContext.body = allSanitizedHtmlString + draftInContext.body
modified = true
}

realm.add(draftInContext, update: .modified)
guard modified else {
return
}

writableRealm.add(draftInContext, update: .modified)
}
}

Expand Down
11 changes: 4 additions & 7 deletions MailCore/Cache/ContactManager/ContactManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ public final class ContactManager: ObservableObject, ContactManageable {
public static let constants = ContactManagerConstants()

public let realmConfiguration: Realm.Configuration
private let backgroundRealm: BackgroundRealm
public let transactionExecutor: Transactionable

let apiFetcher: MailApiFetcher
Expand All @@ -85,8 +84,8 @@ public final class ContactManager: ObservableObject, ContactManageable {
AddressBook.self
]
)
backgroundRealm = BackgroundRealm(configuration: realmConfiguration)
transactionExecutor = TransactionExecutor(realmAccessible: backgroundRealm)
let realmAccessor = MailCoreRealmAccessor(realmConfiguration: realmConfiguration)
transactionExecutor = TransactionExecutor(realmAccessible: realmAccessor)

excludeRealmFromBackup()
}
Expand Down Expand Up @@ -123,10 +122,8 @@ public final class ContactManager: ObservableObject, ContactManageable {

// Process addressBooks
let addressBooks = try await addressBooksRequest
await backgroundRealm.execute { realm in
try? realm.safeWrite {
realm.add(addressBooks, update: .modified)
}
try? writeTransaction { writableRealm in
writableRealm.add(addressBooks, update: .modified)
}
await backgroundTaskTracker.end()

Expand Down
24 changes: 9 additions & 15 deletions MailCore/Cache/MailboxInfosManager/MailboxInfosManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ public final class MailboxInfosManager {
private static let currentDbVersion: UInt64 = 7
private let dbName = "MailboxInfos.realm"

private let backgroundRealm: BackgroundRealm

public let realmConfiguration: Realm.Configuration
public let transactionExecutor: Transactionable

Expand All @@ -51,8 +49,8 @@ public final class MailboxInfosManager {
objectTypes: [Mailbox.self, MailboxPermissions.self, Quotas.self, ExternalMailInfo.self]
)

backgroundRealm = BackgroundRealm(configuration: realmConfiguration)
transactionExecutor = TransactionExecutor(realmAccessible: backgroundRealm)
let realmAccessor = MailCoreRealmAccessor(realmConfiguration: realmConfiguration)
transactionExecutor = TransactionExecutor(realmAccessible: realmAccessor)

excludeRealmFromBackup()
}
Expand All @@ -78,15 +76,13 @@ public final class MailboxInfosManager {
}

mailboxRemovedIds = mailboxRemoved.map(\.objectId)
}

await backgroundRealm.execute { realm in
let detachedMailboxes = mailboxes.map { $0.detached() }
try? realm.write {
realm.delete(realm.objects(Mailbox.self).filter("objectId IN %@", mailboxRemovedIds))
realm.add(detachedMailboxes, update: .modified)
}
let mailboxes = writableRealm.objects(Mailbox.self).filter("objectId IN %@", mailboxRemovedIds)
writableRealm.delete(mailboxes)
writableRealm.add(detachedMailboxes, update: .modified)
}

return mailboxRemoved
}

Expand Down Expand Up @@ -138,11 +134,9 @@ public final class MailboxInfosManager {
}

public func updateUnseen(unseenMessages: Int, for mailbox: Mailbox) async {
await backgroundRealm.execute { realm in
let freshMailbox = mailbox.fresh(using: realm)
try? realm.safeWrite {
freshMailbox?.unseenMessages = unseenMessages
}
try? writeTransaction { writableRealm in
let freshMailbox = mailbox.fresh(using: writableRealm)
freshMailbox?.unseenMessages = unseenMessages
}
}

Expand Down
9 changes: 4 additions & 5 deletions MailCore/Cache/MailboxManager/MailboxManager+Calendar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,11 @@ extension MailboxManager {
}

private func saveCalendarEventResponse(to messageUid: String, eventResponse: CalendarEventResponse) async {
await backgroundRealm.execute { realm in
if let liveMessage = realm.object(ofType: Message.self, forPrimaryKey: messageUid) {
try? realm.safeWrite {
liveMessage.calendarEventResponse = eventResponse
}
try? writeTransaction { writableRealm in
guard let liveMessage = writableRealm.object(ofType: Message.self, forPrimaryKey: messageUid) else {
return
}
liveMessage.calendarEventResponse = eventResponse
}
}
}
22 changes: 10 additions & 12 deletions MailCore/Cache/MailboxManager/MailboxManager+DB.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,18 @@ import Foundation
public extension MailboxManager {
func cleanRealm() {
Task {
await backgroundRealm.execute { realm in
try? writeTransaction { writableRealm in
let threads = writableRealm.objects(Thread.self)
writableRealm.delete(threads)

let folders = realm.objects(Folder.self)
let threads = realm.objects(Thread.self)
let messages = realm.objects(Message.self)
let messages = writableRealm.objects(Message.self)
writableRealm.delete(messages)

try? realm.safeWrite {
realm.delete(threads)
realm.delete(messages)
for folder in folders {
folder.cursor = nil
folder.resetHistoryInfo()
folder.computeUnreadCount()
}
let folders = writableRealm.objects(Folder.self)
for folder in folders {
folder.cursor = nil
folder.resetHistoryInfo()
folder.computeUnreadCount()
}
}
}
Expand Down
36 changes: 16 additions & 20 deletions MailCore/Cache/MailboxManager/MailboxManager+Draft.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,17 +81,16 @@ public extension MailboxManager {
func save(draft: Draft) async throws {
do {
let saveResponse = try await apiFetcher.save(mailbox: mailbox, draft: draft)
await backgroundRealm.execute { realm in
try? writeTransaction { writableRealm in
// Update draft in Realm
guard let liveDraft = realm.object(ofType: Draft.self, forPrimaryKey: draft.localUUID) else {
guard let liveDraft = writableRealm.object(ofType: Draft.self, forPrimaryKey: draft.localUUID) else {
self.logError(.missingDraft)
return
}
try? realm.safeWrite {
liveDraft.remoteUUID = saveResponse.uuid
liveDraft.messageUid = saveResponse.uid
liveDraft.action = nil
}

liveDraft.remoteUUID = saveResponse.uuid
liveDraft.messageUid = saveResponse.uid
liveDraft.action = nil
}
} catch let error as MailApiError {
// Do not delete draft on invalid identity
Expand Down Expand Up @@ -131,14 +130,13 @@ public extension MailboxManager {
}

func deleteLocally(draft: Draft) async throws {
await backgroundRealm.execute { realm in
guard let liveDraft = realm.object(ofType: Draft.self, forPrimaryKey: draft.localUUID) else {
try? writeTransaction { writableRealm in
guard let liveDraft = writableRealm.object(ofType: Draft.self, forPrimaryKey: draft.localUUID) else {
self.logError(.missingDraft)
return
}
try? realm.safeWrite {
realm.delete(liveDraft)
}

writableRealm.delete(liveDraft)
}
}

Expand All @@ -150,14 +148,12 @@ public extension MailboxManager {

let existingMessageUids = Set(draftFolder.threads.flatMap(\.messages).map(\.uid))

await backgroundRealm.execute { realm in
try? realm.safeWrite {
let noActionDrafts = realm.objects(Draft.self).where { $0.action == nil }
for draft in noActionDrafts {
if let messageUid = draft.messageUid,
!existingMessageUids.contains(messageUid) {
realm.delete(draft)
}
try? writeTransaction { writableRealm in
let noActionDrafts = writableRealm.objects(Draft.self).where { $0.action == nil }
for draft in noActionDrafts {
if let messageUid = draft.messageUid,
!existingMessageUids.contains(messageUid) {
writableRealm.delete(draft)
}
}
}
Expand Down
Loading

0 comments on commit bbe4d51

Please sign in to comment.