[HN Gopher] A taste of pavex, an upcoming Rust web framework
       ___________________________________________________________________
        
       A taste of pavex, an upcoming Rust web framework
        
       Author : lukastyrychtr
       Score  : 101 points
       Date   : 2022-12-31 10:51 UTC (12 hours ago)
        
 (HTM) web link (www.lpalmieri.com)
 (TXT) w3m dump (www.lpalmieri.com)
        
       | 29athrowaway wrote:
       | You identify a problem then create a leaky abstraction that is
       | hard to understand to solve it and then call it ergonomic.
        
         | [deleted]
        
       | vbezhenar wrote:
       | Is there popular Rust web server which uses just threads with no
       | async stuff?
        
         | mfashby wrote:
         | Rocket.rs I believe
        
           | DoubleFree wrote:
           | Rocket is moving towards async as well
        
             | 0x457 wrote:
             | Rocket is not moving anywhere right now. 0.5 supposed to be
             | async, but it's delayed more than a year because maintainer
             | doesn't have time.
        
         | stevedonovan wrote:
         | I suppose async web servers is the poster child of async, and
         | drove a lot of the development. However, then _everything_ went
         | async, adding the cognitive overhead of dealing with Rust async
         | throughout the ecosystem, whether needed or not.
         | 
         | In short, it still feels like a leaky abstraction: marvelous to
         | look at working code, but errors (both compile and run-time)
         | expose the underlying machinery underneath the syntactical
         | sugar.
         | 
         | This is probably heresy, but as a former Rust dev I'm enjoying
         | web-services in Go more these days.
        
           | [deleted]
        
           | afavour wrote:
           | I love Rust but I kind of agree. It's really, really rare for
           | a web service to need the low-level stuff Rust provides. A
           | garbage collected is going to be just fine.
        
             | marcosdumay wrote:
             | And if you want to make it async anyway, take a look at the
             | abstractions a garbage collected language like Haskell can
             | get you. (But well, the ones Go provide are probably more
             | than enough already.)
             | 
             | Rust was not made for web development, and the fact that
             | people keep creating frameworks and keep deciding they are
             | good only shows how bad the usual practices are around the
             | web.
        
             | nbittich wrote:
             | I hated async for months. Refused to touch it. Recently I
             | tried it again. It (seems) way better now. Just avoid weird
             | libraries like diesel & rocket, and everything works just
             | as expected. I even wrote some generic code with async and
             | surprisingly it works without me having to get a phd in
             | type theory to please the compiler.
        
           | virtualritz wrote:
           | There are other applications, e.g. trading, where async is a
           | godsent (monitoring hundreds of financial instrument for
           | changes) but any sort of GC is prohibitive.
           | 
           | And where you also need the fine grained control that Rust
           | provides.
           | 
           | E.g. halting all async tasks immediately while keeping a
           | single core free to execute a trade as fast a possible.
        
         | Waterluvian wrote:
         | Is a thread per request scalable? Aren't most of those threads
         | just waiting for I/O? I guess thousands of concurrent requests
         | via thousands of threads isn't a big deal.
        
           | aseipp wrote:
           | Yes, you can run absolutely massive systems with very high
           | throughput and high concurrency using only OS threads and
           | "normal" synchronous programming, if done correctly. However
           | it's generally a pain in the ass because most languages often
           | have their own threading models that may have their own
           | limitations or interaction-with-the-OS quirks, while in C or
           | C++ you're typically on your own for like, all your
           | dependencies including trivialities like thread pools and
           | stuff. And all newer languages tend to instead design their
           | I/O ecosystems around asynchronous stuff. So you have to
           | choose your poison. But handling massive systems always
           | requires a bit of special care anyway.
           | 
           | You will often encounter many other bottlenecks that hold
           | your system back. There are other concerns like latency and
           | utilization to care about. But assuming a purely "compute/IO"
           | driven data plane, yes, you can scale synchronous APIs with
           | threading quite far.
        
           | vbezhenar wrote:
           | It's reasonably scalable. Operating system can deal with
           | thousands of sleeping threads just fine. And I don't need
           | more than that (on a single machine anyway).
        
           | marcosdumay wrote:
           | You mean at the application layer?
           | 
           | There never was any problem scaling things at the application
           | layer. You can use almost any architecture there without
           | issues. All the bottlenecks are elsewhere.
        
         | cytzol wrote:
         | I love Rouille: https://docs.rs/rouille/latest/rouille/
        
       | sanderjd wrote:
       | I like the idea!
       | 
       | I disagree with other commenters here that dependency injection
       | is not useful. I think it doesn't come across well in toy
       | examples, but in my experience it is very useful for large
       | services, which otherwise tend to accrue a big rats nest of
       | instantiation in the startup code, which is difficult to
       | modularize. I haven't built a service like that in Rust yet, so
       | maybe other patterns work well, but I have noted these big
       | instantiation entry points in rust code that I've read, so I'm
       | skeptical that it is a solved problem.
       | 
       | I do agree that it introduces a significant legibility and
       | debugging burden, but I think that can be significantly better
       | with _compile time_ DI. However, I think it does require good
       | tools that would take quite awhile to be built for an immature
       | framework like this.
       | 
       | But the thing I'm most skeptical of here is the implementation.
       | Is there not enough information available in a normal procedural
       | macro to figure out the dependencies, without using this trick
       | with the rustdoc data? That approach seems very cheesy and likely
       | fragile to me.
        
       | jiggawatts wrote:
       | FYI: This framework uses rust _doc-comments_ for essential
       | functionality. It's basically using the documentation tool's JSON
       | output programmatically during compile time.
       | 
       | Generally this kind of "too clever" programming tends to fail in
       | creative ways, especially over longer periods of time.
        
       | tunnuz wrote:
       | If you haven't also check out Zero to Production in Rust, it's an
       | excellent book by the author of this framework.
        
         | satvikpendem wrote:
         | Yes, it's a great book, going through it now.
         | 
         | https://zero2prod.com
        
       | [deleted]
        
       | ptato wrote:
       | The answer to help beginners understand highly generic rust code
       | is not more abstraction and magic.
        
         | [deleted]
        
       | i_am_toaster wrote:
       | Not sure if author is the same as OP (I'm leaning towards not?),
       | but if they are...
       | 
       | I'm curious what caused you to go down the route of transpiling?
       | Do you think that this methodology will be a core facet of the
       | architecture, and will it be able to be changed when rust gives
       | you the tools you seemingly want? Do you think that the
       | transpiling will be annoying to debug and update as rust
       | continues to mature?
        
       | pxeger1 wrote:
       | I'm always wary of tools that as an extra compilation step,
       | because of the added complexity.
       | 
       | (Look at the common C workflow: cc was too hard to use on its
       | own, so make was created; make was too hard to use on its own, so
       | autoconf was created; m4; ...)
       | 
       | I hope the user experience makes it worth the complexity.
        
       | BoardsOfCanada wrote:
       | I'll definitely check this out, I have a microservice that I have
       | rewritten in rocket, warp and axum that I'll port for comparison.
       | 
       | Rocket was nice but has stalled, I read the author has health
       | problems to focus on, so my go-to framework is axum for now.
       | 
       | What I miss the most in the rust ecosystem compared to the
       | kotlin+spring boot stuff I do at work is the dependency
       | injection, I haven't found anything I like much in rust.
        
         | chromatin wrote:
         | FYI Rocket has revived, and I heard recently he (Sergio) has
         | made plans for a Rocket foundation so that the development team
         | can be expanded and there is no longer SPOF
        
           | nindalf wrote:
           | I respect Sergio but I've heard that like too many times in
           | the last 3 years. Every few months it's the same excitement
           | whenever some activity is spotted on the repo. It always ends
           | the same way - stalled yet again. The goodwill earned has
           | been squandered.
           | 
           | I'll believe in rocket when I see releases being cut. Until
           | then I strongly recommend no one touch rocket.
        
             | db48x wrote:
             | Why do other people need to be working on a library for it
             | to be useful to you? Can't you pitch in?
        
             | Grimburger wrote:
             | It's weird seeing this sentiment when Sergio is on matrix
             | answering questions all the time and the contributor graph
             | for alternatives like Axum is basically identical, one
             | person making all the commits, another person doing a fair
             | amount of work, and the rest are drive-by PR's.
             | 
             | Seems more like an entitled open source user issue rather
             | than a repo issue, he's never slept on any security
             | notifications as far as I know.
             | 
             | The 0.5 release was a big re-write, it takes time. I likely
             | will still use 0.4 in future because not having to mess
             | around with async is nicer and it's still perfectly fast
             | enough for many usecases.
        
               | norman784 wrote:
               | The issue is that in the past rocket author went missing
               | and no one could take the lead to continue the
               | development, axum in the other hand is under tokio org,
               | so the community could take the lead in that regard.
               | 
               | I loved rocket when I first learned about it, now two
               | years passed and it stalled because no one could pick up
               | the project, there were (I don't know it there still are)
               | a lot of PR's from the community that were waiting for
               | someone to review and merge it.
               | 
               | But if rocket is being migrating to an org, kudos to the
               | project and hope it continues to innovate like in the
               | past.
        
             | capitainenemo wrote:
             | So, the last time I asked on #rocket they told me the
             | release was basically done, but they were not going to move
             | past RC until the documentation was completed, which seems
             | stalled.
             | 
             | Is there anything else missing that you heard of?
        
         | BFLpL0QNek wrote:
         | Have you read this good series of blogposts on implementing
         | Hexagonal Architecture in Rust? https://alexis-
         | lozano.com/hexagonal-architecture-in-rust-1/
         | 
         | I'm the opposite, I don't find much need for "dependency
         | injection" frameworks. It's trivial to do DI without
         | frameworks.
        
           | BoardsOfCanada wrote:
           | Thanks, will check it out
        
           | eklavya wrote:
           | This hexagon architecture looks a lot like a free monad
           | interpreter.
        
       | i_dursun wrote:
       | Looks interesting and I am totally behind this for exploring new
       | design decisions.
        
       | dmitriid wrote:
       | I skimmed the post. Looks like asp.net approach of registering
       | all dependencies up front (with various lifetimes/scopes).
       | 
       | Still looks very verbose. But then asp.net has had a decade, and
       | this project is new.
        
         | smt88 wrote:
         | I loathe this approach. Declarative architecture is incredibly
         | hard to debug and understand.
        
           | dmitriid wrote:
           | There's nothing declarative in asp.net.
           | 
           | You specifically define services and dependencies in one
           | place in code. It goes something like this:
           | public void ConfigureServices(IServiceCollection services)
           | 
           | { // Add framework services.                   // Add
           | application services.         services.AddTransient<Type,
           | ClassThatImplementsType>();         services.AddScoped<Type,
           | ClassThatImplementsType>();         // etc.
           | 
           | }
           | 
           | So when dependency injection happens, you know exactly which
           | class is used, and where it was added.
        
             | smt88 wrote:
             | That's declarative. You're injecting code using the type
             | system. You aren't directly calling any constructors with
             | those classes -- they're added in code that you can't
             | easily put a breakpoint in.
             | 
             | The result is that you're looking at a class with a
             | dependency of "ISomething" and you can't click through to
             | the class. You have to go back and find where the services
             | were configured (which sometimes isn't intuitive, depending
             | on how the original person wrote the code).
             | 
             | The worst is when there are entire behaviors added this
             | way, and you just have to search your code base for
             | keywords to figure out what's happening. It's awful.
             | 
             | .NET is a great ecosystem, but the ".NET way" of doing the
             | architecture is insane and not ergonomic.
        
               | dmitriid wrote:
               | > The result is that you're looking at a class with a
               | dependency of "ISomething" and you can't click through to
               | the class.
               | 
               | You can. Jetbrains' Rider will happily show you the
               | implementation (Cmd + Option + Click IIRC)
               | 
               | > The worst is when there are entire behaviors added this
               | way, and you just have to search your code base for
               | keywords to figure out what's happening.
               | 
               | Not in ASP.net in mu experience. But true for Spring in
               | Java.
               | 
               | In ASP only the classes you declare in the constructor
               | get injected. Only the classes registered in
               | ConfigureServices get injected etc.
               | 
               | All in all ASP.net has surprisingly little magic compared
               | to many other frameworks.
               | 
               | That's not to say it's without warts. There _are_
               | definitely WTF cases and places where you can 't properly
               | stop a debugger.
        
       | KingOfCoders wrote:
       | Love your book and everything you do !
        
       | jokethrowaway wrote:
       | Very interesting to see movement but personally I found the
       | debug_handler route picked by axum to be easier to understand and
       | work with.
       | 
       | Transpiling means you end up with two codebases and having to
       | think about more abstractions.
       | 
       | I sincerely hate transpiling from all the work I've done in
       | node.js / babel and other similar devilish spawns
        
         | [deleted]
        
       | didip wrote:
       | Ugh, Dependency Injection Framework. This will not be popular.
       | 
       | The blogpost itself is already shown what's wrong with pavex.
       | Adding so much concept and extra code just to be able to
       | instantiate something. $1 abstraction cost for $0.05 problem.
        
         | [deleted]
        
         | aliqot wrote:
         | rust ecosystem is very JS-like in this regard, having spent the
         | last few years working with it.
        
         | 0x457 wrote:
         | Yeah, so many more leaky abstractions that will be hard to
         | debug. Not even sure why? You're not saving anytime by doing it
         | this way. Axum already has good DI that is somewhat ergonomic
         | in rust (well, I hate how extensions aren't checked at compile
         | time like in warp...)
         | 
         | I think the solution to "rust doesn't have DI like C# and Java"
         | isn't trying to make DI like C# and Java (you won't be able
         | without very heavy runtime cost), but make a DI that works well
         | in rust and re-adjust yourself.
        
       | wokwokwok wrote:
       | I was with you all the way until the api example.
       | 
       | That doesn't look ergonomic, it's verbose AF, and the ugly use of
       | f! is (like most crates that lean heavily into macros) going
       | break tooling like the intellij rust plugin.
       | 
       | Does rust really need another web framework?
       | 
       | Does it need a compiles-to-rust meta language that means you cant
       | easily see the actual rust code you're using?
       | 
       | Does this feel ergonomic enough to make it worthwhile the
       | downsides of the first two?
       | 
       | Hm.
        
         | [deleted]
        
         | pryelluw wrote:
         | It's Java written in Rust. :shrugs:
        
         | colejohnson66 wrote:
         | Metaprogramming/macros are my biggest gripe with Rust. Sure,
         | they're cool, but they're annoying when they're thrown all over
         | the place. Especially proc-macros. You have no idea what it's
         | actually doing unless you hunt it down.
        
         | rhodysurf wrote:
         | Yeah I don't get it. The Axum example is pretty easy and the
         | actix counterpart would be easier.
         | 
         | The pavex api looks way messier, but maybe it's cuz I came to
         | rust as an express and flask user
        
       | ploppyploppy wrote:
       | No thank you
        
       | nbittich wrote:
       | It has the worst ideas of the frontend world (transpiler) and the
       | worst ideas of the backend world (verbosity of c#). I'll stick
       | with Axum, thanks.
        
         | [deleted]
        
       ___________________________________________________________________
       (page generated 2022-12-31 23:01 UTC)