In the user guide of FastAPI for SQL databases is following described:
"We need to have an independent database session/connection (SessionLocal) per request, use the same session through all the request and then close it after the request is finished."
https://fastapi.tiangolo.com/tutorial/sql-databases/
It seems to be a common pattern also in webapps. So why is it recommended to have a session per request?
Would it also be possible in any case to have one session per application lifecycle from process start to stop? What will be the disadvantage?
Related
I'm using Spring Boot 2.1.4, Kafka and React as a frontend UI. I have a user registration process from the UI which requires a backend process and it's data before the registration is complete.
The flow is like this:
The frontend UI makes a request to an API which returns a token and puts a message on to a request Kafka queue
The message is processed by a backend process (which takes approximately 1 minute)
When the process is finished, a message with the token and data is written to a reply Kafka queue which indicates the process is complete
What I want is the frontend UI to make the initial API request which returns immediately, show a loading screen and display a ready message when the registration process is complete.
I have thought of a couple of options:
Attach a KafkaListener to the reply queue. Once the reply message appears, store the response and token in a datastore (e.g. Redis). Provide an API to the UI which checks the datastore for the token. The UI will poll this API every 10 seconds. If the response is not available after 2 mins, the user will be asked to check back later.
Use WebSockets with React. I've not used WebSockets before but the only thing I'm unsure of is if I have multiple instances of the registration microservice, will this cause any issues with client/api communication.
Any recommendations or any other options on the best way to handle this?
Attach a KafkaListener to the reply queue. Once the reply message appears, store the response and token in a datastore (e.g. Redis). Provide an API to the UI which checks the datastore for the token. The UI will poll this API every 10 seconds. If the response is not available after 2 mins, the user will be asked to check back later.
This will work. I would use the built in RocksDB for storage though, just for simplicity. Below is the documentation for exposing a state store to be queryable outside of kafka streams.
https://kafka.apache.org/20/documentation/streams/developer-guide/interactive-queries.html
Use WebSockets with React. I've not used WebSockets before but the only thing I'm unsure of is if I have multiple instances of the registration microservice, will this cause any issues with client/api communication.
It can potentially cause issues. It depends on the implementation of the registration service. You won't know which instance of the registration service a client will establish a connection with. For instance session needs to be managed in a external datasource like Redis or you would have to use a laod balancer that supports sticky sessions (a bit of an archaic solution).
I wish to implement sessions in webapp2. From research, I have found this code sample using webapp2_extra.sessions, and a few articles which mentions deprecated or unmaintained session libraries.
I currently lack the knowledge of how sessions work conceptually. This is what I understand so far:
We can include a dispatch() method to a request handler which allows us to create/update a session object; it is during the login phase of the app, the session is created. (Question: how is session stored? In the app's memory or in datastore?)
When a user makes a request to the app, the dispatch() method checks to see if an existing session exists for the user. (Question: How exactly does this validation work? Is there a token inside the request.body or cookie that sessions look for?)
When a user logs out, the session is deleted.
Is my understanding correct? Or perhaps I am missing something important? There seems to be little guidance on this subject on the internet. Thank you for the assistance.
Technically the dispatch() method is not added, it's just overwriting the one that webapp2.RequestHandler already provides, extending it to add session support. If you take a closer look at that method you see that it still calls the original one to do the actual dispatching:
# Dispatch the request.
webapp2.RequestHandler.dispatch(self)
Which could be re-written, if you want, as:
super(BaseHandler, self).dispatch()
All that the extended dispatch() does is picking up the session info from the store making it available to the handler code before dispatching the request (which BTW includes the request processing) and saving it back afterwards, when the request processing completes (when changes to the session info may have been done). For every request! Simply a way to persist info across requests.
The session support is simply that - support - your app is still the one responsible for controlling what info is stored in the webapp2's session dictionary, when is that info added/modified/deleted and how is that info used.
In other words webapp2 itself has no clue what's login/logout/user session, etc (So no, nothing that you mention in #1, #2 and #3 happens in webapp2 itself). It is your app's responsibility to:
set/delete inside the session dictionary the info that represents your "user session" (whatever that means for your app) - typically in the user login/logout request handlers, respectively
use that info as it sees fit while handling incoming requests between the login and the logout one - when the info from the session dictionary represents the "current user session".
For storing the session info webapp2 supports cookies (default), memcache and datastore (ndb). From Sessions:
It has three built-in backends: secure cookies, memcache and
datastore. New backends can be added extending
CustomBackendSessionFactory.
The session store can provide multiple sessions using different keys,
even using different backends in the same request, through the method
SessionStore.get_session(). By default it returns a session using
the default key from configuration.
My application allows a user to enter a URL of an article he/she wishes to analyze. It goes through our API gateway to reach the correct services engaged in this process. The analysis takes between 5 and 30 seconds depending on the article's word count.
For now, my reactjs client sends the request to the API and waits for 5 to 30 seconds to receive the response. Is there a better way to handle this such as enqueuing the job and let the API ping the client (reactjs frontend) once it has been done?
Server-sent Events (SSEs) allow your server to push new information to your browser, and hence look ideal to me for this purpose. They work over HTTP and there is good support for all browsers except for IE.
So the new process could look as follows:
Client send request to server, which initiates the lookup and potentially responds with the topic the browser needs to subscribe to (in case that's unique per lookup)
Server does its thing and sends updates as it processes new content. See how the beauty of this is that you could inform your client about partial updates.
If SSEs is not an option to you, you could leverage good old Websockets for bi-directional communication, but for such a simple endeavor, it might be too much technology to solve the problem.
A third alternative, especially if you are talking amongst services (no web or mobile clients on the other side) is to use web-hooks, so that the interested party would expose and listen on a specific endpoint, that the publisher (the server that does the processing) would write updates to.
Hope this is useful.
We're using sessions in our GAE/J application. Over the weekend, we had a large spike in our datastore writes that appears to have been caused by a large number of _ah_SESSION entities being created (about 100-200 every minute). Near as we can tell, there was a rogue task queue creating them because they stopped when we purged the queue. The task was part of a mapper process we run hourly.
We don't need sessions in that hourly mapper (or indeed in any of our task queues or cron jobs or many other requests). Is there a way to disable creating a session for selected URLs?
Unfortunately that can not be done.
This is particularly nasty when you have a non-browser clients (devices via REST or mapreduce jobs) where every request generates a new _ah_SESSION entity in the database.
The only way to avoid this is to write your own session handler: e.g. a servlet filter that sets/checks cookies and set it so that it ignores certain paths.
EDIT:
I just realized that there could be another way: make sure your client (mapreduce job) sets a dummy cookie with a proper name. GAE uses cookies named ACSID in production and dev_appserver_login on dev server. Just use always the same cookie value, so all requests will be treated as one user/session.
There will still be overhead of looking-up/saving session objects, but at least it will not create countless _ah_SESSION entities.
After reading about how CodeIgniter handles sessions, it has me concerned about the performance impact when sessions are configured to be stored and retrieved from the database.
This is from the CI documentation: "When session data is available in a database, every time a valid session is found in the user's cookie, a database query is performed to match it."
So every AJAX call, every HTML fragment I request is going to have this overhead? That is potentially a huge issue for systems that are trying to scale!
I would have guessed that CI would have implemented it better: include the MD5 hash to cover both the sessionID+timestamp when encoding them in the session record. Then only check the database for the session record every X minutes whenever the sessionID gets regenerated. Am I missing something?
You can make your AJAX requests use a different controller, for example Ajax_Controller instead of MY_Controller. MY_Controller would load the Session class but the Ajax_Controller doesn't. That way when you call to your AJAX, it doesn't touch session data and therefore doesn't make any erroneous calls to the database that aren't necessary.
If you are autoloading the Session class, maybe you can try unloading it for the AJAX requests? I've never tried it but it's talked about here http://codeigniter.com/forums/viewthread/65191/#320552 and then do something like this
if($this->input->is_ajax_request()){
// unload session class code goes here
}