Skip to content
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

fix(analytics): iterate sqlite rows with failableNext #3857

Merged
merged 1 commit into from
Sep 16, 2024
Merged

Conversation

5d
Copy link
Member

@5d 5d commented Sep 9, 2024

Issue #

#3855

Description

The default iteration behavior for SQLite statement results uses try!, which throws a runtime error that can't be caught by Swift's standard do..try mechanism. Since the analytics category runs as a background monitoring thread, it shouldn't cause the app to enter an error state. Instead, use the alternative throwable API failableNext to avoid runtime errors.

General Checklist

  • Added new tests to cover change, if needed
  • Build succeeds with all target using Swift Package Manager
  • All unit tests pass
  • All integration tests pass
  • Security oriented best practices and standards are followed (e.g. using input sanitization, principle of least privilege, etc)
  • Documentation update for the change if required
  • PR title conforms to conventional commit style
  • New or updated tests include Given When Then inline code documentation and are named accordingly testThing_condition_expectation()
  • If breaking change, documentation/changelog update with migration instructions

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

if let event = PinpointEvent.convertToEvent(element) {
result.append(event)
do {
while let element = try rows.failableNext() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a scenario where the next row can fail, but subsequent rows can still be successfully retrieved?

If so, would it better (or even possible) to continue iterating through instead of bailing on the first error thrown?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, it didn’t fail while processing the iterator's current element. It failed when the iterator tried to get the next element, and there should be no more elements after that failure.

Copy link
Member

@ruisebas ruisebas Sep 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's funny is that I was gonna suggest the opposite: If we get an error when attempting to retrieve a subsequent row, we should fail the whole operation instead of just returning whatever results we have so far.

The way I see it is that we're explicitly running a SELECT query that we expect to contain the things we've asked, so just giving us back a subset of stuff just because the DB failed at some point sounds incorrect.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code here attempts to send as many events as possible. Please correct me if I'm wrong, but even if some events fail to process during the failableNext iteration, they will not be removed from the local database and will still be included in the results of the next flushEvent call.

In the case of issue #3855, the first failableNext call will fail due to data protection policy. I can modify the logic to propagate the error to the caller, rather than returning an array of results processed up to that point.

Copy link
Member

@ruisebas ruisebas Sep 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think just propagating the error would be enough, since it will be caught and handled by the callers of this method:

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 updated the PR to propagte the errors.

Copy link

codecov bot commented Sep 16, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 68.44%. Comparing base (4782923) to head (6e3889e).
Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3857      +/-   ##
==========================================
+ Coverage   68.40%   68.44%   +0.04%     
==========================================
  Files        1082     1082              
  Lines       37699    37699              
==========================================
+ Hits        25787    25804      +17     
+ Misses      11912    11895      -17     
Flag Coverage Δ
API_plugin_unit_test 69.35% <ø> (+0.03%) ⬆️
AWSPluginsCore 68.53% <ø> (ø)
Amplify 47.57% <ø> (+0.01%) ⬆️
Analytics_plugin_unit_test 84.52% <ø> (ø)
Auth_plugin_unit_test 79.52% <ø> (+0.18%) ⬆️
DataStore_plugin_unit_test 81.23% <ø> (-0.06%) ⬇️
Geo_plugin_unit_test 72.00% <ø> (ø)
Logging_plugin_unit_test 62.95% <ø> (ø)
Predictions_plugin_unit_test 36.86% <ø> (ø)
PushNotifications_plugin_unit_test 86.21% <ø> (ø)
Storage_plugin_unit_test 76.81% <ø> (ø)
unit_tests 68.44% <ø> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@5d 5d merged commit 39de25d into main Sep 16, 2024
136 checks passed
@5d 5d deleted the 5d/fix-sqlite-crash branch September 16, 2024 20:31
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.

3 participants