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

Improve database container read and reset #3365

Merged
merged 1 commit into from
Aug 7, 2024

Conversation

laevandus
Copy link
Contributor

@laevandus laevandus commented Aug 7, 2024

🔗 Issue Links

Resolves PBE-5422

🎯 Goal

Fix issues around database read wrappers and context resets

📝 Summary

  • One DatabaseContainer read uses DatabaseSession, the async one NSManagedObjectContext > unify to use DatabaseSession
  • Fix and issue where after logout contexts are not reset (keep referencing deleted objects)
  • Change the read assert to trigger only based on counts (did not find a way how to fix the issue of it keeping tracking deleted objects)

🧪 Manual Testing Notes

Case 1:
Log in and log out

Case 2:

  1. Open Demo Configuration Screen
  2. Enable Hard Delete Message
  3. Open a channel
  4. Hard delete a message
  5. Go to background
  6. Wait 1min ( or as soon as web-socket's disconnect is logged)
  7. Open the app again
  8. 💥

☑️ Contributor Checklist

  • I have signed the Stream CLA (required)
  • This change should be manually QAed
  • Changelog is updated with client-facing changes
  • Changelog is updated with new localization keys
  • New code is covered by unit tests
  • Comparison screenshots added for visual changes
  • Affected documentation updated (docusaurus, tutorial, CMS)

@laevandus laevandus added 🐞 Bug An issue or PR related to a bug 🤞 Ready For QA A PR that is Ready for QA labels Aug 7, 2024
@laevandus laevandus requested a review from a team as a code owner August 7, 2024 09:07
)
extraData = [:]
var extraData = [String: RawJSON]()
if !dto.user.extraData.isEmpty {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

If data is empty, error is logged which can happen when trying to convert deleted DTO

@@ -1154,6 +1154,53 @@ extension NSManagedObjectContext: MessageDatabaseSession {
$0.localState = .pendingUpload
}
}

func loadMessage(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved these under DatabaseSession so that I can use DatabaseSession in async version of the read()

Comment on lines +275 to +278
let changeCounts = context.currentChangeCounts()
let results = try actions(context)
if context.hasChanges {
assertionFailure("Background context is read only, but calling actions() created changes")
if changeCounts != context.currentChangeCounts() {
assertionFailure("Context is read only, but actions created changes: (updated=\(context.updatedObjects), inserted=\(context.insertedObjects), deleted=\(context.deletedObjects)")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Did not figure out why deleted message is kept tracked by the context which triggered this assert. Just changed it around so that we only trigger it when actually the actions closure changed something.

Comment on lines +332 to +343
// Finally reset states of all the contexts after batch delete and deletion propagation.
if let writableContext = self?.writableContext, let allContext = self?.allContext {
writableContext.invalidateCurrentUserCache()
writableContext.reset()

for context in allContext where context != writableContext {
context.performAndWait {
context.invalidateCurrentUserCache()
context.reset()
}
}
}
Copy link
Contributor Author

@laevandus laevandus Aug 7, 2024

Choose a reason for hiding this comment

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

Moved these here because context should be reset after we are done with the batch delete. Otherwise deletes stick around to contexts (because I added NSManagedObjectContext.mergeChanges above). Better to keep them clean when dealing with logout

@Stream-SDK-Bot
Copy link
Collaborator

SDK Size

title develop branch diff status
StreamChat 6.79MB 6.79MB 0.0MB 🟢
StreamChatUI 4.41MB 4.41MB 0.0MB 🟢

Copy link

github-actions bot commented Aug 7, 2024

1 Warning
⚠️ The changes should be manually QAed before the Pull Request will be merged
1 Message
📖 There seems to be app changes but CHANGELOG wasn't modified.
Please include an entry if the PR includes user-facing changes.
You can find it at CHANGELOG.md.

Generated by 🚫 Danger

@Stream-SDK-Bot
Copy link
Collaborator

SDK Performance

target metric benchmark branch performance status
MessageList Hitches total duration 10 ms 3.34 ms 66.6% 🔼 🟢
Duration 2.6 s 2.55 s 1.92% 🔼 🟢
Hitch time ratio 4 ms per s 1.32 ms per s 67.0% 🔼 🟢
Frame rate 75 fps 78.11 fps 4.15% 🔼 🟢
Number of hitches 1 0.4 60.0% 🔼 🟢
ChannelList Hitches total duration 12.5 ms 11.68 ms 6.56% 🔼 🟢
Duration 2.6 s 2.56 s 1.54% 🔼 🟢
Hitch time ratio 5 ms per s 4.58 ms per s 8.4% 🔼 🟢
Frame rate 72 fps 74.41 fps 3.35% 🔼 🟢
Number of hitches 1.2 1.0 16.67% 🔼 🟢

// Finally reset states of all the contexts after batch delete and deletion propagation.
if let writableContext = self?.writableContext, let allContext = self?.allContext {
writableContext.invalidateCurrentUserCache()
writableContext.reset()
Copy link
Member

Choose a reason for hiding this comment

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

Did you also tried reseting these context when a delete is performed on write function? (Not sure if this will do anything tho)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Did not test that. Slightly afraid to do it because we use these contexts for DB observers. Thinking about letting it be 😄

Copy link
Member

Choose a reason for hiding this comment

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

Yeah probably better 👍

Copy link
Member

Choose a reason for hiding this comment

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

Out of curiosity, I tested it and it works. Maybe if we still have problems with this in the future we can go back here and apply the following change before the CatabaseContainer.write :

if !self.backgroundReadOnlyContext.deletedObjects.isEmpty {
      self.backgroundReadOnlyContext.reset()
 }

Copy link
Member

@nuno-vieira nuno-vieira left a comment

Choose a reason for hiding this comment

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

LGTM! ✅

… where on logout contexts are referencing DTOs
@laevandus laevandus force-pushed the fix/database-container-read-and-reset branch from befe2cf to 1736ff7 Compare August 7, 2024 11:37
@Stream-SDK-Bot
Copy link
Collaborator

SDK Size

title develop branch diff status
StreamChat 6.73MB 6.73MB 0.0MB 🟢
StreamChatUI 4.41MB 4.41MB 0.0MB 🟢

Copy link

sonarqubecloud bot commented Aug 7, 2024

@testableapple testableapple added 🟢 QAed A PR that was QAed and removed 🤞 Ready For QA A PR that is Ready for QA labels Aug 7, 2024
Copy link
Contributor

@testableapple testableapple left a comment

Choose a reason for hiding this comment

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

LGTM 👍

@laevandus laevandus merged commit 05c210b into develop Aug 7, 2024
15 checks passed
@laevandus laevandus deleted the fix/database-container-read-and-reset branch August 7, 2024 17:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐞 Bug An issue or PR related to a bug 🟢 QAed A PR that was QAed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants