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

[POC] Move Model mappings to Background #2168

Closed
wants to merge 4 commits into from

Conversation

polqf
Copy link
Contributor

@polqf polqf commented Jul 14, 2022

🔗 Issue Links

https://stream-io.atlassian.net/browse/CIS-1854

🎯 Goal

The goal of this PR is to investigate the viability of moving the mapping of DTOs to Model to a background thread, reducing the pressure we put in the view/main thread.

📝 Summary

This PR introduces a new ListDatabaseObserver, matching the same API for simplicity purposes. This new object, named BackgroundListDatabaseObserver does exactly the same as its predecessor, but in a background and asynchronous way, and only notifies about results when those are already mapped.

🛠 Implementation

As of now:

  • The observer listens to a particular fetch request and processes the results of any update that might be coming from the Database
  • It converts the latest snapshot of DTOs into Models in a background thread, thus not leading to pressure on the main thread.
  • It calls its delegate (in this case a block) whenever all the objects have been parsed
  • Because all the mapped objects are assigned to a property on the same (internal) thread, that should result in no data races
  • CoreDataLazy is effectively disabled under the runtime flag _isLazyMappingEnabled

In order for background mapping to work, we cannot use the diffing mechanism on the messages list (for now)
There are several deficiencies that were found during this process and should be addressed before iterating this POC even further.

All this implementation is guarded now behind the following mechanisms:

  • ListDatabaseObserverWrapper, which based on a flag passed on init, internally uses either ListDatabaseObserver or BackgroundListDatabaseObserver
  • _isBackgroundMappingEnabled which enables the usage of BackgroundListDatabaseObserver
  • It is necessary to also disable _isLazyMappingEnabled when enabling _isBackgroundMappingEnabled

When using DemoApp-StreamDevelopers, it uses Background Mapping by default

☑️ Contributor Checklist

  • I have signed the Stream CLA (required)
  • Changelog is updated with client-facing changes
  • New code is covered by unit tests
  • This change follows zero ⚠️ policy (required)
  • Comparison screenshots added for visual changes
  • Affected documentation updated (docusaurus, tutorial, CMS)

🎁 Meme

@emerge-tools
Copy link

emerge-tools bot commented Jul 14, 2022

📏 Size Analysis

Total install size 9.4 MB | This change: ⬆️ +26.6 kB (+0.283%)

Image of diff

🗂 See size breakdown
Item Install size
➕ StreamChat.framework/StreamChat.BackgroundListDatabaseObserver.listenForRemoveAllDataNotifications ⬆️ 4.9 kB
➕ StreamChat.framework/StreamChat.BackgroundListDatabaseObserver.mapItems(completion) ⬆️ 4.5 kB
StreamChat.framework/StreamChat.LazyCachedMapCollection.init(source,map) ⬆️ 2.3 kB
➕ StreamChat.framework/StreamChat.BackgroundListDatabaseObserver.startObserving ⬆️ 2.1 kB
StreamChat.framework/StreamChat.CoreDataLazy.projectedValue.setter ⬆️ 1.9 kB
➕ StreamChat.framework/StreamChat.BackgroundListDatabaseObserver.init(context,fetchRequest,itemCreator,fetchedResultsControllerType) ⬆️ 1.8 kB
➕ StreamChat.framework/StreamChat.BackgroundListDatabaseObserver.processItems ⬆️ 1.5 kB
StreamChat.framework/StreamChat.ListDatabaseObserver.listenForRemoveAllDataNotifications ⬆️ 1.3 kB
➕ ChatSample/ChatSample.DemoAppConfiguration.showPerformanceTracker ⬆️ 1.0 kB
StreamChat.framework/StreamChat.ListChangeAggregator.controller(didChange,at,for,newIndexPath) 900 B
➕ StreamChat.framework/StreamChat.BackgroundListDatabaseObserver.Swift Metadata 511 B

🔎 See the full size analysis (b126fe1) merging into develop (8a01f51)

Provide a baseSha and pullRequestNumber with your upload to ensure diffs are correct. Read more in the docs

@Stream-SDK-Bot
Copy link
Collaborator

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

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 overall 👍 Just added some minor comments

import CoreData
import Foundation

class ListDatabaseObserverWrapper<Item, DTO: NSManagedObject> {
Copy link
Member

Choose a reason for hiding this comment

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

Since it looks like both ListDatabaseObserver's have the same API, instead of having the isBackground spread all over this wrapper, can't we export the API to a protocol, and set the ListDatabaseObserver implementation depending on the isBackground flag?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried the protocol approach but because of the generics it was not possible to then maintain certain APIs

/// When called, release the notification observers
private var releaseNotificationObservers: (() -> Void)?

private let queue = DispatchQueue.global()
Copy link
Member

Choose a reason for hiding this comment

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

Better to create a queue from scratch instead of using the global one

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, and might be good to specify qos in this case.

Copy link
Contributor

@martinmitrevski martinmitrevski left a comment

Choose a reason for hiding this comment

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

As we've discussed, we need to see what happens with the diffing solution, as well as the SwiftUI SDK (there are some glitches there).

@polqf
Copy link
Contributor Author

polqf commented Aug 16, 2022

Closed in benefit of #2237 with uses the new messages list

@polqf polqf closed this Aug 16, 2022
@polqf polqf deleted the feature/mappings-to-background branch August 16, 2022 10:21
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.

4 participants