Is there easy tooling for deploying to something like AWS ECS and having nodes communicate with each other?
Is there easy tooling for deploying to something like AWS ECS and having nodes communicate with each other?
I personally use mix release[2] that assembles a tarball of itself (together with BEAM), then rsync that to Hetzner, restart the remote process and viola. I like simplicity.
Re cluster of nodes, the easiest would be to use a library[3] to automate the formation of said cluster.
[0] https://www.gigalixir.com/
[1] https://fly.io/docs/elixir/getting-started/
[2] https://elixir-lang.org/getting-started/mix-otp/config-and-r...
Our service is primarily a graphql API. The mobile apps talk to our service, and then it internally talks to other services. We use Absinthe for graphql, and a lot of it is subscription based.
Since these nodes (pods in k8s terms) are clustered, each pod is aware of the other pod. Sometimes we get a huge spike in traffic and the clusters can't start fast enough (we're increasing the scale up time in k8s) and a pod can get OOM killed due to number of graphql subscription and then just go in crashloop. This leads to libcluster thinking the node is still good but when infact it's in crashloop, and thus not allowing any new pods coming up to start up.
We're experimenting with few things, but yeah clustering is not without it's pain
libcluster[0] has a bunch of strategies to form clusters. It seems that ECS supports service discovery through DNS, so the DNSPoll[1] strategy should work.
[0] https://github.com/bitwalker/libcluster [1] https://hexdocs.pm/libcluster/Cluster.Strategy.DNSPoll.html
What happens when you have to refactor a large elixir feature on a code base which many teams touch? In such cases you can’t test manually all code paths for runtime errors, so are you just relying (hoping for) perfect test coverage to catch any type related errors you may have caused?
Immutability and pattern-matching get you at least the 80-20 of what a rigid type system does for larger code bases, and your team won't have to be as large when you're using a language like Elixir or Clojure as it would with older, more entrenched languages.
How does immutability or patter matching save me from runtime errors caused by changing the fields or types inside a struct? Wouldn’t the pattern matching just fail and go down the wrong code path since it was matching for the old pattern?
I feel like immutability is great, pattern matching is great, but static typing is also great and there is no reason why it can’t happily live along side the other two.
Elixir structs have compile-time checks: https://elixir-lang.org/getting-started/structs.html
I do want to clear something up. Elixir is strongly typed, but its not statically typed.
More here: https://www.educative.io/answers/statically-v-dynamically-v-...
Even for langs that are statically/ and strongly typed on the BEAM (like Gleam, whose type system is similar to that of Standard ML or OCaml) still subscribe to the "Let is Crash" philosophy, especially when it comes to messages sent and received between processes. The only thing that is guaranteed is your system will fail at some point, how should the system protect its self form that?
https://www.educative.io/courses/concurrent-data-processing-...
In short, its not like working with Ruby or JavaScript or Python, etc..
If you change the shape of a model object and break its type, it’s great that BEAM will gracefully handle that mistake, but no matter how many times that service restarts, it will still be broken at runtime.
I think type systems have gotten so good in modern languages (Kotlin for example) that it’s a disservice to your org to not use a statically typed language.
I haven’t looked at Dialyzer lately, but is it as robust and easy to use as a first class type system? Having experienced partial typing with annotations with python I must say it’s not nearly as smooth as a proper statically typed language.
I do wish something like Gleam was the front runner language on BEAM - I bet it would get taken a lot more readily.
Comparing it to Python's gradual typing isn't entirely fair for a couple of reasons:
1) Elixir is functional, meaning a value's type never changes. This makes it easier to reason about the code and allows tools like Dialyzer to be more effective.
2) The combination of value/pattern matching and the "let it crash" philosophy is unique to the BEAM ecosystem and has proven invaluable for building complex applications. this out side of Dialyzer gets you 80% the way there. (I don't even use Dialyzer in my applications because I don't think it buys you that much. I lean on testing, typically to cover that last 20%)
I'm intrigued, however by the new type system that's being explored for Elixir by Jose and this team. It promises the best of both worlds: dynamic typing with the assurances of a static one.
If we were to impose a Java/Kotlin-like type system onto Erlang/Elixir, there would be several concerns:
It could encourage harmful coding practices that hinder code evolution.
It might conflict with the "let it crash" philosophy, leading to more "nanny coding."
The effort required to satisfy the type system could outweigh its benefits.
It could reduce productivity and readability.
If not integrated into the BEAM core, it might not offer optimization benefits and could create compatibility issues.
It could divide the community and distract from other important work.
Elixir's existing features like testing, value matching, and the "let it crash" philosophy already provide a robust safety net that a static type system might not significantly improve upon.I know they support Elixir/Phoenix.
WRT getting them to communicate? I ended up giving up on that altogether…
I’m usually good at figuring that stuff out but this one ended up not being worth it (in my case).
Was your requirement to have ssl as the distribution communication mechanism ?
As a bonus point, no real need for container orchestration as the BEAM just figures it out.