<div dir="ltr">On Thu, Jun 6, 2013 at 8:58 AM, Garrett Smith <span dir="ltr"><<a href="mailto:g@rre.tt" target="_blank">g@rre.tt</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi Paul,<br>
Sorry I'm not used to seeing questions about my Redis bindings<br>
graduate to the main list :)<br></blockquote><div><br></div><div>Hey, thanks for the reply. I asked on the list first because I didn't want to bug you on github until I was more confident that I wasn't doing something silly.<br>
</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">redis:connect is a wrapper for the process start_link. The return<br>
value is standard for an OTP process: either {ok, Pid} or {error,<br>
Reason}.<br></blockquote><div><br></div><div>Yes, this is what I expected, but in fact when I say<br></div><div> A = redis:connect().<br>when the redis server is not running, I get a crash instead of {error,Reason}. Is that what's supposed to happen? I'm still not clear on this, as it conflicts with what you say further down. What's the point of returning {ok, Pid} instead of just Pid in the non-error case, if there's no possibility of returning anything without ok, in the error case?<br>
</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Not a dumb error at all -- but neither a bug. This is by design and is<br>
pretty common for OTP processes. In particular, risky code gets<br>
executed in the context of the process (for the sake of proper<br>
isolation) and calling processes need to trap exit to deal with<br>
problems, or just let it all crash and get restarted by the<br>
supervisor.<br></blockquote><div><br></div><div>OK, I guess I can trap exit, but I had thought of trapexit itself as being risky and generally best left to the OTP supervision libraries except for special circumstances, and a database being down is relatively normal. The "let it crash" approach would be<br>
</div><div> {ok, Pid} = redis:connect().<br></div><div>which would crash with a pattern match failure in the case of an error return.<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
The question of how to handle connection problems can be tricky. I<br>
typically bake this into a "connection handler" type process that<br>
indeed traps exit and then figures out what to do -- other simply<br>
let's the client process exit propagate up to the supervisor. I'll<br>
typically have a retry logic that waits for a period of time after<br>
failures, logging attempts, errors, etc.<br></blockquote><div><br></div><div>Yes, that seems like the right thing, retry every few seconds until the db is back. I just hadn't thought of trapping exit as part of it (as opposed to just checking for error value). I actually do have a separate gen_server making a persistent connection in its init/1 and holding onto it, and then other parts of my program call this gen_server which in turn makes the redis call. When the init crashes, my top supervisor restarts the gen_server immediately, this repeats until MaxR runs out, and the whole VM crashes. It came as a shock that a fairly routine error case could cause this to happen. I find myself wishing for a general additional OTP supervision strategy (one_for_one_delay, say) that on crash would attempt restart no more than once per retry period (e.g. 1 second). I had kind of thought that was what MaxT does, but I guess not.<br>
</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
I can provide an example of this type of process -- or maybe something<br>
like this would be appropriate as a utility within the library</blockquote><div><br></div><div>This would be great, thanks!<br><br></div><div>Paul<br> <br></div></div></div></div>