To help .NET developers better use Couchbase in their applications, there is a collection of community-supported Couchbase Extensions. These include extensions for caching, session, multiop, compression, and locking. And there are some officially supported extensions for dependency injection, open telemetry, and transactions.
The main extension for discussion today is Couchbase.Extensions.Caching, which implements the .NET Distributed Cache interface using Couchbase. This can be added to your project with NuGet (dotnet add package Couchbase.Extensions.Caching).
Recently, I was working with a customer in the cruise industry that is managing several applications, and wants to store caching data separately for each application. However, creating an entirely new bucket for each application is overkill. They were wondering how to specify a scope/collection when using the Couchbase.Extensions.Caching library.
Session and Caching Extensions
In recent years, the shift from Couchbase SDK 2 to SDK 3 introduced many new features and improvements, including scopes/collections support. The Couchbase.Extensions family has also been updated to support SDK 3.
However, the default usage of this library uses the _default scope and _default collection, with no built-in option to specify anything else.
To see this in action, here’s the line of configuration to add Couchbase as a distributed cache (taken from the GitHub example project):
1 |
builder.Services.AddDistributedCouchbaseCache("myproject", opt => { }); |
In that code, myproject is a bucket name. The opt object doesn’t have an option for scope/collection name.
Using the sample project, you’ll end up with cached information like this:
(Notice the bucket, scope, and collection names are myproject, _default, and _default).
Extending the Extension
Thankfully, the library is extensible enough that with a little bit of code, it can be pointed to whatever collection you’d like.
Let’s look a little deeper at the project, specifically ICouchbaseCacheCollectionProvider.cs and DefaultCouchbaseCacheCollectionProvider.cs
-
- ICouchbaseCacheCollectionProvider contains one method, GetCollectionAsync.
- DefaultCouchbaseCacheCollectionProvider’s implements that method with: return bucket.DefaultCollection();
But what if you don’t want to use the default collection?
In that case, create a custom implementation of ICouchbaseCacheCollectionProvider. I’ll call mine CustomCouchbaseCacheCollectionProvider:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
using Couchbase.KeyValue; namespace Couchbase.Extensions.Caching.Example.Caching; public class CustomCouchbaseCacheCollectionProvider : ICouchbaseCacheCollectionProvider { Â Â private readonly ICouchbaseCacheBucketProvider _bucketProvider; Â Â private readonly string _scopeName; Â Â private readonly string _collectionName; Â Â public CustomCouchbaseCacheCollectionProvider(ICouchbaseCacheBucketProvider bucketProvider, string scopeName, string collectionName) Â Â { Â Â Â Â _bucketProvider = bucketProvider; Â Â Â Â _scopeName = scopeName; Â Â Â Â _collectionName = collectionName; Â Â } Â Â public async ValueTask<ICouchbaseCollection> GetCollectionAsync() Â Â { Â Â Â Â var bucket = await _bucketProvider.GetBucketAsync().ConfigureAwait(false); Â Â Â Â var scope = await bucket.ScopeAsync(_scopeName); Â Â Â Â return await scope.CollectionAsync(_collectionName); Â Â } } |
Consider this a starting point. In your implementation, you can set it up however you’d like, add additional logic, etc.
The next step is to add that as a service (in Program.cs typically), specifying the scope/collection names:
1 2 3 4 5 |
builder.Services.AddSingleton<ICouchbaseCacheCollectionProvider>(x => Â Â new CustomCouchbaseCacheCollectionProvider( Â Â Â Â x.GetRequiredService<ICouchbaseCacheBucketProvider>(), Â Â Â Â "mycachingscope", Â Â Â Â "mycachingcollection")); |
If you’re concerned about this being overwritten by the default provider, note that TryAddSingleton is used inside of AddDistributedCouchbaseCache. This means that it won’t override your custom provider with the default provider.
Custom Provider in Action
This extension will not actually create the specified scope and collection, so make sure you’ve created them ahead of time.
Run the app, and try out the Weather Forecast API with the OpenAPI interactive page. The first time executing the endpoint will result in a “cache miss”, at which point the weather forecast data will be written to the collection specified:
(Notice the bucket, scope, and collection names are myproject, mycachingscope, and mycachingcollection).
Summary
With a custom implementation of an interface, and one extra line in Program.cs, you can specify whatever scope/collection you want to store cached data into.
Further, the Couchbase.Extensions.Session extension uses the caching extension as the underlying storage mechanism.
-
- Happy caching! Source code is available in GitHub.
- For more on .NET, check out the Couchbase .NET forum and .NET SDK documentation.
- If you’ve got questions on caching, session, or architecture in general, check out the Couchbase Discord.