Show HN: Aqueduct – Dart on the Server
aqueduct.io
aqueduct.io
The framework contains behavior for routing and authorizing HTTP requests, persisting data in PostgreSQL, testing, and more.
One thing that makes Aqueduct really interesting is that it runs the application on a few isolated-memory threads. This is a concept interpreted from the Erlang/Elixir that leverages Dart 'Isolate's. (Here's some documentation on that: https://aqueduct.io/docs/http/structure/)
The aqueduct command-line tool serves applications, manages database schemas and OAuth 2.0 clients, and generates OpenAPI specifications.
I am unable to read the examples on the homepage as they scroll by too fast. Could you please do both of: increase the time each example stays on screen; and disable the automatic scrolling if the user makes an effort to select a particular example either by clicking the side arrows or the selector tabs on the bottom.
"Compose modular maintainable code" or "Achieve the productivity of a cohesive framework" doesn't really say anything at all - you can replace that whole thing with a random code snippet and a big title that says "Aqueduct - now, more than ever!".
The 'cohesive framework' one made sense in my head - the ORM and the HTTP stuff work together so that errors thrown by the ORM are translated into the appropriate status codes without having to catch the exception. I can see how just reading that may make no sense.
I'll check out the webpages for both Flask and Spark and adjust accordingly. The real info for developers is at https://aqueduct.io/docs anyhow.
How have you found Dart as a server-side language? What's the performance like and the ease of development?
First impressions of Dart are positive. However, the server-side (interpreted) language landscape is dominated by Python, Ruby, PHP etc. Any thoughts on choosing Dart for server-side programming over these other common languages and what you think the advantages are? Many thanks.
Async/await is implemented really well (Google hired Erik Meijer to help them build it), their threading model is excellent, and there are built-in keywords in the language for stream handling that are seriously productive [1]. Anyone that knows Java/Swift/Kotlin/ObjC is going to be productive in Dart very, very quickly.
Performance has been great, but someone else may be better qualified to answer that question. Much of the lower level socket stuff is just C/C++. I don't want to speak on something I don't fully understand, so I included an article about the Dart VM below [2].
To me, Dart differentiated itself by being more similar to compiled, C-like languages. Obviously, Django, Laravel, Rails, etc. are much more mature. Aqueduct is tested well [3], but nothing beats years of regression tests.
1: https://www.dartlang.org/articles/language/beyond-async 2: https://www.dartlang.org/articles/dart-vm/why-not-bytecode 3: https://github.com/stablekernel/aqueduct
The changelog [1] always has a few entries for the Dart VM with each version, but it's quite clear from using it daily that much more is happening. Some notable recent improvements have been asynchronous breakpoints that are integrated in IntelliJ's debugger and some optimizations for sending messages across isolates.
1: https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md
Where did you get that info? I haven't seen it in the changelog. Is message passing using structured cloning?
Dart now targets the Web (two compilers - one for development, one for "production" - both transpiling to JS), the server (Dart server VM - fast native JIT VM), Mobile via flutter (support for AOT on iOS), and Fuchsia.
[1] https://groups.google.com/a/dartlang.org/forum/?fromgroups=#...
Related question: Is multi-threading accomplished via these Isolates, or is there a threading model within each Isolate too?
Thanks!
Yes, multi-threading is accomplished through isolates. The application is run as a replica on a number of isolates, configurable by a command line option.
Each isolate has its own database connection, etc., but operate exactly the same. This behavior doesn't require any additional effort by the developer. (edit: The initialization code sets up a reactive channel for requests, each isolate instantiates that channel, and Dart's VM manages delivering an HTTP request to the most appropriate isolate.)
So, it's not quite like Erlang/Elixir where each connection gets its own process, rather the default number of isolates is 3. Isolates have their own heap, so memory isn't shared across them, but there is a message hub that isolates can send values across. This is useful when say you have websockets connected to different isolates and you want to broadcast a message to all of them.
You can spawn additional isolates from a 'web server isolate' to move computation to another thread.
How much extra memory usage is there per isolate?
The main isolate creates an Application instance that has N number of supervisors, one for each isolate. The isolates are launched and go thru their initialization steps, reporting back to their supervisor. The application completes its launch once all supervisors have reported back. It fails its launch if an isolate throws an error during initialization or does not hear back in a configurable timeout. Any inter-isolate messages sent during startup are queued until all isolates have completed startup.
Once the isolates are up and running, the main isolate doesn't do anything other than facilitate the inter-isolate message hub. Requests are delivered directly to the isolates running the web server.
When running automated tests, the default behavior is to run everything on the main isolate, since tests are run against a temporary database schema that only exists for the lifetime of the connection.
The memory consumption of an isolate depends on the size of the application code. Each isolate actually has its own copy of the application code that gets tuned by the VM over time. Even stuff like static variables are per-isolate. I just pulled up an OK sized Aqueduct project, and it looks like about 30-40MB per isolate. Most of that is probably Aqueduct itself. A worker isolate is likely an order of magnitude smaller.
1: https://webdev.dartlang.org/articles/performance/event-loop
It's command-line tool runs the application, but there isn't much from stopping you from just using the `dart` command line tool and a Dart script to start it.
edit: Basically, you can run this on any machine that can install Dart.
And yeah, as a native iOS developer for many years, I finally sat down and built something in Flutter this weekend and really liked it.
The interesting thing about the Dart VM is there's no JavaScript at all. You can even link to C and C++ code from Dart.
1: Here's a discussion on how the Dart VM is implemented: https://groups.google.com/a/dartlang.org/forum/#!topic/misc/...)
router.route("/*").pipe(new HTTPFileController("web/");
router.route("/files/*").pipe(new HTTPFileController("something_else/");
An HTTP request for /foo.html returns web/foo.html. An HTTP request for /foo/bar.html returns web/foo/bar.html.An HTTP request for /files/xyz.jpg returns the something_else/xyz.jpg.
If the HTTP path is a directory, then index.html is automatically appended to it. This is a brief overview of the referenced documentation above.
Never mind, I was readding wrong.