-
Notifications
You must be signed in to change notification settings - Fork 257
feat(analytics): Legacy data migration of Pinpoint Endpoint ID #2489
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
Conversation
92a8e87
to
eaf5117
Compare
I based this on the other PR for integration tests because that PR refactors several parts of Analytics that this PR relies on (primarily with configure of the plugin). |
...lify/amplify_analytics_pinpoint/amplify_analytics_pinpoint/AmplifyAnalyticsPinpointPlugin.kt
Outdated
Show resolved
Hide resolved
} | ||
|
||
override fun initialize(pinpointAppId: String, result: Messages.Result<Void>){ | ||
sharedPrefs = context.getSharedPreferences( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initialize inline or add check if already initialized
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think what Dillon might be suggesting is to combine initialize
and getEndpointId
, which makes sense to me since it looks like init is always called right before getEndpointId
. You can check if sharedPrefs has been initialized, and if not, do so. For example:
var sharedPrefs: SharedPreferences? = null
fun getEndpointId(pinpointAppId: String, result: Messages.Result<String?>){
sharedPrefs = sharedPrefs ?: context.getSharedPreferences(
"${pinpointAppId}$PINPOINT_SHARED_PREFS_SUFFIX",
Context.MODE_PRIVATE
)
result.success(sharedPrefs!!.getString(UNIQUE_ID_KEY, null))
}
...s/analytics/amplify_analytics_pinpoint/ios/Classes/SwiftAmplifyAnalyticsPinpointPlugin.swift
Outdated
Show resolved
Hide resolved
...s/analytics/amplify_analytics_pinpoint/ios/Classes/SwiftAmplifyAnalyticsPinpointPlugin.swift
Outdated
Show resolved
Hide resolved
...lytics/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/data_provider.ios.dart
Show resolved
Hide resolved
...s/analytics/amplify_analytics_pinpoint/ios/Classes/SwiftAmplifyAnalyticsPinpointPlugin.swift
Outdated
Show resolved
Hide resolved
...s/analytics/amplify_analytics_pinpoint/ios/Classes/SwiftAmplifyAnalyticsPinpointPlugin.swift
Outdated
Show resolved
Hide resolved
...s/analytics/amplify_analytics_pinpoint/ios/Classes/SwiftAmplifyAnalyticsPinpointPlugin.swift
Outdated
Show resolved
Hide resolved
...lify/amplify_analytics_pinpoint/amplify_analytics_pinpoint/AmplifyAnalyticsPinpointPlugin.kt
Show resolved
Hide resolved
packages/analytics/amplify_analytics_pinpoint_dart/lib/src/analytics_plugin_impl.dart
Outdated
Show resolved
Hide resolved
c1944f7
to
28b5a8c
Compare
93fbbc0
to
084eae2
Compare
a5743b7
to
bb3545f
Compare
7590ceb
to
9864a80
Compare
...lify/amplify_analytics_pinpoint/amplify_analytics_pinpoint/AmplifyAnalyticsPinpointPlugin.kt
Show resolved
Hide resolved
private func data(forKey key: String) -> Data? { | ||
let query = [ | ||
kSecClass: kSecClassGenericPassword, | ||
kSecAttrService: KeychainReader.pinpointAttrService, | ||
kSecAttrAccount: key, | ||
kSecReturnData: true | ||
] as CFDictionary | ||
|
||
var result: AnyObject? | ||
let status = SecItemCopyMatching(query, &result) | ||
|
||
guard status != errSecItemNotFound else { | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you find out if there was any specific reason secure_storage wasn't working? The code here is similar to _getValue() in secure_storage. One difference I see is that secure_storage sets an explicit value for kSecAttrAccessible
, which is not done here. This means it will fallback on the default, which might be what the SDK uses. I can look into what impact that has in accessing data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for helping here, looks like this was resolved.
}) : super( | ||
keyValueStore: keyValueStore ?? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be endpointInfoStore
? It seems like this was renamed in some places and not in others.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1, getting build errors here which prevent testing, seen in integ tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks resolved. I did a rebase and appear to have missed a commit somehow ...
...lytics/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/data_provider.ios.dart
Show resolved
Hide resolved
...ics_pinpoint/lib/src/legacy_native_data_provider/flutter_legacy_native_data_provider_io.dart
Outdated
Show resolved
Hide resolved
), | ||
) | ||
@HostApi() | ||
abstract class PigeonDataProvider { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was marked as resolved but I think still applies
static const String _endpointGlobalAttrsKey = 'EndpointGlobalAttributesKey'; | ||
static const String _endpointGlobalMetricsKey = 'EndpointGlobalMetricsKey'; | ||
|
||
static const String _endpointInformationCurrentVersionValue = '0'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of this? Can you add a comment? Would an enum make more sense here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Version of metadata stored into the `endpointInfoStore`
/// If stored data changes, increment this value
static const String _endpointInformationCurrentVersionValue = '0';
Added the above comments. The initial idea is to track if we have read legacy data from native.
If so, we store this value into secure storage to avoid further reads from legacy data.
In case of future changes, if we need to change legacy read behavior to read other values we would increment this value and store that instead. Having this value stored before allows us to quickly know what the storage state is (either no value, "0", "1", etc)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. I would suggest using an enum for this as we did in Auth. It provides a nice way to document this.
Lines 10 to 20 in 834a81d
/// The credential store version. | |
enum CredentialStoreVersion { | |
/// No credential store version is present. | |
/// | |
/// Either the credential store has never been initialized on this device, or | |
/// the credentials are stored in a legacy format. | |
none, | |
/// The initial implementation of Credential in Amplify Flutter Auth. | |
v1, | |
} |
9864a80
to
5b12a78
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with other comments that would be good to see platform/pigeon stuff consolidated as well as comment about secure storage detail before reviewing again. Biggest question was how non android/ios platforms should avoid the legacy stuff as it did not seem correct when I tested on MacOS (I did not try other platforms).
revision: 52b3dc25f6471c27b2144594abb11c741cb88f57 | ||
channel: stable | ||
|
||
project_type: app |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Shouldn't this be for type: plugin
like the other plugins? How was this file created?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks good catch there. It appears this was created on the flutter create . command not sure how/why it was modified since then though. It should be project_type plugin so I changed it. Looks to be used by flutter when performing upgrades so making this change should be fine.
Used this as a resource in case you're curious to learn more about what metadata is: https://dev.to/swimmingkiim/what-is-metadata-file-in-flutter-project-38m3
}) : super( | ||
keyValueStore: keyValueStore ?? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1, getting build errors here which prevent testing, seen in integ tests
packages/analytics/amplify_analytics_pinpoint/ios/amplify_analytics_pinpoint.podspec
Outdated
Show resolved
Hide resolved
packages/analytics/amplify_analytics_pinpoint/ios/amplify_analytics_pinpoint.podspec
Outdated
Show resolved
Hide resolved
await _legacyNativeDataProvider?.initialize(appId); | ||
retrievedEndpointId = await _legacyNativeDataProvider?.getEndpointId(); | ||
|
||
retrievedEndpointId ??= const Uuid().v1(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Why use this version of uuid instead of uuid()
from aws_common? If there is specific requirement for that could we have a comment here saying why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks there is no reason, wasn't aware of this method in core package.
class FlutterLegacyNativeDataProvider implements LegacyNativeDataProvider { | ||
/// {@macro amplify_analytics_pinpoint.flutter_legacy_native_data_provider} | ||
factory FlutterLegacyNativeDataProvider() { | ||
final provider = Platform.isIOS ? DataProviderIos() : DataProviderAndroid(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Maybe I'm missing something here, but is this using DataProviderAndroid
for all non-ios io platforms (desktop windows, macos, linux)? When I ran example app on macos I got this error:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(channel-error, Unable to establish connection on channel., null, null)
#0 PigeonDataProvider.initialize (package:amplify_analytics_pinpoint/src/legacy_native_data_provider/pigeon_data_provider.android.g.dart:40:7)
<asynchronous suspension>
#1 AmplifyAnalyticsPinpointDart.configure (package:amplify_analytics_pinpoint_dart/src/analytics_plugin_impl.dart:169:7)
<asynchronous suspension>
#2 Future.wait.<anonymous closure> (dart:async/future.dart:522:21)
<asynchronous suspension>
#3 AmplifyClassImpl.configurePlatform (package:amplify_core/src/amplify_class_impl.dart:73:5)
<asynchronous suspension>
#4 AmplifyClass.configure (package:amplify_core/src/amplify_class.dart:107:7)
<asynchronous suspension>
#5 _MyAppState._configureAmplify (package:amplify_analytics_pinpoint_example/main.dart:70:7)
<asynchronous suspension>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks good catch, I'll need to fix this then
key: _endpointInformationVersionKey, | ||
value: _endpointInformationCurrentVersionValue, | ||
); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Should this block only execute on ios/android like:
if (!zIsWeb && (Platform.isAndroid || Platform.isIOS)) {
}
I mentioned in another comment I got an error from here on macos but I wonder if it would simplify things just to stop this logic far upstream (here) to simplify non ios/android platforms as much as possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks yes updated the logic
5b12a78
to
5df46c6
Compare
5df46c6
to
0371b05
Compare
Do not merge until PR fixes to secure storage are in: That PR allows us to properly extract legacy ios data using the secure storage plugin instead of custom ios code. |
...lify/amplify_analytics_pinpoint/amplify_analytics_pinpoint/AmplifyAnalyticsPinpointPlugin.kt
Outdated
Show resolved
Hide resolved
|
||
analyzer: | ||
exclude: | ||
- "**/**/**/*.g.dart" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
**/**/**/
should be reducible to **/
- "**/**/**/*.g.dart" | |
- "**/*.g.dart" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Merging with next was unsuccessful. Please fix and address Jordan's comment:
analyzer:
errors:
implementation_imports: error #TODO(equartey): Remove when lint is enforced project-wide
exclude:
- "**/*.g.dart"
packages/analytics/amplify_analytics_pinpoint/lib/src/analytics_plugin_impl.dart
Outdated
Show resolved
Hide resolved
static const String _endpointGlobalAttrsKey = 'EndpointGlobalAttributesKey'; | ||
static const String _endpointGlobalMetricsKey = 'EndpointGlobalMetricsKey'; | ||
|
||
static const String _endpointInformationCurrentVersionValue = '0'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. I would suggest using an enum for this as we did in Auth. It provides a nice way to document this.
Lines 10 to 20 in 834a81d
/// The credential store version. | |
enum CredentialStoreVersion { | |
/// No credential store version is present. | |
/// | |
/// Either the credential store has never been initialized on this device, or | |
/// the credentials are stored in a legacy format. | |
none, | |
/// The initial implementation of Credential in Amplify Flutter Auth. | |
v1, | |
} |
...tics_pinpoint_dart/lib/src/impl/flutter_provider_interfaces/legacy_native_data_provider.dart
Show resolved
Hide resolved
packages/analytics/amplify_analytics_pinpoint_dart/lib/src/analytics_plugin_impl.dart
Outdated
Show resolved
Hide resolved
await _legacyNativeDataProvider?.initialize(appId); | ||
retrievedEndpointId = await _legacyNativeDataProvider?.getEndpointId(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these two functions are called twice (here & lines 153/154 above). Is that on purpose? I think they both get called during data migration. Since this is a one time event, that is not the end of the world, but it is a little confusing to follow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am having a bit of a hard time following this. I believe you want to achieve something like:
- Check version
- If version is null, attempt migration (one time event)
- read ID from legacy storage
- if non-null, write to new storage
- update version to
'0'
to prevent migration on future app inits
- Read version from storage
- If null, generate a new one
- generate new ID
- write to storage
This is an example of a flow that I think is easier to follow.
// Attempt migration if version is null.
if (endpointInformationVersion == null) {
await _legacyNativeDataProvider?.initialize(appId);
final legacyEndpointId = await _legacyNativeDataProvider?.getEndpointId();
// Migrate legacy data if it is non-null
if (legacyEndpointId != null) {
await _endpointInfoStore.write(
key: endpointIdStorageKey,
value: legacyEndpointId,
);
}
// Update the version to prevent future legacy data migrations.
await _endpointInfoStore.write(
key: _endpointInformationVersionKey,
value: _endpointInformationCurrentVersionValue,
);
}
// Read the existing ID.
final currentEndpointId = await _endpointInfoStore.read(
key: endpointIdStorageKey,
);
final String fixedEndpointId;
// Generate a new ID if one does not exist.
if (currentEndpointId == null) {
fixedEndpointId = uuid();
await _endpointInfoStore.write(
key: endpointIdStorageKey,
value: fixedEndpointId,
);
} else {
fixedEndpointId = currentEndpointId;
}
This will result in reading the ID twice in the scenario where there is data to migrate (first from legacy storage, and then from the new storage), but since it is a one time event I think that is fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright it seems like a bit longer of a solution and possibly more complex because there are now 2 conditionals but I see how some of the code before was implicit. I think it's good that the read call no longer requires a force cast, so if something goes wrong and currentEndpointId is null we no everything will still work and no crash will occur.
packages/analytics/amplify_analytics_pinpoint_dart/lib/src/analytics_plugin_impl.dart
Outdated
Show resolved
Hide resolved
2c63b22
to
d6a194e
Compare
...cs/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/data_provider.android.dart
Outdated
Show resolved
Hide resolved
...lytics/amplify_analytics_pinpoint/lib/src/legacy_native_data_provider/data_provider.ios.dart
Outdated
Show resolved
Hide resolved
} | ||
|
||
override fun initialize(pinpointAppId: String, result: Messages.Result<Void>){ | ||
sharedPrefs = context.getSharedPreferences( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think what Dillon might be suggesting is to combine initialize
and getEndpointId
, which makes sense to me since it looks like init is always called right before getEndpointId
. You can check if sharedPrefs has been initialized, and if not, do so. For example:
var sharedPrefs: SharedPreferences? = null
fun getEndpointId(pinpointAppId: String, result: Messages.Result<String?>){
sharedPrefs = sharedPrefs ?: context.getSharedPreferences(
"${pinpointAppId}$PINPOINT_SHARED_PREFS_SUFFIX",
Context.MODE_PRIVATE
)
result.success(sharedPrefs!!.getString(UNIQUE_ID_KEY, null))
}
packages/analytics/amplify_analytics_pinpoint_dart/test/analytics_legacy_native_data_test.dart
Show resolved
Hide resolved
packages/analytics/amplify_analytics_pinpoint_dart/lib/src/analytics_plugin_impl.dart
Outdated
Show resolved
Hide resolved
3786350
to
d5d91c1
Compare
packages/analytics/amplify_analytics_pinpoint_dart/test/analytics_legacy_native_data_test.dart
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
approved assuming web crash fixed per comments regarding !zIsWeb
.
...lytics_pinpoint/lib/src/legacy_native_data_provider/flutter_legacy_native_data_provider.dart
Show resolved
Hide resolved
...lytics_pinpoint/lib/src/legacy_native_data_provider/flutter_legacy_native_data_provider.dart
Outdated
Show resolved
Hide resolved
packages/analytics/amplify_analytics_pinpoint_dart/test/analytics_legacy_native_data_test.dart
Outdated
Show resolved
Hide resolved
d5d91c1
to
87006ed
Compare
...lify/amplify_analytics_pinpoint/amplify_analytics_pinpoint/AmplifyAnalyticsPinpointPlugin.kt
Outdated
Show resolved
Hide resolved
|
||
analyzer: | ||
exclude: | ||
- "**/**/**/*.g.dart" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Merging with next was unsuccessful. Please fix and address Jordan's comment:
analyzer:
errors:
implementation_imports: error #TODO(equartey): Remove when lint is enforced project-wide
exclude:
- "**/*.g.dart"
...lytics_pinpoint/lib/src/legacy_native_data_provider/flutter_legacy_native_data_provider.dart
Outdated
Show resolved
Hide resolved
...lytics_pinpoint/lib/src/legacy_native_data_provider/flutter_legacy_native_data_provider.dart
Outdated
Show resolved
Hide resolved
...lytics_pinpoint/lib/src/legacy_native_data_provider/flutter_legacy_native_data_provider.dart
Outdated
Show resolved
Hide resolved
if (endpointInformationVersion == null) { | ||
final legacyEndpointId = | ||
await legacyDataProvider?.getEndpointId(pinpointAppId); | ||
// Migrate legacy data if it is non-null | ||
if (legacyEndpointId != null) { | ||
await store.write( | ||
key: endpointIdStorageKey, | ||
value: legacyEndpointId, | ||
); | ||
} | ||
// Update the version to prevent future legacy data migrations. | ||
await store.write( | ||
key: EndpointStoreKey.version.name, | ||
value: EndpointStoreVersion.v1.name, | ||
); | ||
} | ||
|
||
// Read the existing ID. | ||
final currentEndpointId = await store.read( | ||
key: endpointIdStorageKey, | ||
); | ||
|
||
final String fixedEndpointId; | ||
|
||
// Generate a new ID if one does not exist. | ||
if (currentEndpointId == null) { | ||
fixedEndpointId = uuid(); | ||
await store.write( | ||
key: endpointIdStorageKey, | ||
value: fixedEndpointId, | ||
); | ||
} else { | ||
fixedEndpointId = currentEndpointId; | ||
} | ||
|
||
return fixedEndpointId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the goal is to arrive at a fixed endpoint ID, use a single variable to convey that journey. This also cleans up the logic branches and saves you a read from the DB in some cases.
if (endpointInformationVersion == null) { | |
final legacyEndpointId = | |
await legacyDataProvider?.getEndpointId(pinpointAppId); | |
// Migrate legacy data if it is non-null | |
if (legacyEndpointId != null) { | |
await store.write( | |
key: endpointIdStorageKey, | |
value: legacyEndpointId, | |
); | |
} | |
// Update the version to prevent future legacy data migrations. | |
await store.write( | |
key: EndpointStoreKey.version.name, | |
value: EndpointStoreVersion.v1.name, | |
); | |
} | |
// Read the existing ID. | |
final currentEndpointId = await store.read( | |
key: endpointIdStorageKey, | |
); | |
final String fixedEndpointId; | |
// Generate a new ID if one does not exist. | |
if (currentEndpointId == null) { | |
fixedEndpointId = uuid(); | |
await store.write( | |
key: endpointIdStorageKey, | |
value: fixedEndpointId, | |
); | |
} else { | |
fixedEndpointId = currentEndpointId; | |
} | |
return fixedEndpointId; | |
String? fixedEndpointId; | |
if (endpointInformationVersion == null) { | |
final legacyEndpointId = | |
await legacyDataProvider?.getEndpointId(pinpointAppId); | |
// Migrate legacy data if it is non-null | |
if (legacyEndpointId != null) { | |
fixedEndpointId = legacyEndpointId; | |
await store.write( | |
key: endpointIdStorageKey, | |
value: legacyEndpointId, | |
); | |
} | |
// Update the version to prevent future legacy data migrations. | |
await store.write( | |
key: EndpointStoreKey.version.name, | |
value: EndpointStoreVersion.v1.name, | |
); | |
} | |
// Read the existing ID. | |
fixedEndpointId ??= await store.read( | |
key: endpointIdStorageKey, | |
); | |
// Generate a new ID if one does not exist. | |
if (fixedEndpointId == null) { | |
fixedEndpointId = uuid(); | |
await store.write( | |
key: endpointIdStorageKey, | |
value: fixedEndpointId, | |
); | |
} | |
return fixedEndpointId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah while you were gone I had a single variable implementation beforehand as well. Your suggestion is close to what I had before.
But previous comments suggested a different approach.
This is clearly a bit subjective, let's use your suggestion here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My comments are not in conflict with Jordan's. He was confused about the duplication of logic and unnecessary reads/writes.
packages/analytics/amplify_analytics_pinpoint_dart/test/analytics_legacy_native_data_test.dart
Outdated
Show resolved
Hide resolved
packages/analytics/amplify_analytics_pinpoint_dart/lib/src/analytics_plugin_impl.dart
Outdated
Show resolved
Hide resolved
packages/analytics/amplify_analytics_pinpoint_dart/test/analytics_legacy_native_data_test.dart
Outdated
Show resolved
Hide resolved
packages/analytics/amplify_analytics_pinpoint_dart/test/analytics_legacy_native_data_test.dart
Outdated
Show resolved
Hide resolved
Extract endpoint id from Amplify iOS and Android Analytics
…/kotlin/com/amazonaws/amplify/amplify_analytics_pinpoint/amplify_analytics_pinpoint/AmplifyAnalyticsPinpointPlugin.kt Co-authored-by: Jordan Nelson <[email protected]>
….yaml Co-authored-by: Jordan Nelson <[email protected]>
Co-authored-by: Jordan Nelson <[email protected]>
e285a2b
to
f2f9e28
Compare
- fix(auth)!: Fetch Auth Session offline behavior ([aws-amplify#2585](aws-amplify#2585)) - fix(api): do not include null values in ModelMutations.create ([aws-amplify#2504](aws-amplify#2504)) - fix(api): model helpers use targetNames in schemas with CPK enabled ([aws-amplify#2559](aws-amplify#2559)) - fix(auth): Clear credentials before redirect on Web ([aws-amplify#2603](aws-amplify#2603)) - fix(auth): Refresh token in non-state machine calls ([aws-amplify#2572](aws-amplify#2572)) - fix(authenticator): ARB syntax ([aws-amplify#2560](aws-amplify#2560)) - fix(aws_common): AWSFile contentType getter should not throw exception - fix(datastore): prevent unhandled exception crashing App rebuilding sync expression - fix(storage): incorrect transferred bytes emitted from upload task - feat(analytics): Legacy data migration of Pinpoint Endpoint ID ([aws-amplify#2489](aws-amplify#2489)) - feat(smithy_aws): add copyWith to S3ClientConfig - feat(storage): allow configuring transfer acceleration Updated-Components: Amplify Flutter, Amplify Dart, Amplify UI, DB Common, Secure Storage, AWS Common, Smithy, Worker Bee
- fix(auth)!: Fetch Auth Session offline behavior ([aws-amplify#2585](aws-amplify#2585)) - fix(api): do not include null values in ModelMutations.create ([aws-amplify#2504](aws-amplify#2504)) - fix(api): model helpers use targetNames in schemas with CPK enabled ([aws-amplify#2559](aws-amplify#2559)) - fix(auth): Clear credentials before redirect on Web ([aws-amplify#2603](aws-amplify#2603)) - fix(auth): Refresh token in non-state machine calls ([aws-amplify#2572](aws-amplify#2572)) - fix(authenticator): ARB syntax ([aws-amplify#2560](aws-amplify#2560)) - fix(aws_common): AWSFile contentType getter should not throw exception - fix(datastore): prevent unhandled exception crashing App rebuilding sync expression - fix(storage): incorrect transferred bytes emitted from upload task - feat(analytics): Legacy data migration of Pinpoint Endpoint ID ([aws-amplify#2489](aws-amplify#2489)) - feat(smithy_aws): add copyWith to S3ClientConfig - feat(storage): allow configuring transfer acceleration Updated-Components: Amplify Flutter, Amplify Dart, Amplify UI, DB Common, Secure Storage, AWS Common, Smithy, Worker Bee
* chore(repo): Update component definition Adds `amplify_api_dart` to the mix and creates components for DB Common, Secure Storage, and AWS Common * fix(aft): Update changelog logic For the version commit message changelog, only include publishable packages. Also updates base ref logic to ensure packages can be moved in and out of components. * chore(version): Bump version - fix(auth)!: Fetch Auth Session offline behavior ([#2585](#2585)) - fix(api): do not include null values in ModelMutations.create ([#2504](#2504)) - fix(api): model helpers use targetNames in schemas with CPK enabled ([#2559](#2559)) - fix(auth): Clear credentials before redirect on Web ([#2603](#2603)) - fix(auth): Refresh token in non-state machine calls ([#2572](#2572)) - fix(authenticator): ARB syntax ([#2560](#2560)) - fix(aws_common): AWSFile contentType getter should not throw exception - fix(datastore): prevent unhandled exception crashing App rebuilding sync expression - fix(storage): incorrect transferred bytes emitted from upload task - feat(analytics): Legacy data migration of Pinpoint Endpoint ID ([#2489](#2489)) - feat(smithy_aws): add copyWith to S3ClientConfig - feat(storage): allow configuring transfer acceleration Updated-Components: Amplify Flutter, Amplify Dart, Amplify UI, DB Common, Secure Storage, AWS Common, Smithy, Worker Bee --------- Co-authored-by: Dillon Nys <[email protected]>
Issue #, if available:
Description of changes:
Add code to extract the previous Analytics Pinpoint Endpoint ID stored in Android or iOS.
Users upgrading to our next release won't have their Pinpoint Endpoint regenerated and can keep pinpoint session on a given user device between the upgrade.
Testing
Before, when upgrading Analytics, a new Pinpoint ID would be assigned. This causes the AWS Pinpoint console to register a new endpoint and therefore increment the 'daily active endpoint' in the analytics dashboard. This is problematic because Pinpoint is now detecting a new user.
With this change, when upgrading and running the same Analytics app on the same device, the 'daily active endpoint' number should NOT increment.
You can test this by modifying the Analytics example app pubspec.yaml to use 0.6.1 and to remove the local path dependencies. You will also need to delete the pubspec_overrides.yaml generated by aft bootstrap. Then modify example app's main.dart to simply add the analytics/auth plugins (in dart first there are new initialization options). Run the app and verify the AWS console registers your session and 'daily active endpoint' increases by 1. Afterwards, undo the previous changes and run the Analytics dart first version. The code will now retrieve the old pinpoint id, and thus 'daily active endpoint' will not increment.
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.