the new snapshot has support for dealing with return values from server mutations
but I think we found a bug in it...
In general, the recommended approach is to do a mutation with a follow-on remote read and a post-mutation. The new return value support makes that better, but unfortunately there was something amiss. Um...who was using that? Did we fix it? Sorry, lot's going on
@tony.kay I remember that I read you talking about it, the new return value support, but I can't remember how it was supposed to be used
The basic API is to install a return-handler
method at app start time, which hacks into the merge
See the parameter of that name in the client construction function
generally you'd make a multimethod on the symbol that has a RV, and co-locate the defmethod for the return next to the mutation
I think @jasonjckn was trying it out
cool, I'll check it out
the bug has to do with where in the process it runs
curiosity: how does the tx/fallback
captures an error above?
fallback runs if there is a real server hard error
e.g. throw an exception on server and generate a status code of 500
I think you have to throw an ex-info
fallbacks are about reallllly unhappy path
the behavioral tests on it pass, but the subtle problem is that the atom is hit twice and ends up undoing the return value's change
so someone needs to tinker with the plumbing to move that up. Haven't had time to look at it.
ha, now that you pointed out, my template actually had an example with it :picard-facepalm:
oh right...I knew I coded an example somewhere
it seems to be working
but I wish it provided the full enviroment, not just state
you're not in a parser at that stage, you're in a merge
which just means you should include context in the return value to reconstruct what you need
the bug is going to force a breaking change.
I remember the idea about colocating the response, do you think in our return-handler
we could just call the parser again and use a different target function to dispatch the response?
I don't have the query at that stage. It isn't passed through by Om
so, you'll have to put all needed info into your response.
which means you might have to pass extra info in the mutation itself
I'm not sure the rv handling really helps much. I think follow-on remote reads make more sense in most cases
validation, for example, is solved better by having a cljc file that makes validation possible on both sides without needing to worry about a response. Other responses would be better served (due to normalization needs) by asking a question of the server with a proper query as part of the overall transaction
which is the main reason I had never added it...I think in general most cases don't need it, or there is a better "Om" way of doing it.
what about validations that can't be handled on the client, for example to check if a user name is taken, what you think should be the common way to handle?
The double-swap problem in the current implementation just points out the additional incidental complexity of the overall solution required for return values to function properly in the context of Om
(load-data :name-taken :params { :desired-name "boo" })
with a UI query on [:name-taken '_]
in other words: ask 🙂
in my case, I'm currently trying to implement some authentication mechanisms. when you detect unauthorized access, you fail with some HTTP status or do something else?
there is a gamut of possibilities. Choose one in specific
password failure on login?
session expired, or user trying to access resources he doesn't own
probably a combo of throwing exceptions on the server and a global error handler in the client
those are global concerns
the first should go t a login screen. The second is someone trying to break in and should be considered less friendly (and common)...who cares how badly you treat an attacker?
easy enough to do the former via a js redirect
:network-error-callback
is a function of two arguments, the app state atom and the error, which will be invoked for
every network error (status code >= 400, or no network found), should you choose to use the built-in networking record.
from the client constructor
global network error handler
right, makes sense
I think the template demos login, right?
it does, I saw the tx/fallback example there
so, a mutation followed by a "who am I"
it uses local, not global handling
no big deal 🙂
that's fine too. Login is a localized concern. The ones you named are more global
expire and illegal can come from anywhere at any time
don't want to code fallback into everything
yeah, agreed
thanks @tony.kay! I'll go back to coding now 🙂
cool
welcome
Btw @tony.kay I tried the return-handler
and had lot’s of problems, the first one is that you get an app-state atom which will be overwritten by the merge. After that we tried to trigger a mutation from the return-handler
that somehow get’s run in the between the merge and also get overwritten.. :lol: Now we fixed it by wrapping our return handler in a setTimeout
, which works but feels dirty.
I think https://github.com/untangled-web/untangled-client/pull/53 this fixes it already ^^
@mitchelkuijpers: yes, but untested
Did it last minute yesterday
I am considering changing the api and putting it back in merge but making return handler be f state -> state instead of giving the atom.
Torn. The new way is probably better because it can be placed after post mutations
Ie using the atom but fixed
@tony.kay Or you could make an atom in the merge en then run them all and then dereference the atom and use that to merge on (that was the solution we thought of)
But running it after the merge also makes it possible to trigger transactions from the return handlers (although I am not sure you should do this)
Ah that's true, but seems silly to add an atom in fp for that
That’s true but then it feels like the same api as mutations..
When you put it that way the maybe pull request #53 is the right solutino
I'm headed to work now, I'll give it more thought on the wat
Way
I’ll wait it out, we have a hack for now 🙂
Always a good idea to let it simmer
So, my proposed fix doesn't work. That section only runs for queries
Thnx for the heads up @tony.kay So then it will probably become the f state -> state
. I’m off now if I think of a elegant solution I’ll let you know
Yeah, that's what I'm going to try next
Trying out untangled for first time using https://github.com/untangled-web/untangled-template-workspace. Doesn’t seem to be working out of the box. Client can’t reach server on localhost:3449/api
when running (start-figwheel)
. Also /cards.html
can’t find cards.js
. Am I missing something or is it still WIP?
you have to run the server
the instructions are pretty clear about how to use it, I thought. If you find an error let me know
ah, i had the server running but i was using 3449 instead of 3000 in browser
right....that too 😄
Do I need to run anything else for cards to build?
This did the trick (start-figwheel [:dev :cards])
FYI: I'm releasing an update to U.C. 0.6.0-SNAPSHOT which has a breaking change on the new return handler API. Details coming as soon as I've tested in against all of the cookbooks to make sure I've not broken anything.
Thanks for the heads up
ok, I just released 0.6.0 of Untangled Client to clojars
untangled-template-workspace and cookbook pushed with updated versions
http://github.com/untangled-web/untangled-template-workspace
I just pushed an updated devguide. I added documentation on the new load
function, as well as the mutation merge support. Both are in section H.
http://untangled-web.github.io/untangled/guide.html#!/untangled_devguide.H_Server_Interactions
The new load
should be considered of alpha quality, as we have not used it much yet. I'll be using it more heavily in the coming days and will bug fix things as I find them.
NOTE: cookbook now has a recipe showing a couple of working examples of the new load API: https://github.com/untangled-web/untangled-cookbook/tree/master/recipes/load-samples
does untangled have a built in helper for the pattern of conditionally doing a server read on df/load [x/by-id "123"] only if the data is not present in the app-state?