<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Sep 25, 2015 at 6:03 PM, Damien Krotkine <span dir="ltr"><<a href="mailto:damien@krotkine.com" target="_blank">damien@krotkine.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div id=":op" class="a3s" style="overflow:hidden">I'm sure this code is horrible from the point of view of a seasoned<br>
Erlang developer, and I welcome any feedback. Especially regarding speed<br>
and robustness against faults.<br></div></blockquote></div><br>The key two questions to think about:</div><div class="gmail_extra"><br></div><div class="gmail_extra">* What happens if your spawned children die?</div><div class="gmail_extra">* If a child locks up, does you system exhibit liveness/progress?</div><div class="gmail_extra"><br></div><div class="gmail_extra">Since you spawn children with spawn_link, they all link to the parent process. So if one child dies, so does the parent. This gives you all-or-nothing semantics: either all keys are returned, or the system fails. An alternative semantics, based on spawn_monitor for instance, could have you handle each key individually and return an error for keys which fail.</div><div class="gmail_extra"><br></div><div class="gmail_extra">Your receive expression never times out. So if a key fetch blocks, so does your call. In some situations, when you can guarantee children have progress, this is no problem, but it is often clever to add some kind of timeout. However, when doing so, you must handle the case where a blob arrives late to the process. This usually means you need to make sure the mailbox flushes appropriately (which is something you need to peruse the webmachine documentation for).</div><div class="gmail_extra"><br></div><div class="gmail_extra">It is often impossible to a-priori declare what kind of semantics you want for these things. It is a weakness of "frameworks" that tries to automate these kinds of things. You get a predetermined semantics, but then you can't switch it up when you need a different semantics. So you have to make the analysis of how you want your system to behave if it starts failing.</div><div class="gmail_extra"><br></div><div class="gmail_extra">Finally, binary() values form a monoid under concatenation, with <<>> as the neutral element. Thus you can write your binary join as</div><div class="gmail_extra"><br></div><div class="gmail_extra">binary_join(Parts) -></div><div class="gmail_extra">    lists:foldl(fun(P, Acc) -> <<Acc/binary, P/binary>> end, <<>>, Parts).</div><div class="gmail_extra"><br>The special case [] then returns <<>> and the case [X] forms << (<<>>)/binary, X/binary>> which evaluates to X as expected. With these changes, binary_join/1 is so simple it is probably worth just folding into the call site directly.<br clear="all"><div><br></div>-- <br><div class="gmail_signature">J.</div>
</div></div>