338 karma · joined September 18, 2015
> When disagreeing, please reply to the argument instead of calling names. "That is idiotic; 1 + 1 is 2, not 3" can be shortened to "1 + 1 is 2, not 3."
In Elixir, bang functions per convention will raise on error. `get/2` will return error tuples allowing you to handle errors. In fact, get!/2 just calls get/2 and raises for you[^1].
> no mention of JSON at all
Req is the most "batteries included" Elixir HTTP lib out there. I can't speak for Wojtek, but I believe the goal was to make Req extremely easy to use in scripting or things like LiveBook without having to do much work. That being said, the automatic decoding is mentioned in the readme[^2] and the docs[^3].
> if "body" is JSON, how do you even get the raw body, or can you?
Per the docs[^3], you can either skip with the `:decode_body` option, or just build your own request using only the steps you want.
> just seems over engineered/over fitted whatever you want to call it.
Fair, but again, this library is designed to be on that end of the spectrum. There are plenty of other libraries further down the stack that you can use. I am partial to Finch[^4], upon which Req is built.
To address the sibling comment about "Let it Crash", the language allows you to easily recover from crashes, but that is for resiliency, not error handling. In practice you would use the non-bang get/2, pattern match on the response, handle any errors, perhaps use Kernel.get_in/2 to safely traverse the map, etc. The example provided by the author is not "production ready".
[^1]: https://github.com/wojtekmach/req/blob/v0.3.11/lib/req.ex#L3...
[^2]: https://github.com/wojtekmach/req
When a stream starts I start a supervisor that then starts a GenServer to manage the port. On init a port is started for FFmpeg (using the above bash wrapper) with args that sends 16-bit PCM audio back to the port through the `handle_info/2` callback.
When a new live HLS segment is downloaded by FFmpeg the entire segment's audio is sent to the GenServer all at once (could be a few handle_info/2 calls, but it happens quickly). Since I want to work in small fixed chunks, I send the segment's audio to an AudioBuffer GenServer (started as a sibling under the same supervisor). This buffer uses binary pattern matching to segment the audio in chunks exactly 2 seconds long while keeping any remainder in the GenServer's state for the next buffer event. I then send the chunks to another ChunkBuffer GenServer that pops chunks at 2-second intervals for processing.
Since everything is supervised, if (when...) FFmpeg crashes the supervisor just restarts it. Meanwhile, the audio in the buffer is still processing and nothing goes down. There might be a duplicate word or two in the transcription if the restarted port processes a segment again, but everything keeps running smoothly.
For even more reliability, I have the application running clustered across four locations in the US, EMEA, and APAC using libcluster[^2]. The stream supervisor is started under a Horde.DynamicSupervisor[^3] with a custom distribution strategy. The strategy prefers the region closest to the company HQ, but if it goes down, the processes will be restarted in another region.
[^1]: https://hexdocs.pm/elixir/1.13.4/Port.html#module-zombie-ope...
Little over 3 weeks from `mix new` to the live event. Not sure how I could have done it so easily without OTP and LiveView.
If employees are being paid to stay after 5 or be on call, then their shift isn't over. If they aren't being paid for their time, they absolutely should go home. If the product cannot afford to go down, the company is responsible for keeping paid staff on hand. Expecting people to work beyond the agreed amount and punishing those that don't by removing opportunities for advancement is reproachable. It may be the norm, but it shouldn't be.
Agreed. But why name them at all if the structure is so simple? Keep your simple, understandable structure, colocate your styles with tailwind classes, and avoid the unnecessary cognitive overhead of naming obvious things (is it .username or .user-name?) and linking them with remote styles in a different file.
Not saying it’s the “one true way”, but I don’t think your way is necessarily simpler.
My interpretation was vertical scaling is within a single node and adding cores or CPUs to a single node is vertical. Multi-core and multi-node really present similar problems, so adding more cores or adding more nodes isn't terribly different from a design perspective.
> ...easy to scale horizontally by tacking on additional CPU cores or physical CPUs.
If you define adding more cores to a single machine is actually horizontal scaling, then we agree in principle, just not in the definition of scaling.
Yes, the relevant part of his demo with the membrane pipeline appears to be here: https://github.com/lawik/lively/blob/master/lib/lively/media...
[1] https://github.com/elixir-desktop/desktop
[2] https://natetodd.com/building-for-web-and-native-with-livevi...
Between this new project, "regular" LiveView, Nx, Livebook, and FireFly, the Elixir ecosystem is expanding at an impressive rate.
Push notifications in Safari are only supported on desktop for now.
See: https://github.com/elixir-lang/elixir/releases/tag/v1.13.4