Skip to content

Commit

Permalink
feat: add ability to use cache over bootstrap (#56)
Browse files Browse the repository at this point in the history
* chore: address feedback

* feat: add ability to use cache over bootstrap

* test: verify cache is used instead of bootstrap
  • Loading branch information
daniel-statsig authored Oct 16, 2024
1 parent 5d97e56 commit 46377c7
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 6 deletions.
18 changes: 13 additions & 5 deletions Sources/StatsigOnDeviceEvaluations/Statsig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -443,15 +443,23 @@ extension Statsig {
_ context: StatsigContext,
_ value: SynchronousSpecsValue
) -> Error? {
let (result, error) = parseSpecsValue(value)
let (bootstrap, error) = parseSpecsValue(value)

guard error == nil, let result = result else {
guard error == nil, let bootstrap = bootstrap else {
return error ?? StatsigError.invalidSynchronousSpecs
}


if context.options?.useNewerCacheValuesOverProvidedValues == true {
context.store.loadFromCache(context.sdkKey)

if bootstrap.response.time < context.store.getSourceInfo().lcut {
return nil
}
}

context.store.setAndCacheValues(
response: result.response,
responseData: result.raw,
response: bootstrap.response,
responseData: bootstrap.raw,
sdkKey: context.sdkKey,
source: .bootstrap
)
Expand Down
7 changes: 6 additions & 1 deletion Sources/StatsigOnDeviceEvaluations/StatsigOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@ import Foundation
* Plugin to override SDK evaluations
*/
@objc public var overrideAdapter: OverrideAdapter?


/**
* When bootstrapping (initializeSync or updateSync), set this flag if you would like to use cache values if they are "fresher" then the bootstrap values
*/
@objc public var useNewerCacheValuesOverProvidedValues: Bool = false

public override init() {
environment = StatsigEnvironment()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import Quick
import Nimble
import XCTest
import StatsigTestUtils

@testable import StatsigOnDeviceEvaluations

func getTestDcsWithTimeField(_ res: String, _ time: Int) -> NSString {
var json = TestResources.getJson(res)
json["time"] = time
return String(data: try! JSONSerialization.data(withJSONObject: json), encoding: .utf8)! as NSString
}

final class SynchronousInitTest: QuickSpec {
override class func spec() {
describe("SynchronousInit") {
let user = StatsigUser(userID: "a-user")

func primeCache() {
NetworkStubs.clearAllStubs()

NetworkStubs.stubEndpoint(
endpoint: "download_config_specs",
resource: "RulesetsDownloadConfigsSpecs"
)

let client = Statsig()
waitUntil { done in
client.initialize("client-key") { _ in done() }
}

client.shutdown()

NetworkStubs.clearAllStubs()
}

it("uses cache if newer and useNewerCacheValuesOverProvidedValues is true") {
primeCache()

let opts = StatsigOptions()
opts.useNewerCacheValuesOverProvidedValues = true

let dcs = getTestDcsWithTimeField("EmptyDcs", 123)
let client = Statsig()
let _ = client.initializeSync("client-key", initialSpecs: dcs, options: opts)

let gate = client.getFeatureGate("test_public", user)
expect(gate.evaluationDetails.reason).to(equal("Cache"))
}

it("uses bootstrap if useNewerCacheValuesOverProvidedValues is false") {
primeCache()

let dcs = getTestDcsWithTimeField("RulesetsDownloadConfigsSpecs", 123)
let client = Statsig()
let _ = client.initializeSync("client-key", initialSpecs: dcs)

let gate = client.getFeatureGate("test_public", user)
expect(gate.evaluationDetails.reason).to(equal("Bootstrap"))
}

it("uses bootstrap if newer") {
primeCache()

let opts = StatsigOptions()
opts.useNewerCacheValuesOverProvidedValues = true

let dcs = getTestDcsWithTimeField("RulesetsDownloadConfigsSpecs", Int.max)
let client = Statsig()
let _ = client.initializeSync("client-key", initialSpecs: dcs, options: opts)

let gate = client.getFeatureGate("test_public", user)
expect(gate.evaluationDetails.reason).to(equal("Bootstrap"))
}
}
}
}
20 changes: 20 additions & 0 deletions Tests/TestUtils/Resources/EmptyDcs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"dynamic_configs": [],
"feature_gates": [],
"layer_configs": [],
"id_lists": {},
"layers": {},
"has_updates": true,
"time": 1697131166636,
"company_id": "5NprLGRxV3W28hreG51Z7n",
"diagnostics": {
"initialize": 1000,
"dcs": 1000,
"download_config_specs": 1000,
"idlist": 100,
"get_id_list": 100,
"get_id_list_sources": 100,
"log": 100,
"log_event": 100
}
}

0 comments on commit 46377c7

Please sign in to comment.