Skip to content

Fixes for Offline mode and Add stableSession mode#150

Open
madhuchavva wants to merge 11 commits intomainfrom
feature/clean-modes
Open

Fixes for Offline mode and Add stableSession mode#150
madhuchavva wants to merge 11 commits intomainfrom
feature/clean-modes

Conversation

@madhuchavva
Copy link
Contributor

@madhuchavva madhuchavva commented Mar 5, 2026

Summary

Introduces two new SDK modes to give apps precise control over when feature-flag updates are applied.

1. Offline Mode

When a pre-fetched payload is passed directly to the builder, the SDK uses it immediately — no network call, no disk round-trip. Call refreshCache() explicitly when you're ready to pick up the latest.

let featuresData: Data = ... // from your own cache, bundled file, prior API call, etc.

var sdkInstance = GrowthBookBuilder(
    apiHost: "https://cdn.growthbook.io",
    clientKey: "sdk-abc123",
    attributes: userAttributes,
    features: featuresData,           // supply pre-fetched payload
    trackingCallback: { _, _ in },
    backgroundSync: false             // no automatic background sync
)
.initializer()

// Features are immediately available — no async wait required.
let isEnabled = sdkInstance.isOn(feature: "my-feature")

// When you're ready for the latest, call refreshCache() explicitly.
// It will fetch, cache, and apply the new payload right away.
sdkInstance.refreshCache()

2. Stable Session Mode

With stableSession: true, features are locked at init and will not change for the lifetime of that SDK instance — even if refreshCache() is called or an SSE update arrives. The new payload is written to cache silently and applied on the next cold start.

var sdkInstance = GrowthBookBuilder(
    apiHost: "https://cdn.growthbook.io",
    clientKey: "sdk-abc123",
    attributes: userAttributes,
    features: featuresData,           // optional: pre-fetched fallback
    trackingCallback: { _, _ in },
    backgroundSync: false,
    stableSession: true               // lock features for this session
)
.setRefreshHandler { _ in
    // New payload has been cached but is NOT yet active.
    // It will become active on the next SDK initialization (next cold start).
    print("New features cached — will apply on next launch")
}
.initializer()

// Warm the cache in the background so the next session starts fresh.
NotificationCenter.default.addObserver(
    forName: UIApplication.didEnterBackgroundNotification,
    object: nil, queue: .main
) { _ in
    sdkInstance.refreshCache()
}

stableSession works with backgroundSync: true as well — SSE updates keep the cache warm while the running session stays stable.

Changes

  • Offline mode fix: When features: Data is provided to the builder, the SDK
    now passes the already-parsed features directly to GrowthBookSDK.init(), skipping
    the unnecessary refreshCache() call and disk round-trip. No network call is made
    on init when backgroundSync: false and features are supplied.

  • stableSession mode: New stableSession: Bool = false flag on both builder inits.
    When enabled, remote feature fetches (manual refreshCache() or SSE) are written to
    cache but not applied to the running SDK. The updated payload is picked up automatically
    on next cold start (app restart). The refreshHandler still fires so the developer
    knows a refresh occurred.

  • FeaturesViewModel: Added preloadedFeatures init param — skips the cache read in
    the constructor when features are already parsed and in memory.

  • Tests: 4 new tests covering no-network-call on init, immediate feature availability,
    stableSession blocking remote apply, and default mode still applying immediately.

@madhuchavva
Copy link
Contributor Author

cursor review

@cursor
Copy link

cursor bot commented Mar 6, 2026

Skipping Bugbot: Bugbot is disabled for this repository. Visit the Bugbot dashboard to update your settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant