Thank you for the great video! I think there are some major problems with the implementation. The tag and key may collide, its better to prefix the redis keys just in case. Another thing is a potential race condition if set and revoke are called concurrently the tag redis key may be set before the revoke method reads it, then the revoke will delete the tag key and the cache key in redis wont be revokeable (because there will be no tag redis key) Switching the order or operations in the set method soves the problem if the redis is a single instance, in case of redis cluster its harder to solve
Thank you, I was waiting for this one :) Now please also make a video how to make the new rate limiting shared via redis and then we have everything we need from an expert!
I liked the video, it's a great example of how to find solutions where there is not official support. At this point there is package from Microsoft: Microsoft.AspNetCore.OutputCaching.StackExchangeRedis
Great video. A good practice for production environment could be to have a InMemoryCache as first level and RedisCache as second level to combine both worlds.
Great stuff. Finally memoization is making it into .NET alongside endpoints defined by lambdas 😂 I'm not so sure though why you'd ever want to lock the cache. By the CAP theorem, given your app is distributed, you cannot drop partition tolerance. So you only have the choice between dropping availability vs. consistency (and I'd always drop consistency for better performance / simpler code if my use case doesn't require it) 🤔 So, your implementation is totally fine. Go find a funny package name and upload it 😉 Guys dealing with distributed consistency will be smart enough to cope with the complexity of event-driven architectures, etc. 😂
@@deadendjesenice How could talking about the CAP theorem and memoization be out of place when this video is about synchronizing a distributed request/response cache? At the end of the video there is a section about locking the service for data synchronization when invalidating Redis keys and that's what I'm referring to 😉 But yeah, maybe you're smarter than me and know that this is totally made up BS, so tell me: I'm curious to hear your criticism 😄
Just catching this one but it would have been a perfect example to implement using TDD/BDD, you knew exactly the response that would have been a pass for the created test. And you could have taken it even further with a test that validates caching logic is working as expected.
I am new to this one, in RedisOUtputCacheStoreCoolectionExtention. why decalre two static functions with same name and basically same content inside it? public static IServiceCollection AddRedisOutputCache one with service and one with service + options (so it can uses the option) I know this is from the original OutputCacheServiceCollectionExtensions. but why is that? anyone can explain?
@@nickchapsas I meant, there might be a case where one may want to swap between Redis, SQL Server or even the in-memory distributed cache and then you would most likely need another abstraction for output caching.
I'd really like to use output cache in my code, the evictByTag is required for my use case. But I'd need to convince my project manager to use .NET7. I hope they'll release this component as a nuget library that can be used in .NET6.
Is there a way to cache responoses for authenticated user using JWT Token? I know it’s a bad practice to cache responses when JWT is present since the data may vary based on the user, but i was wondering if there is a way to cache the response for individual users? And is it even a good practice to do so?
Hey Nick great video, With regards to the lock statements that you wanted to implement, I was wondering why not to use SemaphoreSlim since the code is already asynchronous? Are there any performance traps related to it?
It´s not actually async if it was you could not use the lock keyword. Making the method async generates the whole state machine thing behind the scenes. Im not sure how semaphore slim compares to lock exactly but if you use it in synchronous code at the very least it will have to actively wait for the semaphore to be ready. The implementation of lock should also be far simpler. I don´t think making the method async just for the sake of being able to await the semaphore is worth it in most cases, unless you expect you will spend most of your execution time waiting for it. If you want to await something for other reasons (which you probably do for the redis implementation) you can´t use lock anyways, so you don´t have to ask yourself that question. But it´s somewhat more complicated than that in this case. Both lock and semaphore only lock one instance and if you want to scale out and thats the reason you implement redis in the first place you need a different approach to deal with that as you´d want to lock the redis rather than an instance of your program.
@@shioli3927 Yep the base in-memory version is not async because it returns a value task which is a struct but Nick's implementation actually is, because his code is awaiting the responses from Redis. `unless you expect you will spend most of your execution time waiting for it` it is partially true because the SemaphoreSlim returns you a task that you can await thus giving your thread something else to do in this time e.g. handling other HTTP requests. This use case is a great case study for benchmarking it, semaphore slim vs simple lock, but honestly, I have no idea how to tie it together with async calls to Redis.
@@11abi94 It's not about value task the async keyword is not there. You can't use lock in async code is the main takeaway. It does not compile. So... a lot of the time you don't have a choice. Nick would have to use semaphore over lock. But probably would not use either as both fail when you have multiple instances. Redis has something called "Distributed locks" probably would use those instead.
Your videos are simply awsome. They are power packed tutorial. Just one suggestion...please run the visual studio in Light mode. The dark mode is not suitable for making video although dark mode may be good for personal use. Many subscribers would agree.
Thank you for the great video!
I think there are some major problems with the implementation.
The tag and key may collide, its better to prefix the redis keys just in case.
Another thing is a potential race condition if set and revoke are called concurrently the tag redis key may be set before the revoke method reads it, then the revoke will delete the tag key and the cache key in redis wont be revokeable (because there will be no tag redis key)
Switching the order or operations in the set method soves the problem if the redis is a single instance, in case of redis cluster its harder to solve
Thank you, I was waiting for this one :) Now please also make a video how to make the new rate limiting shared via redis and then we have everything we need from an expert!
I liked the video, it's a great example of how to find solutions where there is not official support. At this point there is package from Microsoft: Microsoft.AspNetCore.OutputCaching.StackExchangeRedis
Great video. A good practice for production environment could be to have a InMemoryCache as first level and RedisCache as second level to combine both worlds.
Exactly! I ran into a real world example of this. Supper short in memory backed by longer Redis works beautifully together.
Great stuff. Finally memoization is making it into .NET alongside endpoints defined by lambdas 😂
I'm not so sure though why you'd ever want to lock the cache. By the CAP theorem, given your app is distributed, you cannot drop partition tolerance. So you only have the choice between dropping availability vs. consistency (and I'd always drop consistency for better performance / simpler code if my use case doesn't require it) 🤔
So, your implementation is totally fine. Go find a funny package name and upload it 😉 Guys dealing with distributed consistency will be smart enough to cope with the complexity of event-driven architectures, etc. 😂
What are you even talking about?
@@deadendjesenice Which particular statement do you mean? Memoization or CAP theorem or what? 😂
@@marcotroster8247 Your whole out of place comment
@@deadendjesenice How could talking about the CAP theorem and memoization be out of place when this video is about synchronizing a distributed request/response cache? At the end of the video there is a section about locking the service for data synchronization when invalidating Redis keys and that's what I'm referring to 😉
But yeah, maybe you're smarter than me and know that this is totally made up BS, so tell me: I'm curious to hear your criticism 😄
Nice, looking forward for an official implementation
That's what i have been waiting for!!
Awesome 😎 great video. It is very useful.
For the MemoryOutputCahceStore, any idea why they'd choose to use a dictionary and do their own locking over using a ConcurrentDictionary?
Thanks Nick. Do you know how we cache authenticated requests?
Hello, In .NET 6 output caching can't be used for Auhorized Controllers. Is possible in .NET 7?
Just catching this one but it would have been a perfect example to implement using TDD/BDD, you knew exactly the response that would have been a pass for the created test. And you could have taken it even further with a test that validates caching logic is working as expected.
Couldn't find the previous video can you send here please thanks
I am new to this one, in RedisOUtputCacheStoreCoolectionExtention. why decalre two static functions with same name and basically same content inside it?
public static IServiceCollection AddRedisOutputCache one with service and one with service + options (so it can uses the option)
I know this is from the original OutputCacheServiceCollectionExtensions. but why is that? anyone can explain?
Such a great video
Have you tried to plug IDistributedCache, rather than deal with Redis specific abstractions, in order to abstract away the caching provider?
The output cache interface is the abstraction. I dont need an abstraction on the abstraction.
@@nickchapsas I meant, there might be a case where one may want to swap between Redis, SQL Server or even the in-memory distributed cache and then you would most likely need another abstraction for output caching.
Awesome!
I'd really like to use output cache in my code, the evictByTag is required for my use case. But I'd need to convince my project manager to use .NET7. I hope they'll release this component as a nuget library that can be used in .NET6.
thank bro
Is there a way to cache responoses for authenticated user using JWT Token? I know it’s a bad practice to cache responses when JWT is present since the data may vary based on the user, but i was wondering if there is a way to cache the response for individual users? And is it even a good practice to do so?
Hey Nick great video,
With regards to the lock statements that you wanted to implement, I was wondering why not to use SemaphoreSlim since the code is already asynchronous? Are there any performance traps related to it?
It´s not actually async if it was you could not use the lock keyword. Making the method async generates the whole state machine thing behind the scenes. Im not sure how semaphore slim compares to lock exactly but if you use it in synchronous code at the very least it will have to actively wait for the semaphore to be ready. The implementation of lock should also be far simpler. I don´t think making the method async just for the sake of being able to await the semaphore is worth it in most cases, unless you expect you will spend most of your execution time waiting for it. If you want to await something for other reasons (which you probably do for the redis implementation) you can´t use lock anyways, so you don´t have to ask yourself that question. But it´s somewhat more complicated than that in this case. Both lock and semaphore only lock one instance and if you want to scale out and thats the reason you implement redis in the first place you need a different approach to deal with that as you´d want to lock the redis rather than an instance of your program.
@@shioli3927 Yep the base in-memory version is not async because it returns a value task which is a struct but Nick's implementation actually is, because his code is awaiting the responses from Redis. `unless you expect you will spend most of your execution time waiting for it` it is partially true because the SemaphoreSlim returns you a task that you can await thus giving your thread something else to do in this time e.g. handling other HTTP requests. This use case is a great case study for benchmarking it, semaphore slim vs simple lock, but honestly, I have no idea how to tie it together with async calls to Redis.
@@11abi94 It's not about value task the async keyword is not there. You can't use lock in async code is the main takeaway. It does not compile. So... a lot of the time you don't have a choice. Nick would have to use semaphore over lock. But probably would not use either as both fail when you have multiple instances. Redis has something called "Distributed locks" probably would use those instead.
@@shioli3927 Thanks for the tip about "distributed locks" 😀 As for multiple instances, you mean multiple instances of an API?
@@11abi94 Yes exactly.
Nice
Impressive but as you say I imagine MS will provide connectors to 3rd party caching platforms at release of 7.0
Plz provide Previous vedio link
Hi, Where is this video source code?!
Your videos are simply awsome. They are power packed tutorial.
Just one suggestion...please run the visual studio in Light mode. The dark mode is not suitable for making video although dark mode may be good for personal use. Many subscribers would agree.
Check the poll in my community page
I disagree, white theme hurts my eyes !
Most people don't know better, just like in politics
Course promo pleasee
Lol at another redis desktop manager
First!
Nice