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

Create RolloutCacheConfiguration #605

Merged
merged 3 commits into from
Jan 20, 2025
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
20 changes: 20 additions & 0 deletions Split.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,12 @@
C5E967432D36CB2200112DAC /* GeneralInfoStorageTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5E967422D36CB2200112DAC /* GeneralInfoStorageTest.swift */; };
C5E9674C2D36E87600112DAC /* GeneralInfoStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5E9674B2D36E87600112DAC /* GeneralInfoStorage.swift */; };
C5E9674D2D36E87600112DAC /* GeneralInfoStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5E9674B2D36E87600112DAC /* GeneralInfoStorage.swift */; };
C5E9674F2D37098000112DAC /* RolloutCacheManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5E9674E2D37098000112DAC /* RolloutCacheManager.swift */; };
C5E967502D37098000112DAC /* RolloutCacheManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5E9674E2D37098000112DAC /* RolloutCacheManager.swift */; };
C5E967522D37FA2000112DAC /* RolloutCacheConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5E967512D37FA2000112DAC /* RolloutCacheConfiguration.swift */; };
C5E967532D37FA2000112DAC /* RolloutCacheConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5E967512D37FA2000112DAC /* RolloutCacheConfiguration.swift */; };
C5E967552D37FDD500112DAC /* RolloutCacheConfigurationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5E967542D37FDD500112DAC /* RolloutCacheConfigurationTest.swift */; };
C5E967572D38013000112DAC /* GeneralInfoStorageMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5E967562D38013000112DAC /* GeneralInfoStorageMock.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -1931,6 +1937,10 @@
C5BD1E512D130FB6008EF198 /* splitchanges_toggle.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = splitchanges_toggle.json; sourceTree = "<group>"; };
C5E967422D36CB2200112DAC /* GeneralInfoStorageTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralInfoStorageTest.swift; sourceTree = "<group>"; };
C5E9674B2D36E87600112DAC /* GeneralInfoStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralInfoStorage.swift; sourceTree = "<group>"; };
C5E9674E2D37098000112DAC /* RolloutCacheManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RolloutCacheManager.swift; sourceTree = "<group>"; };
C5E967512D37FA2000112DAC /* RolloutCacheConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RolloutCacheConfiguration.swift; sourceTree = "<group>"; };
C5E967542D37FDD500112DAC /* RolloutCacheConfigurationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RolloutCacheConfigurationTest.swift; sourceTree = "<group>"; };
C5E967562D38013000112DAC /* GeneralInfoStorageMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralInfoStorageMock.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -2150,6 +2160,7 @@
95715A8029D22C1B00A1B2F9 /* SplitEncryptionLevel.swift */,
95DAF21A29DDFAF4001C7BBE /* SplitHttpsAuthenticator.swift */,
95F7BC222C3876C800C5F2E4 /* SplitCertPinningAuthenticator.swift */,
C5E967512D37FA2000112DAC /* RolloutCacheConfiguration.swift */,
);
path = Api;
sourceTree = "<group>";
Expand Down Expand Up @@ -2590,6 +2601,7 @@
954F9C6F25795CD300140B81 /* SplitsStorageStub.swift */,
95B17FF4275EAA6F002DC9DF /* InMemoryTelemetryStorageTest.swift */,
95715A9629DB16A000A1B2F9 /* SecureStorageStub.swift */,
C5E967562D38013000112DAC /* GeneralInfoStorageMock.swift */,
);
path = Storage;
sourceTree = "<group>";
Expand Down Expand Up @@ -3077,6 +3089,7 @@
children = (
95EEF7C6270E16ED00761B9D /* SplitComponentFactory.swift */,
952FA12A2A2E593900264AB5 /* SplitComponentCatalog.swift */,
C5E9674E2D37098000112DAC /* RolloutCacheManager.swift */,
);
path = Initialization;
sourceTree = "<group>";
Expand Down Expand Up @@ -3367,6 +3380,7 @@
95ABF4B7292FF451006ED016 /* ConfigObjcTest.m */,
95ABF4B9293003C1006ED016 /* ConfigTest.swift */,
95B0A99F2BC6B72200C31A9E /* SplitClientTests.swift */,
C5E967542D37FDD500112DAC /* RolloutCacheConfigurationTest.swift */,
);
path = Init;
sourceTree = "<group>";
Expand Down Expand Up @@ -3929,6 +3943,7 @@
95CED0362B459A10005E3C34 /* LocalhostSynchronizer.swift in Sources */,
9505682426836B20001D7B10 /* ImpressionsCountRecorder.swift in Sources */,
3B6DEF3020EA6AE50067435E /* Evaluator.swift in Sources */,
C5E967502D37098000112DAC /* RolloutCacheManager.swift in Sources */,
598EDE78224BB3E9005D4762 /* InternalSplitClient.swift in Sources */,
95D9446D283BF76A00D7FFED /* UniqueKeysRecorderWorker.swift in Sources */,
952FA1242A2A5D4D00264AB5 /* FeatureFlagsSynchronizer.swift in Sources */,
Expand All @@ -3944,6 +3959,7 @@
955E123F2BFE1E7A00AE6D10 /* HashedImpressionStorage.swift in Sources */,
3B6DEF3A20EA6AE50067435E /* Dictionary+Extensions.swift in Sources */,
95125625276B72B60091895B /* Stopwatch.swift in Sources */,
C5E967522D37FA2000112DAC /* RolloutCacheConfiguration.swift in Sources */,
957E67B025F6B3E1006F5B19 /* BackgroundSyncWorker.swift in Sources */,
3B6DEF2620EA6AE50067435E /* SplitClientConfig.swift in Sources */,
95825BD8271F4E3700A0CDAD /* Bundle+Name.swift in Sources */,
Expand Down Expand Up @@ -4223,6 +4239,7 @@
59B2043924F5667A0092F2E9 /* SseNotificationProcessorTest.swift in Sources */,
592C6AC6211B718E002D120C /* SplitEventsManagerTest.swift in Sources */,
95C7569D2696457500696148 /* NotificationHelperStub.swift in Sources */,
C5E967572D38013000112DAC /* GeneralInfoStorageMock.swift in Sources */,
952FA12F2A2F6E4D00264AB5 /* SyncGuardianStub.swift in Sources */,
95F3EFFE258D3C8600084AF8 /* EventsRecorderWorkerTests.swift in Sources */,
955B5960280DF75E00D105CD /* MySegmentsPayloadDecoderTest.swift in Sources */,
Expand Down Expand Up @@ -4277,6 +4294,7 @@
59F4AAA82508120500A1C69A /* SyncManagerTest.swift in Sources */,
5919017B24A27629005BD12A /* EndpointTest.swift in Sources */,
5959C479227B89980064F968 /* FactoryRegistryTest.swift in Sources */,
C5E967552D37FDD500112DAC /* RolloutCacheConfigurationTest.swift in Sources */,
595AD21524E1CD4700A7B750 /* JwtTokenParserTest.swift in Sources */,
9573FB37273D762200086DDE /* AnyValueValidatorTests.swift in Sources */,
95ED4A9826497EEA00FD3569 /* TestSplitFactory.swift in Sources */,
Expand Down Expand Up @@ -4642,6 +4660,7 @@
95B02CED28D0BDC20030EC8B /* MatcherGroup.swift in Sources */,
95CED0502B4DCDB1005E3C34 /* LocalhostClientManager.swift in Sources */,
95B02CEE28D0BDC20030EC8B /* MatcherProtocol.swift in Sources */,
C5E9674F2D37098000112DAC /* RolloutCacheManager.swift in Sources */,
95B02CEF28D0BDC20030EC8B /* MatcherType.swift in Sources */,
95B02CF028D0BDC20030EC8B /* Segment.swift in Sources */,
95B02CF128D0BDC20030EC8B /* Status.swift in Sources */,
Expand All @@ -4663,6 +4682,7 @@
95B02CFF28D0BDC20030EC8B /* SplitClientManager.swift in Sources */,
C5E9674D2D36E87600112DAC /* GeneralInfoStorage.swift in Sources */,
95B02D0028D0BDC20030EC8B /* SplitComponentFactory.swift in Sources */,
C5E967532D37FA2000112DAC /* RolloutCacheConfiguration.swift in Sources */,
95B02D0128D0BDC20030EC8B /* SplitApiFacade.swift in Sources */,
95B02D0228D0BDC20030EC8B /* SplitFactory.swift in Sources */,
952FA1392A33778500264AB5 /* SyncGuardian.swift in Sources */,
Expand Down
57 changes: 57 additions & 0 deletions Split/Api/RolloutCacheConfiguration.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import Foundation

/// Configuration class for rollout cache.
@objc public class RolloutCacheConfiguration: NSObject {
private(set) var expirationDays: Int
private(set) var clearOninit: Bool

init(expirationDays: Int, clearOnInit: Bool) {
self.expirationDays = expirationDays
self.clearOninit = clearOnInit
}

/// Provides abuilder for RolloutCacheConfiguration.
@objc(builder)
public static func builder() -> Builder {
return Builder()
}

@objc(RolloutCacheConfigurationBuilder)
public class Builder: NSObject {
private let kMinExpirationDays = 1

private var expiration = ServiceConstants.defaultRolloutCacheExpiration
private var clearOnInit = false

@objc
public func build() -> RolloutCacheConfiguration {
return RolloutCacheConfiguration(expirationDays: expiration, clearOnInit: clearOnInit)
}

/// Set the expiration time for the rollout definitions cache, in days. Default is 10 days.
/// - Parameter expirationDays: The expiration time in days.
/// - Returns: This builder.
@discardableResult
@objc(setExpirationDays:)
public func set(expirationDays: Int) -> Builder {
if expirationDays < kMinExpirationDays {
Logger.w("Cache expiration must be at least 1 day. Using default value.")
expiration = ServiceConstants.defaultRolloutCacheExpiration
} else {
expiration = expirationDays
}

return self
}

/// Set if the rollout definitions cache should be cleared on initialization. Default is false.
/// - Parameter clearOnInit: If the cache should be cleared on initialization.
/// - Returns: This builder.
@discardableResult
@objc(setClearOnInit:)
public func set(clearOnInit: Bool) -> Builder {
self.clearOnInit = clearOnInit
return self
}
}
}
3 changes: 2 additions & 1 deletion Split/Common/ServiceConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ struct ServiceConstants {
static var maxSyncPeriodInMillis: Int64 {
return values?.maxSyncPeriodInMillis ?? (defaultSseConnectionDelayInSecs * 1000)
}

static let defaultSegmentsChangeNumber: Int64 = -1
// Created for testing purposes only
struct Values {
Expand All @@ -51,4 +51,5 @@ struct ServiceConstants {
static let defaultMlsTimeMillis: Int64 = 60000
static let defaultMlsHash = 1
static let defaultMlsSeed = 0
static let defaultRolloutCacheExpiration = 10 // days
}
24 changes: 24 additions & 0 deletions Split/Initialization/RolloutCacheManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Foundation

protocol RolloutCacheManager {
func validateCache(listener: (() -> Void)?)
}

class DefaultRolloutCacheManager: RolloutCacheManager {
private let kMinCacheClearDays = 1
private let generalInfoStorage: GeneralInfoStorage
private let splitsStorage: SplitsStorage
private let mySegmentsStorage: MySegmentsStorage
private let myLargeSegmentsStorage: MySegmentsStorage

init(generalInfoStorage: GeneralInfoStorage, splitsStorage: SplitsStorage, mySegmentsStorage: MySegmentsStorage, myLargeSegmentsStorage: MySegmentsStorage) {
self.generalInfoStorage = generalInfoStorage
self.splitsStorage = splitsStorage
self.mySegmentsStorage = mySegmentsStorage
self.myLargeSegmentsStorage = myLargeSegmentsStorage
}

func validateCache(listener: (() -> Void)?) {
// TODO: implementation
}
}
25 changes: 25 additions & 0 deletions SplitTests/Fake/Storage/GeneralInfoStorageMock.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Foundation
@testable import Split

class GeneralInfoStorageMock: GeneralInfoStorage {

let queue = DispatchQueue(label: "test", target: .global())
var updateTimestamp: Int64 = 0
var rolloutCacheLastClearTimestamp: Int64 = 0

func getUpdateTimestamp() -> Int64 {
return updateTimestamp
}

func setUpdateTimestamp(timestamp: Int64) {
updateTimestamp = timestamp
}

func getRolloutCacheLastClearTimestamp() -> Int64 {
return rolloutCacheLastClearTimestamp
}

func setRolloutCacheLastClearTimestamp(timestamp: Int64) {
rolloutCacheLastClearTimestamp = timestamp
}
}
3 changes: 2 additions & 1 deletion SplitTests/Helpers/TestingHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ struct TestingHelper {
uniqueKeyStorage: PersistentUniqueKeyStorageStub(),
flagSetsCache: FlagSetsCacheMock(),
persistentHashedImpressionsStorage: PersistentHashedImpressionStorageMock(),
hashedImpressionsStorage: HashedImpressionsStorageMock())
hashedImpressionsStorage: HashedImpressionsStorageMock(),
generalInfoStorage: GeneralInfoStorageMock())
}

static func createApiFacade() -> SplitApiFacade {
Expand Down
26 changes: 26 additions & 0 deletions SplitTests/Init/RolloutCacheConfigurationTest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import XCTest
@testable import Split

final class RolloutCacheConfigurationTest: XCTestCase {

func testDefaultValues() throws {
let config = RolloutCacheConfiguration.builder().build()
XCTAssertEqual(config.expirationDays, 10)
XCTAssertFalse(config.clearOninit)
}

func testExpirationIsCorrectlySet() throws {
let config = RolloutCacheConfiguration.builder().set(expirationDays: 1).build()
XCTAssertEqual(config.expirationDays, 1)
}

func testClearOnInitIsCorrectlySet() throws {
let config = RolloutCacheConfiguration.builder().set(clearOnInit: true).build()
XCTAssertTrue(config.clearOninit)
}

func testNegativeExpirationIsSetToDefault() throws {
let config = RolloutCacheConfiguration.builder().set(expirationDays: -1).build()
XCTAssertEqual(config.expirationDays, 10)
}
}
3 changes: 2 additions & 1 deletion SplitTests/Streaming/FeatureFlagsSynchronizerTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ class FeatureFlagsSynchronizerTest: XCTestCase {
uniqueKeyStorage: PersistentUniqueKeyStorageStub(),
flagSetsCache: FlagSetsCacheMock(),
persistentHashedImpressionsStorage: PersistentHashedImpressionStorageMock(),
hashedImpressionsStorage: HashedImpressionsStorageMock())
hashedImpressionsStorage: HashedImpressionsStorageMock(),
generalInfoStorage: GeneralInfoStorageMock())

splitConfig = SplitClientConfig()
splitConfig.syncEnabled = syncEnabled
Expand Down
3 changes: 2 additions & 1 deletion SplitTests/Streaming/ImpressionsTrackerTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,8 @@ class ImpressionsTrackerTest: XCTestCase {
uniqueKeyStorage: PersistentUniqueKeyStorageStub(),
flagSetsCache: flagSetsCache,
persistentHashedImpressionsStorage: PersistentHashedImpressionStorageMock(),
hashedImpressionsStorage: HashedImpressionsStorageMock())
hashedImpressionsStorage: HashedImpressionsStorageMock(),
generalInfoStorage: GeneralInfoStorageMock())

let apiFacade = try! SplitApiFacade.builder()
.setUserKey("userKey")
Expand Down
3 changes: 2 additions & 1 deletion SplitTests/Streaming/SynchronizerTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ class SynchronizerTest: XCTestCase {
uniqueKeyStorage: PersistentUniqueKeyStorageStub(),
flagSetsCache: flagSetsCache,
persistentHashedImpressionsStorage: PersistentHashedImpressionStorageMock(),
hashedImpressionsStorage: HashedImpressionsStorageMock())
hashedImpressionsStorage: HashedImpressionsStorageMock(),
generalInfoStorage: GeneralInfoStorageMock())

splitConfig = SplitClientConfig()
splitConfig.syncEnabled = syncEnabled
Expand Down
3 changes: 2 additions & 1 deletion SplitTests/TreatmentManagerTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ class TreatmentManagerTest: XCTestCase {
uniqueKeyStorage: PersistentUniqueKeyStorageStub(),
flagSetsCache: flagSetsCache,
persistentHashedImpressionsStorage: PersistentHashedImpressionStorageMock(),
hashedImpressionsStorage: HashedImpressionsStorageMock())
hashedImpressionsStorage: HashedImpressionsStorageMock(),
generalInfoStorage: GeneralInfoStorageMock())
}
}

Expand Down