Fork me on GitHub
#re-frame
<
2020-02-02
>
mccraigmccraig11:02:43

so I'm wanting to implement retrying network ops for our mobile app, so missing content gets displayed when your phone gets signal again etc

mccraigmccraig11:02:30

but seems to be no longer favoured

mccraigmccraig11:02:38

is there another approach which would allow me to determine whether a particular request is "live" and should be retried, or is "stale" and can be forgotten about (because it relates to some no longer visible UI, or a disposed sub etc)

mikethompson11:02:46

I believe it it is best to keep all the logic, including retries and what to do on failure, etc, in event handlers. These handlers update app-db Subscriptions should just be about obtaining state from app-db and forming necessary materialised view of that data ...

mikethompson11:02:46

... so as to allow views to render the current state, which might be "loading" or "error" etc

mikethompson12:02:48

For example, I personally have never liked the idea of views being imperative and initiating server queries. Views should just render the state of the app.

mikethompson12:02:19

Same with subscriptions ... I don't (now) like the idea of them being imperative and initiating server requests

mikethompson12:02:48

That logic and all its consequences (timeouts, errors, etc) should happen in event handlers.

mccraigmccraig12:02:00

I'm there with the views, but the :on-dispose of the sub seems to offer capabilities which aren't available anywhere else...

mikethompson12:02:38

Event handlers are, to me, the only thing that should update state (in response to an error, or a timeout, etc)

mikethompson12:02:57

But, that's just me

p-himik12:02:59

If so, what would be the best way to implement the "whenever :x is changed in the DB, fire event :e" workflow? There's a number of ways I know of, none of which seem awfully practical.

p-himik12:02:35

The most practical one, probably, is to have a global interceptor that always checks the field.

mikethompson12:02:16

Yeah, I experimented with an interceptor for that scenario

mikethompson12:02:18

If that scenario was a recuring problem for me (which it isn't), I'd probably handle it the way that event sourcing works ...

mikethompson12:02:41

... I'd have event handler produce "notifications" when they made changes

mikethompson12:02:33

... as an effect ... and then have another entire set of "handlers" registered for certain kinds of notifications

mikethompson12:02:49

But that's only if it is a real problem

mikethompson12:02:54

(which it isn't for me)

mikethompson12:02:16

But I'm not sure we are answering @mccraigmccraig oringal question

mccraigmccraig12:02:31

I'm certainly not thinking of subs modifying any state, although i am maybe thinking along the lines of an fx for a sub

p-himik12:02:31

Yeah, that's my personal question. :) For the past 4 years, I have been developing a few fairly complex applications with multiple reusable components. Such a workflow happens there pretty regularly. Using explicit notification effects for this workflow automatically prohibits reusable components (some library may change :x and not send a notification, but I would still like that :e to get fired).

p-himik12:02:57

None of the "let the user handle it" solutions really work with anything that attempts to be reusable.

p-himik12:02:37

However, that would be possible in a not encumbering way with just a little help from re-frame - with a function like add-global-interceptor. At least, I think so.

mikethompson12:02:23

Checking: so you have no control over the components you are reusing?

mikethompson12:02:44

For example, no way to alter the registration of their handlers

mikethompson12:02:17

(to include more interceptors)

mikethompson12:02:37

BTW, in this regard I always liked the idea of precept https://github.com/CoNarrative/precept

p-himik12:02:03

Even if I have this control (I think I have - can't quickly check), it may not be the case for every future project, or for any other re-frame user.

mikethompson12:02:16

So, am i right in saying that your solution would be to register a global handler hook?

mikethompson12:02:26

You are making the case for that?

mikethompson12:02:42

Or global interceptor hook

mikethompson12:02:06

Or are you just floating the problem generally and shooting the breeze for solutions?

p-himik12:02:57

That's not a solution itself, but that would allow to implement a proper solution. I have thought about the problem quite a bit, and have implemented other solutions that I could think of that don't require any changes in re-frame. None of them was able to solve the problem in general.

mikethompson12:02:35

A good problem definition is always the first step ... so let me try to repeat back to you what I have got ATM ...

mikethompson12:02:28

1. You would like a mechanism to respond to arbitrary (event handler caused) changes at certain paths within app-db 2. The motivation comes from wanting to create, and consume re-useable components. In the case of consuming these components, you have no way to change them.

mikethompson12:02:56

Okay, sorry, i edited the above a few times

mikethompson12:02:48

@mccraigmccraig did I answer your question from before?

p-himik12:02:48

Yes, you got the points right. Also: 2.1. I want the solution to be robust. I don't want to introduce potential places where :x can change without firing :e, ever. For example, it means that even if I have control over every single piece, I don't want to add a {:notify-changed [:x]} effect into every single event handler that might change :x. It will be a nightmare to maintain.

mikethompson12:02:49

@p-himik I'm hitting the wall a bit here, because it is getting on to midnight and I have an early start tomorrow. Would you consider creating a re-frame issue to further refine the problem statement?

p-himik12:02:00

Of course!

mikethompson12:02:43

BTW, i have doodled around with these kinds of ideas previously ... https://gist.github.com/mike-thompson-day8/7c2d7e770b7bb6ff9627b08c3903a449

p-himik12:02:35

I'll read it, thanks!