Replies: 4 comments 3 replies
-
Wrote some thoughts here on ways to move towards local-first (must be a logged-in HackMD user to view): https://hackmd.io/BEH4VnnYTwacPo6zd_qp5w |
Beta Was this translation helpful? Give feedback.
-
I see in the docs that there is talk about marking zome calls as read only so that they can be re-run when there is new data that was understood as relevant to that zome function, and then return the result to the UI, so that the UI always has "the latest result for all these gets". If I understand correctly, the purpose of this is to move all the "query aggregator code" to the backend. With "query aggregator code" here I mean that code that, for a given non-content addressable query, filters, sorts and does some preprocessing to the query to return the relevant pieces of information. Let's play with a forum happ toy example: User Story: I want to see a list of all the posts within the app, sorted by "last created first". The "query aggregator code" here would be the piece of code that from a list of links, returns the list of action hashes for all the posts that I need to get to render the UI, in the form of The "query aggregator code" can live in either the UI or the backend. I see the effort to have subscription like zome calls backed by the intention to have it be in the backend. In my experience, this code is better suited to be in UI. Here is an example of why. Imagine we have the So... I think if we have the query aggregator code in the backend, that presents two problems:
I know we may be talking about sub-second intervals here, but it's what actually matters to have UIs feel good... It needs to feel alive. My current solution to this is holochain-based UI query aggregator code. This store maintains a list of the alive links for a given base and link type, by polling and listening to signals emitted in post-commit (these could be system-level signals), both I'm actually also finding that waiting for the signal to return is too slow. It takes just a little bit of time from the end of the zome call until the signal is received (maybe 300ms), and specially in mobile that time is seen by the user as "oh that didn't do anything - oh wait it did". I think what I'll need to do with this is have the UI await to receive the signal before actually resolving the I guess what I'm trying to say is that implementing the zome call subscription pattern adds a lot of complexity and magic that not all apps would necessary want in the same way, and it doesn't solve these issues. So I would be quite reluctant to go that path, at least from my experience and from where I'm standing right now... @mattyg I would be interested in knowing your experience in building UIs around this and what motivates you to want to move this logic to the backend. Happy that this is being talked about at the moment. It'll be exciting to be able to code real-time UIs in holochain really easily. |
Beta Was this translation helpful? Give feedback.
-
my suggestion would be to offer the additional two modalities and keep the existing default alongside greater front-end control with status signals (health service)
The NetworkSubscription call would immediately return with a subscription token so you can add callback function logic to the signal response array. In order to give the end-user more control or generally better UI/UX In the case of NetworkBlocking, it would be useful to implement sagas (mostly for holochain-as-a-server usecases). In addition for greater performance you could implement more of a CQRS like pattern. its generally a good idea to make all zome functions idempotent and not rely on the client code bouncing etc., the NetworkBlocking option would be better for non-idempotent zome functions of course. |
Beta Was this translation helpful? Give feedback.
-
Looks like we have a bunch of "network health" related information exposed to the admin api, but not the app api. I made an issue for it here: #3314 I also made another issue to track our "wish list" for additional network data we'd like exposed to the app api: #3315 |
Beta Was this translation helpful? Give feedback.
-
In #3221, I proposed to remove the notion of "joining the network". The basic reasoning is that "joining the network" is an abstract, fuzzy notion that can't be concretely determined. The real concrete things are connections to peers, but it's not straightforward to define how many peers you have to be connected to in order to be "online".
Moreover, we had apps set up to remain in a disabled state if the network could not be "joined". The reason for this was to try to ensure a good "online" experience for apps upon starting up, to avoid the confusion of an app which can't receive new data, and instead is timing out all of its requests, since it expects to be "online" but actually isn't. In 0.3.x, something shifted so that network join errors were much more prevalent, making this experience very common.
This safeguard is not robust or realistic though, because I might lose my ability to talk to peers at any time, not just at app startup. Apps need to be responsive to changing network conditions and should not assume they they are always-online. So that's what this discussion is about: what features and patterns do we need to empower apps to be respond to changing network conditions, and how do we best get there?
It's not enough to differentiate between an "offline" and an "online" state, in terms of internet connection or ability to see some "beacon". For instance, in a small network where only myself and one other node are connected, if my internet connection dies, it will be indistinguishable from if my counterpart turns off their laptop -- in both cases it will appear my connection to "the network" was severed, and in both cases the app should respond accordingly.
Namely, when I have limited or zero network availability, the app UI should display some indication of this, and potentially disable certain features. Offline functionality can continue to work, like viewing local and cached data and potentially even committing new data to your chain (with the caveat that it won't be published and potentially won't be able to pass validation).
What's needed
In my mind, there are a few things that need to be in place for this kind of robust local-first experience:
1 is something that needs to be added to Holochain: probably something like an enhanced
NetworkInfo
, which is already available in limited form over the App Interface2 is available in limited form through things like
GetStrategy::Content
, but it's not super well-defined, is not available for get_links, and in the wild it seems to be rarely used. These sorts of patterns could be expanded upon.3 is open territory. It could take the form of pub/sub, where we subscribe to data and then simply never get notified if we're offline, rather than blocking and waiting for data which may never come. It could also look like an adaptation of 2, where local get calls could trigger an async network request for the data and then send a signal when the data is ready to be re-queried through another local get. Either way, this seems to involve some sort of push-based model, but I'm not sure. The motivation is, when 1 fails and causes us to misjudge the network conditions (i.e. we think some peers are there but they really aren't), it would be nice to have a way of attempting to get stuff from the network that doesn't fail spectacularly when we misjudge (like a 60 second timeout).
I don't want this to be the definitive guide to what's needed but I want to get the ball rolling and seed the conversation with some initial directions to look in, and reflect some things some of us have already talked about. Other views welcome.
How to get there
Currently the only feasible option for getting data in most situations involves making blocking calls out to the network with 60 second timeouts. If full-on pub/sub turns out to be the best solution, we still want to provide a more gradual migration so that app devs don't have to suddenly change their entire data transfer paradigm overnight. This seems to fall under category 2 above.
There are already some front-end solutions to the local data fetching problem that are in general use, like @guillemcordoba's readable stores and tanstack/query (thanks @mattyg for the links). Since those kinds of patterns work well it would be nice to have Holochain work well as a backend to those patterns (currently a lot of solutions involve frequent polling, which is not ideal for performance).
Working Group
There is a lot to decide here, both short-term and long-term, and I imagine this discussion could be the start of a working group to address these questions. Whoever is interested and has bandwidth can help identify patterns and techniques and help write specs and maybe even PRs. These decisions have a large impact on app devs and of course Holochain users, and the decisions should come from those most affected. If there comes to be a time of high activity on this we could even have some regular meetings to keep the feedback loops tighter.
Beta Was this translation helpful? Give feedback.
All reactions