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

perf: Fix app freeze after login #20729

Merged
merged 19 commits into from
Jul 26, 2024
Merged

Conversation

ilmotta
Copy link
Contributor

@ilmotta ilmotta commented Jul 11, 2024

Summary

This PR does a few things to reduce the initial load and make the app more responsive after login. The scenario we are covering in this PR is a user who joined communities with a large number of members and/or which contain token-gated channels with many members.

  • Optimize how we convert a community from JS to CLJS. Community members and chat members are no longer transformed to CLJS, they are kept as JS. Read more details below.
  • Delay processing lower-priority events by creating a third login phase. The goal is to not put on the same queue we process communities less important events, like fetching the count of unread notifications. Around 15 events could be delayed without causing trouble (and this further prevent a big chain of more events to be dispatched right after login).
  • Edit: removed due to uncertainty, check out the discussion: perf: Fix app freeze after login #20729 (comment) Use re-frame's support for the flush-dom metadata whenever a signal arrives. According to the official documentation, this should tell re-frame to only process the event after the UI has been updated. It's hard to say if this makes any difference, but the theory is sound.
  • Reduce the amount of data returned to the subscription that renders a list of communities. We were returning too much, like all members, chats, token permissions, etc.

Other things I fixed or improved along the way:

  • Because members are now stored as JS, I took the opportunity to fix how members are sorted when they are listed.
  • Removed a few unused subs.
  • Configured oops to not throw during development (in production the behavior is to never throw). This means oops is now safe to be used instead of interop that can mysteriously fail in advanced compilation.
  • Show compressed key instead of public key in member list for the account currently logged in.

Technical details

The number one reason affecting the freeze after login was coming from converting thousands of members inside communities and also because we were doing it in an inefficient way using clojure.walk/stringify-keys. We shouldn't also transform that much data on the client as the parent issue created by @flexsurfer correctly recommends. Ever since this PR #20414 was merged, status-go doesn't return members in open channels, which greatly helps, for example, to load the Status community. The problem still exists for communities with token-gated channels with many members.

The current code in develop does something quite inefficient: it fetches the communities, then transforms them recursively with js->clj and keywordizes keys, then transforms again all the potentially thousands of member IDs back to strings. This PR changes this. We now shallowly convert a community and ignore members because they can grow too fast. From my artificial benchmarks simulating many members in token-gated channels, or communities with thousands of members, the difference is night and day when the app loads.

Is this PR really better than develop?

You will only really notice improvements if you have spectated or joined a community with 1000+ members and/or a community with many token-gated channels, each containing perhaps hundreds of members.

To me, as a member of the Status community, in this particular scenario I see no freeze on Android or iOS, from the develop branch and from this PR. Therefore, this PR is not making things worse, but it's a significant improvement to handle communities with more members.

What's the ideal solution?

I think in the future, community members and channel members should be removed from the community entity returned by status-go entirely and be a separate resource and paginated. This would allow us to remove custom code to optimize and scale better even in the face of much larger communities than Status.

Why not use bean?

Members' data is only ever used when the user wants to see community/channel members, and we only care about the members' IDs (a JS array of IDs), so I thought there wouldn't be much to gain from using cljs-bean. But I'm very curious to know how re-frame would behave with beans stored in the app-db.

Areas that may be impacted

Login, community, and channel members' list.

Steps to test

This PR is hard to test in terms of performance unless you can test with a community larger than Status, with a lot more members. I recommend the focus should be on the functionality first, checking that there are no regressions for data we know has to be loaded after login, like contacts, notifications, communities, channels, etc.

When listing channel members, currently in develop we are sorting by public key due to an incorrect implementation. That's why it looks as if it's random. This PR now sorts members by their displayed name. If we want to improve sorting even further I think we can this to a new issue because I had to fix just because the performance improvements required that.

status: ready

Risk

Low risk, but a dev & QA testing would be great.

@ilmotta ilmotta self-assigned this Jul 11, 2024
@ilmotta ilmotta marked this pull request as draft July 11, 2024 19:43
@status-im-auto
Copy link
Member

status-im-auto commented Jul 11, 2024

Jenkins Builds

Click to see older builds (42)
Commit #️⃣ Finished (UTC) Duration Platform Result
7a0c3a6 #1 2024-07-11 19:46:42 ~2 min tests 📄log
✔️ 7a0c3a6 #1 2024-07-11 19:50:29 ~6 min android-e2e 🤖apk 📲
da37a5a #2 2024-07-11 19:53:30 ~2 min tests 📄log
✔️ da37a5a #2 2024-07-11 19:57:42 ~7 min android-e2e 🤖apk 📲
✔️ da37a5a #2 2024-07-11 19:57:55 ~7 min android 🤖apk 📲
✔️ da37a5a #2 2024-07-11 20:00:41 ~10 min ios 📱ipa 📲
✔️ 2dbe4cd #3 2024-07-11 20:45:37 ~4 min tests 📄log
✔️ 2dbe4cd #3 2024-07-11 20:49:08 ~8 min android-e2e 🤖apk 📲
✔️ 2dbe4cd #3 2024-07-11 20:49:15 ~8 min android 🤖apk 📲
✔️ 2dbe4cd #3 2024-07-11 20:50:29 ~9 min ios 📱ipa 📲
✔️ 1e2e180 #4 2024-07-11 21:30:12 ~3 min tests 📄log
✔️ 1e2e180 #4 2024-07-11 21:33:38 ~7 min android-e2e 🤖apk 📲
✔️ 1e2e180 #4 2024-07-11 21:33:40 ~7 min android 🤖apk 📲
✔️ 1e2e180 #4 2024-07-11 21:36:21 ~10 min ios 📱ipa 📲
5ae8fa2 #5 2024-07-12 13:02:39 ~2 min tests 📄log
✔️ 5ae8fa2 #5 2024-07-12 13:07:51 ~7 min android-e2e 🤖apk 📲
✔️ 5ae8fa2 #5 2024-07-12 13:07:55 ~7 min android 🤖apk 📲
✔️ 5ae8fa2 #5 2024-07-12 13:10:40 ~10 min ios 📱ipa 📲
a53e41e #6 2024-07-12 18:06:05 ~2 min tests 📄log
✔️ a53e41e #6 2024-07-12 18:09:59 ~6 min android 🤖apk 📲
✔️ a53e41e #6 2024-07-12 18:11:54 ~8 min android-e2e 🤖apk 📲
✔️ a53e41e #6 2024-07-12 18:14:41 ~11 min ios 📱ipa 📲
✔️ 5096da6 #7 2024-07-15 19:14:42 ~4 min tests 📄log
✔️ 5096da6 #7 2024-07-15 19:18:38 ~8 min android-e2e 🤖apk 📲
✔️ 5096da6 #7 2024-07-15 19:18:40 ~8 min android 🤖apk 📲
✔️ 5096da6 #7 2024-07-15 19:19:48 ~9 min ios 📱ipa 📲
✔️ 0de002c #8 2024-07-15 21:08:25 ~4 min tests 📄log
✔️ 0de002c #8 2024-07-15 21:11:44 ~7 min android-e2e 🤖apk 📲
✔️ 0de002c #8 2024-07-15 21:11:50 ~7 min android 🤖apk 📲
✔️ 0de002c #8 2024-07-15 21:13:58 ~9 min ios 📱ipa 📲
✔️ 0b0b452 #9 2024-07-15 22:20:11 ~4 min tests 📄log
✔️ 0b0b452 #9 2024-07-15 22:23:51 ~8 min android-e2e 🤖apk 📲
✔️ 0b0b452 #9 2024-07-15 22:23:52 ~8 min android 🤖apk 📲
✔️ 0b0b452 #9 2024-07-15 22:25:00 ~9 min ios 📱ipa 📲
✔️ 8015b0d #10 2024-07-22 02:33:05 ~4 min tests 📄log
✔️ 8015b0d #10 2024-07-22 02:36:18 ~7 min android 🤖apk 📲
✔️ 8015b0d #10 2024-07-22 02:36:29 ~7 min android-e2e 🤖apk 📲
✔️ 8015b0d #10 2024-07-22 02:38:29 ~9 min ios 📱ipa 📲
✔️ 5fa5d8d #11 2024-07-22 02:47:32 ~4 min tests 📄log
✔️ 5fa5d8d #11 2024-07-22 02:51:13 ~8 min android-e2e 🤖apk 📲
✔️ 5fa5d8d #11 2024-07-22 02:51:22 ~8 min android 🤖apk 📲
✔️ 5fa5d8d #11 2024-07-22 02:52:20 ~9 min ios 📱ipa 📲
Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ ffdc8b1 #12 2024-07-25 01:50:06 ~4 min tests 📄log
✔️ ffdc8b1 #12 2024-07-25 01:51:56 ~6 min android 🤖apk 📲
✔️ ffdc8b1 #12 2024-07-25 01:53:07 ~7 min android-e2e 🤖apk 📲
✔️ ffdc8b1 #12 2024-07-25 01:55:27 ~9 min ios 📱ipa 📲
✔️ 1a5d675 #13 2024-07-26 00:07:09 ~4 min tests 📄log
✔️ 1a5d675 #13 2024-07-26 00:09:47 ~7 min android 🤖apk 📲
✔️ 1a5d675 #13 2024-07-26 00:09:48 ~7 min android-e2e 🤖apk 📲
✔️ 1a5d675 #13 2024-07-26 00:22:35 ~20 min ios 📱ipa 📲

@ilmotta ilmotta force-pushed the ilmotta-20283/fix-freeze-after-login branch 4 times, most recently from 5ae8fa2 to a53e41e Compare July 12, 2024 18:03
@pavloburykh pavloburykh self-assigned this Jul 12, 2024
@ilmotta ilmotta force-pushed the ilmotta-20283/fix-freeze-after-login branch 3 times, most recently from 0de002c to 0b0b452 Compare July 15, 2024 22:15
@ilmotta ilmotta changed the title [WIP] perf: Fix app freeze after login perf: Fix app freeze after login Jul 15, 2024
@ilmotta ilmotta marked this pull request as ready for review July 15, 2024 22:19
Copy link
Contributor

@ulisesmac ulisesmac left a comment

Choose a reason for hiding this comment

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

Hey @ilmotta

Thank you for this PR. It's great to see performance improvements!

I've left some comments and questions 👍

src/native_module/core.cljs Show resolved Hide resolved
;; been updated, i.e., after the next Reagent animation frame. In such a
;; case, the event should be dispatched with :flush-dom metadata. For more
;; details, check re-frame's source code and documentation.
(re-frame/dispatch ^:flush-dom [:signals/signal-received raw-event])))
Copy link
Contributor

Choose a reason for hiding this comment

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

So, is this a way to schedule this event until the end of the frame?

Is this the same as wrapping the event in js/requestAnimationFrame? 🤔

If so, I thought reagent (an so re-frame) already executed their tasks at the end of the frame by default.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The comment I added is a copy & paste from the documentation. I'm taking re-frame's word for this, check it out from the docs https://github.com/day8/re-frame/blob/09e2d7132c479aa43f2a64164e54e42bf8511902/docs/Solve-the-CPU-hog-problem.md#L195:

In these kinds of cases, where you are only going to give the UI 
**one chance to update** (not a repeated chance every few milliseconds), 
then you had better be sure the DOM is fully synced. 

To do this, you put metadata on the event being dispatched:

(re-frame.core/reg-event-fx
  :process-x
  (fn 
    [{db :db} event-v]
    {:dispatch  ^:flush-dom [:do-work-process-x]   ;; <--- NOW WITH METADATA         
     :db (assoc  db  :processing-X true)}))  ;; so the modal gets rendered

Notice the `^:flush-dom` metadata on the event being dispatched.  Use 
that when you want the UI to be fully updated before the event dispatch 
is handled. 

You only need this technique when you: 

  1. want the DOM to be fully updated
  2. because you are going to hog the CPU for a while and not give it back. One chunk of work.

If you handle via multiple chunks you don't have to do this, because 
you are repeatedly handing back control to the browser/UI.  Its just 
when you are going to tie up the CPU for a one, longish chunk. 

The key part for me was Use that when you want the UI to be fully updated before the event dispatch is handled. Which I'm assuming is a good thing because we don't want signals dispatching :signals/signal-received to immediately interrupt anything, they can wait a tiny bit.

That's why I said the theory is sound, but I couldn't measure differences, but sounds good on paper. Could it have side-effects? I really can't tell.

I can clearly see this technique being useful (again, in theory) in places where we still use rf/merge because they hog the CPU for longer in one chunk.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Another piece of the docs:

;;   - when the event has :flush-dom metadata we schedule via
;;       "reagent.core.after-render"
;;     which will run event processing after the next Reagent animation frame.

It sounds good on paper for processing signal events. Or do you have reservations?

Copy link
Contributor

Choose a reason for hiding this comment

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

Now I'm having more questions.

  1. Does this metadata work on the re-frame/dispatch call or just when we are inside an event handler?

  2. I misunderstood and compared it with js/requestAnimationFrame, but I think it works the same as dispatch-sync, am I right? could we use it instead?

  3. Which I'm assuming is a good thing because we don't want signals dispatching :signals/signal-received to immediately interrupt anything, they can wait a tiny bit.

    So, are you trying to delay the execution of the event? 🤔 if so, I think you don't want to use this approach.

I know one or two places in the wallet where this can be used, sometimes we navigate but the re-frame data is not ready yet, so we could dispatch with this metadata so that we don't wait for one frame more. In the past I managed to solve it by delaying the navigation one frame (js/requestAnimationFrame), but the team didn't like this approach, you may remember it:

And the other usage is when we navigate to view a collectible, we store it in re-frame, but it's not ready until the next frame, so we have a one-frame blink

Copy link
Contributor

Choose a reason for hiding this comment

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

Regarding to rf/merge yes, I think it can be applied there if there's much work to do

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 know as much as you about this part @ulisesmac.

I think the implications of this metadata should be explored simply because it's there already for us to be used. It should only make a difference in signals that are handled in the same chunk as :signals/signal-received. So for instance, this means the second dispatch to handle a wallet signal won't be affected by the metadata optimization, but a signal like "envelope.sent" should be affected because it uses rf/merge.

Does this metadata work on the re-frame/dispatch call or just when we are inside an event handler?

I think it works only for the immediate handler. Further re-dispatches from the handler will be treated the same. This metadata is useful in events that are more expensive, as they say in the docs.

So, are you trying to delay the execution of the event?

Correct, this is a form of delaying, telling re-frame that the handler for a signal should be processed only after the next Reagent animation frame.

Does this metadata work on the re-frame/dispatch call or just when we are inside an event handler?

dispatch-sync would be the opposite of what I tried in this PR because it would immediately process a signal, without enqueueing, which would more likely affect responsiveness when there are too many (more important) events competing for resources.

I know one or two places in the wallet where this can be used

It would quite useful if we could experiment with this metadata with real data, as in the wallet, and start to get a feeling of it based on profiling. If it proves to be useless we can always take it away easily.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hey @ilmotta Now I'm not sure if the metadata :flush-dom executes everything "now" or delay the next execution. I personally understand it as a way of dispatch-sync but for content that is inside event handlers. So:

Correct, this is a form of delaying, telling re-frame that the handler for a signal should be processed only after the next Reagent animation frame.

As far as I understand, by default they are executed at the end of the frame, if you are willing to delay it even one frame more, you can wrap it use js/requestAnimationFrame or reagent/next-tick (they should be exactly the same in React Native).

dispatch-sync would be the opposite of what I tried in this PR
What you did in this PR and dispatch-sync are, according to what I see, the same thing, not the opposite. But we may need to read the source code to properly understand what is happening.

I've done a test where I know re-frame, sometimes, takes one frame more to propagate the given DB state.
Please consider replicating this example, and it'd be great if it's part of this PR (or should I open a new issue PR for it?)

  1. In status-im.contexts.wallet.collectible.view move the collectible binding in collectible-details outside the render function:
    image

  2. In status-im.contexts.wallet.collectible.events inside the event handler for :wallet/navigate-to-collectible-details we navigate to the collectible page delaying the navigation 17ms (slightly more than a frame). So that re-frame propagates its state:
    image

  3. If we use a regular dispatch:

    image

    And with the changes in 1, once the collectible value is defined, it'll never be updated, so if the image is not found and we'll get an error in the UI, here is a video of it, it works as expected:

    Screencast.from.2024-07-19.14-32-15.mp4

    As said before, re-frame sometimes is not able to propagate its DB state on time.

  4. Now let's just add the metadata :flush-dom,
    image

    The app now looks smoother and NEVER fails to propagate the data on time:

    Screencast.from.2024-07-19.14-36-08.mp4

So, :flush-dom seems like a way of dispatch-sync 🤔 for the event where it's used (not the vent marked with the metadata).

WDYT?

Copy link
Contributor Author

@ilmotta ilmotta Jul 22, 2024

Choose a reason for hiding this comment

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

Very interesting results @ulisesmac 💯 Happy to see a problem could be solved by the metadata.

But I'm going to remove the metadata from this PR and then we can introduce it with a separate PR focusing on solving a specific problem. I hope that's okay for you :) The thing is that this PR still needs to be QAed, and I'm a bit weary it could introduce a small regression based on our investigations, and since this is maybe the last week before cutting the release branch 🤷🏼 And I still would like to get more approvals if possible.

So, :flush-dom seems like a way of dispatch-sync 🤔 for the event where it's used (not the vent marked with the metadata).

The implementation of dispatch-sync is different, we can see that it literally skips the queue, whereas normal dispatch calls (push event-queue event). I prefer to not think of it as dispatch sync for that reason. I saw that there are lots of little comments about the metadata sprinkled in re-frame's source. The comments mention that it can "pause processing". This confused me and it's now unclear to me exactly what the metadata does and I don't trust the docs anymore. For example:

Copy link
Contributor

Choose a reason for hiding this comment

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

But I'm going to remove the metadata from this PR and then we can introduce it with a separate PR focusing on solving a specific problem.

Sounds good! @ilmotta

The comments mention that it can "pause processing". This confused me and it's now unclear to me exactly what the metadata does and I don't trust the docs anymore. For example:

We can ask in the Clojurians Slack, it's a bit confusing.

Thank you so much for sharing this info 👍 👍

src/status_im/setup/oops.cljs Show resolved Hide resolved
src/status_im/subs/communities.cljs Show resolved Hide resolved
src/utils/transforms.cljs Show resolved Hide resolved
src/utils/transforms_test.cljs Outdated Show resolved Hide resolved
Copy link
Contributor

@ulisesmac ulisesmac left a comment

Choose a reason for hiding this comment

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

@ilmotta

As I've discussed with you before, I still think we could implement a priority queue to process events automatically by batches and by priority so that no matter the amount of work, the app is always (or almost always) responsive, ideally everything would go through that queue. But I understand this is not the focus of this PR and the soultion requires time to investigate if it's reliable or not.

On the other hand, having arbitrary timeouts to delay a processing might not be enough for some phones or datasets, also they require a manual measurement.

Besides that, I completely think this PR is going in the right way, thanks for paying attention to the login process! 💯

@ilmotta
Copy link
Contributor Author

ilmotta commented Jul 19, 2024

On the other hand, having arbitrary timeouts to delay a processing might not be enough for some phones or datasets, also they require a manual measurement.

Besides that, I completely think this PR is going in the right way, thanks for paying attention to the login process! 💯

Thank you so much for your thoughtful review @ulisesmac ❤️

On the other hand, having arbitrary timeouts to delay a processing might not be enough for some phones or datasets, also they require a manual measurement.

Agreed 👍🏼

As I've discussed with you before, I still think we could implement a priority queue to process events automatically by batches and by priority so that no matter the amount of work, the app is always (or almost always) responsive, ideally everything would go through that queue. But I understand this is not the focus of this PR and the soultion requires time to investigate if it's reliable or not.

The custom queue idea deserves exploration, it sounds too good on paper to ignore because we know from OSes that we can optimize a scheduler for responsiveness and minimal latency. Perhaps re-frame's algorithm is not the best for us. I will create an issue to capture this idea once and for all, and maybe somebody can pick it up when feeling adventurous.

@ilmotta ilmotta force-pushed the ilmotta-20283/fix-freeze-after-login branch from 0b0b452 to 8015b0d Compare July 22, 2024 02:28
@status-im-auto
Copy link
Member

59% of end-end tests have passed

Total executed tests: 51
Failed tests: 20
Expected to fail tests: 1
Passed tests: 30
IDs of failed tests: 702845,702840,702894,703086,702947,702958,702786,702844,702841,702839,702809,702838,704615,702948,702859,703629,702869,702957,702843,703194 
IDs of expected to fail tests: 727232 

Failed tests (20)

Click to expand
  • Rerun failed tests

  • Class TestActivityMultipleDevicePR:

    1. test_activity_center_reply_read_unread_delete_filter_swipe, id: 702947

    Device 1: Tap on found: Button
    Device 1: Find `Button` by `xpath`: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user2']`

    Test setup failed: activity_center/test_activity_center.py:270: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    Device sessions

    Class TestCommunityMultipleDeviceMergedTwo:

    1. test_community_leave, id: 702845

    Test setup failed: critical/chats/test_public_chat_browsing.py:864: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    2. test_community_mentions_push_notification, id: 702786

    Device 1: Tap on found: Button
    Device 1: Find Button by xpath: //*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']

    Test setup failed: critical/chats/test_public_chat_browsing.py:864: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    Device sessions

    3. test_community_markdown_support, id: 702809

    Test setup failed: critical/chats/test_public_chat_browsing.py:864: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    4. test_community_hashtag_links_to_community_channels, id: 702948

    Test setup failed: critical/chats/test_public_chat_browsing.py:864: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    5. test_community_join_when_node_owner_offline, id: 703629

    Test setup failed: critical/chats/test_public_chat_browsing.py:864: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    Class TestCommunityOneDeviceMerged:

    1. test_community_undo_delete_message, id: 702869

    Device 1: Tap on found: Button
    Device 1: Find Button by xpath: //*[@text="Undo"]

    critical/chats/test_public_chat_browsing.py:76: in test_community_undo_delete_message
        self.channel.element_by_text("Undo").click()
    ../views/base_element.py:92: in click
        element.click()
    ../../../../status-app-prs-rerun@tmp/venv/lib/python3.10/site-packages/selenium/webdriver/remote/webelement.py:94: in click
        self._execute(Command.CLICK_ELEMENT)
    ../../../../status-app-prs-rerun@tmp/venv/lib/python3.10/site-packages/selenium/webdriver/remote/webelement.py:395: in _execute
        return self._parent.execute(command, params)
    ../../../../status-app-prs-rerun@tmp/venv/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:345: in execute
        self.error_handler.check_response(response)
    ../../../../status-app-prs-rerun@tmp/venv/lib/python3.10/site-packages/appium/webdriver/errorhandler.py:122: in check_response
        raise exception_class(msg=message, stacktrace=format_stacktrace(stacktrace))
     The element 'By.xpath: //*[@text="Undo"]' does not exist in DOM anymore; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#stale-element-reference-exception
    E   Stacktrace:
    E   io.appium.uiautomator2.common.exceptions.StaleElementReferenceException: The element 'By.xpath: //*[@text="Undo"]' does not exist in DOM anymore
    E   	at io.appium.uiautomator2.model.ElementsCache.restore(ElementsCache.java:117)
    E   	at io.appium.uiautomator2.model.ElementsCache.get(ElementsCache.java:153)
    E   	at io.appium.uiautomator2.handler.Click.safeHandle(Click.java:36)
    E   	at io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:59)
    E   	at io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:277)
    E   	at io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:271)
    E   	at io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:68)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    E   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
    E   	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    E   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
    E   	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:435)
    E   	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
    E   	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)
    E   	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:250)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    E   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
    E   	at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:266)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    E   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
    E   	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1294)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    E   	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:911)
    E   	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
    E   	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:611)
    E   	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:552)
    E   	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:466)
    E   	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:438)
    E   	at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:140)
    E   	at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
    E   	at java.lang.Thread.run(Thread.java:1012)
    
    During handling of the above exception, another exception occurred:
    critical/chats/test_public_chat_browsing.py:78: in test_community_undo_delete_message
        pytest.fail("Can't press Undo button, not enough time")
    E   Failed: Can't press Undo button, not enough time
    



    Device sessions

    Class TestActivityMultipleDevicePRTwo:

    1. test_activity_center_admin_notification_accept_swipe, id: 702958

    Test setup failed: activity_center/test_activity_center.py:410: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    2. test_activity_center_mentions, id: 702957

    Device 1: Tap on found: Button
    Device 1: Find Button by xpath: //*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user2']

    Test setup failed: activity_center/test_activity_center.py:410: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    Device sessions

    Class TestCommunityMultipleDeviceMerged:

    1. test_community_emoji_send_copy_paste_reply, id: 702840

    Test setup failed: critical/chats/test_public_chat_browsing.py:344: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    2. test_community_contact_block_unblock_offline, id: 702894

    Test setup failed: critical/chats/test_public_chat_browsing.py:344: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    3. test_community_mark_all_messages_as_read, id: 703086

    Test setup failed: critical/chats/test_public_chat_browsing.py:344: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    4. test_community_links_with_previews_github_youtube_twitter_gif_send_enable, id: 702844

    Test setup failed: critical/chats/test_public_chat_browsing.py:344: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    5. test_community_unread_messages_badge, id: 702841

    Test setup failed: critical/chats/test_public_chat_browsing.py:344: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    6. test_community_message_delete, id: 702839

    Test setup failed: critical/chats/test_public_chat_browsing.py:344: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    7. test_community_message_send_check_timestamps_sender_username, id: 702838

    Device 1: Tap on found: Button
    Device 1: Find Button by xpath: //*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']

    Test setup failed: critical/chats/test_public_chat_browsing.py:344: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    Device sessions

    8. test_community_edit_delete_message_when_offline, id: 704615

    Test setup failed: critical/chats/test_public_chat_browsing.py:344: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    9. test_community_one_image_send_reply, id: 702859

    Test setup failed: critical/chats/test_public_chat_browsing.py:344: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    10. test_community_message_edit, id: 702843

    Test setup failed: critical/chats/test_public_chat_browsing.py:344: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    11. test_community_several_images_send_reply, id: 703194

    Test setup failed: critical/chats/test_public_chat_browsing.py:344: in prepare_devices
        self.community_1.invite_to_community(self.community_name, self.username_2)
    ../views/chat_view.py:487: in invite_to_community
        Button(self.driver, xpath=xpath).click()
    ../views/base_element.py:90: in click
        element = self.find_element()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by xpath: `//*[@content-desc='user-avatar']/following-sibling::android.widget.TextView[@text='user_2']` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    Expected to fail tests (1)

    Click to expand

    Class TestWalletOneDevice:

    1. test_wallet_add_remove_watch_only_account, id: 727232

    Device 1: Find EditBox by accessibility id: add-address-to-watch
    Device 1: Type 0x8d2413447ff297d30bdc475f6d5cb00254685aae to EditBox

    critical/test_wallet.py:249: in test_wallet_add_remove_watch_only_account
        self.wallet_view.add_watch_only_account(address=address_to_watch, account_name=new_account_name)
    ../views/wallet_view.py:163: in add_watch_only_account
        self.account_has_activity_label.wait_for_visibility_of_element()
    ../views/base_element.py:147: in wait_for_visibility_of_element
        raise TimeoutException(
     Device 1: Text by accessibility id:`account-has-activity` is not found on the screen after wait_for_visibility_of_element 
    

    [[Missing networks in account address, https://github.com//issues/20166]]

    Device sessions

    Passed tests (30)

    Click to expand

    Class TestWalletMultipleDevice:

    1. test_wallet_send_asset_from_drawer, id: 727230
    2. test_wallet_send_eth, id: 727229

    Class TestOneToOneChatMultipleSharedDevicesNewUiTwo:

    1. test_1_1_chat_mute_chat, id: 703496
    Device sessions

    2. test_1_1_chat_is_shown_message_sent_delivered_from_offline, id: 702783
    Device sessions

    3. test_1_1_chat_delete_via_long_press_relogin, id: 702784
    Device sessions

    Class TestDeepLinksOneDevice:

    1. test_links_deep_links, id: 702775
    Device sessions

    2. test_links_open_universal_links_from_chat, id: 704613
    Device sessions

    Class TestGroupChatMultipleDeviceMergedNewUI:

    1. test_group_chat_reactions, id: 703202
    Device sessions

    2. test_group_chat_join_send_text_messages_push, id: 702807
    Device sessions

    3. test_group_chat_offline_pn, id: 702808
    Device sessions

    4. test_group_chat_pin_messages, id: 702732
    Device sessions

    5. test_group_chat_send_image_save_and_share, id: 703297
    Device sessions

    6. test_group_chat_mute_chat, id: 703495
    Device sessions

    Class TestWalletOneDevice:

    1. test_wallet_add_remove_regular_account, id: 727231
    Device sessions

    Class TestCommunityOneDeviceMerged:

    1. test_community_copy_and_paste_message_in_chat_input, id: 702742
    Device sessions

    2. test_community_navigate_to_channel_when_relaunch, id: 702846
    Device sessions

    3. test_restore_multiaccount_with_waku_backup_remove_switch, id: 703133
    Device sessions

    4. test_community_mute_community_and_channel, id: 703382
    Device sessions

    5. test_community_discovery, id: 703503
    Device sessions

    Class TestActivityCenterContactRequestMultipleDevicePR:

    1. test_activity_center_contact_request_accept_swipe_mark_all_as_read, id: 702851
    Device sessions

    2. test_activity_center_contact_request_decline, id: 702850
    Device sessions

    3. test_add_contact_field_validation, id: 702777
    Device sessions

    Class TestOneToOneChatMultipleSharedDevicesNewUi:

    1. test_1_1_chat_edit_message, id: 702855
    Device sessions

    2. test_1_1_chat_message_reaction, id: 702730
    Device sessions

    3. test_1_1_chat_non_latin_messages_stack_update_profile_photo, id: 702745
    Device sessions

    4. test_1_1_chat_pin_messages, id: 702731
    Device sessions

    5. test_1_1_chat_text_message_delete_push_disappear, id: 702733
    Device sessions

    6. test_1_1_chat_push_emoji, id: 702813
    Device sessions

    7. test_1_1_chat_emoji_send_reply_and_open_link, id: 702782
    Device sessions

    8. test_1_1_chat_send_image_save_and_share, id: 703391
    Device sessions

    @pavloburykh
    Copy link
    Contributor

    Hey @ilmotta! Thanks for the PR. Please take a look at the issue.

    ISSUE 1 "[object Object] is bot ISeqable" when opening Invite people to contact list in community longtap menu

    Preconditions: User is a member of community and has at least 1 contact in contacts list

    Steps:

    1. Longtap on community
    2. Tap Invite people to contact list
    3. Observe the error

    Expected result: no error, contact list is opened.

    Actual result: app crashes with "[object Object] is bot ISeqable" error

    Status-debug-logs - 2024-07-22T120408.832.zip

    photo_2024-07-22 11 49 44

    telegram-cloud-document-2-5256000446484470926.mp4

    @VolodLytvynenko
    Copy link
    Contributor

    hi @ilmotta thank you for PR. No issues from my side. PR is ready to be merged

    @ilmotta ilmotta force-pushed the ilmotta-20283/fix-freeze-after-login branch from ffdc8b1 to 1a5d675 Compare July 26, 2024 00:02
    @ilmotta ilmotta merged commit c1d2d44 into develop Jul 26, 2024
    5 checks passed
    @ilmotta ilmotta deleted the ilmotta-20283/fix-freeze-after-login branch July 26, 2024 00:23
    ilmotta added a commit that referenced this pull request Jul 28, 2024
    We do a few things to reduce the initial load and make the app more responsive
    after login. The scenario we are covering is a user who joined communities with
    a large number of members and/or which contain token-gated channels with many
    members.
    
    - Related to #20283
    - Related to #20285
    
    - Optimize how we convert a community from JS to CLJS. Community members and
      chat members are no longer transformed to CLJS, they are kept as JS. Read more
      details below.
    - Delay processing lower-priority events by creating a third login phase. The
      goal is to not put on the same queue we process communities less important
      events, like fetching the count of unread notifications. Around 15 events
      could be delayed without causing trouble (and this further prevent a big chain
      of more events to be dispatched right after login).
    - Tried to use re-frame's flush-dom metadata, but removed due to uncertainty,
      check out the discussion:
      #20729 (comment)
      Use re-frame’s support for the flush-dom metadata whenever a signal arrives.
      According to the official documentation, this should tell re-frame to only
      process the event after the UI has been updated. It’s hard to say if this
      makes any difference, but the theory is sound.
    - Reduce the amount of data returned to the subscription that renders a list of
      communities. We were returning too much, like all members, chats, token
      permissions, etc.
    
    Other things I fixed or improved along the way:
    
    - Because members are now stored as JS, I took the opportunity to fix how
      members are sorted when they are listed.
    - Removed a few unused subs.
    - Configured oops to not throw during development (in production the behavior is
      to never throw). This means oops is now safe to be used instead of interop
      that can mysteriously fail in advanced compilation.
    - Show compressed key instead of public key in member list for the account
      currently logged in.
    
    Technical details
    
    The number one reason affecting the freeze after login was coming from
    converting thousands of members inside communities and also because we were
    doing it in an inefficient way using clojure.walk/stringify-keys. We shouldn't
    also transform that much data on the client as the parent issue created by
    flexsurfer correctly recommends. Ever since PR
    #20414 was merged, status-go
    doesn't return members in open channels, which greatly helps, for example, to
    load the Status community. The problem still exists for communities with
    token-gated channels with many members.
    
    The current code in develop does something quite inefficient: it fetches the
    communities, then transforms them recursively with js->clj and keywordizes keys,
    then transforms again all the potentially thousands of member IDs back to
    strings. This PR changes this. We now shallowly convert a community and ignore
    members because they can grow too fast. From artificial benchmarks simulating
    many members in token-gated channels, or communities with thousands of members,
    the improvement is noticeable.
    
    You will only really notice improvements if you have spectated or joined a
    community with 1000+ members and/or a community with many token-gated channels,
    each containing perhaps hundreds of members.
    
    What's the ideal solution?
    
    We should consider removing community members and channel members from the
    community entity returned by status-go entirely. The members should be a
    separate resource and paginated so that the client doesn't need to worry
    about the number of members, for the most part.
    ilmotta added a commit that referenced this pull request Jul 30, 2024
    Revisions from develop:
    
    - 59ceddb develop origin/develop fix(wallet): fix bridge transactions (#20902)
    - 99ccbc3 Cover wallet send events with tests Part 2 #20411 #20533 (#20721)
    - 8c2d539 Enabling WalletConnect feature flag (#20906)
    - 67c83b1 fix(wallet): remove edit routes button in bridging (#20874)
    - 11a84ba feat(wallet): disable complex routing (#20901)
    - 1f5bb57 chore(wallet): disable bridging on unsupported tokens (#20846)
    - 4586f80 Add toggle in advanced settings for mobile data
    - 55c620e fix: create password for small screen (#20645)
    - 525609f Wallet Activity: transactions are not sorted by time #20808 (#20862)
    - 9065395 chore(settings): Disable telemetry option (#20881)
    - d27ab75 fix_:display group message using the new ui (#20787)
    - c6a1db6 ci: enable split apks & build only for arm64-v8a (#20683)
    - 73777e0 Ensure keycard account can send transaction after upgrading from v1 to v2 #20552 (#20845)
    - a6d3fc3 [#20524] fix: the missed keypairs are shown in the key pair list screen (#20888)
    - a671c70 fix broken screen and navigation when syncing fails (#20887)
    - a45991b 🥅 Filter connected dapps based on testnet mode, reject proposals and requests gracefully (#20799)
    - 2e9fa22 feat: wallet router v2 (#20631)
    - 737d8c4 rename sub to fix error when requesting to join community (#20868)
    - 3aa7e10 Sync process is blocked on Enabled notifications screen (#20883)
    - c1d2d44 perf: Fix app freeze after login (#20729)
    - 0fed811 e2e: updated testnet switching and added one test into smoke
    - 53c35cb fix(wallet): Linear gradient exception on invalid colors for watched account cards (#20854)
    - be82365 chore(settings)_: Remove testnet toggle from legacy advanced settings (#20875)
    - eae8a65 feat(wallet)_: Add beta info box in activity tab (#20873)
    - fe54a25 fix: not clearing network & web3-wallet on logout (#20886)
    - 15a4219 Reject wallet-connect request by dragging the modal down (#20763) (#20836)
    - 2ffbdac WalletConnect show expired toast (#20857)
    - 402eb83 fix Issue with scrolling WalletConnect transaction on Android (#20867)
    - ff88049 Fix WalletConnect header alignment on Android (#20860)
    - cee2124 WalletConnect no internet edge-cases (#20826)
    - 60ad7c8 chore(tests): New match-strict? cljs.test directive (#20825)
    - 4989c92 fix_: Adding own address as saved addresses (#20839)
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    Archived in project
    Development

    Successfully merging this pull request may close these issues.

    5 participants