7

Why is the new JavaScript module request synchronous? Is it supposed to be only used in a job queue?

Is there any way to make asynchronous http(s) requests in ArangoDB?

Alan Plum
  • 10,814
  • 4
  • 40
  • 57
  • This question should not be on hold. It's valid due to the different embedded operating environment. It's very legitimate actually.... – Brian Vanderbusch Mar 20 '15 at 06:22
  • @Brian Vanderbusch: Don't confuse "valid" or "legitimate" with "on-topic". Sure, this question may be valid - it just doesn't belong here because the OP is asking for external resources. Removing that portion entirely would make the question on-topic, but it would also render your answer obsolete. – BoltClock Mar 25 '15 at 15:51
  • @BoltClock I've reworded the question to fit the rules. OP wasn't asking for external resources but for a way to make async requests (which is not supported by the platform, so the definite answer to external resources is "there aren't any and there never will be"). – Alan Plum Apr 15 '15 at 16:54

1 Answers1

8

Full disclosure: I'm part of ArangoDB's development team and primarily work on Foxx and everything JavaScript. I'm also the guy who wrote the org/arangodb/request module.


ArangoDB is a different environment than Node.js, despite sharing many similarities (such as using the V8 JavaScript engine). Unlike Node.js (or the browser), ArangoDB uses a thread-based concurrency model and doesn't feature an Event Loop. However the threads are not exposed in JavaScript (and in fact in V8 every thread is fully isolated) so you normally don't even have to think of them.

In the browser and in Node.js functions like setTimeout work by delaying code execution via the Event Loop (until a certain amount of time has passed or until an external event has occurred).

In ArangoDB the code is always executed linearly. For example, incoming HTTP requests are passed to Foxx controllers in JavaScript and the response is sent as soon as the controller returns. Even if you could use setTimeout, the external resources you were working with (or even "internal" ones like the document collections and transactions) would likely be already gone by the time the delayed code could execute.

Because of this, the request function provided by the org/arangodb/request module is also entirely synchronous. Instead of returning a promise or taking a callback it directly returns the incoming response data. It is also decidedly not the same module as request on npm but rather a synchronous implementation based on that module's API to the extent that implementing its API is possible outside Node.js (e.g. not including streams and returning the remote response instead of taking callbacks).

If you come from a Node.js/io.js background, this may feel wrong because non-blocking IO can achieve higher throughput, but keep in mind that the design goals of ArangoDB and Node.js are very different. Node.js is built around streams and network connections. ArangoDB is built as a persistent data storage and has to deal with transactions and locks instead.

It is probably not the best idea to access external APIs directly from your Foxx controllers if you have a high likelihood of serious network latency or if the external API's response is not essential to the client response. This is what the Foxx queues are for. Transactional e-mails are a prime example for this.

While Foxx is very versatile, its primary focus is to allow you to move most of your application (especially logic that benefits from running closer to the data) directly into the database. For small to medium scale projects that, you can probably get away with doing external API calls in-bounds. But if your application is primarily concerned with talking to other services over the network, running that code in a database is probably not the optimal solution.

Luckily ArangoDB plays well with others, so it's easy to move your network-intensive code out of Foxx if you find that it becomes a performance bottleneck at higher loads. Foxx doesn't eliminate the need for application servers, but it can considerably reduce their complexity.


As a correction to Brian's answer: sadly promises won't let you write async code in a synchronous environment either. The Promises/A+ spec defines promises as having to be executed asynchronously. Where they aren't natively supported they still have to be built on top of existing functions like setTimeout or process.nextTick, neither of which ArangoDB implements.

Alan Plum
  • 10,814
  • 4
  • 40
  • 57
  • Thanks for checking in and helping to get this re-opened and addressed, as well as answered. Also appreciate you addressing what was wrong with my answer. The arango docs are terrific. I knew that Foxx didn't use node, due to single-threadedness causing issues with the rest of Arango, but I didn't know the synchronous nature of Foxx on top of V8. Gives me a better idea of how to use my system resources when deciding when to scale Arango. – Brian Vanderbusch Apr 18 '15 at 06:40
  • @BrianVanderbusch Thanks for the feedback. If you find anything that could be improved in the documentation, feel free to open an issue on GitHub or hit me up on IRC. Sorry if I came across harsher than intend. – Alan Plum Apr 24 '15 at 20:19