Made a couple of tweaks to the GRDBStorage interface

Updated the ControlMessageProcessRecord to allow for duplicate handling of UnsendRequest messages
This commit is contained in:
Morgan Pretty 2022-06-21 13:39:46 +10:00
parent 1720e85e8f
commit 4133a49a34
17 changed files with 91 additions and 78 deletions

View File

@ -397,7 +397,7 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate {
let webRTCSession: WebRTCSession = self.webRTCSession
GRDBStorage.shared
.write { db in webRTCSession.sendOffer(db, to: sessionId, isRestartingICEConnection: true) }
.read { db in webRTCSession.sendOffer(db, to: sessionId, isRestartingICEConnection: true) }
.retainUntilComplete()
}

View File

@ -417,7 +417,7 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat
ModalActivityIndicatorViewController.present(fromViewController: navigationController) { _ in
GRDBStorage.shared
.write { db in
.writeAsync { db in
if !updatedMemberIds.contains(userPublicKey) {
return try MessageSender.leave(db, groupPublicKey: threadId)
}

View File

@ -196,27 +196,28 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
let selectedContacts = self.selectedContacts
let message: String? = (selectedContacts.count > 20) ? "Please wait while the group is created..." : nil
ModalActivityIndicatorViewController.present(fromViewController: navigationController!, message: message) { [weak self] _ in
let promise: Promise<SessionThread> = GRDBStorage.shared.write { db in
try MessageSender.createClosedGroup(db, name: name, members: selectedContacts)
}
let _ = promise.done(on: DispatchQueue.main) { thread in
GRDBStorage.shared.write { db in
try? MessageSender.syncConfiguration(db, forceSyncNow: true).retainUntilComplete()
GRDBStorage.shared
.writeAsync { db in
try MessageSender.createClosedGroup(db, name: name, members: selectedContacts)
}
self?.presentingViewController?.dismiss(animated: true, completion: nil)
SessionApp.presentConversation(for: thread.id, action: .compose, animated: false)
}
promise.catch(on: DispatchQueue.main) { [weak self] _ in
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
let title = "Couldn't Create Group"
let message = "Please check your internet connection and try again."
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("BUTTON_OK", comment: ""), style: .default, handler: nil))
self?.presentAlert(alert)
}
.done(on: DispatchQueue.main) { thread in
GRDBStorage.shared.writeAsync { db in
try? MessageSender.syncConfiguration(db, forceSyncNow: true).retainUntilComplete()
}
self?.presentingViewController?.dismiss(animated: true, completion: nil)
SessionApp.presentConversation(for: thread.id, action: .compose, animated: false)
}
.catch(on: DispatchQueue.main) { [weak self] _ in
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
let title = "Couldn't Create Group"
let message = "Please check your internet connection and try again."
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("BUTTON_OK", comment: ""), style: .default, handler: nil))
self?.presentAlert(alert)
}
.retainUntilComplete()
}
}

View File

@ -1680,7 +1680,7 @@ extension ConversationVC {
return promise
.then { _ -> Promise<Void> in
GRDBStorage.shared.write { db in
GRDBStorage.shared.writeAsync { db in
try MessageSender.sendNonDurably(
db,
message: messageRequestResponse,

View File

@ -359,7 +359,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
// MARK: - Functions
public func updateDraft(to draft: String) {
GRDBStorage.shared.write { db in
GRDBStorage.shared.writeAsync { db in
try SessionThread
.filter(id: self.threadId)
.updateAll(db, SessionThread.Columns.messageDraft.set(to: draft))

View File

@ -92,24 +92,26 @@ final class JoinOpenGroupModal: Modal {
presentingViewController.dismiss(animated: true, completion: nil)
GRDBStorage.shared.write { db in
OpenGroupManager.shared.add(
db,
roomToken: room,
server: server,
publicKey: publicKey,
isConfigMessage: false
)
}
.done(on: DispatchQueue.main) { _ in
GRDBStorage.shared.write { db in
try MessageSender.syncConfiguration(db, forceSyncNow: true).retainUntilComplete() // FIXME: It's probably cleaner to do this inside addOpenGroup(...)
GRDBStorage.shared
.writeAsync { db in
OpenGroupManager.shared.add(
db,
roomToken: room,
server: server,
publicKey: publicKey,
isConfigMessage: false
)
}
}
.catch(on: DispatchQueue.main) { error in
let alert = UIAlertController(title: "Couldn't Join", message: error.localizedDescription, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "BUTTON_OK".localized(), style: .default, handler: nil))
presentingViewController.present(alert, animated: true, completion: nil)
}
.done(on: DispatchQueue.main) { _ in
GRDBStorage.shared.writeAsync { db in
try MessageSender.syncConfiguration(db, forceSyncNow: true).retainUntilComplete() // FIXME: It's probably cleaner to do this inside addOpenGroup(...)
}
}
.catch(on: DispatchQueue.main) { error in
let alert = UIAlertController(title: "Couldn't Join", message: error.localizedDescription, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "BUTTON_OK".localized(), style: .default, handler: nil))
presentingViewController.present(alert, animated: true, completion: nil)
}
.retainUntilComplete()
}
}

View File

@ -591,18 +591,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
guard Date().timeIntervalSince(lastSync) > (7 * 24 * 60 * 60) else { return } // Sync every 2 days
GRDBStorage.shared.write { db in
try MessageSender.syncConfiguration(db, forceSyncNow: false)
.done {
// Only update the 'lastConfigurationSync' timestamp if we have done the
// first sync (Don't want a new device config sync to override config
// syncs from other devices)
if UserDefaults.standard[.hasSyncedInitialConfiguration] {
UserDefaults.standard[.lastConfigurationSync] = Date()
}
GRDBStorage.shared
.writeAsync { db in try MessageSender.syncConfiguration(db, forceSyncNow: false) }
.done {
// Only update the 'lastConfigurationSync' timestamp if we have done the
// first sync (Don't want a new device config sync to override config
// syncs from other devices)
if UserDefaults.standard[.hasSyncedInitialConfiguration] {
UserDefaults.standard[.lastConfigurationSync] = Date()
}
.retainUntilComplete()
}
}
.retainUntilComplete()
}
}

View File

@ -444,7 +444,9 @@ class NotificationActionHandler {
throw NotificationError.failDebug("unable to find thread with id: \(threadId)")
}
let promise: Promise<Void> = GRDBStorage.shared.write { db in
let (promise, seal) = Promise<Void>.pending()
GRDBStorage.shared.writeAsync { db in
let interaction: Interaction = try Interaction(
threadId: thread.id,
authorId: getUserHexEncodedPublicKey(db),
@ -468,12 +470,15 @@ class NotificationActionHandler {
in: thread
)
}
promise.catch { [weak self] error in
GRDBStorage.shared.read { db in
.done { seal.fulfill(()) }
.catch { error in
GRDBStorage.shared.read { [weak self] db in
self?.notificationPresenter.notifyForFailedSend(db, in: thread)
}
seal.reject(error)
}
.retainUntilComplete()
return promise
}

View File

@ -163,7 +163,7 @@ final class JoinOpenGroupVC: BaseVC, UIPageViewControllerDataSource, UIPageViewC
ModalActivityIndicatorViewController.present(fromViewController: navigationController, canCancel: false) { [weak self] _ in
GRDBStorage.shared
.write { db in
.writeAsync { db in
OpenGroupManager.shared.add(
db,
roomToken: roomToken,

View File

@ -154,17 +154,16 @@ final class NukeDataModal: Modal {
@objc private func clearDeviceOnly() {
ModalActivityIndicatorViewController.present(fromViewController: self, canCancel: false) { [weak self] _ in
GRDBStorage.shared.write { db in
try MessageSender.syncConfiguration(db, forceSyncNow: true)
.ensure(on: DispatchQueue.main) {
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
UserDefaults.removeAll() // Not done in the nuke data implementation as unlinking requires this to happen later
General.cache.mutate { $0.encodedPublicKey = nil } // Remove the cached key so it gets re-cached on next access
NotificationCenter.default.post(name: .dataNukeRequested, object: nil)
}
.retainUntilComplete()
}
GRDBStorage.shared
.writeAsync { db in try MessageSender.syncConfiguration(db, forceSyncNow: true) }
.ensure(on: DispatchQueue.main) {
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
UserDefaults.removeAll() // Not done in the nuke data implementation as unlinking requires this to happen later
General.cache.mutate { $0.encodedPublicKey = nil } // Remove the cached key so it gets re-cached on next access
NotificationCenter.default.post(name: .dataNukeRequested, object: nil)
}
.retainUntilComplete()
}
}

View File

@ -170,7 +170,7 @@ public final class WebRTCSession : NSObject, RTCPeerConnectionDelegate {
}
}
GRDBStorage.shared
.write { db in
.writeAsync { db in
try MessageSender
.sendNonDurably(
db,

View File

@ -71,6 +71,13 @@ public struct ControlMessageProcessRecord: Codable, FetchableRecord, Persistable
// the unique constraints on that table prevent duplicate messages
if message is VisibleMessage { return nil }
// Allow duplicates for UnsendRequest messages, if a user received an UnsendRequest
// as a push notification the it wouldn't include a serverHash and, as a result,
// wouldn't get deleted from the server - since the logic only runs if we find a
// matching message the safest option is to allow duplicate handling to avoid an
// edge-case where a message doesn't get deleted
if message is UnsendRequest { return nil }
// Allow duplicates for all call messages, the double checking will be done on
// message handling to make sure the messages are for the same ongoing call
if message is CallMessage { return nil }

View File

@ -130,7 +130,7 @@ public enum MessageSendJob: JobExecutor {
details.message.threadId = (details.message.threadId ?? job.threadId)
// Perform the actual message sending
GRDBStorage.shared.write { db -> Promise<Void> in
GRDBStorage.shared.writeAsync { db -> Promise<Void> in
try MessageSender.sendImmediate(
db,
message: details.message,
@ -170,6 +170,7 @@ public enum MessageSendJob: JobExecutor {
failure(job, error, false)
}
}
.retainUntilComplete()
}
}

View File

@ -35,7 +35,7 @@ public enum SendReadReceiptsJob: JobExecutor {
}
GRDBStorage.shared
.write { db in
.writeAsync { db in
try MessageSender.sendImmediate(
db,
message: ReadReceipt(

View File

@ -194,7 +194,7 @@ public final class OpenGroupManager: NSObject {
// Note: We don't do this after the db commit as it can fail (resulting in endless loading)
OpenGroupAPI.workQueue.async {
dependencies.storage
.write { db in
.writeAsync { db in
OpenGroupAPI
.capabilitiesAndRoom(
db,
@ -809,7 +809,7 @@ public final class OpenGroupManager: NSObject {
// Trigger the download on a background queue
DispatchQueue.global(qos: .background).async {
dependencies.storage
.write { db in
.writeAsync { db in
OpenGroupAPI
.downloadFile(
db,
@ -832,6 +832,7 @@ public final class OpenGroupManager: NSObject {
seal.fulfill(imageData)
}
.catch { seal.reject($0) }
.retainUntilComplete()
}
dependencies.mutableCache.mutate { cache in

View File

@ -164,8 +164,7 @@ extension MessageSender {
}
if let error: Error = errors.first { return Promise(error: error) }
return GRDBStorage.shared.write { db in
return GRDBStorage.shared.writeAsync { db in
try MessageSender.sendImmediate(
db,
message: message,

View File

@ -221,7 +221,7 @@ final class ThreadPickerVC: UIViewController, UITableViewDataSource, UITableView
ModalActivityIndicatorViewController.present(fromViewController: shareVC!, canCancel: false, message: "vc_share_sending_message".localized()) { activityIndicator in
GRDBStorage.shared
.write { [weak self] db -> Promise<Void> in
.writeAsync { [weak self] db -> Promise<Void> in
guard let thread: SessionThread = try SessionThread.fetchOne(db, id: threadId) else {
activityIndicator.dismiss { }
self?.shareVC?.shareViewFailed(error: MessageSenderError.noThread)