Skip to content

Commit

Permalink
feat: revert canges to calculated updated keys
Browse files Browse the repository at this point in the history
  • Loading branch information
ioannisj committed Nov 7, 2024
1 parent 315d42c commit 646864f
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 175 deletions.
36 changes: 20 additions & 16 deletions PostHog.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1277,11 +1277,11 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = PostHogExample/PostHogExample.entitlements;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"PostHogExample/Preview Content\"";
DEVELOPMENT_TEAM = PNC2XCH2XP;
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "$(PRODUCT_NAME)";
Expand All @@ -1296,6 +1296,7 @@
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.posthog.PostHogExample;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
Expand All @@ -1312,11 +1313,11 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = PostHogExample/PostHogExample.entitlements;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"PostHogExample/Preview Content\"";
DEVELOPMENT_TEAM = PNC2XCH2XP;
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "$(PRODUCT_NAME)";
Expand All @@ -1331,6 +1332,7 @@
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.posthog.PostHogExample;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
Expand Down Expand Up @@ -1562,10 +1564,10 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = PNC2XCH2XP;
DEVELOPMENT_TEAM = "";
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
Expand All @@ -1577,6 +1579,7 @@
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.posthog.PostHogTests;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx watchos watchsimulator";
SUPPORTS_MACCATALYST = YES;
SWIFT_EMIT_LOC_STRINGS = NO;
Expand All @@ -1594,10 +1597,10 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = PNC2XCH2XP;
DEVELOPMENT_TEAM = "";
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
Expand All @@ -1609,6 +1612,7 @@
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.posthog.PostHogTests;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx watchos watchsimulator";
SUPPORTS_MACCATALYST = YES;
SWIFT_EMIT_LOC_STRINGS = NO;
Expand All @@ -1629,7 +1633,7 @@
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = PNC2XCH2XP;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = PostHogObjCExample/Info.plist;
Expand Down Expand Up @@ -1664,7 +1668,7 @@
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = PNC2XCH2XP;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = PostHogObjCExample/Info.plist;
Expand Down Expand Up @@ -1700,7 +1704,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"PostHogExampleTvOS/Preview Content\"";
DEVELOPMENT_TEAM = PNC2XCH2XP;
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
Expand Down Expand Up @@ -1733,7 +1737,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"PostHogExampleTvOS/Preview Content\"";
DEVELOPMENT_TEAM = PNC2XCH2XP;
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
Expand Down Expand Up @@ -1768,7 +1772,7 @@
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"PostHogExampleMacOS/Preview Content\"";
DEVELOPMENT_TEAM = PNC2XCH2XP;
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
Expand Down Expand Up @@ -1803,7 +1807,7 @@
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"PostHogExampleMacOS/Preview Content\"";
DEVELOPMENT_TEAM = PNC2XCH2XP;
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
Expand Down Expand Up @@ -1832,7 +1836,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = PNC2XCH2XP;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = PostHogExampleStoryboard/Info.plist;
Expand Down Expand Up @@ -1865,7 +1869,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = PNC2XCH2XP;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = PostHogExampleStoryboard/Info.plist;
Expand Down
83 changes: 15 additions & 68 deletions PostHog/PostHogFeatureFlags.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class PostHogFeatureFlags {
distinctId: String,
anonymousId: String,
groups: [String: String],
callback: @escaping (Set<String>) -> Void
callback: @escaping () -> Void
) {
loadingLock.withLock {
if self.loadingFeatureFlags {
Expand All @@ -99,9 +99,9 @@ class PostHogFeatureFlags {
else {
hedgeLog("Error: Decide response missing correct featureFlags format")

callback([])
self.notifyAndRelease()

return self.notifyAndRelease()
return callback()
}
let errorsWhileComputingFlags = data?["errorsWhileComputingFlags"] as? Bool ?? false

Expand All @@ -127,44 +127,25 @@ class PostHogFeatureFlags {
#endif

self.featureFlagsLock.withLock {
let cachedFeatureFlags = self.getCachedFeatureFlags() ?? [:]
let cachedFeatureFlagsPayloads = self.getCachedFeatureFlagPayload() ?? [:]
if errorsWhileComputingFlags {
let cachedFeatureFlags = self.getCachedFeatureFlags() ?? [:]
let cachedFeatureFlagsPayloads = self.getCachedFeatureFlagPayload() ?? [:]

let newFeatureFlags: [String: Any]
let newFeatureFlagPayloads: [String: Any]
let newFeatureFlags = cachedFeatureFlags.merging(featureFlags) { _, new in new }
let newFeatureFlagsPayloads = cachedFeatureFlagsPayloads.merging(featureFlagPayloads) { _, new in new }

if errorsWhileComputingFlags {
// if not all flags were computed, we upsert flags instead of replacing them
newFeatureFlags = cachedFeatureFlags.merging(featureFlags) { _, new in new }
newFeatureFlagPayloads = cachedFeatureFlagsPayloads.merging(featureFlagPayloads) { _, new in new }
self.setCachedFeatureFlags(newFeatureFlags)
self.setCachedFeatureFlagPayload(newFeatureFlagsPayloads)
} else {
newFeatureFlags = featureFlags
newFeatureFlagPayloads = featureFlagPayloads
}

self.setCachedFeatureFlags(newFeatureFlags)
self.setCachedFeatureFlagPayload(newFeatureFlagPayloads)

// calculate a set of keys that were updated, added or removed
//
// Note: payload changes are not currently tracked, as this update mechanism
// is primarily used for capturing `$feature_flag_called` events tied to flag values.
let newKeys = Set(newFeatureFlags.keys)
let cachedKeys = Set(cachedFeatureFlags.keys)
let addedKeys = newKeys.subtracting(cachedKeys)
let removedKeys = cachedKeys.subtracting(newKeys)
let updatedKeys = cachedKeys.intersection(newKeys).filter {
if let cached = cachedFeatureFlags[$0], let new = newFeatureFlags[$0] {
return !areEqual(cached, new)
}
return false
self.setCachedFeatureFlags(featureFlags)
self.setCachedFeatureFlagPayload(featureFlagPayloads)
}
let allUpdatedKeys = removedKeys.union(addedKeys).union(updatedKeys)

callback(allUpdatedKeys)
}

return self.notifyAndRelease()
self.notifyAndRelease()

return callback()
}
}
}
Expand Down Expand Up @@ -271,37 +252,3 @@ class PostHogFeatureFlags {
}
#endif
}

/// Compares two optional `Any` values for equality, best effort
private func areEqual(_ lhs: Any?, _ rhs: Any?) -> Bool {
guard let lhs, let rhs else { return false }

// assume here that different types cannot be equal
guard type(of: lhs) == type(of: rhs) else { return false }

// AnyHashable is handy here. Most types should conform to this
if let lhs = lhs as? AnyHashable, let rhs = rhs as? AnyHashable {
return lhs == rhs
}

// Equatable types is a good next candidate
if let lhs = lhs as? (any Equatable), let rhs = rhs as? (any Equatable) {
return lhs.isEqual(rhs)
}

// Equatable types is a good next candidate
if let lhs = lhs as? NSObject, let rhs = rhs as? NSObject {
return lhs == rhs
}

return false
}

private extension Equatable {
func isEqual(_ other: any Equatable) -> Bool {
guard let other = other as? Self else {
return false
}
return self == other
}
}
31 changes: 20 additions & 11 deletions PostHog/PostHogSDK.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ let maxRetryDelay = 30.0
private let setupLock = NSLock()
private let optOutLock = NSLock()
private let groupsLock = NSLock()
private let featureFlagsLock = NSLock()
private let personPropsLock = NSLock()

private var queue: PostHogQueue?
Expand Down Expand Up @@ -345,7 +346,9 @@ let maxRetryDelay = 30.0
// storage also removes all feature flags
storage?.reset()
config.storageManager?.reset()
flagCallReported.removeAll()
featureFlagsLock.withLock {
flagCallReported.removeAll()
}
PostHogSessionManager.shared.endSession {
self.resetViews()
}
Expand Down Expand Up @@ -791,8 +794,10 @@ let maxRetryDelay = 30.0
distinctId: storageManager.getDistinctId(),
anonymousId: storageManager.getAnonymousId(),
groups: groups ?? [:],
callback: { updatedKeys in
self.flagCallReported.subtract(updatedKeys)
callback: {
self.featureFlagsLock.withLock {
self.flagCallReported.removeAll()
}
callback()
}
)
Expand Down Expand Up @@ -847,15 +852,17 @@ let maxRetryDelay = 30.0
}

private func reportFeatureFlagCalled(flagKey: String, flagValue: Any?) {
if !flagCallReported.contains(flagKey) {
let properties: [String: Any] = [
"$feature_flag": flagKey,
"$feature_flag_response": flagValue ?? "",
]
featureFlagsLock.withLock {
if !flagCallReported.contains(flagKey) {
let properties: [String: Any] = [
"$feature_flag": flagKey,
"$feature_flag_response": flagValue ?? "",
]

flagCallReported.insert(flagKey)
flagCallReported.insert(flagKey)

capture("$feature_flag_called", properties: properties)
capture("$feature_flag_called", properties: properties)
}
}
}

Expand Down Expand Up @@ -929,7 +936,9 @@ let maxRetryDelay = 30.0
self.reachability?.stopNotifier()
reachability = nil
#endif
flagCallReported.removeAll()
featureFlagsLock.withLock {
flagCallReported.removeAll()
}
context = nil
PostHogSessionManager.shared.endSession {
self.resetViews()
Expand Down
Loading

0 comments on commit 646864f

Please sign in to comment.