It's also the brave new world that lies behind us. Doom, one of the most influential computer games due to technical innovation, was created by a team of 3 programmers (and 8 non-programmers).
Small teams of brilliant people can produce phenonemal results. Unfortunately in big companies a manager is not only measured by his results, but also by his budget and the number of people under him. The division of 100 people simply looks more impressive than the room of 10. So you end up hiring lots of (at best) mediocre programmers, pay them as little as possible, and use big architectures and processes designed to cope with idiots (Enterprise architectures and Enterprise processes, as we call them).
Clayton Christen wrote about this in 1997 with "The Innovator's Dilemma". He believed it was still repeatable in large organizations via 'intrapreneurship', which I'm not convinced is entirely true... considering the enterprises continued obsession with middle management and hierarchy, and top-down R&D.
> Aynchronous Request Handling (#17) > > In 0.5, Rocket will migrate to the latest asynchronous version of hyperand futures with compatibility for async/await syntax. Of utmost importance is preserving Rocket's usability. As such, these changes will be largely internal, with asynchronous I/O peeking over the covers only when explicitly desired or required. As a side effect, we expect a substantial performance boost from the migration as well as resolution to long-standing issues.
Lacking async was my main reason at the time for switching out a hobby project from Rocket to Actix, It's exciting to see that this might change soon as Rocket really just hits the nail on the head when it comes to useability. It _feels_ fantastic compared to so many frameworks both in Rust and other languages.
So I’m guessing they have optimized their threaded model with futures, plus given you the ability to turn on a non blocking mode, but your routes will need to use futures if you do that?
While there will ever be only one Sergio in the world, there are many others in the broader Rust community who are signaling many of the same positive qualities. The signal is only increasing in strength as new talent adopts the language for critical path work.
I am more optimistic than ever about Rust as a tool for general use, not just because of the tools but because of the leadership in its community.
I am shocked that Sergio maintained rocket alone for so long. I would have figured there was a team of 3-4 people working on rocket. Glad to see he is getting help!
Sorry I am not a webdev. Curious what these are compared to something like RoR.
What's it like to work with? Do you prefer it to JS/PHP/Python for web related projects?
Can you iterate on code quickly, or is there a compile step on every iteration?
Are there stable libraries for interacting with MySQL/Redis/Postgres asynchronously?
Is there good IDE support, for example in Atom?
Thanks!
If you want type safety, speed, expressive language & native binaries, Rust is a good choice.
Those three things are very appealing, whether it's web or anything else.
For the most part, there's very little risk running Rust nightly and in fact, that's my MO. I like being able to receive the latest benefits and opt into compiler gates and whatnot. I couldn't do that on Rust stable.
Overall, I feel very little friction sticking with nightly rust and using libraries that are still nightly-only.
It becomes less healthy if the whole community is relying on nightly.
There are other frameworks you can use if you want to use stable, many of them are async already. Granted, none are really 'mature', but this is a new-ish space for Rust anyway.
(EDIT: I just reviewed the flag list and I am 99% sure this is true; the never type could use a library instead, and I am pretty (but not %100) sure proc_macro_hack could fix the other one. It’s quite possible I’m wrong, but in the end, it’s still basically three features left to go.)
The post does discuss this as well.
I hope the Tide will do.
Yikes!
Does anyone know where I can get an overview of the entirety of rocket's dependency graph. Crates.io only lists 11 direct dependencies.
These 166 packages you need to compile Rocket, not your hello-world. Rocket itself is much more complex then your hello-world, like libc.so is much more complex than hello-world coded in C, I see nothing wrong with it. Rocket and libc.so were created for solving a wide class of problems and hello-world is just one problem from that class.
Looking for ActiveMerchant equivalent in Rust.
How do you handle subscription billing?
[1] https://github.com/SergioBenitez/Rocket/issues/19
edit: specify Rocket release, not Rust release
Diesel is the main library for interacting with SQL databases, it wasn't async last time I used it, and a quick web search tells me it still isn't - this has been a BIG problem with Rust over the last year, as everyone waits for the async implementation to finally become stable.
Rust is a funny beast at the moment - you have to deal with the learning curve, you have to deal with the unstable/pre-1.0 libraries (some of which are fine), you have to deal with all the errors the compiler throws at you.
But once you've done all that, something magical happens: you end up with software that is mind-blowingly stable and blazingly fast. It doesn't throw segfaults, it doesn't leak memory, it just works, and works amazingly well.
Fairly sure you can leak memory, just no memory safety issues (in safe Rust).
That basically made me shelf it for about two years, until last year when Rocket was rising and I gave it a shot. Got hung up again that year due to missing expressiveness in query handling and shelved it again. In the last month I picked it back up and have been working on it again and I must say - this is the best server side development experience I've had, either on the side or working with node / rails / etc for money.
I also definitely feel the performance bump, even without async in yet, and scaling Rocket apps is much more trivial than trying to scale Flask / Django via multiprocess.
I've also been spoiled by the Rust compiler and RLS, despite its breakages its still some really impressive stuff with how if you can get something to compile it is substantially more likely to work and not have errant edge cases that something written in a less prudent language would struggle with.
I haven't really gotten involved in any larger scale Rust projects or took on a maintainer role on anything substantial - I've just made a few patches to Rocket and some support libraries - but I can easily imagine this is the best kind of environment to do collaborative work in. You get rustfmt for style, you get the best compiler ever for debugging, and the project management of Cargo is just impossibly elegant and delightful over anything else I've used. Its definitely something I'd love to work in at a day job as it matures onto the market.
That is what expected the least, when I was starting out. I was looking for something that is a little like Python, but faster than it. It gives me a sense of security to see the compiler call me out for a reason, telling me exactly which cases I forgot. Together with the type system I often find myself in situation where I do something quite complicated (for my experience) and then I am at a point where I am confident it works, I `cargo run` the whole thing and it works like a charm.
In Python a lot of things would run, but also broken things. Having it run was no guarantee at all it won't end up in a convoluted traceback later. In Rust having it run is a great part of the deal, I rarely encountered Panics afterwards, and when I encountered them it was me willfully defining where I would encounter them.
The weird thing is: because it takes much more to just get a program that compiles – even if you're lazy you end up with a higher code quality. It won't let you take some shortcuts that will haunt you later and that is a good thing.
Of the popular frameworks in languages you mention, Rocket is fairly close to Flask in terms of feel. Rust is a typed language and Rocket uses code generation and function's type signatures to automatically check the incoming parameters.
This can be fairly simple, like verifying+converting a param to a number. It can be fairly involved like setting it up so that if one of your handler function's arguments is an AdminUser, Rocket will take the user id from the request/cookie, connect to the database, and verify that the user is an admin. This is doable with middleware in many frameworks for the languages you mention but the difference is that this is on-demand based on the argument types.
> Can you iterate on code quickly, or is there a compile step on every iteration?
Rust is a compiled language. There's a compile step when you make a code change.
> Are there stable libraries for interacting with MySQL/Redis/Postgres asynchronously?
There are libraries for interacting with all those things. That said, the Rust async ecosystem is in a transition period at the moment. If you're familiar with the JS transition from callbacks to Promises to async/await, it's basically that. Check back in 6 months.
> Is there good IDE support, for example in Atom?
IDE support in Rust isn't particularly good yet. In general, find references and go to defintion work but autocomplete does not.
That said, it really depends on what you're doing. If you are debugging something, it can be a bit painful but not terrible (typically, you're just changing a few things as you go along). If you're implementing a feature or refactoring, you're better served using "cargo check" (especially in combination with "cargo watch") to only run typechecking but not code generation, which means extremely fast feedback.
Coming from dynamic languages it will feel very different, especially if you don't have a lot of experience with typed compiled languages. Personally, I came from a JS background and I love it. It totally sold me on the benefits of a good type system so much so that I sorely miss it when working with JS now.
Writing web servers in Rust is a fairly new space, it's not as mature as js/php/python, however things are moving quickly. Having your code run orders of magnitude faster is pretty nice too.
> Can you iterate on code quickly, or is there a compile step on every iteration?
I think conflating 'working on code quickly' with compilation is a mistake, however, yes, you do need to compile your code. IMO a compiler will help you iterate more quickly because it's able to check for errors before you run your code.
> Are there stable libraries for interacting with MySQL/Redis/Postgres asynchronously?
If you want an ORM the thing you want to look at is diesel. I'm not sure if it's async or not.
> Is there good IDE support, for example in Atom?
rust language server (RLS) has plugins for most editors. I think the best experience for developing rust right now is in VScode or vim, IMO.
> > If you want an ORM the thing you want to look at is diesel. I'm not sure if it's async or not.
Diesel isn't async yet, but interfacing with it in async frameworks such as actix seems to be pretty straightforward: https://actix.rs/docs/databases/
Intellij + Rust Intellij plugin is probably the best, in terms of actual usefulness (code completion etc) and stability.
Rust has such a great tooling. In Python starting new projects, remembering whether to use pipenv pyenv, pew, pip virtualenv, which file was supposed to mean what feels much much more convoluted. In rust this is a two word shell command.
The compiler will fuck with you more than you would like, but if you don't fight it, but try to figure out why it is right, you will find that most compile errors are totally for a reason. I had FAR less runtime errors with rust. If the code compiles it is either code with a logic error or it just works as intended.
And it is performant as hell.
The framework itself is similar to Flask in productivity and amount of boilerplate, though it's even better. It converts all input data to proper types for you using type signatures of handlers. So I don't need to convert strings into ints, or into json and then check if it conforms to a schema. If handler is called, input is parsed and converted.
Rust itself is more verbose than python. Typical data manipulation, like put something in dict, extract/count uniques, "transpose" a datastructure, load data from file, usually takes 1.5x-3x as much chars. For this price you get strict compile-time type checks that take lots and lots of mental load off code refactoring, C++ level performance, and real multithreading, including easy data parallelism with libs like rayon. Rust also has enums (aka algebraic types or tagged unions) that can help to represent problem space better and make fewer logic mistakes later.
It would be all unicorns and rainbows for me if a more concise database interface was awailable. Currently the go-to ORM is Diesel, and it's very verbose comparing to, say, python's sqlalchemy. Current solution is to move database access from views into methods of a model.
About iteration: code requires recompilation. Changes to non-compiled templates do not. I use Maud templates and they make html look suprisingly clean, they compile and are fast, but well, you need to recompile them every time. Currently debug build takes ~10s, though parsing and typecheking are done in the first several seconds.
Diesel doesn't support async yet, AFAIK. But async is usually used to save on context switches and stack space, allowing to support tens of thousands of live connections. You won't ever have tens of thousands of connections to database like Postgres. 100 connections is quite generous. 500 connections may be possible on the fattest DB boxes. Postgres is not async itself, it allocates a 4MB scratch buffer for each client from the start, IIRC. The only good reason to use async for communication with postgres may be if all of your other code is async and you don't want to deal with sync/async impedance mismatch. Though you'll likely want have connection pool anyway.
About IDEs I can't say much, I use emacs with LSP, it works most of the time.
Here are couple of examples (didn't test them, but they should illustrate the point):
// Simple with admin user.
#[get("/admin")]
fn admin(user: AdminUser) -> String {
// Request is made as admin user.
format!("Allowed.")
}
#[get("/admin"), rank = 2]
fn admin(user: User) -> String {
// Request is made as a normal user.
format!("Not allowed!")
}
#[get("/admin"), rank = 3]
fn admin(user: AnonymousUser) -> String {
// Request is made as a anonymous user.
format!("Please login.")
}
// More flexable, with permissions.
#[get("/article/<id>/edit")]
fn aritcle_edit(permission: PermissionEditContent, article_id: u64) -> String {
// Request is made with a user that has the correct permission.
format!("Allowed.")
}
#[get("/article/<id>/edit"), rank = 2]
fn aritcle_edit(article_id: u64) -> String {
// Request is made with a user that doesn't have the correct permission.
format!("Not allowed!")
}
// Or in single handler.
#[get("/article/<id>/edit")]
fn aritcle_edit(permission: Option<PermissionEditContent>, article_id: u64) -> String {
if permissions.is_some() {
format!("Allowed.")
} else {
format!("Not allowed!")
}
}
This is just one of the nice things that rocket brings. To know more, the guide is really good source: https://rocket.rs/v0.4/guide/.In short, I'd say Q2 2019 would be a time to seriously jump into it if you don't want to do it now.
And those are almost always the good "in depth" reasoning comments you want in software, not the mandatory "Function save saves the file to where parameter location is" which just repeats the definition.
I still love Python, but I can't even argue its a productivity win for me to use over Rust anymore, because while I might sometimes make something that seems to work faster the lack of confidence makes scaling the program much harder and there really is nothing syntactically in Rust besides the static typing (which is a good thing in my book anyway, its why Python added function signature type hints after all) and verbosity (semicolons, mandatory braces, etc) that prevents you from writing code as fast as a Python variant with the right library support.
Well that's the thing it's all about libraries, and now in Rust it's nowhere compare to Python for the web dev.
That's just the open issue around pinning.
There are however a few open discussions around the futures/task/waker parts, from the other RFC. I just wrote down a list of the open points here: https://github.com/aturon/rfcs/pull/15#issuecomment-44549238...
Right, but this is presumably a one-time investment while learning Rust, much less of an ongoing hurdle.
a) you used .clone() everywhere and therefore are probably modifying something and failing to propagate the modifications to where they need to go; or
b) your design is inherently better, saner, easier-to-optimize, etc., than one which doesn't have to satisfy the borrow checker.
Look at the kind of programs that NLL now allows. You wouldn't have to jump through those hoops in another language.
That's just my opinion, of course.
I wasn't sure if bare-bones Rust+Lamba-Rust-Runtime was already enough.