Someday I will finish my Express port...
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...)
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. =)
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.
> 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.
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, ...
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.
Generally Go code isn't written like typical multithreaded code with synchronization unless you're really trying to optimize something.
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.
When a thread responsible for async/await needs to block, the task is parked and another one will get allocated to the running thread.
[1] https://github.com/rust-lang/rfcs/pull/2033 [2] https://github.com/alexcrichton/futures-await
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.
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.
It doesn’t seem to be an advertisement for C++ or a condemnation of Rust.
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.
That's in no way a fair characterization of the parent poster.
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.
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.