Hi @RazvanFarte,
thanks for the detailed report. You touched quite a few separate topics, so I will go through them one by one. One thing up front: the “Extremely slow performance on Android” thread you refer to is an older post from before the current release, and a lot has changed since then.
Where we are today with sign-in
The “13 sequential calls” number is from an older version. In the current app (3.2.0) only five calls stand between tapping “sign in” and seeing the home screen: fetching the server PGP key and the RSA key (these two run in parallel, and they are fired early, while you are still on the passphrase screen, so they are usually done before you finish typing or unlock with biometrics), the login itself, feature flags and RBAC rules. Everything else was moved out of the way. Metadata type and key settings are now fetched inside the background refresh. Password policies, password expiry settings and user profile are fetched lazily, only when a screen actually needs them.
Where we are today with the data refresh
3.2.0 was, for the most part, a performance release. The main things that landed:
- items on a page are decrypted and validated in parallel, and this now applies to every entity type, not only resources
- resources, folders, users and groups are upserted and only rows that disappeared server-side are deleted, instead of wiping and re-inserting everything
- resource types are skipped entirely when nothing changed
- all database writes for a page happen in one transaction
- the extra toString re-serialization of v4 resources for schema validation is gone
- page size is now picked automatically based on the device tier, with the expert setting as an override
- a deterministic progress bar, so you can see where the refresh is
and a number of smaller things. We have internal design documents for both the sign-in work and the refresh work, if you want to dig in let me know.
Also please find the full changelog for 3.2.0 here - https://www.passbolt.com/changelog/android/passbolt-android-app-3-2-0.
The architecture migration
You asked about an ETA of MVI migration - it is fully done. All screens are now on the new architecture (MVI with Compose).
Your points / changes, one by one
Parallelizing the independent fetches. You are right that the TODO is still in our code. We agree it is a win, but a small one, because it only shortens the network part. The expensive part is what happens after the response arrives (decryption, validation, DB insert), and that part has to stay in a specific sequential order because of database constraints.
The 15 second debounce. I would be careful with this one. The extra refresh you are suppressing is mostly the one triggered after creating or editing a resource, and for those we already write the server response into the local database, so skipping the refresh is harmless. But delete and share do not do that yet, they rely on that automatic refresh to update the local data. With a debounce, delete a resource shortly after a refresh finishes and it will stay in your list until the next one. Replacing that post-action refresh with a direct local update is on our list, but note this does not change how long a single refresh takes, it only changes how often it runs.
Passphrase cache 5 to 30 minutes. This one does not do what you wrote it does. The passphrase cache only controls how long the passphrase stays in memory. When it expires the app simply asks for it again the next time it is needed. It never triggers a refresh, and re-entering the passphrase never triggers one either. So the change gained nothing for speed but keeps a secret in memory for a longer time. I would revert it.
Session key cache upload not blocking “sync finished”. You are right that it is the last step and the refresh waits for it. Two things that can change the full picture: 1) the upload is skipped when nothing changed locally 2) errors there do not fail the refresh. Making it fully asynchronous is possible, but only if we make sure a new refresh cannot start while the previous upload is still in progress. It is doable, it just needs care.
About the fixed cost per request
Here is what happens with each page that comes back from the server: it is parsed, each resource is decrypted (or the decryption is skipped if the modified date did not change), validated against the schema, and written into the encrypted local database. With each page there is additional network call, additional initialization cost, and after a page there is also a decryption library garbage collection call, which can be noticeable. That is why it is important to use as big page size as the device can handle and why we introduced the device class detection with predefined defaults with an option to bump that in settings manually.
That said, we do have a separate report open on GitHub (https://github.com/passbolt/mobile-passbolt-android/issues/35) where the encrypted preferences storage is recreated on every request and adds a noticeable delay per call on some devices. The pattern looks similar to what you measured, but we have not verified yet that it is the same thing. We are looking into it right now, and depending on what the measurements show it will land in 3.3.0 or 3.4.0. If the measured data in the issue is correct it can save time, but the decryption and validation still have to happen. If possible could you provide an app log from the device? Here are the instructions if needed https://www.passbolt.com/docs/hosting/maintenance/diagnostics/collect-info/#mobile-applications.
What a cold start looks like now
On the first start after sign-in you get the loading bar, there is no way around processing everything once. On every following start the list is shown immediately from the local database while the refresh runs in the background, and the app is usable in read-only mode during that time. Edits wait for the refresh to finish. In 3.2.0 we unfortunately introduced a bug where opening resource details also waits for the refresh with showing the secret section, which in practice blocks viewing a secret until the sync is done. That is fixed in 3.3.0 (MOB-4888), and we start regression tests and the release process next week. After the fix you can browse and read your secrets while the refresh is running, only editing still waits.
Server side
Nothing in Traefik or PHP-FPM will change this. The time is spent on the device, which matches your own measurements.
Summary
If you would like to investigate more with us, could you please:
- confirm which version your fork is based on? Is it current 3.2.0 release?
- share an app log from the device (instructions linked above)
- consider reverting the passphrase cache change and the debounce, for the reasons above
We will:
- verify whether the encrypted preferences overhead from the GitHub issue explains the per-request gaps you and the GitHub reporter see
- ship the resource details fix (MOB-4888) in 3.3.0 so secrets can be viewed during refresh
- in future versions: replace the automatic refresh after create, edit, delete and share with direct local updates