1. 4

    ’Miss this man.

    1. 4

      I love OpenBSD, and recommend it to anyone who didn’t foolishly purchase a laptop with an nVidia GPU.

      1. 1

        It works fine on my (most?) laptop with a nvidia GPU. I think my laptop thinkpad440p has intel video for non 3d stuff.

        1. 2

          I mean, it works perfectly on mine with an nvidia chip for the most part. I just can’t persuade it to drive an external display

          1. 1

            oh :/ good to know

        2. 1

          I’m about to embark on buying a laptop dedicated to OpenBSD. Would you recommend a dream machine for this purpose that you believe to be a good pairing with this OS? Thanks in advance…

          1. 2

            I am not an expert, and I have only used OpenBSD on one laptop. I think any not-too-new thinkpad should be fine, ideally without an nvidia GPU

            1. 1

              Indeed! I was leaning that way. Not-too-new… I suppose for the reason that OpenBSD has had time to support the older ones? er…?

              1. 2

                For anyone who cares, I ended up going with a Thinkpad T480. I’ll probably write up something regarding my experience with OpenBSD running on it.

        1. 4

          As an Erlanger, and ex-rubyist, I recall when I first heard of Elixir: I had a glance at the equivalent of the Rails’ `routes.rb,’ but in this new Phoenix/Elixir project that was gaining popularity. It was clear to me that one of the main goals of Elixir had to be to emulate the ruby syntax/patterns as much as possible from looking at that file (can’t recall what its namespace is in Phoenix). To my eyes, the sameness was uncanny. So despite the constant backpedaling from Elixir people that they’re only like Erlang, it’s clear to me that Elixir was designed to look like Ruby as much as possible.

          1. 3

            So despite the constant backpedaling from Elixir people that they’re only like Erlang, it’s clear to me that Elixir was designed to look like Ruby as much as possible.

            Well, not really. Elixir is for sure Ruby-inspired, but for sure it is nit designed to be “as much Ruby as possible”. It is designed to have bells and whistles that makes language as flexible as possible though - hence macros that allows for stuff that can be seen in Phoenix. Macros are great, even if overused sometimes.

          1. 13

            Give OTP a try sometime. Battle-hardened patterns for concurrency-model demands.

            1. 1

              Do you know of anyone who’s tried to build something like OTP in Go? I think, with the right juggling of channels behind the scenes, it should be generally possible?

              1. 11

                OTP builds on top of Erlang. There is one fundamental rule that you have to follow if you want to have even a vague chance of getting concurrency right: No object may be both mutable and shared between concurrent execution contexts. In Erlang, that is trivial: the only mutable objects are the process dictionaries, which you cannot take a reference to and so cannot share. Everything else is immutable and so safe to share.

                In Go, there is nothing in the type system that helps you avoid accidentally sharing mutable objects. There is no real notion of immutability in the language, so you have to build immutable abstractions by creating objects that expose only read-only accessors for their state.

                For a language that has channels or message passing and also has mutable objects, you want to guarantee that one of two properties holds for any object that you send. It is either immutable, or you gave up your reference to it at the time that you sent it. Pony and Verona enforce this in the type system, Rust tries to build this the standard library, C++ makes it possible to express this via smart pointers (but doesn’t make it easy), Go doesn’t even make it possible to express this in any way that can be statically checked.

                Go is one of the worst languages around for concurrency. It makes it incredibly easy to write concurrent code but gives you no help in writing correct concurrent code.

                1. 2

                  Yikes. Thanks for the insights!

                2. 1

                  Not off hand. Sounds like a fantastic idea, though. Not familiar with Go, but I know that some of the fundamentals that probably need to be at hand to do something OTP-like are monitors, links, and an error model that’s rooted in message passing.

              1. 1

                Even though the lion’s share of langs can be used to develop for the web, I found that embracing languages other than the typical go-to web-dev langs was the path that got me programming outside of the web world. It was probably just a side-effect, but that’s what happened all the same. Of course, coming back to the web, ouch; now that really hurts after tasting the fruits off of yummier trees.

                1. 4

                  Hi. My name is Nato. And I’m (somewhere) on the ol’ Spectrum.

                  Question to the author, should you care to divulge: @baweaver, does coding accentuate/agitate some of the ASD-ness? ‘Was curious. I find that coding resonates to that type-a-ness to such a degree, that it’s perhaps the last craft I should have chosen for myself. Perhaps I should have chosen a craft that mollifies all the ASD type feelings.

                  P.S. I mean no snark in the first part of the comment, to be clear.

                  1. 4

                    It does, and to some extent that’s bad but to another it’s amazingly helpful. It’s allowed me a level of focus and creativity that’s not normal, and now I’ve leveraged that into doing conference talks using cartoon lemurs to teach programming as an outlet for some of those crazy ideas:

                    https://www.youtube.com/watch?v=TVwVLBor8WE

                    There are several such talks of mine in circulation: Reducing Enumerable, Scaling Christmas, The ActionCable Symphony, Tales from the Ruby Grimoire, The Night Before Code Freeze, Professor When and the Timey Wimey Extensions (soon), and more on the way.

                    In a lot of ways I leaned in once I realized that my level of eccentric was not only tolerated but celebrated in the Ruby community.

                    1. 1

                      Thanks for taking the time to reply. Looking forward to going through these. Best to you.

                  1. 1

                    The Knuthian TeX versioning is droll, for those who haven’t heard of it: It (used to?) use precision of numbers in pi to increment the version… (from wikipedia of Software_versioning)

                    The current version is 3.14159265. This is a reflection of TeX being very stable, and only minor updates are anticipated. TeX developer Donald Knuth has stated that the “absolutely final change (to be made after [his] death)” will be to change the version number to π, at which point all remaining bugs will become permanent features.

                    1. 3

                      I remember at an Erlang conference, there was a question to Robert Virding and Mike Williams (co-creators of the lang) about how do they deal with `imposter syndrome.’ They were dumbfounded; they had no idea what that concept could even mean.

                      1. 1

                        I had that happen once with a co-founder. Had to explain the concept. In retrospect that explained a lot of things about them and our relationship (both the good and the bad).

                        1. 1

                          I’ve never had impost syndrome, it’s a mystery to me. But then I got started in programming during the 80’s with 8 bit micros. In those days tech was hugely uncool (in my area), and there was more of a culture among enthusiast around sharing knowledge and knowhow. I have noticed there tends in todays coders there seems to be a lot more one upsmanship and showing off which I try to discourage any chance I get.

                        1. 6

                          Thanks for the invite @pushcx, and happy bday. A nice little community.

                          1. 3

                            Paul Graham sold me years ago on all this: saying that email broke because it morphed from `do you want to grab lunch?’ to a pattern whereby others give you TODOs, without your prior consent. The tool was meant for the former, not the later, and inbox zero is impossible for a good deal of us. When I look at my wife’s Gmail and the inbox says 1200 new unread mails, it makes me sad, because her main mode of communicating with her work is via email, as it is for a good deal of us. IM arrived and started to address the original use for email – the need for quick, informal quasi synchronous queries from others. On the other hand, I love email, and try my darnedest to make it work for me. It’s probably my favorite software technology.

                            1. 3

                              On another hand, my score is four on ten, that’s better than my best Google pagerank [sic]

                              So funny.

                              1. 3

                                Love Mnesia. The story behind its name is droll – upper management at Altel/Ericsson said: `there’s no way in heck we are calling this DB Amnesia!’ So the core Erlang team re-named it to what it is today.

                                Small niggle,

                                Another important thing to note is that Mnesia stores all of the Erlang data types natively…

                                I believe, under the covers, DETS (or when Mnesia is used to write to disk) converts atoms to strings, which has a performance penalty. Some info on that here: https://www.slideshare.net/ErlangSolutionsLtd/erlang-meetup-19-september-2017

                                1. 3

                                  I always wondered why Colin was involved in FreeBSD over OpenBSD (seeing how he’s into security, and is Canadian being banal reasons why he may champion the later). One reason he states right off the top of the show is FreeBSD was easy for him to install!

                                  1. 4

                                    In new OTP releases there is handle_continue/2 for that and you do not need to utilise such dirty hacks.

                                    1. 2

                                      Thank-you, @hauleth. I added a note about this on the post.

                                      1. 1

                                        Dependent of course on what I am doing, I tend to just have my handle_continue pass directly to handle_cast which lines things up for me to use handle_cast(hup, State) as a generic point to handle reloads throughout the lifetime of my processes.

                                        Before continue was an option, I just used to just call gen_server:cast(?MODULE, hup) before my init function returned.

                                        1. 1

                                          The problem with message to self is that it causes race condition. If anything send message after spawn but before such message then server can receive messages while in wrong state. handle_continue avoids that as it is ran just after the message is processed but before next loop call.

                                          1. 1

                                            Why would you want init to return immediately but then not actually be ready to service requests and care about this race condition?

                                            1. 1

                                              Because long running init will stop launching other processes in the supervision tree. So sometimes you want to continue launching while still prepping the process and queue all messages that will arrive in the meantime. This is where handle_continue becomes handy.

                                              1. 1

                                                I think you need to go back and read my comments and bear in mind that the comments are about what the article is setting out to solve and not telling you what you should be doing.

                                                The whole point of supervision is that it expects after your init returns your process is in a stable state. If you are using tricks (continue, gen_server:cast() from init, …) to speed up your startup time you have officially declared “I do not care about supervison” as your now out of bound long init task could still lead to a crash of that process.

                                                Your point of a race condition is correct but is replacing it with an unstable supervision tree just to get a faster startup times something that is correct for everyone?

                                                Either you think everyone should do this, or (more likely) you have not read or taken onboard:

                                                • before continue was an option…”
                                                • “Dependent of course on what I am doing…”
                                                • continue is a recent OTP feature (stated by yourself)
                                                • continue is not available in all generic servers (stated by the author)

                                                So beating up on me to use continue when it may not be an option is not really fair, right?

                                                Throwing out a stable supervision tree may be okay and manageable in your environment. The race condition you describe is correct but has zero impact on my life as either I arrange it so dropping those messages is okay (two lines in a gen_server) or alternatively expose ‘readiness’ to a load balancer (where startup times are often irrelevant) so making the race a non-issue.

                                                I suspect others may have their own thoughts here, and I am interested in hearing from them. What I do not appreciate is being told to swap a race condition for a unstable supervision tree whilst being told to suck eggs.

                                                1. 1

                                                  The obvious case, to me, is starting up a process/service that is inherently flaky, e.g. a database connection. The “stable state” of the process is disconnected, and whenever it is disconnected it is attempting to establish a connection/reconnect. While in that disconnected/trying to connect state, it can still service requests from clients, by simply returning an error. The rest of the system can proceed with startup, even if the database service was temporarily unavailable, or otherwise flaky during boot.

                                                  This is especially important for resilience in the supervision tree. Using the example from above, if your process tries to establish a connection during init, and it fails, it will likely fail again immediately, probably triggering the max restarts of the supervisor and bringing down large swaths of the application (or in the worst case, the entire node). The same applies later on in the nodes life, should the database connection fail, and trigger a restart, if the connection cannot be immediately re-established, then it is very likely that the process will restart in a loop, trigger the max restarts, and take down a bunch of stuff it shouldn’t have impacted.

                                                  The idea of doing that fragile work post-init is not to boot faster, it is to boot stable, and to ensure that restarts during the application lifecycle aren’t prone to the crash loop problem I described above.

                                                  1. 1

                                                    As database disconnects are ‘normal’ and expected (not exceptional) though this sounds like the stable process here describes a behaviour similar to a simple_one_for_one supervisor (where you do not care but if you did you would instead use one_for_one)?

                                                    I still need to fix my Erlang as I am still ‘broken’ in the manner that I prefer a SIGHUP-via-cast approach over process restarting as I am yet to see a simple way of handling multiple reload requests without a global lock; though I guess you could drain your message queue with a pattern for only reload requests and debounce the whole system that way before exiting?

                                                    1. 1

                                                      As database disconnects are ‘normal’ and expected (not exceptional) though this sounds like the stable process here describes a behaviour similar to a simple_one_for_one supervisor

                                                      The example of a database connection was illustrative, not meant as the best example, as typically they are created on demand and so would not be restarted, or would run under a simple_one_for_one supervisor. However the point it was meant to demonstrate is that some processes/services that have external dependencies are by definition unreliable; as you point out, this is part of their “normal” behavioral profile, so it is critical that the process handles the flakiness gracefully. An alternative example might be an S3/RabbitMQ/etc. consumer/producer - the same rules apply, if you require init to block on successfully connecting to the service, it will bite you eventually, and adds fragility where it isn’t necessary.

                                                      I still need to fix my Erlang as I am still ‘broken’ in the manner that I prefer a SIGHUP-via-cast approach over process restarting as I am yet to see a simple way of handling multiple reload requests without a global lock

                                                      I’m not sure I follow, they are essentially orthagonal concerns right? You can have supervision/process restarts and provide the ability to do some kind of “soft restart” via a SIGHUP-like message sent to the process. The part I think I’m missing here is what you mean by handling multiple reload requests - for a single process the requests are all serialized anyway, so if they trigger an actual process restart, then only the first message matters. If you are doing some kind of soft restart, then you could “debounce” them by dropping duplicate restart requests that come within some window of time (no need to drain the mailbox with a selective receive). In general though, I would assume the SIGHUP-like signal you are sending is something triggered by an operator, not by the system, in which case handling that edge case seems like worrying about something that is unlikely to ever happen in practice. Maybe an example of where you are using this pattern would help illustrate the problem it solves though.

                                      1. 1

                                        It may seem trivial, but the OTP team is chipping away at making the Erlang syntax a bit dev-friendlier with this major release. With R23, integers can take the syntax: 1_000_000 to represent `1000000.’ Considering how much back-lash Erlang syntax gets, the more efforts like this, the better.

                                        1. 2

                                          If the syntax is somebody’s primary concern why not use Elixir instead? For me the Erlang syntax makes more sense than Javascript for example. I think Joe really got that right. Expressing so many things so easily. Pattern matching baked into the language the the core, ease of use of recursive functions. I could go on and on. Do people get hang up on the syntax that much?

                                          1. 1

                                            Yes

                                        1. 2

                                          A link to a pdf version of Shannon’s paper can be found via here:

                                          https://twitter.com/snailtext/status/1254054254869770240

                                          1. 1

                                            I’m sure I’m just cross-eyed right now, but would someone that understands this explain the mechanism for a commercial company getting hit financially; if they don’t get on board with EARN IT? Is it a fee? THANKS in advance!!

                                            1. 8

                                              I’ve been thinking about state machines in the last couple days. Specifically, I think Erlang’s gen_statem pattern (from OTP) is the 8th wonder of the world. The author of this behavior tackled a huge problem and I’ll be damned, hit it out of the park, considering how muddled one can get when thinking about state machines, let alone coding them up. I did a shallow dive into it a good while back (http://blog.snailtext.com/posts/bend-it-like-gen-statem.html), which isn’t bad. OK, not Rust related, but gen_statem certainly is something to marvel at in this space.

                                              1. 1

                                                Hey thanks to much for the link to your post! I’m an Elixir fellow myself, so I’ll happily digest what you’ve written.

                                                1. 1

                                                  Nice blog post, and also a v. nice website design!

                                                  If you’d enjoy it, could you spend a few words gushing about the things that gen_statem gets right that other state machine implementations get wrong, or don’t get at all? I love reading enthusiastic praises, and also I’m curious about the design space of the interfaces of state machine libraries.

                                                  1. 1

                                                    I regularly tell Rust people to learn about FUCRS, since this blog really got me thinking a lot about techniques for combating rightward pressure when I was working more with Erlang :) gen_statem and generally all of the behaviors are particularly nice IMO because they push all of their state in your face during transitions, and they keep the reality of the system more on your mind. For a dynamic language, erlang is able to specify so many beautiful properties that can be tested in a way that kind of approaches a much more usable dependent type system in some cases, with the features of dialyzer and general amenability to model-based testing that gets bugs to fall out of a system so quickly. Working in erlang has significantly impacted how I write Rust, and especially how I try to lean into state machine-based approaches for anything distributed-systems related.

                                                  1. 1

                                                    Host my own email and websites. OpenBSD, OpenSMTP, httpd on small vultr vps’s Home fileserver running freenas on an older desktop.

                                                    1. 2

                                                      I also do this (save for Home server freenas). Gmail blocks a good deal of my outgoing mail, but honestly, this has been covered a lot recently, so I won’t rant here about is worth it or not. (Yes, it’s worth the risk of having undelivered email, but not having google handle all my email needs.)

                                                    1. 5

                                                      Cowboy is certainly the most entrenched app, and I like it quite a bit. The author is a champ, too. However, I’ve been using and quite like https://github.com/elli-lib/elli in the last few years – just pointing out the option… and I believe elli' is actually small.’ I think they have slightly different goals, but on my stuff, they’re used interchangeably (js fetch calls api endpoints).