Hacker News new | past | comments | ask | show | jobs | submit login

Strikes me as having quite a big cognitive overhead. I wouldn't try using this in unless being cornered by performance considerations or wanting a pure rust software architecture.



Note that he is using Hyper, which is a low level library. The article mentions [Rocket](https://rocket.rs/guide/getting-started/), which has higher level API.


If you're defining your APIs using Swagger/OpenAPI (https://swagger.io/specification/), you can autogenerate Rust client and server stubs using the standard Swagger code generators (https://github.com/swagger-api/swagger-codegen/).

In case you're not familiar with Swagger/OpenAPI, it's a format for specifying (generally REST-ful) HTTP APIs. The key benefit over just writing your API directly in Rocket is that you specify your API once and then generate client and server implementations that join up - even if they're in different languages.

(I did a lot of the development work on the "rust-server" Swagger codegen, and blogged on it at https://www.metaswitch.com/blog/metaswitch-swagger-codegen-f...)


Or, for another point of view: personally, I really, really don't like codegen. I view it as a wart. So for if you're using Ruby, you can use my Modern framework (not yet publicized, but being used in a pre-production capacity right now, docs to come) to generate an OpenAPI document from your API. Fire up the web server, it automatically generates and serves an OpenAPI document and you're off to the races.

https://github.com/modern-project/modern-ruby

IMO it's a smarter framework than Grape for the tasks I've set out to tackle--JSON-based RESTful APIs (though, as it's an OpenAPI-first service, there's no reason you can't handle binary data or XML or whatever you want) that leverage tools like dry-types to unambiguously define OpenAPI schema--and it addresses a lot of my pet peeves with stuff like weirdly stateful and mutable DSLs during the definition step.

The reason I mention it is because there are three languages I've been using regularly: Ruby, Node, and Rust. I intend to, next time I need a service in Node or Rust, write a Modern equivalent there. =)


Agreed, code generation can be unpleasant, but I think it depends on your workflow.

The key point with the Rust Swagger codegen is that it generates a whole crate, so you just import it and don't really need to worry that it's auto-generated.

Our Swagger/OpenAPI specifications are mastered in a repository separate from our client/server code.

Our plan is to use CI on these repos to generate crates and push them to an internal crate repository. We've prototyped this, but are limited until the alternative crate repositories (https://github.com/rust-lang/rfcs/blob/master/text/2141-alte...) work completes. (We've been quite active in pushing this forward.)

All the client/server code that uses the APIs then just imports the crate as usual.

(I think this is pretty slick.)

It's kind of clever to generate the OpenAPI document from the service that's implementing it, but how do you handle multiple parallel implementations of the same service?

For example, we're building software that we sell to telecoms operators, and one of our APIs is for retrieving information about a telephone number. Depending on the operator, they might store their data in a number of different types of databases (there are standards, but not everyone follows them :( ). These databases are fundamentally different from each other; it's not just different flavors of SQL - it's actually different query primitives. As a result, we have different implementations of this service - one per database type (there is essentially no common code between them). I think defining the API separate from the implementation is pretty crucial to making this work.


That sounds distinctly less awful than most other codegen solutions, I'll give you that. =) Codegen will forever and always make me uncomfortable but that's a better model for sure.

> It's kind of clever to generate the OpenAPI document from the service that's implementing it, but how do you handle multiple parallel implementations of the same service?

I don't. Like, emphatically I don't. I don't view an OpenAPI document as a standard to code against (though that idea is interesting)--I view OpenAPI documents as an easy way to document an API and to generate clients.


The rocket API still looks messier and harder to use than any node.js or golang web application library.


That boils down to preference though. A lot of people, myself included, find Rocket to be a highly ergonomic, state-of-the-art web framework. I think you're wrong to discount it because it doesn't look, at first glance, the exact same as the libraries you've used yourself.


Rocket might, but it's also using lots of Rust-specific features. If you want to copy Node, you can: https://users.rust-lang.org/t/a-new-crate-simple-server-a-ba...

Someday I will finish my Express port...


Looks about on par with Express with all the obvious benefits that Express does not have.


Why? Even writing micro service in C++ is dead simple these days:

1. write the service specification in Thrift.

2. Generate the server and client stub with the framework.

3. Write the service functions.

4. Most probably you'd need to include some database/cache libraries. Poco project does a fairly good job.

5. Add some more logging and metric libraries.

6. General tools/libs are available in poco and folly.

7. If you are messing with REST, Microsoft Rest SDK and Facebook Proxygen is already providing a very solid foundation. High performance servers are already written. You just need to fill the call backs and configure the thread pools.

Why do you consider this more difficult than doing the same in Go? You just need some intermediate C++ knowledge for above tasks. No need to touch template programming, manually managing threads, ...


Because Go has built in primitives to make micro services.

The cleanest asynchronous io model that I have ever seen.

Simple serialization by default.

Did I mention the blazing fast compile times? Just that would make it way more “faster” to build your service in Go :)

And above all the language is simple with robust idioms.

Okay, I admit it is somewhat too simple, cough generics. And you won’t get C like performances for sure.


IMO, the goroutine model has the same synchronization challenges as multithreaded programming. For network code that is io bound, I find async/await much cleaner.


It's not that bad with channels. I suppose you don't have to worry about synchronization issues as much with async/await on Node since that's a single threaded environment, but async/await with something like C# isn't any less complicated in that regard that goroutines and channels.

Generally Go code isn't written like typical multithreaded code with synchronization unless you're really trying to optimize something.


async/await and goroutine is not same thing here.

When you talking about async/await, you're actually talking about asynchronization, and when you talking about goroutine, you're talking about parallel (which is a selling point of Go).

If the thread that responsible for executing the async/await blocks, then the entire progress/thread rely on that async/await will block. So if you want to comfortably use async/await, the entire call stack must be build for it, and that can be a huge challenge for the ecosystem of that language.

goroutine resolved that problem by spawn a new system thread so the rest of the progress will not be effected too much by the block. Go also resolved that problem by wrapping IO on top of an internal async API so basic IO operation will not cause actual block for too long.


Not necessarily, .NET and C++ task models (as done on Windows) rely on thread pools.

When a thread responsible for async/await needs to block, the task is parked and another one will get allocated to the running thread.


the effort to add async/await to Rust is ongoing, with an experimental RFC [1]. There is also a working implementation using procedural macros [2].

[1] https://github.com/rust-lang/rfcs/pull/2033 [2] https://github.com/alexcrichton/futures-await


If you want a compiled systems language with async/await you should take a look at Nim. Implemented fully using macros so you can even extend it (Nim's metaprogramming features are awesome).


Code generation sucks...Especially when it breaks...the more you use it, the more you try to avoid it.


well I think Code generation can suck. But it does not need to suck.

I like how grpc/protobuf work. And generating the code saving it in a repo and using it, is fine. for RPC-like stuff.

However, generating code with a compiler can actually suck. Like having your database layer (jooq like) generated while compiling so the code does not get checked in anywhere.


How come on every thread showing an example of how to do something in Rust there's a staunch C++ defender thinking the whole world should be using their language? C++ is a complex beast that due to its age has quite a number of disadvantages and no two codebases I've seen are the same - a measure of a language is its simplicity and C++ subjectively isn't thus. If you like C++ that's fine; doesn't mean you can't do it in Rust as well.

I think it's good that other languages are evolving that are safer, make it easier to do concurrency, have an idiomatic style and still are performant whilst removing legacy cruft. It's the natural evolution of things. Every C++ team I've been on debates every feature usage (e.g. auto/lambdas/etc) where one team's good code is another's bad idea due to sheer amount of legacy features vs new ways, what language constructs are good vs completely bad ideas (everyone has completely different opinions), how should I import libraries, what build tool to use, etc.


Because some of us actually like both languages, Rust and C++, and dislike the misconception some have about what C++ is capable of, because they only know how to write "C with a C++ compiler" kind of thing.

Any complex language that gets wide market adoption evolves into "complex beast that due to its age has quite a number of disadvantages and no two codebases I've seen are the same".

Even something like C.


> there's a staunch C++ defender thinking the whole world should be using their language?

That's in no way a fair characterization of the parent poster.


> Every C++ team I've been on debates every feature usage (e.g. auto/lambdas/etc) where one team's good code is another's bad idea due to sheer amount of legacy features vs new ways, what language constructs are good vs completely bad ideas (everyone has completely different opinions), how should I import libraries, what build tool to use, etc.

well yeah, and if you then ask these people to debate instead the use of $LANG instead of C++ you will get 100 times more debate.


The commenter to which you’re replying is arguing that the cognitive overhead in developing a microservice even in C++ isn’t so bad compared to, say, Go.

It doesn’t seem to be an advertisement for C++ or a condemnation of Rust.


> Why? Even writing micro service in C++ is dead simple these days

Apologies to the commenter then. I misread that to be a "why bother?" to the original blog post and do this instead. All tech has its pros and cons and trying other things can be good too.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: