We list half a dozen in the readme, with https://fluxonui.com/ being the most recent, and fully accessible. There is also one inspired by shadcn
https://github.com/phoenixframework/phoenix_live_view?tab=re...
2,665 karma · joined December 9, 2011
We list half a dozen in the readme, with https://fluxonui.com/ being the most recent, and fully accessible. There is also one inspired by shadcn
https://github.com/phoenixframework/phoenix_live_view?tab=re...
https://www.youtube.com/watch?v=FADQAnq0RpA&t=2322s
This demo doesn't update the URL to keep state (but push_patch would make that trivial). I'll think about more complex examples for cursor pagination, but the solution to massive collections (thousands of entries) is going to be stream + limit
To your point though, LiveView indeed requires a semi reliable connection for reasonable UX, but there is a ton of nuance to this topic that is usually missed from the discussions. Apps should more or less degrade similarly to SPA's that are going to the server. For robust UX on unreliable connections you need offline/local-first SPAs, and in my experience the vast majority of SPAs do not handle this. Failing that, most SPA frameworks seem to place the optimistic UI/rollback concerns on the developer. In fact most degrade quite poorly on bad connections. It goes against folks intuition, but even with degraded connections LiveView does better than people imagine because we have the existing connection established and don't need to go through the overheard of reestablishing things, and our payloads are generally smaller.
Annecdata of me driving through the mountains with spotty cell tethering and browsing facebook vs a LiveView app: https://x.com/chris_mccord/status/1799100642654638543/video/...
In case folks missed it, buried in the blog post is a new installer that lets folks try out elixir/phoenix in seconds. It installs elixir and generates a new phoenix project from a single command:
osx/linux:
$ curl https://new.phoenixframework.org/yourappname | sh
windows powershell: > curl.exe -fsSO https://new.phoenixframework.org/app.bat; .\app.bat
You can visit those url's directly to see what the scripts do. It extends the official elixir prebuilt installers: https://elixir-lang.org/install.sh and
https://elixir-lang.org/install.batedit: You can see it in action here: https://x.com/chris_mccord/status/1864067247255306332
Of course we also have non |sh installation guides if that's what you're after: https://hexdocs.pm/phoenix/installation.html
Now that this is out, I'm looking forward to put together a few new demos. What would folks like to see? Happy hacking!
My goal with FLAME is to move us as an industry away from the silly places serverless has taken us.
The demo app linked in the post is here if you want to speed test your own applications: https://worldpagespeed.fly.dev/
If you're talking about a FLAME.call at app shutdown that hasn't yet reached the runner, it will follow the same app shutdown flows of the rest of your code and eventually drop into the ether like any other code path you have. If you want durability you'd reach for your job queue (like Oban in Elixir) under the same considerations as regular app code. Make sense?
Confirm. Each parent node runs its own pool. There is no global coordination by design.
> Does it make a difference in pricing or anything else to run on hot workers instead of starting up per parent?
A lot would depend on what you are doing, the size of runner machines you decide to start in your pools (which can be different sizes from the app or other pools), etc. In general Elixir scales well enough that you aren't going to be running your app in every possible region. You'll be in a handful of regions servicing traffic in those regions and the load each region has. You could build in your own global coordination on top, ie try to find processes running on the cluster already (which could be running in a FLAME runner), but you're in distributed systems land and it All Depends™ what you're building the tradeoffs you want.
> It's probably a non-issue, the number of things done at initialization could be kept minimal, and FLAME could just have some checks to skip initialization code when in a flame context.
Exactly :)
For hot runners, the only overhead is the latency between the parent and child, which should be the same datacenter so 1ms or sub 1ms.
> * Pretending that starting a fly machine doesn't cost the same as triggering via s3 seems disingenuous.
You're going to be paying for resources wherever you decide to run your code. I don't think this needs to be spelled out. The point about costs is rather than paying to run "my app", I'm paying at multiple layers to run a full solution to my problem. Lambda gateway requests, S3 put, SQS insert, each have their own separate costs. You pay a toll at every step instead of a single step on Fly or wherever you host your app.
> * I wouldn't do this at all. There's no reason the results need to be queued. Put them in a deterministically named s3 bucket where they'll live and be served from. Period. This is totally unnecessary. Your application should forget it dispatched work. That's the point of dispatching it. If you need subscribers to notice it or do some additional work I'd do it differently rather than chaining lambdas.
You still need to tell your app about the generated thumbnails if you want to persist the fact they exist where you placed them in S3, how many exist, where you left off, etc.
> * Your lambda really should be doing the DB work not your main application. If you've got subscribers waiting to be informed the lambda can fire an SNS notification and all subscribed applications will see "job 1234 complete"
This is exactly my point. You bolt on ever more Serverless offerings to accomplish any actual goal of your application. SNS notifications is exactly the kind of thing I don't want to think about, code around, and pay for. I have Phoenix.PubSub.broadcast and I continue shipping features. It's already running on all my nodes and I pay nothing for it because it's already baked into the price of what I'm running – my app.
Think Jupyter Notebooks (if you're familiar with the python world), but collaborative and for Elixir.
Current SPA trends are about deploying your app separate from the backend, often CDN-style close to the user (because speed of light matters). Most apps at scale use caching for reads on hot-code paths, so now we have "eventual consistency" in the mix.
Elixir is distributed out of the box, so while "global distribution" sounds fanciful, it's literally baked into the Virtual Machine, Fly simply gives us a private ipv6 network across the globe. All Elixir sees is a cluster of hosts that it can connect to, and it's off to the races.
What I'm getting at is all this snark actually describes most application folks build today at any scale, and we build distributed apps with Elixir because it's a distributed platform.
> All of this tech sounds cool, but like the author, I'm unsure when it's called for.
Imagine if you could write your dynamic UI with realtime updates, and you didn't have to bootstrap JSON apis, or GraphQL schemas for it. Imagine doing `PubSub.broadcast(room, "new_message", ...)` and it gets sent globally to all your instances – with no external dependency. Want to show some activity on the page when something happens on the cluster? Broadcast the event, then write 3 lines of code to update your UI. Imagine writing "naive" template code that renders some markup, but what falls out is smaller payloads on the wire than your carefully typed and specified GraphQL schemas that require serialization rules for all your objects. Imagine doing away with all that and gaining all the benefits of payload size.
If that sounds interesting, Phoenix + LiveView would be called for any time you wanted a dynamic UI or realtime updates and bonus points if you care about writing less code and killing layers of abstraction. Fly would be called for for the same reason folks use CDN's today, to serve resources of the app close to the user, except we just serve the app there instead.
> It seems like this would add a whole new class of bugs, like “I just submitted a form to change a setting and when the page reloaded, it still showed my previous value in the form” – since the write hadn’t propagated to the local read replica yet.
Elixir is distributed out of the box, so nodes can message each other. This allowed us to easily ship a `fly_postgres_elixir` library that guarantees read-your-own-writes: https://github.com/superfly/fly_postgres_elixir
It does this by sending writes to the primary region over RPC (via distributed elixir). The write is performed on a primary instance adjacent to the DB, then the result, and the postgres log-sequence-number, is sent back to the remote node. When the library gets a result of the RPC write, it blocks locally until its local read replica matches an LSN >= write LSN, then the result is returned to the caller
This gives us read-your-own-writes for the end-user, and the calling code remains unchanged for standard code paths. This doesn't solve all classes of race conditions – for example you may broadcast a message over Phoenix.PubSub that causes a read on the remote node for data that isn't yet replicated, but typically you'd avoid an N query problem from pubsub in general by populating the data in the message on the publisher beforehand.
There's no completely avoiding the fact you have a distributed system where the speed of light matters, but it's Fly's (and Phoenix's) goal to push those concerns back as far as possible. For read heavy apps, or apps that use caching layers for reads, developers already face these kinds of problems. If you think of your read-replicas as cache with a convenient SQL interface, you can avoid most foot guns.
I'm happy to answer other questions as it relates to Phoenix, Fly or what Phoenix + Fly enables from my perspective.
> I don't know what a solution is, but perhaps a concerted effort to create a documentation and library ecosystem that never links back to Erlang would help. And where there are critical systems that use an Erlang library, perhaps rebuilding it in Elixir is in order?
This would not be helpful. Erlang has over three decades of features, heritage, and libraries. Elixir helped usher in first class documentation as a core language feature, but that doesn't make rock solid Erlang libraries somehow things that should be avoided. Rewriting for rewriting sake is also not a good idea. One of the benefits of bootstrapping off an already amazing platform is exactly because you don't have to invent the universe. See Clojure and Java.
In fact, Elixir has helped Erlang up its documentation game, and there is already work done to help the ecosystems share documentation tools. Both ecosystems work by rising together, not masking one or the other. We see this in tools like `telemetry`, documentation generators, and recently the Erlang Ecosystem Foundation: https://erlef.org