mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			129 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Swift
		
	
			
		
		
	
	
			129 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Swift
		
	
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
 | 
						|
 | 
						|
import Foundation
 | 
						|
import GRDB
 | 
						|
import SessionUtilitiesKit
 | 
						|
 | 
						|
// MARK: - ConfigColumnAssignment
 | 
						|
 | 
						|
public struct ConfigColumnAssignment {
 | 
						|
    var column: ColumnExpression
 | 
						|
    var assignment: ColumnAssignment
 | 
						|
    
 | 
						|
    init(
 | 
						|
        column: ColumnExpression,
 | 
						|
        assignment: ColumnAssignment
 | 
						|
    ) {
 | 
						|
        self.column = column
 | 
						|
        self.assignment = assignment
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
// MARK: - ColumnExpression
 | 
						|
 | 
						|
extension ColumnExpression {
 | 
						|
    public func set(to value: (any SQLExpressible)?) -> ConfigColumnAssignment {
 | 
						|
        ConfigColumnAssignment(column: self, assignment: self.set(to: value))
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
// MARK: - QueryInterfaceRequest
 | 
						|
 | 
						|
public extension QueryInterfaceRequest where RowDecoder: FetchableRecord & TableRecord {
 | 
						|
    
 | 
						|
    // MARK: -- updateAll
 | 
						|
    
 | 
						|
    @discardableResult
 | 
						|
    func updateAll(
 | 
						|
        _ db: Database,
 | 
						|
        _ assignments: ConfigColumnAssignment...
 | 
						|
    ) throws -> Int {
 | 
						|
        return try updateAll(db, assignments)
 | 
						|
    }
 | 
						|
    
 | 
						|
    @discardableResult
 | 
						|
    func updateAll(
 | 
						|
        _ db: Database,
 | 
						|
        _ assignments: [ConfigColumnAssignment]
 | 
						|
    ) throws -> Int {
 | 
						|
        return try self.updateAll(db, assignments.map { $0.assignment })
 | 
						|
    }
 | 
						|
    
 | 
						|
    @discardableResult
 | 
						|
    func updateAllAndConfig(
 | 
						|
        _ db: Database,
 | 
						|
        calledFromConfig: Bool = false,
 | 
						|
        _ assignments: ConfigColumnAssignment...
 | 
						|
    ) throws -> Int {
 | 
						|
        return try updateAllAndConfig(db, calledFromConfig: calledFromConfig, assignments)
 | 
						|
    }
 | 
						|
    
 | 
						|
    @discardableResult
 | 
						|
    func updateAllAndConfig(
 | 
						|
        _ db: Database,
 | 
						|
        calledFromConfig: Bool = false,
 | 
						|
        _ assignments: [ConfigColumnAssignment]
 | 
						|
    ) throws -> Int {
 | 
						|
        let targetAssignments: [ColumnAssignment] = assignments.map { $0.assignment }
 | 
						|
        
 | 
						|
        // Before we do anything custom make sure the changes actually do need to be synced
 | 
						|
        guard SessionUtil.assignmentsRequireConfigUpdate(assignments) else {
 | 
						|
            return try self.updateAll(db, targetAssignments)
 | 
						|
        }
 | 
						|
        
 | 
						|
        return try self.updateAndFetchAllAndUpdateConfig(db, calledFromConfig: calledFromConfig, assignments).count
 | 
						|
    }
 | 
						|
    
 | 
						|
    // MARK: -- updateAndFetchAll
 | 
						|
    
 | 
						|
    @discardableResult
 | 
						|
    func updateAndFetchAllAndUpdateConfig(
 | 
						|
        _ db: Database,
 | 
						|
        calledFromConfig: Bool = false,
 | 
						|
        _ assignments: ConfigColumnAssignment...
 | 
						|
    ) throws -> [RowDecoder] {
 | 
						|
        return try updateAndFetchAllAndUpdateConfig(db, calledFromConfig: calledFromConfig, assignments)
 | 
						|
    }
 | 
						|
    
 | 
						|
    @discardableResult
 | 
						|
    func updateAndFetchAllAndUpdateConfig(
 | 
						|
        _ db: Database,
 | 
						|
        calledFromConfig: Bool = false,
 | 
						|
        _ assignments: [ConfigColumnAssignment]
 | 
						|
    ) throws -> [RowDecoder] {
 | 
						|
        // First perform the actual updates
 | 
						|
        let updatedData: [RowDecoder] = try self.updateAndFetchAll(db, assignments.map { $0.assignment })
 | 
						|
        
 | 
						|
        // Then check if any of the changes could affect the config
 | 
						|
        guard
 | 
						|
            !calledFromConfig &&
 | 
						|
            SessionUtil.assignmentsRequireConfigUpdate(assignments)
 | 
						|
        else { return updatedData }
 | 
						|
        
 | 
						|
        defer {
 | 
						|
            // If we changed a column that requires a config update then we may as well automatically
 | 
						|
            // enqueue a new config sync job once the transaction completes (but only enqueue it once
 | 
						|
            // per transaction - doing it more than once is pointless)
 | 
						|
            let userPublicKey: String = getUserHexEncodedPublicKey(db)
 | 
						|
            
 | 
						|
            db.afterNextTransactionNestedOnce(dedupeId: SessionUtil.syncDedupeId(userPublicKey)) { db in
 | 
						|
                ConfigurationSyncJob.enqueue(db, publicKey: userPublicKey)
 | 
						|
            }
 | 
						|
        }
 | 
						|
        
 | 
						|
        // Update the config dump state where needed
 | 
						|
        switch self {
 | 
						|
            case is QueryInterfaceRequest<Contact>:
 | 
						|
                return try SessionUtil.updatingContacts(db, updatedData)
 | 
						|
                
 | 
						|
            case is QueryInterfaceRequest<Profile>:
 | 
						|
                return try SessionUtil.updatingProfiles(db, updatedData)
 | 
						|
                
 | 
						|
            case is QueryInterfaceRequest<SessionThread>:
 | 
						|
                return try SessionUtil.updatingThreads(db, updatedData)
 | 
						|
                
 | 
						|
            default: return updatedData
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |