Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Scheduler #1599

Merged
merged 5 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DuckDuckGo/AppDelegate/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, FileDownloadManagerDel
#endif

#if DBP
DataBrokerProtectionManager.shared.startSchedulerIfPossible()
DataBrokerProtectionManager.shared.runOperationsAndStartSchedulerIfPossible()
#endif
}

Expand Down
6 changes: 4 additions & 2 deletions DuckDuckGo/DBP/DataBrokerProtectionManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,15 @@ public final class DataBrokerProtectionManager {
redeemUseCase.shouldAskForInviteCode()
}

public func startSchedulerIfPossible() {
public func runOperationsAndStartSchedulerIfPossible() {
guard !redeemUseCase.shouldAskForInviteCode() else { return }

// If there's no saved profileQueryData we don't need to start the scheduler
// We should probably use a faster query for this, i.e: instead of returning data just check the count in the db
if !dataManager.fetchBrokerProfileQueryData().isEmpty {
scheduler.start()
scheduler.runQueuedOperations(showWebView: false) { [weak self] in
self?.scheduler.startScheduler()
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,7 @@ final class DataBrokerOperationsCollection: Operation {
}

private func runOperation() async {
os_log("Running operation: %{public}@", log: .dataBrokerProtection, String(describing: id.uuidString))

let sortedOperationsData: [BrokerOperationData]
let filteredAndSortedOperationsData: [BrokerOperationData]
let operationsData: [BrokerOperationData]

switch operationType {
Expand All @@ -114,15 +112,15 @@ final class DataBrokerOperationsCollection: Operation {
}

if let priorityDate = priorityDate {
sortedOperationsData = operationsData
filteredAndSortedOperationsData = operationsData
.filter { $0.preferredRunDate != nil && $0.preferredRunDate! <= priorityDate }
.sorted { $0.preferredRunDate! < $1.preferredRunDate! }

} else {
sortedOperationsData = operationsData
filteredAndSortedOperationsData = operationsData
}

for operationData in sortedOperationsData {
for operationData in filteredAndSortedOperationsData {
if isCancelled {
return
}
Expand All @@ -135,12 +133,16 @@ final class DataBrokerOperationsCollection: Operation {
continue
}
do {
os_log("Running operation: %{public}@", log: .dataBrokerProtection, String(describing: operationData))

try await DataBrokerProfileQueryOperationManager().runOperation(operationData: operationData,
brokerProfileQueryData: brokerProfileData,
database: database,
notificationCenter: notificationCenter,
runner: runner,
showWebView: showWebView)
os_log("Finished operation: %{public}@", log: .dataBrokerProtection, String(describing: id.uuidString))

if let sleepInterval = intervalBetweenOperations {
os_log("Waiting...: %{public}f", log: .dataBrokerProtection, sleepInterval)
try await Task.sleep(nanoseconds: UInt64(sleepInterval) * 1_000_000_000)
Expand All @@ -155,7 +157,6 @@ final class DataBrokerOperationsCollection: Operation {
}
}
}
os_log("Finished operation: %{public}@", log: .dataBrokerProtection, String(describing: id.uuidString))
}

private func finish() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ final class DataBrokerProtectionProcessor {
}

// MARK: - Public functions
func runScanOnAllDataBrokers(showWebView: Bool = false, completion: (() -> Void)? = nil) {
func runAllScanOperations(showWebView: Bool = false, completion: (() -> Void)? = nil) {
operationQueue.cancelAllOperations()
runOperations(operationType: .scan,
priorityDate: nil,
Expand All @@ -58,6 +58,16 @@ final class DataBrokerProtectionProcessor {
}
}

func runAllOptOutOperations(showWebView: Bool = false, completion: (() -> Void)? = nil) {
operationQueue.cancelAllOperations()
runOperations(operationType: .optOut,
priorityDate: nil,
showWebView: showWebView) {
os_log("Scans done", log: .dataBrokerProtection)
completion?()
}
}

func runQueuedOperations(showWebView: Bool = false, completion: (() -> Void)? = nil ) {
runOperations(operationType: .all,
priorityDate: Date(),
Expand All @@ -67,7 +77,7 @@ final class DataBrokerProtectionProcessor {
}
}

func forceRunOperations(showWebView: Bool = false, completion: (() -> Void)? = nil ) {
func runAllOperations(showWebView: Bool = false, completion: (() -> Void)? = nil ) {
runOperations(operationType: .all,
priorityDate: nil,
showWebView: showWebView) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,28 @@ public enum DataBrokerProtectionSchedulerStatus {
}

public protocol DataBrokerProtectionScheduler {
func start(showWebView: Bool)
func forceRunOperations(showWebView: Bool)
func stop()
func scanAllBrokers(showWebView: Bool, completion: (() -> Void)?)
var statusPublisher: Published<DataBrokerProtectionSchedulerStatus>.Publisher { get }
var status: DataBrokerProtectionSchedulerStatus { get }

func startScheduler(showWebView: Bool)
func stopScheduler()

func optOutAllBrokers(showWebView: Bool, completion: (() -> Void)?)
func scanAllBrokers(showWebView: Bool, completion: (() -> Void)?)
func runQueuedOperations(showWebView: Bool, completion: (() -> Void)?)
func runAllOperations(showWebView: Bool)
}

public extension DataBrokerProtectionScheduler {
func start() {
start(showWebView: false)
extension DataBrokerProtectionScheduler {
public func startScheduler() {
startScheduler(showWebView: false)
}

func forceStart() {
forceRunOperations(showWebView: false)
public func runAllOperations() {
runAllOperations(showWebView: false)
}

func scanAllBrokers() {
public func scanAllBrokers() {
scanAllBrokers(showWebView: false, completion: nil)
}
}
Expand Down Expand Up @@ -99,7 +103,7 @@ public final class DefaultDataBrokerProtectionScheduler: DataBrokerProtectionSch
activity.repeats = true
activity.interval = SchedulerCycle.interval
activity.tolerance = SchedulerCycle.tolerance
activity.qualityOfService = QualityOfService.utility
activity.qualityOfService = QualityOfService.default

self.dataManager = dataManager
self.privacyConfigManager = privacyConfigManager
Expand All @@ -111,18 +115,19 @@ public final class DefaultDataBrokerProtectionScheduler: DataBrokerProtectionSch
self.captchaService = CaptchaService(redeemUseCase: redeemUseCase)
}

public func forceRunOperations(showWebView: Bool = false) {
stop()

self.status = .running
self.dataBrokerProcessor.forceRunOperations(showWebView: showWebView) { [weak self] in
self?.status = .stopped
public func startScheduler(showWebView: Bool = false) {
guard status == .stopped else {
os_log("Trying to start scheduler when it's already running, returning...", log: .dataBrokerProtection)
return
}
}

public func start(showWebView: Bool = false) {
self.status = .idle
status = .idle
activity.schedule { completion in
guard self.status != .stopped else {
os_log("Activity started when scheduler was already running, returning...", log: .dataBrokerProtection)
completion(.finished)
return
}
self.status = .running
os_log("Scheduler running...", log: .dataBrokerProtection)
self.dataBrokerProcessor.runQueuedOperations(showWebView: showWebView) { [weak self] in
Expand All @@ -132,15 +137,33 @@ public final class DefaultDataBrokerProtectionScheduler: DataBrokerProtectionSch
}
}

public func stop() {
public func stopScheduler() {
os_log("Stopping scheduler...", log: .dataBrokerProtection)
activity.invalidate()
status = .stopped
}

public func runAllOperations(showWebView: Bool = false) {
os_log("Running all operations...", log: .dataBrokerProtection)
self.dataBrokerProcessor.runAllOperations(showWebView: showWebView)
}

public func runQueuedOperations(showWebView: Bool = false, completion: (() -> Void)? = nil) {
os_log("Running queued operations...", log: .dataBrokerProtection)
dataBrokerProcessor.runQueuedOperations(showWebView: showWebView,
completion: completion)

}

public func scanAllBrokers(showWebView: Bool = false, completion: (() -> Void)? = nil) {
os_log("Scanning all brokers...", log: .dataBrokerProtection)
self.dataBrokerProcessor.runScanOnAllDataBrokers(showWebView: showWebView,
completion: completion)
self.dataBrokerProcessor.runAllScanOperations(showWebView: showWebView,
completion: completion)
}

public func optOutAllBrokers(showWebView: Bool = false, completion: (() -> Void)?) {
os_log("Opting out all brokers...", log: .dataBrokerProtection)
self.dataBrokerProcessor.runAllOptOutOperations(showWebView: showWebView,
completion: completion)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ final class ContainerViewModel: ObservableObject {
updateHeaderStatus()
setupNotifications()
setupCancellable()
startSchedulerIfProfileAvailable()
}

private func setupCancellable() {
Expand Down Expand Up @@ -76,12 +75,6 @@ final class ContainerViewModel: ObservableObject {
useFakeBroker = FakeBrokerUserDefaults().isFakeBrokerFlagOn()
}

private func startSchedulerIfProfileAvailable() {
if dataManager.fetchProfile() != nil {
startScheduler()
}
}

private func setupNotifications() {
notificationCenter.addObserver(self,
selector: #selector(handleReloadNotification),
Expand Down Expand Up @@ -124,17 +117,20 @@ final class ContainerViewModel: ObservableObject {
self.headerStatusText = status
}

func startScheduler() {
if scheduler.status == .stopped {
scheduler.start(showWebView: showWebView)
func runQueuedOperationsAndStartScheduler() {
scheduler.runQueuedOperations(showWebView: showWebView) { [weak self] in
guard let self = self else { return }
self.scheduler.startScheduler(showWebView: self.showWebView)
}
}

func forceSchedulerRun() {
scheduler.forceRunOperations(showWebView: showWebView)
scheduler.runAllOperations(showWebView: showWebView)
}

func scan(completion: @escaping (ScanResult) -> Void) {
func scanAfterProfileCreation(completion: @escaping (ScanResult) -> Void) {
scheduler.stopScheduler()

scheduler.scanAllBrokers(showWebView: showWebView) { [weak self] in
guard let self = self else { return }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ struct DataBrokerProtectionContainerView: View {
viewModel: profileViewModel,
scanButtonClicked: {
navigationViewModel.updateNavigation(.scanStarted)
containerViewModel.scan { scanResult in
containerViewModel.scanAfterProfileCreation { scanResult in
switch scanResult {
case .noResults:
navigationViewModel.updateNavigation(.noResults)
case .results:
resultsViewModel.reloadData()
navigationViewModel.updateNavigation(.results)
containerViewModel.startScheduler()
containerViewModel.runQueuedOperationsAndStartScheduler()
}
}
}, backToDashboardClicked: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ final class PreviewScheduler: DataBrokerProtectionScheduler {
internal init() {
self.status = .idle
}

func start(showWebView: Bool) { }
func forceRunOperations(showWebView: Bool) { }
func stop() { }
func startScheduler(showWebView: Bool) { }
func stopScheduler() { }
func optOutAllBrokers(showWebView: Bool, completion: (() -> Void)?) { }
func runQueuedOperations(showWebView: Bool, completion: (() -> Void)?) { }
func scanAllBrokers(showWebView: Bool, completion: (() -> Void)?) { }

func runAllOperations(showWebView: Bool) { }
}

final class PreviewDataManager: DataBrokerProtectionDataManaging {
Expand Down