Is it possible to invalidate cache from another microfrontend RTK-query - redux

I have a micro-frontend 1 that is using RTK-query and micro-frontend 2 which just a general react application. In theory, I would like for MF-2 to make some api (Post/Put) calls that should invalidate a query from MF-1. I'm wondering if this would actually work ? Can a separate service invalidate the cache of another so they can be in sync ?

It's possible to programmatically invalidate an API endpoint, if you have access to the Redux store and the API slice object and can dispatch actions:
store.dispatch(
api.util.invalidateTags(['Post']))
)
So yes, if your MF-2 can get access to the store from MF-1 somehow, or you can expose some kind of method or event emitter from MF-1 that wraps that "invalidate" logic, this can work.
See https://redux-toolkit.js.org/rtk-query/api/created-api/api-slice-utils#invalidatetags

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.

Revalidating nextjs within existing api route

I'm confused about why so many of the examples for NextJS revalidation use a separate endpoint for revalidation. Is that because some folks set up some polling to revalidate via that endpoint?
For my use case, I have a route and when the user makes an update to it I want to call revalidate... But I would rather not have to call fetch and make a separate call and just use the existing NextApiResponse object to revalidate the route. Is this a bad practice for some reason?

Storing Additional Information via Next-Auth's JWT Callback or Session callback? (Saving Patreon Tier in Next-Auth)

I am trying to use next-auth with the patreon api. Logging in & out works fine, but I now want to also save the users tier somewhere - the question is where? I was thinking of putting it directly on the jwt via the jwt callback, or maybe in the session via the session callback.
I have tried adding it to the session, but it seems to really slow down login:
async session({ session, token, user }) {
session.access_token = token.access_token;
let tier = await getUserTier({ access_token: token.access_token });
session.tier = tier;
return session;
}
It also feels inefficient fetching this data every single time the session callback is called - which seems to be a lot. Is there any way to speed up this process of checking the tier? Is there any convention over where I could save the tier?
Its slowing down the process naturally because, additionaly to the network traffic that is neccesary by default, you have to wait for your getUserTier request.
I think you have 2 options:
Saving the user Tier in the User table of the database directly, then you should have access to it through one of the callback parameters.
Not include the tier in the session at all, but fetching it in your client code only at the time you really need it.
I think i would go with the second option because there is no real need to include this information in the session. If your argument is that need that information everywhere in your app, you can still do the request somewhere central - like in a Layout component - and then provide the info via Context or Redux Store or similar(depends on what you use in your app already)

Axoniq Event Handler Resuming from offset

I am looking at the AxonIQ framework and have managed to get a test application up and running. But I have a question about how EventHandlers should be treated when using a store that has persistence in the Read Model.
From my (possible naive) understanding. #EventHandler annotated methods in my Projection class get called from the beginning when first launched. This would mechanism seems to assume that the Projection utilises some kind of in volatile store (e.g. an in memory sql like h2) which is re-created from scratch during the application bootup.
However, if the store was persistent in something like Elastic Search, I would want the #EventHandler to resume from its last persisted event instead of from the beginning event.
Is there anyway to control the behaviour of the #EventHandler in this way?
Axon has two types of Event Processors: Subscribing and Tracking.
The Subscribing mode (which was the default up to Axon 3) will handle events in the thread that delivers them. That means you're at "the mercy" of the delivery guarantees of whichever component delivers the events.
The Tracking mode (which is the default since Axon 4 when using an Event Store or otherwise a source that supports it) will have events handled in dedicated threads, managed by the Event Processor itself. That means events are handled asynchronously from the actual publication mechanism.
The Tracking Event Processor uses Tokens to keep track of progress. These Tokens are stored in a TokenStore and updates as the Processor has correctly processed each incoming event (possibly batched). You decide where those tokens are stored. If you update a relational database, we recommend storing the tokens in the same database, so that event changes and tokens are updated atomically.
If you don't specify any TokenStore, it depends on whether you're on Spring Boot, in which case Axon will attempt to detect a suitable TokenStore implementation for you. Otherwise, it may very well just be an in-memory TokenStore, which causes Processors to re-initialize on every startup (and possibly start from the beginning).
To configure a TokenStore
On Spring (Boot), simply add a bean of type TokenStore with the implementation you want to use
When using Axon's Configuration API, on the EventProcessingConfigurer, use one of the registerTokenStore(...) methods.
When the Tracking Processor starts, it will check the Token Store for previous progress, and continue from there automatically.

Is it correct aspnetcore way? Service & Dependency Injection

so i want to create some service that accesses external API, and i want to cache common requests from the API inside of that service, it depends on 3 other services, but i want to give it its own instance of cache, MemoryDistributedCache might later be changed for something else
services.AddSingleton<ISomeApi, SomeApi>(provider => new SomeApi(
Configuration.Get<Options>(),
new MemoryDistributedCache(new MemoryCache(new MemoryCacheOptions())),
provider.GetService<ILogger<SomeApi>>()
));
now from my Controllers i can access the api via DI, it works nicely but im not sure if its some sort of an anti-pattern or if there are better ways of doing it
i mean the real problem is separating the internal cache, requesting
IDistributedMemory from one service would give me the same object as if i request it from another service, they must be separated
This sounds like something you could use a proxy or decorator pattern for. The basic problem is that you have a service that does some data access, and another service responsible for caching the results of the first service. I realize you're not using a repository per se, but nonetheless the CachedRepository pattern should work for your needs. See here:
http://ardalis.com/introducing-the-cachedrepository-pattern
and
http://ardalis.com/building-a-cachedrepository-via-strategy-pattern
You can write your cached implementation such that it takes in the actual SomeApi type in its constructor if you don't need that part of the design to be flexible.

Resources