Skip to content
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
91 changes: 31 additions & 60 deletions Split/FetcherEngine/Refresh/PeriodicSyncWorker.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
//
// PeriodicSplitsSyncWorker.swift
// Split
//
// Created by Javier Avrudsky on 26-Sep-2020
//
//

import Foundation

protocol PeriodicTimer {
func trigger()
func stop()
Expand Down Expand Up @@ -35,15 +33,13 @@ class DefaultPeriodicTimer: PeriodicTimer {

func trigger() {
if !isRunning.getAndSet(true) {
fetchTimer.schedule(deadline: .now() + .seconds(deadLineInSecs),
repeating: .seconds(intervalInSecs))
// fetchTimer.resume()
fetchTimer.schedule(deadline: .now() + .seconds(deadLineInSecs), repeating: .seconds(intervalInSecs))
// fetchTimer.resume()
}
}

func stop() {
// Not suspending the timer to avoid crashes
isRunning.set(false)
isRunning.set(false) // Not suspending the timer to avoid crashes
}

func destroy() {
Expand All @@ -61,8 +57,8 @@ class DefaultPeriodicTimer: PeriodicTimer {
}

protocol PeriodicSyncWorker {
// typealias SyncCompletion = (Bool) -> Void
// var completion: SyncCompletion? { get set }
// typealias SyncCompletion = (Bool) -> Void
// var completion: SyncCompletion? { get set }
func start()
func pause()
func resume()
Expand All @@ -77,17 +73,13 @@ class BasePeriodicSyncWorker: PeriodicSyncWorker {
private let eventsManager: SplitEventsManager
private var isPaused: Atomic<Bool> = Atomic(false)

init(timer: PeriodicTimer,
eventsManager: SplitEventsManager) {
init(timer: PeriodicTimer, eventsManager: SplitEventsManager) {
self.eventsManager = eventsManager
self.fetchTimer = timer

self.fetchTimer.handler { [weak self] in
guard let self = self else {
return
}
if self.isPaused.value {
return
}
guard let self = self, self.isPaused.value else { return }

self.fetchQueue.async {
self.fetchFromRemote()
}
Expand Down Expand Up @@ -140,6 +132,7 @@ class BasePeriodicSyncWorker: PeriodicSyncWorker {
}
}

// MARK: Sync Splits (Targeting Rules)
class PeriodicSplitsSyncWorker: BasePeriodicSyncWorker {

private let splitFetcher: HttpSplitFetcher
Expand All @@ -149,46 +142,32 @@ class PeriodicSplitsSyncWorker: BasePeriodicSyncWorker {
private let ruleBasedSegmentsChangeProcessor: RuleBasedSegmentChangeProcessor
private let syncHelper: SplitsSyncHelper

init(splitFetcher: HttpSplitFetcher,
splitsStorage: SplitsStorage,
generalInfoStorage: GeneralInfoStorage,
ruleBasedSegmentsStorage: RuleBasedSegmentsStorage,
splitChangeProcessor: SplitChangeProcessor,
ruleBasedSegmentsChangeProcessor: RuleBasedSegmentChangeProcessor,
timer: PeriodicTimer,
eventsManager: SplitEventsManager,
splitConfig: SplitClientConfig) {

init(splitFetcher: HttpSplitFetcher, splitsStorage: SplitsStorage, generalInfoStorage: GeneralInfoStorage, ruleBasedSegmentsStorage: RuleBasedSegmentsStorage, splitChangeProcessor: SplitChangeProcessor, ruleBasedSegmentsChangeProcessor: RuleBasedSegmentChangeProcessor, timer: PeriodicTimer, eventsManager: SplitEventsManager, splitConfig: SplitClientConfig) {
self.splitFetcher = splitFetcher
self.splitsStorage = splitsStorage
self.ruleBasedSegmentsStorage = ruleBasedSegmentsStorage
self.splitChangeProcessor = splitChangeProcessor
self.ruleBasedSegmentsChangeProcessor = ruleBasedSegmentsChangeProcessor
self.syncHelper = SplitsSyncHelper(splitFetcher: splitFetcher,
splitsStorage: splitsStorage,
ruleBasedSegmentsStorage: ruleBasedSegmentsStorage,
splitChangeProcessor: splitChangeProcessor,
ruleBasedSegmentsChangeProcessor: ruleBasedSegmentsChangeProcessor,
generalInfoStorage: generalInfoStorage,
splitConfig: splitConfig)
super.init(timer: timer,
eventsManager: eventsManager)
self.syncHelper = SplitsSyncHelper(splitFetcher: splitFetcher, splitsStorage: splitsStorage, ruleBasedSegmentsStorage: ruleBasedSegmentsStorage, splitChangeProcessor: splitChangeProcessor, ruleBasedSegmentsChangeProcessor: ruleBasedSegmentsChangeProcessor, generalInfoStorage: generalInfoStorage, splitConfig: splitConfig)

super.init(timer: timer, eventsManager: eventsManager)
}

override func fetchFromRemote() {
// Polling should be done once sdk ready is fired in initial sync
if !isSdkReadyFired() {
return
}
if !isSdkReadyFired() { return } // Polling should be done once sdk ready is fired in initial sync

let changeNumber = splitsStorage.changeNumber
let rbChangeNumber: Int64 = ruleBasedSegmentsStorage.changeNumber

// 1. Try to Sync
guard let result = try? syncHelper.sync(since: changeNumber, rbSince: rbChangeNumber) else {
let event = SplitInternalEventWithMetadata(.sdkError, metadata: EventMetadata(type: .segmentsSyncError, data: []))
// Fail
let event = SplitInternalEventWithMetadata(.sdkError, metadata: EventMetadata(type: .featureFlagsSyncError, data: []))
notifyUpdate(event)
return
}

// 2. Process Result
if result.success, result.featureFlagsUpdated || result.rbsUpdated {
// Success
notifyUpdate(.splitsUpdated)
Expand All @@ -200,42 +179,34 @@ class PeriodicSplitsSyncWorker: BasePeriodicSyncWorker {
}
}

// MARK: Sync Segments
class PeriodicMySegmentsSyncWorker: BasePeriodicSyncWorker {

private let mySegmentsStorage: ByKeyMySegmentsStorage
private let myLargeSegmentsStorage: ByKeyMySegmentsStorage
private let telemetryProducer: TelemetryRuntimeProducer?
private let syncHelper: SegmentsSyncHelper

init(mySegmentsStorage: ByKeyMySegmentsStorage,
myLargeSegmentsStorage: ByKeyMySegmentsStorage,
telemetryProducer: TelemetryRuntimeProducer?,
timer: PeriodicTimer,
eventsManager: SplitEventsManager,
syncHelper: SegmentsSyncHelper) {

init(mySegmentsStorage: ByKeyMySegmentsStorage, myLargeSegmentsStorage: ByKeyMySegmentsStorage, telemetryProducer: TelemetryRuntimeProducer?, timer: PeriodicTimer, eventsManager: SplitEventsManager, syncHelper: SegmentsSyncHelper) {
self.mySegmentsStorage = mySegmentsStorage
self.myLargeSegmentsStorage = myLargeSegmentsStorage
self.telemetryProducer = telemetryProducer
self.syncHelper = syncHelper

super.init(timer: timer,
eventsManager: eventsManager)
super.init(timer: timer, eventsManager: eventsManager)
}

override func fetchFromRemote() {
// Polling should be done once sdk ready is fired in initial sync
if !isSdkReadyFired() {
return
}
if !isSdkReadyFired() { return } // Polling should be done once sdk ready is fired in initial sync

do {
let result = try syncHelper.sync(msTill: mySegmentsStorage.changeNumber,
mlsTill: myLargeSegmentsStorage.changeNumber,
headers: nil)
// 1. Try to sync
let result = try syncHelper.sync(msTill: mySegmentsStorage.changeNumber, mlsTill: myLargeSegmentsStorage.changeNumber, headers: nil)

// 2. Process result
if result.success {
// Success
if result.msUpdated || result.mlsUpdated {
// For now is not necessary specify which entity was updated
notifyUpdate(.mySegmentsUpdated)
}
} else {
Expand All @@ -245,9 +216,9 @@ class PeriodicMySegmentsSyncWorker: BasePeriodicSyncWorker {
}
} catch {
// Fail
Logger.e("Problem fetching segments: %@", error.localizedDescription)
let event = SplitInternalEventWithMetadata(.sdkError, metadata: EventMetadata(type: .segmentsSyncError, data: []))
notifyUpdate(event)
Logger.e("Problem fetching segments: %@", error.localizedDescription)
}
}
}
Loading
Loading