FastAPI persist DB connection - fastapi

I use FastAPI in a microservice environment on a public cloud. Most of the request needs a pymongo and redis connection. The preferred model of FastAPI is to inject db connections via dependencies. However the DB is rolling its credentials once a month. For a new DB connection I retrieve the secret from the secret store (https request) and initiate the connection. This process is quite heavy if you do this at every request. Thus, I would init the client and pass it as variable to the dependencies. But if the credentials change, this would lead to an error.
Can I do something like this in FastAPI (I did in Flask):
try:
crud_to_db()
except ConnectionError:
re_init_db_connection_on_app_level()
crud_to_db()

Related

HonoJs: Best way to start a Twitter SDK connection in Hono with CloudFlare?

In an old-school server environment, you initialize an SDK (like the Twitter SDK) when the server starts up, using dotenv to read secrets and tokens from your .env file like so:
import dotenv from 'dotenv';
import {Client} from 'twitter-api-sdk';
dotenv.config();
const twitterClient = new Client (TWITTER_SECRET_INFO);
And then you would use the twitterClient object to get data in one of the route handlers.
What's the best practice for initializing something like the twitter client in Hono with Cloudflare?
In the old service worker framework, I could have treated the secret info as a global environment variable much like in Node/Express, but in the new module worker code you have to access the environment variables as a parameter passed to a function call. It looks like Hono manages this by passing contexts to methods like .use/.get/.post.
Ideally, though, I wouldn't reinitialize the twitter connection on every request, especially since I'm just getting public info with a token, not dealing with any user login/password info.
Is there any way to do this in Hono/Cloudflare, or do I have to initialize the Twitter client middle ware each request? I looked at the Hono class constructer, but from what I can tell, all it does is take a router config object.
And from what I can tell of the cloudflare docs, module workers have the same issue. Whereas constants in a service worker were declared outside the route handler, it looks like everything in a module worker is declared inside a fetch handler. Is there anyway to initialize once during the life of the worker and not for each request?
In principle you could initialize the client on the first request:
let twitterClient = null;
export default {
async fetch(req, env, ctx) {
if (!twitterClient) {
twitterClient = new Client(env.TWITTER_SECRET_INFO);
}
// ... normal code ...
}
}
That said, though, is creating a new client actually expensive?
Constructing the client does not "initialize a connection". The client presumably makes requests by calling fetch(). The fetch() API doesn't expose any way to control the underlying connections used; each fetch() operates effectively independently. But, the Workers Runtime will automatically reuse connections behind the scenes, when possible. It could even reuse the same connection for two completely unrelated Workers, if they are contacting the same destination host. So it may be that even creating a new client with every request, you're already getting good connection reuse.
That said, perhaps the client has to do some sort of key exchange upfront, e.g. exchanging a long-lived refresh token for an access token. That is annoying to have to repeat on every request. So in that sense, maybe caching it in a global helps.
However, note that Workers creates LOTS of instances of your Worker around the world. You may find if you curl your Worker several times in a row, each request lands on a different instance. You may find that caching in global state does not actually have much impact unless you have a large amount of traffic.
Caching may be more effective if you use the Cache API to store cached values into the colo-wide cache. Unfortunately, client libraries designed for Node environments may not provide the right hooks to do this.
One final note: Note that putting live resources (things that are not just plain data structures) into the global scope can be dangerous on Workers, because in general a Promise created on behalf of one incoming request cannot be awaited in the context of some other request. So if that twitter client does do some sort of upfront key exchange and tries to have all requests wait for that to complete, you may find that if you receive multiple requests at once before the initial key exchange finishes, all except the first request end up failing. To be honest, I would recommend creating a new client for every request unless you see a measurable performance problem from this.

How to track status of an async long running process from stateless spring boot services in GCP?

We have a few Spring Boot services running in a GCP Kubernetes Engine which expose their HTTP(over gRpc) API to the clients.
One task is to import very large data files. The proposed way is to upload files to Google storage and trigger an asynchronous import by providing the file-path to the import location and return HTTP 202 in case the request was valid.
Next, we set the status of the import to pending within the persistence layer (spanner) and trigger an asynchronous parsing and batch ingestion process. In case the import was successful we set the status to completed.
The only way for a client to know if the import was successful is to come back and poll our API for the current status.
And there arises the question then.
There are several load-balanced pods of the same kind. If the importing service crashes (i mean crash, not exception handling), there is no straightforward way for us to finally set the status to aborted. The status will remain pending forever.
We would like to circumvent the use of an additional layer like hazelcast if possible. Also, we`d like to avoid having another service that communicates with one or other pods directly, observes the states and does some fancy callback stuff.
Can anyone give a hint of how to tackle that problem in a best practice manner?
Many thanks.

When is the right time to create dynamodb connection in a server application?

Let's assume you are developing a server-side application with express and for incoming requests, you have to access DynamoDb and retrieve something. The question is, when is the right time to instantiate the DynamoDb connection:
const dynamodb = new AWS.DynamoDB({
region: process.env.AWS_DEFAULT_REGION,
});
const docClient = new AWS.DynamoDB.DocumentClient({ service: dynamodb });
Should I do this once for all the API handlers or should I create a new connection for each incoming request?
As a best practice, it is recommended to declare DocumentClient the outside the function. However, please note that DocumentClient is not a database connection object. DocumentClient is just an abstraction in the AWS.DynamoDB namespace. The document client abstraction makes it easier to read and write data to Amazon DynamoDB with the AWS SDK for JavaScript.
Unlike RDBMS connection, it is not required to maintain the connection or connection pool to connect to DynamoDB database.
DynamoDB is a web service, and interactions with it are stateless.
Applications do not need to maintain persistent network connections.
Instead, interaction with DynamoDB occurs using HTTP(S) requests and
responses.
new AWS.DynamoDB(options = {}) ⇒ Object
The service object AWS.DynamoDB uses asynchronous request to send data to DynamoDB. The DocumentClient also uses this service object internally.
By default, the SDK will send asynchronous HTTP requests to DynamoDB. However, you can change the default behavior by setting the attribute httpOptions.xhrAsync to false.

Session Consistency and the .NET Client SDK

I am trying to understand what Sessions Consistency actually means when working with Azure DocumentDb via the .NET client SDK i.e. What defines (and bounds) a session. Is a new session created each time we create a new instance of DocumentClient and if so does the behavior change if we are using the IReliableReadWriteDocumentClient wrapper?
Yes, a new session is created each time you create a new instance of the DocumentClient class. Each DocumentClient instance maintains a map of collection -> session token mapping. The client saves the latest session token received from the server, and echoes it as a header (x-ms-sessiontoken) during read requests. This enables DocumentDB to locate an up-to-date replica of your collection to serve session (or read-your-writes) consistency. This is the same with IReliableReadWriteDocumentClient, since it's a wrapper over the DocumentClient.
Note: the easiest way to achieve session consistency is to have a single DocumentClient instance manage it for you automatically. You can also manage a logical session across multiple DocumentClient instances with a little more complexity. For example, let's say that you have a load balanced Web API with two servers each with a DocumentClient instance, and you want session consistency across these servers.
client writes -> App Server 1 -> DocumentDB
client reads -> App Server 2 -> DocumentDB
You can implement this by saving the x-ms-sessiontoken returned in step 1 by saving it as a cookie in the client, then echoing that x-ms-sessiontoken in the read request. By round-tripping the session token, you can get session consistency.

Two-Phase commit in EJB

I getting Two-Phase commit Exption in my application for one of the datasource. Point is application only does ready only data option using Oracle Toplink. Here is what happling in Application
Request come to webservice
Webservice calls to JMS Queue. Application need response from queue so used queue with Read Respose
In Message Bean( Lets call this ProcessBean), several successful hit goes to Oracle DB using Oracle Toplink, [b]no exception is trown[/b].
After DB data read pointer goes to call to Blaze rule RMI API provided by Blaze. we get successful result.
Queue Calles Response Queue and Response Message is send back.
Now exception comes and Pointer again come to ProcessingBean
In webservice never get response back.
P.S. If you desible Global transation in Weblogic connection Pool then everything works fine. Or If I checked enable Two-Phase commit then also everything is working fine.

Resources