Skip to content

Commit

Permalink
Release 5.4.1 (#244)
Browse files Browse the repository at this point in the history
* Reset lastKnownFlagValidity to nil when we make a successful stream connection

* Made comment about lastKnownFlagValidity having a value more clear

* Changed guard let to if let in DarklyService EventSource extension

* Updated README, CHANGELOG, and podspec for 4.2.0

* [4.2.1] - 2019-11-15 (#81)

* Added 4.2.1 changes including Dictionary fix and test and eventsource version bump

* Added Carthage build files

* Added attribution to CHANGELOG

* Evaluation Reasons (#82)

* Initial Evaluation Reasons prototype

* Changed evaluationReasons to reasons, fixed mangled question mark in url query parameters

* Added errorKinds

* Added reason to debug events

* Changed reason nil handling in events

* Removed unnecessary private functions, removed event nil coalesce

* Event change for reason nil

* Removed if in Event for reason nil, added guard let NSNull for dictionary in Events

* Added reason null to normal variation calls

* Testing alternate reason null set

* Change Event comparison code to add reason

* Removed reason from event dictionary matches

* Removed Event Equatable reason and changed Event Dictionary matches

* Explicitly set featureflag reason property to nil when not send feature event for variationDetail

* Fixed DeprecatedCacheModel unit tests, added v6 model tests, added variation detail unit tests, changed event reason nil check

* Added variationDetail to objective c, fixed cache converter unit tests, deprecated variationAndSource

* Added new files to correct target membership

* Simplify featureflag reason nil check

* Removed unnecessary comments, deprecated objc variationAndSource

* Improved doc strings, cut down on variation doc string repetition, added reason tests for Event and EventReporter, added EvaluationDetail generic

* Added ObjCEvaluationDetail to correct target membership

* Differentiated objc evaluation detail return type, change reason constant in unit tests

* Removed Optional value on fallback variation

* Added Event test for reason false but flag reason present, cleaned up objc doc strings, changed optional types in objc evaluation detail

* Experimentation 1.5 (#83)

* Added trackReasons and metricValue as well as doc and unit tests

* Added unit tests for reason false track reason true, added objc track without metricValue, changed and trackReason to or trackReason

* Added explicit event store reason test

* Fixed objc track comment

* Updated reason to includeReason for clarity

* Explicitly check both feature and debug events

* Prepare version 4.3.0

* Update ios-eventsource to 4.1.0 (#84)

* Updated ios-eventsource to 4.1.0, updated version strings

* Added sentence about iOS SDK compat to CHANGELOG

* pod repo update to get new eventsource version

* Fixed change listener not firing when only value changes (#85)

* Fixed change listener not firing when only value changes

* Fixed a unit test variable name typo

* Cast flag value to dictionary instead of string, improved unit test

* Remove debug printout, remove unnecessary parameter

* Updated CHANGELOG, README, and podspec for 4.3.2

* Adds startAwaitingFlags function (#86)

* Added newStart function, updated README, podspec, and CHANGELOG

* Changed newStart to startAwaitingFlags

* Added doc strings for startAwaitingFlags and deprecated start

* Added cocoapods lib lint flag to ignore depracted API usage in ObjCLDClient, added startAwaitingFlags to ObjC

* Fixed alow to allow, changed startAwaitFlags to startCompleteWhenFlagsReceived, added unit tests for startCompleteWhenFlagsReceived

* Updated deprecation message to startCompleteWhenFlagsReceived

* [ch61092] Add X-LaunchDarkly-Payload-ID to event request headers (#87)

* Added X-LaunchDarkly-Payload-ID header to event request headers, add string length check on LD payload ID header in header unit tests

* Added CHANGELOG Added entry for event request header

* Added UUID generation to DarklyService so it's regenerated on each request

* Change CHANGELOG entry for new header to match other SDKs

* Added single retry attempt to event post (#88)

* Added single retry attempt to event post

* Added payloadId to the correct point to maintain value between retries, retry on error

* reportSyncComplete on 2nd error, always log on event post error, add 1 second delay with log on event post retry

* Added 1 second delay to retry event post

* async'd event post to prevent blocking main thread on retry sleep

* Increased event test waitUntil timeout to 10 seconds

* Bumped patch version, added CHANGELOG for 4.4.1

* Changed 4.4.1 entry

* Further 4.4.1 entry revision

* Changed retry event post for loop to function call (#89)

* [ch65670] Fix Xcode 11.4 build and unit tests (#90)

* Fixed build errors, fixed some unit tests

* Added shell script to remove duplicate sourcery method mock

* sed now matches specific pattern instead of line numbers

* Add project config file containing run script step

* Bump CircleCI Xcode to 11.4

* Bump CircleCI Xcode to 11.4.0

* Changed iPhone simulator in CircleCI from XS to Xs

* Changed CircleCI xcodebuild from OS:latest to OS:12.4

* Testing NSURLRetryPolicy on CI

* Removed DeprecatedCache from automock

* Fix FlagStore to synchronize reads with writes.

* multi env: init, config, client methods, and ObjCLDClient

* Remove accidentally checked in IDE file

* Add xcode compatibility information to readme (#93)

* Add xcode compatibility information to readme (#93)

* Fixed comments, added flush to close, started migrating unit tests

* Added multi environment methods to ObjCLDClient, added better comments for said methods

* Changed init completion behavior for correct ordering, removed deprecated variationAndSource methods, more unit test changes

* Added primary instance to instances, fixed completion behavior

* Made UserEnvironmentFlagCache shared between instances, made FlagSynchronizer DispatchQueue not static

* Fixed user clobbering by deep copying FlagStore

* Fix for concurrency bug exposed by restwrapper. (#94)

* General cleanup. (#92)

* [ch75316] Added maxCachedUsers to LDConfig and UserEnvironmentFlagCache (#96)

* Added maxCachedUsers to LDConfig and UserEnvironmentFlagCache

* Changed specific -1 to 0

* Added unlimited users tests

* Added CHANGELOG for 4.6

* Added maxCachedUsers to objc LDConfig (#97)

* Changed version to 4.6.0

* [ch66864] Added startCompleteWhenFlagsReceivedTimeout (#98)

* Added startCompleteWhenFlagsReceivedTimeout which allows a timeout in seconds to be given for the completion to be fired indicating that flags have been received

* Fixed doc typo, removed bad ms to second conversion

* Fix previous doc typo that got copied into objc

* Added serial queue to timeOutCheck to fix possible race condition

* Simplified unit tests by swapping if for assertion

* Simplified start timeout method name, fixed doc about timedOut return

* Moved DispatchQueue off of main

* Moved sync dispatchqueue from variable to func

* Changed labeled queue to global queue

* Added test for start timeout timing out, added doc note about start timeout and starting offline

* [ch70792] Swift EventSource (#99)

* Integrating Swift eventsource.

* No longer set `-sdk` on `xcodebuild` commands for circle. There seems
to be some sort of interaction between `-sdk` or `SDKROOT` and the
implicit dependency resolution system. Since Xcode 10.2, Xcode can
find implicit dependencies in `OTHER_LINKER_FLAGS` such as when
Cocoapods links a framework with `-F`. When `SDKROOT` is not set, this
doesn't conflict with anything, but I believe the behavior of finding
the framework as an implicit dependency is not required (I think it
just resolves to the same target Cocoapods is building). If `SDKROOT`
is set, xcodebuild seems to decide that it must first resolve and
build the framework. It gives the warning "Multiple targets match
implicit dependency for linker flags '-framework LDSwiftEventSource'",
as LDSwiftEventSource generates a product by the same name
(`LDSwiftEventSource.framework`) regardless of the platform/sdk being
built. Now apparently it completely forgets about the set `SDKROOT`
(which normally seems to be fed through and used to resolve the target
being built) and decides that it should build the iOS target (no idea
why, it's not even the default `SDKROOT` for
`LDSwiftEventSource`). When `SDKROOT` is set to `macosx`, `xcodebuild`
proceeds to simultaneously build both the iOS and macOS targets (I
believe the macOS target is from Cocoapods operating correctly), then
fails as it's still actually building the iOS target with the macOS
SDK configuration. The actual build error is that the
'LDSwiftEventSource-iOS-umbrella.h' header can't find 'UIKit/UIKit.h'
as UIKit is not available on macOS.

* Update LDSwiftEventSource to 0.3.0, handle some minor todos.

* This updates the circle config to actually do a `pod install`. Removes
Gemfile that was for CocoaPods.

* Specify sources for pod spec lint.

* I think spec lint tries to test the spec file against code on the
master branch, so only run a spec lint if commit is on master.

* Allow warnings for now.

* Bump version to 4.7.0 and add CHANGELOG

* Changed startWaitSeconds type signature from Int to TimeInterval

* Changed startWaitSeconds doc string type to TimeInterval

* Clarified 4.7.0 CHANGELOG

* Fixed no log output when isDebugMode = true

* Fixed old EventSource still sticking around, removed default to fix compiler warning

* Added startWaitSeconds to start, added more debug logging, added flagsynchronizer config.streamingMode

* Fixed LDClient offline by putting internalIdentify in an async DispatchQueue, removed print statements

* Unit tests build but LDClientSpec crashes

* [ch72204] drop events after failed retry (#100)

* Drop events after failed retry, as well as some general cleanup and
consistency changes.

* Don't disabled event reporting in background.

* Added ClientServiceFactory back to init

* Throttler mock isn't firing, migrating unit tests to TestContext init pattern

* [ch61747] Diagnostic events (#101)

* Start specs build and run but fail

* Removed public set LDClient.config, added more failing specs, removed prints

* Removed convenience init flagSynchronizer set to avoid malloc error, all but 2 LDClient specs build and run

* All LDClient specs build and run

* Fixed LDClient spec flagstore mock being replaced

* Remove EventTrackingContext

* Added config didSet back to init, removed outdated tests

* Removed outdated tests for client not started, fixed some incorrectly ported tests

* Fix more LDClient unit tests failures

* Remove EventTrackingContext (#102)

* Remove DeprecatedCacheModelV6, which was never needed.

* A bit of cleanup.

* Update some old comments.

* Update diagnostic events to include count of secondary mobile keys.

* Added waitUntil to internalIdentify calls to fix timing issue in some tests

* Added setOnline for background tests, removed unnecessary runMode parameter on test start

* set hasStarted false for starting tests

* Fixed static timeOutCheck not being reset, trigger service didSet for pollingInterval tests

* Added secondaryMobileKeys to ObjCLDConfig, change Array<String>? to [String]?, changed getEnvNames return, removed unnecessary returns in ClientServiceFactory, changed to internalSetOnline in close

* Set instances to nil after loop in close

* Remove UUID queue labels

* Forgot empty FlagStore init

* Added waitUntil to identify to fix Circle timing

* Only internal ObjC methods can set the ObjCLDClient.ldClient

* Moved all internalIdentify calls to waitUntil to fix Circle timing

* Make config public private(set)

* Added debug method to set config allUserAttributesPrivate

* Make testing allUserAttributesPrivate method public

* Move setAllUserAttributesPrivate to public

* Attempted timing fix for Circle

* Lowered timeout with troublesome test

* Troublesome test false to true

* Try synchronized instead of DispatchQueue.sync

* Change sync queue and if ordering in start timeout

* Forgot to add to testing version

* Removed spurious changes from FlagSynchronizer and FlagStore

* Try synced with if change start timeout

* Changed setAllUserAttributesPrivate to apply to all instances, changed setOnline to internalSetOnline in configDidSet

* Changed LDClient internal setOnline calls to internalSetOnline

* Removed synced, added serial queues to identify and setonline

* Removed true check in start timeout

* Test removing serial queue from setOnline and identify

* Change serial queues in setOnline and identify to sync

* Move if outside sync serial queue in start timeout

* Move if back inside serial queue but make queue async start timeout

* remove static from internal method queues

* Add secondaryMobileKeys to convertCacheData

* Switched global to main queue in start timeout

* Try name queue instead of main in start timeout

* Remove internalIdentifyQueue

* Changed named queue back to global, added back InternalIdentifyQueue, changed CircleCi simulator from iOS 12.4 to 13.4

* Change iOS 13.4 to 13.4.1 in Circle

* Change iOS simulator from Xs to iPhone 11 Pro Max

* Updating to iOS 13.4.1 on Circle fix disparity between DarklyServiceSpec on local vs Circle

* Removed static from timeOutCheck and queue and made them function scope variables

* Made main queues named queues in LDClientSpec

* Explicitly turn off parallel testing on Circle

* Added waitUntil with asyncAfter to setRunMode and background notification

* Changed all asyncAfter deadlines to 0.2

* Passes thread sanitizer locally

* More thread sanitizer finds

* Fixed recursive sync queues in EventReporter and FlagSynchronizer

* Improve Throttler code.

* Hopefully fix sync queue crash in FlagChangeNotifier.

* I don't think we actually want to loop through converting all
environment cache data here.

* changed internalIdentifyQueue to sync, added sync queue to internalSetOnline

* PR feedback, removed convenience init

* Fixed onSuccess tests

* Removes isStarting variable, to make initialization more clear.

* Removes all remaining LDFlagSource code.

* Fix logging of type conversion errors.

* Update more code doc for multi-environment branch changes.

* Remove unnecessary objc class and improve interface for type
mismatches on changed flag handlers.

* Prefer `is` to `as != nil`.

* Use DispatchGroup for static loops.

* Make time constraint a bit more lenient for more reliable CircleCI
tests.

* Add a threshold for testing delay on throttler executions to prevent
spurious test failures.

* Replaced timeOutCheck with completed, simplified start test close, removed unnecessary string cast in LDConfig

* Removed unnecessary nil check in start for tests

* Removed unnecessary string cast in LDConfig, made waitUntil longer than start timeout

* Fix after merge.

* Change setUserSpec to identifySpec, fix doc strings

* Remove internalInstances from LDClient, remove isOnlineQueue from DiagnosticReporter

* Should improve LDClientSpec test runtime substantially.

* 3 second for timeout seems a bit long even for circleci.

* Update OHHTTPStubs for SwiftPM support.

* Update DarklyServiceMock for changes in OHHTTPStubs 9.0.0

* Update DarklyServiceSpec for OHHTTPStubs 9.0.0

* Add explicit import for Foundation in tests. Make linter slightly more
lienent and specify linted paths better. Fix mocks.stencil to allow
specifying a defaultMockValue for an Optional type variable. Change
default value for EnvironmentReporting.backgroundNotification and
EnvironmentReporting.foregroundNotification to delegate to
EnvironmentReporter to handle running tests on platforms without
UIKit. Avoid using XCTFail.

* Add initial SwiftPM Package.swift definition. Add SwiftPM build folder
to .gitignore. Add missing Foundation import in
LDClientSpec.swift. Comment out test that was previously disabled in
the xcode test configuration, which SwiftPM doesn't use.

* Use github reference for LDSwiftEventSource rather than local
reference.

* Try specifying ssh urls for dependencies in Package.swift as xcode is
choking when adding the package.

* Remove setAllUserAttributesPrivate public method

* Changed ObjcLDClient to act as a wrapper instead of keeping an internal LDClient, updated doc strings

* Fixed weird setOnline tests, fixed doc strings, added throws setter to secondaryMobileKeys, fixed ObjcLDClient

* Fixed LDClient close tests, added getter setter doc strings for secondaryMobileKeys, removed commented out code in LDConfig, removed unnecessary setOnline method in ObjcLDClient

* Fix doc strings in LDClient

* Removed logs from throws in LDConfig

* Added .swiftpm/ to .gitignore, removed all occurrences of fallback and replaced them with defaultValue (#111)

* Added .swiftpm/ to .gitignore, removed all occurrences of fallback and replaced them with defaultValue

* Change .swiftpm/ to /.swiftpm

* Removed defaultValue value

* Fix 2 typos

* Updated SDK version and supported iOS and Xcode versions in README

* Use Mint for tooling.

* Update CONTRIBUTING.md

Co-authored-by: Ben Woskow <[email protected]>

* Add @objc annotation to start objc bridge methods.

* (5.0) Use SwiftPM for SDK dependencies. (#114)

* (5.0) Fix of crash when logging is enabled. (#115)

Also removed unused test code. Improve documentation on LDClient.flush()

* (5.0) Update installation instructions (#116)

* (5.0) Changelog and some final removals and renames of public APIs (#117)

Fix a bug with preventing the SDK from retrying eventsource connections when the service returns a 5XX error code. Renamed a couple of public APIs. Removed some publicly exposed implementation details. Updated CHANGELOG.md for 5.0.

* [ch69438] Add ability to set additional headers on requests (#119)

* A jazzy doc build and update lint configuration (#120)

* [ch84954] Fix nested bundles in carthage build and missing dynamic library in SwiftPM build. (#121)

* Focus week cleanup (#122)

* [ch87108] Fix LDUser serialization to report redacted custom attributes in all cases (#123)

* [ch87107] Add LDUser secondary attribute (#124)

* [ch88282] Fix DiagnosticEvent build warnings on Xcode 12 (#125)

* Update dependencies after release of Nimble 9.0.0 (#126)

* Update doc comments for LDClient.identify (#127)

* [ch91505] Dynamic header configuration (#128)

Allow dynamic configuration of http headers through LDConfig.headerDelegate

* [ch94946] Multi Environment Bug Fix: Decouple FlagStore from LDUser (#130)

* Removed FlagStore from LDUser

* All unit tests build and LDClientSpec doesn't crash

* Fixed 1 unit test, removed unnecessary testing parameter in internalIdentify

* Fixed 29 unit tests

* Fixed 26 unit tests

* Fix all but 4 unit tests

* Removed comment

* Addressed PR feedback

* Removed unnecessary for each in LDUserSpec

* Removed unnecessary contexts in LDUserSpec, removed user value in FlagChangeNotifierSpec

* Fixed LDUserSpec context, added stub flags to DarklyServiceSpec

* Make LDClientSpec init less hacky

* Clear FlagStore if new user does not have cached flags, make flagStore a let

* Added FlagStore back to LDUser for init from flag dictionary, check for user.flagStore on LDClient init and identify

* Added deprecation comment to dictionary init for LDUser, prioritize LDUser FlagStore over cache in identify

* Changed identify ordering back to cache over flagstore, made FlagStore a let

* Bump version and CHANGELOG for 5.3.1

* Removed the guides link

* Added sync queue boolean check on go completion (#131)

* Update LDSwiftEventSource dependency (#132)

* Correlate anonymous users (#129)

* Clean up mock generation. (#133)

* Remove extraneous comments. (#134)

* Remove extraneous code for removing flag change observers (#135)

* Non-nilable flags unchanged handler (#136)

* Remove redundant args from LDClientSpec TestContext init calls (#137)

* Delegate FlagMaintainingMock to FlagStore. (#138)

* Remove redundant tests in LDClientSpec. (#139)

* Clean up onSyncCompleteErrorSpec. (#140)

* Separate transition to background tests from start tests. (#141)

* Clean up observeSpec. (#142)

* Improve allFlags spec. (#143)

* Remove unused variation function of FlagStore. (#144)

* Make service in LDClient immutable. (#145)

* [ch98013] Rework the diagnostic reporter and add tests. (#146)

* [ch61000] Add `isInitialized` method to the public API (#147)

* Added isInitialized method and unit tests

* Fix unit tests, stop double testContext.start

* PR feedback

* Remove returns doc

* Avoid sending contextKind for non-anonymous users in feature and custom events. (#148)

* Make `isInitialized` a property rather than a method. (#149)

* Simplify Event Reporter (#150)

* Cleanup flag store spec (#151)

* Cleanup cache tests. (#152)

* Added resetTimer to Throttler (#153)

* Added resetTimer to Throttler

* Fix race condition in access and then decrement/increment of runAttempts

* PR feedback

* Avoid potential issue with timer lifecycle.

Co-authored-by: Gavin Whelan <[email protected]>

* Prepare 5.4.1 patch release

Co-authored-by: Gavin Whelan <[email protected]>
Co-authored-by: Ben Woskow <[email protected]>
Co-authored-by: Elliot <[email protected]>
  • Loading branch information
4 people authored Apr 7, 2021
1 parent 12298b6 commit 3c359d1
Show file tree
Hide file tree
Showing 34 changed files with 1,047 additions and 3,146 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

All notable changes to the LaunchDarkly iOS SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org).

## [5.4.1] - 2021-04-06
### Fixed
- Internal throttling logic would sometimes delay new poll or stream connections even when there were no recent connections. This caused switching active user contexts using `identify` to sometimes delay retrieving the most recent flags and calling the completion.

## [5.4.0] - 2021-02-26
### Added
- Added the `alias` method to `LDClient`. This can be used to associate two user objects for analytics purposes with an alias event.
Expand Down
2 changes: 1 addition & 1 deletion LaunchDarkly.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Pod::Spec.new do |ld|

ld.name = "LaunchDarkly"
ld.version = "5.4.0"
ld.version = "5.4.1"
ld.summary = "iOS SDK for LaunchDarkly"

ld.description = <<-DESC
Expand Down
24 changes: 14 additions & 10 deletions LaunchDarkly.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@
83FEF8DF1F2667E4001CF12C /* EventReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83FEF8DE1F2667E4001CF12C /* EventReporter.swift */; };
B40B419C249ADA6B00CD0726 /* DiagnosticCacheSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = B40B419B249ADA6B00CD0726 /* DiagnosticCacheSpec.swift */; };
B4265EB124E7390C001CFD2C /* TestUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4265EB024E7390C001CFD2C /* TestUtil.swift */; };
B43D5AD025FBE1C30022EC90 /* DeprecatedCacheModelSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43D5ACF25FBE1C30022EC90 /* DeprecatedCacheModelSpec.swift */; };
B467791324D8AEEC00897F00 /* LDSwiftEventSourceStatic in Frameworks */ = {isa = PBXBuildFile; productRef = B467791224D8AEEC00897F00 /* LDSwiftEventSourceStatic */; };
B467791524D8AEF300897F00 /* LDSwiftEventSourceStatic in Frameworks */ = {isa = PBXBuildFile; productRef = B467791424D8AEF300897F00 /* LDSwiftEventSourceStatic */; };
B467791724D8AEF800897F00 /* LDSwiftEventSourceStatic in Frameworks */ = {isa = PBXBuildFile; productRef = B467791624D8AEF800897F00 /* LDSwiftEventSourceStatic */; };
Expand Down Expand Up @@ -476,6 +477,7 @@
83FEF8DE1F2667E4001CF12C /* EventReporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventReporter.swift; sourceTree = "<group>"; };
B40B419B249ADA6B00CD0726 /* DiagnosticCacheSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiagnosticCacheSpec.swift; sourceTree = "<group>"; };
B4265EB024E7390C001CFD2C /* TestUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestUtil.swift; sourceTree = "<group>"; };
B43D5ACF25FBE1C30022EC90 /* DeprecatedCacheModelSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeprecatedCacheModelSpec.swift; sourceTree = "<group>"; };
B468E70F24B3C3AC00E0C883 /* ObjcLDEvaluationDetail.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjcLDEvaluationDetail.swift; sourceTree = "<group>"; };
B46F344025E6DB7D0078D45F /* DiagnosticReporterSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiagnosticReporterSpec.swift; sourceTree = "<group>"; };
B4C9D42D2489B5FF004A9B03 /* DiagnosticEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiagnosticEvent.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -637,6 +639,7 @@
83D5597D1FDA01F9002D10C8 /* KeyedValueCacheSpec.swift */,
8354AC76224316F800CDE602 /* UserEnvironmentFlagCacheSpec.swift */,
832D68AB224B3321005F052A /* CacheConverterSpec.swift */,
B43D5ACF25FBE1C30022EC90 /* DeprecatedCacheModelSpec.swift */,
83D1523A22545BB20054B6D4 /* DeprecatedCacheModelV5Spec.swift */,
83D15238225455D40054B6D4 /* DeprecatedCacheModelV4Spec.swift */,
83D15236225400CE0054B6D4 /* DeprecatedCacheModelV3Spec.swift */,
Expand Down Expand Up @@ -1463,6 +1466,7 @@
83F0A5641FB5F33800550A95 /* LDConfigSpec.swift in Sources */,
83CFE7D11F7AD8DC0010544E /* DarklyServiceMock.swift in Sources */,
832EA061203D03B700A93C0E /* AnyComparerSpec.swift in Sources */,
B43D5AD025FBE1C30022EC90 /* DeprecatedCacheModelSpec.swift in Sources */,
832307AA1F7ECA630029815A /* LDConfigStub.swift in Sources */,
8354AC77224316F800CDE602 /* UserEnvironmentFlagCacheSpec.swift in Sources */,
83EBCBB120D9C7B5003A7142 /* FlagCounterSpec.swift in Sources */,
Expand Down Expand Up @@ -1591,7 +1595,7 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "$(PROJECT_DIR)/LaunchDarkly/LaunchDarkly/Support/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
MARKETING_VERSION = 5.4.0;
MARKETING_VERSION = 5.4.1;
MODULEMAP_FILE = "";
PRODUCT_BUNDLE_IDENTIFIER = "com.launchdarkly.Darkly-tvOS";
PRODUCT_NAME = LaunchDarkly_tvOS;
Expand All @@ -1614,7 +1618,7 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "$(PROJECT_DIR)/LaunchDarkly/LaunchDarkly/Support/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
MARKETING_VERSION = 5.4.0;
MARKETING_VERSION = 5.4.1;
MODULEMAP_FILE = "";
PRODUCT_BUNDLE_IDENTIFIER = "com.launchdarkly.Darkly-tvOS";
PRODUCT_NAME = LaunchDarkly_tvOS;
Expand All @@ -1637,7 +1641,7 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "$(PROJECT_DIR)/LaunchDarkly/LaunchDarkly/Support/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
MARKETING_VERSION = 5.4.0;
MARKETING_VERSION = 5.4.1;
PRODUCT_BUNDLE_IDENTIFIER = "com.launchdarkly.Darkly-macOS";
PRODUCT_NAME = LaunchDarkly_macOS;
SDKROOT = macosx;
Expand All @@ -1658,7 +1662,7 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "$(PROJECT_DIR)/LaunchDarkly/LaunchDarkly/Support/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
MARKETING_VERSION = 5.4.0;
MARKETING_VERSION = 5.4.1;
PRODUCT_BUNDLE_IDENTIFIER = "com.launchdarkly.Darkly-macOS";
PRODUCT_NAME = LaunchDarkly_macOS;
SDKROOT = macosx;
Expand Down Expand Up @@ -1702,7 +1706,7 @@
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
DYLIB_COMPATIBILITY_VERSION = 5.4.0;
DYLIB_CURRENT_VERSION = 5.4.0;
DYLIB_CURRENT_VERSION = 5.4.1;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
FRAMEWORK_VERSION = B;
Expand Down Expand Up @@ -1773,7 +1777,7 @@
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 5.4.0;
DYLIB_CURRENT_VERSION = 5.4.0;
DYLIB_CURRENT_VERSION = 5.4.1;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_VERSION = B;
Expand Down Expand Up @@ -1812,7 +1816,7 @@
INFOPLIST_FILE = "$(PROJECT_DIR)/LaunchDarkly/LaunchDarkly/Support/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
MARKETING_VERSION = 5.4.0;
MARKETING_VERSION = 5.4.1;
MODULEMAP_FILE = "$(PROJECT_DIR)/Framework/module.modulemap";
PRODUCT_BUNDLE_IDENTIFIER = com.launchdarkly.Darkly;
PRODUCT_NAME = LaunchDarkly;
Expand All @@ -1832,7 +1836,7 @@
INFOPLIST_FILE = "$(PROJECT_DIR)/LaunchDarkly/LaunchDarkly/Support/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
MARKETING_VERSION = 5.4.0;
MARKETING_VERSION = 5.4.1;
MODULEMAP_FILE = "$(PROJECT_DIR)/Framework/module.modulemap";
PRODUCT_BUNDLE_IDENTIFIER = com.launchdarkly.Darkly;
PRODUCT_NAME = LaunchDarkly;
Expand Down Expand Up @@ -1874,7 +1878,7 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "$(PROJECT_DIR)/LaunchDarkly/LaunchDarkly/Support/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
MARKETING_VERSION = 5.4.0;
MARKETING_VERSION = 5.4.1;
PRODUCT_BUNDLE_IDENTIFIER = "com.launchdarkly.Darkly-watchOS";
PRODUCT_NAME = LaunchDarkly_watchOS;
SDKROOT = watchos;
Expand All @@ -1896,7 +1900,7 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "$(PROJECT_DIR)/LaunchDarkly/LaunchDarkly/Support/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
MARKETING_VERSION = 5.4.0;
MARKETING_VERSION = 5.4.1;
PRODUCT_BUNDLE_IDENTIFIER = "com.launchdarkly.Darkly-watchOS";
PRODUCT_NAME = LaunchDarkly_watchOS;
SDKROOT = watchos;
Expand Down
24 changes: 3 additions & 21 deletions LaunchDarkly/GeneratedCode/mocks.generated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -245,15 +245,6 @@ final class ErrorNotifyingMock: ErrorNotifying {
// MARK: - EventReportingMock
final class EventReportingMock: EventReporting {

var configSetCount = 0
var setConfigCallback: (() -> Void)?
var config: LDConfig = LDConfig.stub {
didSet {
configSetCount += 1
setConfigCallback?()
}
}

var isOnlineSetCount = 0
var setIsOnlineCallback: (() -> Void)?
var isOnline: Bool = false {
Expand All @@ -263,15 +254,6 @@ final class EventReportingMock: EventReporting {
}
}

var serviceSetCount = 0
var setServiceCallback: (() -> Void)?
var service: DarklyServiceProvider = DarklyServiceMock() {
didSet {
serviceSetCount += 1
setServiceCallback?()
}
}

var lastEventResponseDateSetCount = 0
var setLastEventResponseDateCallback: (() -> Void)?
var lastEventResponseDate: Date? = nil {
Expand Down Expand Up @@ -334,10 +316,10 @@ final class FeatureFlagCachingMock: FeatureFlagCaching {

var storeFeatureFlagsCallCount = 0
var storeFeatureFlagsCallback: (() -> Void)?
var storeFeatureFlagsReceivedArguments: (featureFlags: [LDFlagKey: FeatureFlag], user: LDUser, mobileKey: String, lastUpdated: Date, storeMode: FlagCachingStoreMode)?
func storeFeatureFlags(_ featureFlags: [LDFlagKey: FeatureFlag], forUser user: LDUser, andMobileKey mobileKey: String, lastUpdated: Date, storeMode: FlagCachingStoreMode) {
var storeFeatureFlagsReceivedArguments: (featureFlags: [LDFlagKey: FeatureFlag], userKey: String, mobileKey: String, lastUpdated: Date, storeMode: FlagCachingStoreMode)?
func storeFeatureFlags(_ featureFlags: [LDFlagKey: FeatureFlag], userKey: String, mobileKey: String, lastUpdated: Date, storeMode: FlagCachingStoreMode) {
storeFeatureFlagsCallCount += 1
storeFeatureFlagsReceivedArguments = (featureFlags: featureFlags, user: user, mobileKey: mobileKey, lastUpdated: lastUpdated, storeMode: storeMode)
storeFeatureFlagsReceivedArguments = (featureFlags: featureFlags, userKey: userKey, mobileKey: mobileKey, lastUpdated: lastUpdated, storeMode: storeMode)
storeFeatureFlagsCallback?()
}
}
Expand Down
21 changes: 7 additions & 14 deletions LaunchDarkly/LaunchDarkly/LDClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -306,11 +306,8 @@ public class LDClient {
if let cachedFlags = self.flagCache.retrieveFeatureFlags(forUserWithKey: self.user.key, andMobileKey: self.config.mobileKey), !cachedFlags.isEmpty {
flagStore.replaceStore(newFlags: cachedFlags, completion: nil)
} else {
if let userFlagStore = user.flagStore {
flagStore.replaceStore(newFlags: userFlagStore.featureFlags, completion: nil)
} else {
flagStore.replaceStore(newFlags: [:], completion: nil)
}
// Deprecated behavior of setting flags from user init dictionary
flagStore.replaceStore(newFlags: user.flagStore?.featureFlags ?? [:], completion: nil)
}
self.service.user = self.user
flagSynchronizer = serviceFactory.makeFlagSynchronizer(streamingMode: ConnectionInformation.effectiveStreamingMode(config: config, ldClient: self),
Expand All @@ -326,7 +323,7 @@ public class LDClient {
self.internalSetOnline(wasOnline, completion: completion)

if !config.autoAliasingOptOut && previousUser.isAnonymous && !newUser.isAnonymous {
self.internalAlias(context: newUser, previousContext: previousUser)
self.alias(context: newUser, previousContext: previousUser)
}

self.service.clearFlagResponseCache()
Expand Down Expand Up @@ -715,7 +712,7 @@ public class LDClient {

private func updateCacheAndReportChanges(user: LDUser,
oldFlags: [LDFlagKey: FeatureFlag]) {
flagCache.storeFeatureFlags(flagStore.featureFlags, forUser: user, andMobileKey: config.mobileKey, lastUpdated: Date(), storeMode: .async)
flagCache.storeFeatureFlags(flagStore.featureFlags, userKey: user.key, mobileKey: config.mobileKey, lastUpdated: Date(), storeMode: .async)
flagChangeNotifier.notifyObservers(flagStore: flagStore, oldFlags: oldFlags)
}

Expand Down Expand Up @@ -771,10 +768,6 @@ public class LDClient {
return
}

internalAlias(context: new, previousContext: old)
}

private func internalAlias(context new: LDUser, previousContext old: LDUser) {
self.eventReporter.record(Event.aliasEvent(newUser: new, oldUser: old))
}

Expand Down Expand Up @@ -949,14 +942,14 @@ public class LDClient {
LDUserWrapper.configureKeyedArchiversToHandleVersion2_3_0AndOlderUserCacheFormat()
cacheConverter = self.serviceFactory.makeCacheConverter(maxCachedUsers: configuration.maxCachedUsers)
flagChangeNotifier = self.serviceFactory.makeFlagChangeNotifier()
throttler = self.serviceFactory.makeThrottler(maxDelay: Throttler.Constants.defaultDelay, environmentReporter: environmentReporter)
throttler = self.serviceFactory.makeThrottler(environmentReporter: environmentReporter)

config = configuration
let anonymousUser = LDUser(environmentReporter: environmentReporter)
user = startUser ?? anonymousUser
service = self.serviceFactory.makeDarklyServiceProvider(config: config, user: user)
diagnosticReporter = self.serviceFactory.makeDiagnosticReporter(service: service)
eventReporter = self.serviceFactory.makeEventReporter(config: config, service: service)
eventReporter = self.serviceFactory.makeEventReporter(service: service)
errorNotifier = self.serviceFactory.makeErrorNotifier()
connectionInformation = self.serviceFactory.makeConnectionInformation()
flagSynchronizer = self.serviceFactory.makeFlagSynchronizer(streamingMode: config.allowStreamingMode ? config.streamingMode : .polling,
Expand All @@ -973,7 +966,7 @@ public class LDClient {

NotificationCenter.default.addObserver(self, selector: #selector(didCloseEventSource), name: Notification.Name(FlagSynchronizer.Constants.didCloseEventSourceName), object: nil)

eventReporter = self.serviceFactory.makeEventReporter(config: config, service: service, onSyncComplete: onEventSyncComplete)
eventReporter = self.serviceFactory.makeEventReporter(service: service, onSyncComplete: onEventSyncComplete)
flagSynchronizer = self.serviceFactory.makeFlagSynchronizer(streamingMode: config.allowStreamingMode ? config.streamingMode : .polling,
pollingInterval: config.flagPollingInterval(runMode: runMode),
useReport: config.useReport,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Foundation

//Data structure used to cache feature flags for a specific user from a specific environment
struct CacheableEnvironmentFlags {
enum CodingKeys: String, CodingKey {
enum CodingKeys: String, CodingKey, CaseIterable {
case userKey, mobileKey, featureFlags
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import Foundation
]
*/
struct CacheableUserEnvironmentFlags {
enum CodingKeys: String, CodingKey {
enum CodingKeys: String, CodingKey, CaseIterable {
case userKey, environmentFlags, lastUpdated
}

Expand All @@ -45,15 +45,17 @@ struct CacheableUserEnvironmentFlags {
let lastUpdated: Date

init(userKey: String, environmentFlags: [MobileKey: CacheableEnvironmentFlags], lastUpdated: Date) {
(self.userKey, self.environmentFlags, self.lastUpdated) = (userKey, environmentFlags, lastUpdated)
self.userKey = userKey
self.environmentFlags = environmentFlags
self.lastUpdated = lastUpdated
}

init?(dictionary: [String: Any]) {
guard let userKey = dictionary[CodingKeys.userKey.rawValue] as? String,
let environmentFlagsDictionary = dictionary[CodingKeys.environmentFlags.rawValue] as? [MobileKey: [LDFlagKey: Any]],
let lastUpdated = (dictionary[CodingKeys.lastUpdated.rawValue] as? String)?.dateValue
else { return nil }
let environmentFlags = environmentFlagsDictionary.compactMapValues { (cacheableEnvironmentFlagsDictionary) in
let environmentFlags = environmentFlagsDictionary.compactMapValues { cacheableEnvironmentFlagsDictionary in
CacheableEnvironmentFlags(dictionary: cacheableEnvironmentFlagsDictionary)
}
self.init(userKey: userKey, environmentFlags: environmentFlags, lastUpdated: lastUpdated)
Expand All @@ -65,21 +67,13 @@ struct CacheableUserEnvironmentFlags {
self.init(dictionary: dictionary)
}

static func makeCollection(from dictionary: [String: Any]) -> [UserKey: CacheableUserEnvironmentFlags] {
dictionary.compactMapValues { CacheableUserEnvironmentFlags(object: $0) }
}

var dictionaryValue: [String: Any] {
[CodingKeys.userKey.rawValue: userKey,
CodingKeys.lastUpdated.rawValue: lastUpdated.stringValue,
CodingKeys.environmentFlags.rawValue: environmentFlags.compactMapValues { $0.dictionaryValue } ]
}
}

extension Dictionary where Key == UserKey, Value == CacheableUserEnvironmentFlags {
var dictionaryValues: [UserKey: [String: Any]] { compactMapValues { $0.dictionaryValue } }
}

extension DateFormatter {
/// Date formatter configured to format dates to/from the format 2018-08-13T19:06:38.123Z
class var ldDateFormatter: DateFormatter {
Expand Down
6 changes: 0 additions & 6 deletions LaunchDarkly/LaunchDarkly/Models/Event.swift
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,6 @@ struct Event {
}
}

extension Array where Element == Event {
func dictionaryValues(config: LDConfig) -> [[String: Any]] {
self.map { $0.dictionaryValue(config: config) }
}
}

extension Array where Element == [String: Any] {
var jsonData: Data? {
guard JSONSerialization.isValidJSONObject(self)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,9 @@ final class CacheConverter: CacheConverting {

let currentCache: FeatureFlagCaching
private(set) var deprecatedCaches = [DeprecatedCacheModel: DeprecatedCache]()
let maxAge: TimeInterval

init(serviceFactory: ClientServiceCreating, maxCachedUsers: Int, maxAge: TimeInterval = Constants.maxAge) {
init(serviceFactory: ClientServiceCreating, maxCachedUsers: Int) {
currentCache = serviceFactory.makeFeatureFlagCache(maxCachedUsers: maxCachedUsers)
self.maxAge = maxAge
DeprecatedCacheModel.allCases.forEach { version in
deprecatedCaches[version] = serviceFactory.makeDeprecatedCacheModel(version)
}
Expand All @@ -49,13 +47,13 @@ final class CacheConverter: CacheConverting {
guard let cachedData = deprecatedCache?.retrieveFlags(for: user.key, and: mobileKey),
let cachedFlags = cachedData.featureFlags
else { continue }
currentCache.storeFeatureFlags(cachedFlags, forUser: user, andMobileKey: mobileKey, lastUpdated: cachedData.lastUpdated ?? Date(), storeMode: .sync)
currentCache.storeFeatureFlags(cachedFlags, userKey: user.key, mobileKey: mobileKey, lastUpdated: cachedData.lastUpdated ?? Date(), storeMode: .sync)
return //If we hit on a cached user, bailout since we converted the flags for that userKey-mobileKey combination; This prefers newer caches over older
}
}

private func removeData() {
let maxAge = Date().addingTimeInterval(self.maxAge)
let maxAge = Date().addingTimeInterval(Constants.maxAge)
deprecatedCaches.values.forEach { deprecatedCache in
deprecatedCache.removeData(olderThan: maxAge)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ extension DeprecatedCache {
}
}

enum DeprecatedCacheModel: CaseIterable {
enum DeprecatedCacheModel: String, CaseIterable {
case version5, version4, version3, version2 //version1 is not supported
}

Expand Down
Loading

0 comments on commit 3c359d1

Please sign in to comment.