Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Nuxt or Angular + Fiery and concurrent requests? #26

Closed
lautiamkok opened this issue Oct 31, 2017 · 10 comments
Closed

Question: Nuxt or Angular + Fiery and concurrent requests? #26

lautiamkok opened this issue Oct 31, 2017 · 10 comments

Comments

@lautiamkok
Copy link

After a few years of using Shiny and we have had lots of issues with it, e.g. it is too opinionated and it does not support concurrent requests on the open source version.

I wonder Fiery support concurrent requests?

We would like to use fiery as an API only and use Nuxt or Angular to send the requests, so we need CORS, does Fiery support CORS then?

@dpastoor
Copy link

I will let @thomasp85 speak to the specifics, but I think you could do that with the future stack? I am not positive on how the requests are scoped, but given there is an event loop, you may not even need that, and just to use some abstraction like the later/promises to not block while working.

That being said, I would think carefully about whether your requests are truly concurrent, or do you need to support parallel requests. That is, if you are using fiery to support more computationally heavy tasks (parallel) vs needing to support tasks like not blocking while waiting on database calls (concurrent) then the implementations would be very different.

IMO, for computationally heavy tasks, it may be worth routing them through some other web server then load balance across a number of fiery instances, which will isolate and provide control over throughput. For example, I stand up fiery workers using a go(lang) based web server with a semaphore to keep the current number of requests being executed at a time bounded.

And yes fiery supports CORS

@lautiamkok
Copy link
Author

@dpastoor thanks for the reply. Do we need any specific code to enable CORS in Fiery? For instance, if I use ExpressJS or KoaJS and I need CORS support, we need to enable it in our API, e.g.

// CORS.
// https://github.com/koajs/cors
app.use(cors({
  origin: 'http://127.0.0.1:3000',
  credentials: true,
  allowHeaders: ['Origin, X-Requested-With, Content-Type, Accept']
}))

@lautiamkok
Copy link
Author

lautiamkok commented Oct 31, 2017

@dpastoor I am a bit confused with parallel requests and concurrent requests - I thought they are they same?

The problem in our Shiny apps are:

  1. computationally heavy tasks
  2. thread blocking: if one user is doing some calculation, the other user must wait until that process finished!

We hope Fiery is a better alternative to Shiny (which has been a nightmare to us after a few years using it for our apps).

@thomasp85
Copy link
Owner

Hi @lautiamkok

To answer your first question about concurrency: R is single threaded and there is no way around that - requests are handled one at a time so the next request will only be started once a response has been returned to the current request. This is not a limit in fiery per se, but in httpuv which is the http server powering most R server framework. Still, there are ways in fiery to handle the problem of computational heavy task without congesting the server. fiery allows computations to be send of to a parallel process using the async() method. You would then return a 202 - Accepted response to indicate that the request is being processed. While it is being processed the fiery server is free to handle other requests. The client will need to regularly request whether the processing is done, of course...

Alternatively you would pack the fiery app into a container and put it behind a load balancer, but I generally think it is best practice to return a response as quick as possible instead of letting the client hang until the computation finishes...

Regarding CORS, there is nothing in fiery hindering you from implementing it, but there is nothing helping you either (there might eventually be a plugin...). Supporting simple requests are quite straightforward and just require you to check the request for the Origin header and set the Access-Control-Allow-Origin header on the response... Supporting preflight requests requires some more work such as setting up a OPTIONS endpoint in your router to take care of the preflight, but there is nothing that should case much trouble...

If you end up implementing CORS support it would be cool if you abstracted it away and implemented it as a fiery plugin so others could benefit from it :-)

I hope this answers your question...

@lautiamkok
Copy link
Author

@thomasp85 thanks for the answers. Just another question - any official documentation for Fiery?

@thomasp85
Copy link
Owner

Not outside of the package itself, but I think I’ve done a decent job with that🙂. Hopefully there will be some online documentation at some point

@dpastoor
Copy link

dpastoor commented Nov 1, 2017

CORS is pretty easy, here is how I had it (to just allow everything) . This is old code, from one of the first implementations of fiery, so @thomasp85 I'm guessing at least the request structure may be different?

app$on('request', function(server, id, request, ...) {
    if (request$REQUEST_METHOD == "OPTIONS") {
        ## assuming this is preflight request check
        return(list(
            status=200L,
            headers=list(
                "Access-Control-Allow-Methods" = 'POST, GET, PUT, OPTIONS, DELETE, PATCH',
                "Access-Control-Allow-Origin" = '*',
                "Access-Control-Max-Age"= '3600',
                "Access-Control-Allow-Headers"='Origin, X-Requested-With, Content-Type, Accept'
            ),
            # also need body to satisfy fiery https://github.com/thomasp85/fiery/blob/master/R/Fire.R#L414
            body=""
        ))
    }
...

Point is, at least from an MVP standpoint, you can intercept OPTIONS requests and give back the access control headers.

@lautiamkok
Copy link
Author

@dpastoor thank you for the code.

@dpastoor
Copy link

dpastoor commented Nov 1, 2017

@lautiamkok it sounds like your problem is not just an issue with shiny, its an issue with scale, at which point infrastructure considerations are important.

concurrency is the ability of a program to manage multiple requests at once - think keep track of what a bunch of users are asking at once. For example, if you just are querying a database (so most of the time is actually waiting on the DB to return results), concurrency is the ability to make those multiple queries at once and wait for them. This is the foundational principle of node, it is highly concurrent as it has an event loop and (much) of the code is written in a way that it asynchronously makes requests then just kind of checks on the status (by cycling through the event loop) of each request over and over until it is done and can do something else.

parallelization is the ability to execute multiple tasks at once. For example, running multiple models at the same time for different people.

@thomasp85
Copy link
Owner

The code example will need to be updated to at least use reqres, but probably also use routr as the app logic is more manageable...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants