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
11 changes: 5 additions & 6 deletions Split/Api/SplitDatabaseHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,15 @@ struct SplitDatabaseHelper {
let flagSetsCache: FlagSetsCache =
DefaultFlagSetsCache(setsInFilter: splitClientConfig.bySetsFilter()?.values.asSet())
let persistentSplitsStorage = DefaultPersistentSplitsStorage(database: splitDatabase)
let splitsStorage = openSplitsStorage(database: splitDatabase, flagSetsCache: flagSetsCache)
let generalInfoStorage = openGeneralInfoStorage(database: splitDatabase)
let splitsStorage = openSplitsStorage(database: splitDatabase, flagSetsCache: flagSetsCache, generalInfoStorage: generalInfoStorage)

let persistentImpressionsStorage = openPersistentImpressionsStorage(database: splitDatabase)
let impressionsStorage = openImpressionsStorage(persistentStorage: persistentImpressionsStorage)
let impressionsCountStorage = openImpressionsCountStorage(database: splitDatabase)

let persistentEventsStorage = openPersistentEventsStorage(database: splitDatabase)
let eventsStorage = openEventsStorage(persistentStorage: persistentEventsStorage)

let generalInfoStorage = openGeneralInfoStorage(database: splitDatabase)

let mySegmentsStorage = openMySegmentsStorage(database: splitDatabase, generalInfoStorage: generalInfoStorage)
let myLargeSegmentsStorage = openMyLargeSegmentsStorage(database: splitDatabase, generalInfoStorage: generalInfoStorage)
Expand All @@ -133,7 +132,7 @@ struct SplitDatabaseHelper {
generalInfoStorage: generalInfoStorage)

let ruleBasedSegmentsStorage = DefaultRuleBasedSegmentsStorage(
persistentStorage: persistentRuleBasedSegmentsStorage)
persistentStorage: persistentRuleBasedSegmentsStorage, generalInfoStorage: generalInfoStorage)

return SplitStorageContainer(splitDatabase: splitDatabase,
splitsStorage: splitsStorage,
Expand Down Expand Up @@ -175,9 +174,9 @@ struct SplitDatabaseHelper {
}

static func openSplitsStorage(database: SplitDatabase,
flagSetsCache: FlagSetsCache) -> SplitsStorage {
flagSetsCache: FlagSetsCache, generalInfoStorage: GeneralInfoStorage) -> SplitsStorage {
return DefaultSplitsStorage(persistentSplitsStorage: openPersistentSplitsStorage(database: database),
flagSetsCache: flagSetsCache)
flagSetsCache: flagSetsCache, GeneralInfoStorage: generalInfoStorage)
}

static func openPersistentMySegmentsStorage(database: SplitDatabase) -> PersistentMySegmentsStorage {
Expand Down
5 changes: 4 additions & 1 deletion Split/Events/SplitEventsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ class DefaultSplitEventsManager: SplitEventsManager {
self.triggered.append(event)
switch event {
case .splitsUpdated, .mySegmentsUpdated, .myLargeSegmentsUpdated:
print(" EVENT !! **************\n\(event)\n EVENT !! **************")
if isTriggered(external: .sdkReady) {
print(" SDK UPDATED ")
trigger(event: .sdkUpdated)
continue
}
Expand Down Expand Up @@ -181,7 +183,7 @@ class DefaultSplitEventsManager: SplitEventsManager {
var triggered = false
dataAccessQueue.sync {
if let times = executionTimes[event.toString()] {
triggered = (times == 0)
triggered = (times == 0)
} else {
triggered = false
}
Expand All @@ -197,6 +199,7 @@ class DefaultSplitEventsManager: SplitEventsManager {
if !isTriggered(external: .sdkReadyFromCache) {
self.trigger(event: .sdkReadyFromCache)
}
print(" --------- *** TRIGGER READy")
self.trigger(event: .sdkReady)
}
}
Expand Down
5 changes: 3 additions & 2 deletions Split/FetcherEngine/Refresh/BackgroundSyncWorker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ class BackgroundSplitsSyncWorker: BackgroundSyncWorker {
splitChangeProcessor: SplitChangeProcessor,
ruleBasedSegmentsChangeProcessor: RuleBasedSegmentChangeProcessor,
cacheExpiration: Int64,
splitConfig: SplitClientConfig) {
splitConfig: SplitClientConfig,
generalInfoStorage: GeneralInfoStorage) {

self.persistenSplitsStorage = persistentSplitsStorage
self.persistentRuleBasedSegmentsStorage = persistentRuleBasedSegmentsStorage
Expand All @@ -66,7 +67,7 @@ class BackgroundSplitsSyncWorker: BackgroundSyncWorker {
self.cacheExpiration = cacheExpiration
self.syncHelper = SplitsSyncHelper(splitFetcher: splitFetcher,
splitsStorage: BackgroundSyncSplitsStorage(persistentSplitsStorage: persistentSplitsStorage),
ruleBasedSegmentsStorage: DefaultRuleBasedSegmentsStorage(persistentStorage: persistentRuleBasedSegmentsStorage),
ruleBasedSegmentsStorage: DefaultRuleBasedSegmentsStorage(persistentStorage: persistentRuleBasedSegmentsStorage, generalInfoStorage: generalInfoStorage),
splitChangeProcessor: splitChangeProcessor,
ruleBasedSegmentsChangeProcessor: ruleBasedSegmentsChangeProcessor,
generalInfoStorage: nil, // Pass nil to disable proxy handling for background sync
Expand Down
3 changes: 2 additions & 1 deletion Split/FetcherEngine/Refresh/SplitBgSynchronizer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ struct BackgroundSyncExecutor {
splitChangeProcessor: changeProcessor,
ruleBasedSegmentsChangeProcessor: ruleBasedSegmentChangeProcessor,
cacheExpiration: cacheExpiration,
splitConfig: SplitClientConfig())
splitConfig: SplitClientConfig(),
generalInfoStorage: generalInfoStorage)

let impressionsRecorder
= DefaultHttpImpressionsRecorder(restClient: restClient,
Expand Down
3 changes: 2 additions & 1 deletion Split/FetcherEngine/Refresh/SplitsSyncHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class SplitsSyncHelper {

private let splitFetcher: HttpSplitFetcher
private let splitsStorage: SyncSplitsStorage
private let ruleBasedSegmentsStorage: RuleBasedSegmentsStorage
private var ruleBasedSegmentsStorage: RuleBasedSegmentsStorage
private let splitChangeProcessor: SplitChangeProcessor
private let ruleBasedSegmentsChangeProcessor: RuleBasedSegmentChangeProcessor
private let splitConfig: SplitClientConfig
Expand Down Expand Up @@ -202,6 +202,7 @@ class SplitsSyncHelper {
ruleBasedSegmentsStorage.clear()
}
firstFetch = false

if splitsStorage.update(splitChange: splitChangeProcessor.process(targetingRulesChange.featureFlags)) {
featureFlagsUpdated = true
}
Expand Down
7 changes: 5 additions & 2 deletions Split/Localhost/LocalhostSplitsStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@
import Foundation

class LocalhostSplitsStorage: SplitsStorage {

var changeNumber: Int64 = -1
var updateTimestamp: Int64 = 1
var splitsFilterQueryString: String = ""
var flagsSpec: String = ""
internal var segmentsInUse: Int64 = 0
var segmentsInUse: Int64 = 0

private let inMemorySplits = ConcurrentDictionary<String, Split>()

Expand Down Expand Up @@ -48,6 +47,10 @@ class LocalhostSplitsStorage: SplitsStorage {
inMemorySplits.setValues(values)
return true
}

func getSegmentsInUse() -> Int64 {
segmentsInUse
}

func update(filterQueryString: String) {
}
Expand Down
1 change: 0 additions & 1 deletion Split/Network/Streaming/SyncUpdateWorker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ class SplitsUpdateWorker: UpdateWorker<TargetingRuleUpdateNotification> {
Logger.v("RBS update received: \(change)")

let processedChange = ruleBasedSegmentsChangeProcessor.process(change)

if self.ruleBasedSegmentsStorage.update(toAdd: processedChange.toAdd,
toRemove: processedChange.toRemove,
changeNumber: processedChange.changeNumber) {
Expand Down
4 changes: 3 additions & 1 deletion Split/Network/Sync/FeatureFlagsSynchronizer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,11 @@ class DefaultFeatureFlagsSynchronizer: FeatureFlagsSynchronizer {

// MARK: Important. This should be called before loadLocal()
// MARK: Part of /memberships hits optimization
if self.storageContainer.generalInfoStorage.getSegmentsInUse() == nil {
if storageContainer.generalInfoStorage.getSegmentsInUse() == nil && storageContainer.splitsStorage.changeNumber > -1 {
Logger.v("Force Parsing flags")
splitsStorage.forceParsing()
ruleBasedSegmentsStorage.forceParsing()
TimeChecker.logInterval("Time for Force Parsing", startTime: start)
}

// Load local
Expand Down
16 changes: 14 additions & 2 deletions Split/Storage/GeneralInfo/GeneralInfoStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ protocol GeneralInfoStorage {
class DefaultGeneralInfoStorage: GeneralInfoStorage {

private let generalInfoDao: GeneralInfoDao
private var queue = DispatchQueue(label: "io.split.DefaultGeneralInfoStorage")

// Part of Smart Pausing Optimization Feature
private var segmentsInUse: Int64? = nil

init(generalInfoDao: GeneralInfoDao) {
self.generalInfoDao = generalInfoDao
Expand Down Expand Up @@ -84,10 +88,18 @@ class DefaultGeneralInfoStorage: GeneralInfoStorage {
}

func getSegmentsInUse() -> Int64? {
generalInfoDao.longValue(info: .segmentsInUse)
queue.sync {
if segmentsInUse == nil { // This happens just on start
segmentsInUse = generalInfoDao.longValue(info: .segmentsInUse)
}
}
return segmentsInUse
}

func setSegmentsInUse(_ count: Int64) {
generalInfoDao.update(info: .segmentsInUse, longValue: count)
segmentsInUse = count
queue.async { [weak self] in
self?.generalInfoDao.update(info: .segmentsInUse, longValue: count)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ protocol PersistentRuleBasedSegmentsStorage {
func update(toAdd: Set<RuleBasedSegment>, toRemove: Set<RuleBasedSegment>, changeNumber: Int64)
func clear()
func getChangeNumber() -> Int64

func getSegmentsInUse() -> Int64?
func setSegmentsInUse(_ segmentsInUse: Int64)
}

class DefaultPersistentRuleBasedSegmentsStorage: PersistentRuleBasedSegmentsStorage {
Expand Down Expand Up @@ -58,12 +55,4 @@ class DefaultPersistentRuleBasedSegmentsStorage: PersistentRuleBasedSegmentsStor
func getChangeNumber() -> Int64 {
return generalInfoStorage.getRuleBasedSegmentsChangeNumber()
}

func getSegmentsInUse() -> Int64? {
generalInfoStorage.getSegmentsInUse()
}

func setSegmentsInUse(_ segmentsInUse: Int64) {
generalInfoStorage.setSegmentsInUse(segmentsInUse)
}
}
44 changes: 24 additions & 20 deletions Split/Storage/RuleBasedSegments/RuleBasedSegmentsStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import Foundation

protocol RuleBasedSegmentsStorage: RolloutDefinitionsCache {
var changeNumber: Int64 { get }
var segmentsInUse: Int64 { get }

func get(segmentName: String) -> RuleBasedSegment?
func contains(segmentNames: Set<String>) -> Bool
Expand All @@ -22,28 +21,28 @@ protocol RuleBasedSegmentsStorage: RolloutDefinitionsCache {
class DefaultRuleBasedSegmentsStorage: RuleBasedSegmentsStorage {

private var persistentStorage: PersistentRuleBasedSegmentsStorage
private var generalInfoStorage: GeneralInfoStorage
private var inMemorySegments: ConcurrentDictionary<String, RuleBasedSegment>

private(set) var changeNumber: Int64 = -1

internal var segmentsInUse: Int64 = 0

init(persistentStorage: PersistentRuleBasedSegmentsStorage) {
init(persistentStorage: PersistentRuleBasedSegmentsStorage, generalInfoStorage: GeneralInfoStorage) {
self.persistentStorage = persistentStorage
self.inMemorySegments = ConcurrentDictionary()
self.generalInfoStorage = generalInfoStorage
}

func loadLocal() {
segmentsInUse = persistentStorage.getSegmentsInUse() ?? 0
var segmentsInUse: Int64 = generalInfoStorage.getSegmentsInUse() ?? 0
let snapshot = persistentStorage.getSnapshot()
let active = snapshot.segments.filter { $0.status == .active }
let archived = snapshot.segments.filter { $0.status == .archived }

_ = processToAdd(Set(active))
_ = processToRemove(Set(archived))
_ = processToAdd(Set(active), &segmentsInUse)
_ = processToRemove(Set(archived), &segmentsInUse)

changeNumber = snapshot.changeNumber
persistentStorage.setSegmentsInUse(segmentsInUse)
generalInfoStorage.setSegmentsInUse(segmentsInUse)
}

func get(segmentName: String) -> RuleBasedSegment? {
Expand All @@ -68,39 +67,40 @@ class DefaultRuleBasedSegmentsStorage: RuleBasedSegmentsStorage {

func update(toAdd: Set<RuleBasedSegment>, toRemove: Set<RuleBasedSegment>, changeNumber: Int64) -> Bool {

segmentsInUse = persistentStorage.getSegmentsInUse() ?? 0
var segmentsInUse = generalInfoStorage.getSegmentsInUse() ?? 0
self.changeNumber = changeNumber

// Process
let addResult = processToAdd(toAdd)
let removeResult = processToRemove(toRemove)
let addResult = processToAdd(toAdd, &segmentsInUse)
let removeResult = processToRemove(toRemove, &segmentsInUse)

// Update persistent storage
persistentStorage.update(toAdd: toAdd, toRemove: toRemove, changeNumber: changeNumber)
persistentStorage.setSegmentsInUse(segmentsInUse)
generalInfoStorage.setSegmentsInUse(segmentsInUse)

return addResult || removeResult
}

private func processToAdd(_ toAdd: Set<RuleBasedSegment>) -> Bool { // Process segments to add
private func processToAdd(_ toAdd: Set<RuleBasedSegment>, _ segmentsInUse: inout Int64) -> Bool { // Process segments to add
var result = false

for segment in toAdd {
if let segmentName = segment.name?.lowercased() {
updateSegmentsCount(segment)
segmentsInUse += updateSegmentsCount(segment)
inMemorySegments.setValue(segment, forKey: segmentName)
result = true
}
}

return result
}

private func processToRemove(_ toRemove: Set<RuleBasedSegment>) -> Bool { // Process segments to remove
private func processToRemove(_ toRemove: Set<RuleBasedSegment>, _ segmentsInUse: inout Int64) -> Bool { // Process segments to remove
var result = false

for segment in toRemove {
if let segmentName = segment.name?.lowercased(), inMemorySegments.value(forKey: segmentName) != nil {
updateSegmentsCount(segment)
segmentsInUse += updateSegmentsCount(segment)
inMemorySegments.removeValue(forKey: segmentName)
result = true
}
Expand All @@ -115,32 +115,36 @@ class DefaultRuleBasedSegmentsStorage: RuleBasedSegmentsStorage {
}

func forceParsing() {
segmentsInUse = persistentStorage.getSegmentsInUse() ?? 0
var segmentsInUse = generalInfoStorage.getSegmentsInUse() ?? 0
let activeSegments = persistentStorage.getSnapshot().segments.filter { $0.status == .active }

for i in 0..<activeSegments.count {
guard let segmentName = activeSegments[i].name else { continue }

if let parsedSegment = parseSegment(activeSegments[i]) { // Parse it
updateSegmentsCount(parsedSegment)
segmentsInUse += updateSegmentsCount(parsedSegment)
inMemorySegments.setValue(parsedSegment, forKey: segmentName)
}
}

persistentStorage.setSegmentsInUse(segmentsInUse)
generalInfoStorage.setSegmentsInUse(segmentsInUse)
}

fileprivate func parseSegment(_ segment: RuleBasedSegment) -> RuleBasedSegment? {
guard let parsedSegment = try? Json.decodeFrom(json: segment.json, to: RuleBasedSegment.self) else { return nil }
return parsedSegment
}

fileprivate func updateSegmentsCount(_ segment: RuleBasedSegment) {
fileprivate func updateSegmentsCount(_ segment: RuleBasedSegment) -> Int64 {
var segmentsInUse: Int64 = 0

if let segmentName = segment.name?.lowercased(), segment.status == .active, inMemorySegments.value(forKey: segmentName) == nil, StorageHelper.usesSegments(segment.conditions) {
segmentsInUse += 1
} else if inMemorySegments.value(forKey: segment.name?.lowercased() ?? "") != nil, segment.status != .active, StorageHelper.usesSegments(segment.conditions) {
segmentsInUse -= 1
}

return segmentsInUse
}

#if DEBUG
Expand Down
10 changes: 0 additions & 10 deletions Split/Storage/Splits/PersistentSplitsStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ protocol PersistentSplitsStorage {
func update(splitChange: ProcessedSplitChange)
func update(split: Split)
func update(bySetsFilter: SplitFilter?)
func update(segmentsInUse: Int64)
func getBySetsFilter() -> SplitFilter?
func getSplitsSnapshot() -> SplitsSnapshot
func getChangeNumber() -> Int64
func getUpdateTimestamp() -> Int64
func getSegmentsInUse() -> Int64?
func getAll() -> [Split]
func delete(splitNames: [String])
func clear()
Expand Down Expand Up @@ -51,10 +49,6 @@ class DefaultPersistentSplitsStorage: PersistentSplitsStorage {
func update(flagsSpec: String) {
generalInfoDao.update(info: .flagsSpec, stringValue: flagsSpec)
}

func update(segmentsInUse: Int64) {
generalInfoDao.update(info: .segmentsInUse, longValue: segmentsInUse)
}

func getFilterQueryString() -> String {
return generalInfoDao.stringValue(info: .splitsFilterQueryString) ?? ""
Expand All @@ -63,10 +57,6 @@ class DefaultPersistentSplitsStorage: PersistentSplitsStorage {
func getFlagsSpec() -> String {
return generalInfoDao.stringValue(info: .flagsSpec) ?? ""
}

func getSegmentsInUse() -> Int64? {
generalInfoDao.longValue(info: .segmentsInUse)
}

func update(bySetsFilter filter: SplitFilter?) {
guard let filter = filter else {
Expand Down
Loading
Loading