How to Create a Cache Module
In this guide, you’ll learn how to create a Cache Module.
1. Create Module Directory#
Start by creating a new directory for your module. For example, src/modules/my-cache.
2. Create the Cache Service#
Create the file src/modules/my-cache/service.ts that holds the implementation of the cache service.
The Cache Module's main service must implement the ICacheService interface imported from @medusajs/framework/types:
import { ICacheService } from "@medusajs/framework/types"
import { MedusaError } from "@medusajs/framework/utils"
class MyCacheService implements ICacheService {
get<T>(key: string): Promise<T> {
throw new MedusaError(
MedusaError.Types.UNEXPECTED_STATE,
"Method not implemented."
)
}
set(key: string, data: unknown, ttl?: number): Promise<void> {
throw new MedusaError(
MedusaError.Types.UNEXPECTED_STATE,
"Method not implemented."
)
}
invalidate(key: string): Promise<void> {
throw new MedusaError(
MedusaError.Types.UNEXPECTED_STATE,
"Method not implemented."
)
}
}
export default MyCacheService
The service implements the required methods based on the desired caching mechanism.
Implement get Method#
The get method retrieves the value of a cached item based on its key.
The method accepts a string as a first parameter, which is the key in the cache. It either returns the cached item or null if it doesn’t exist.
For example, to implement this method using Memcached:
class MyCacheService implements ICacheService {
// ...
async get<T>(cacheKey: string): Promise<T | null> {
return new Promise((res, rej) => {
this.memcached.get(cacheKey, (err, data) => {
if (err) {
res(null)
} else {
if (data) {
res(JSON.parse(data))
} else {
res(null)
}
}
})
})
}
}
Implement set Method#
The set method is used to set an item in the cache. It accepts three parameters:
- The first parameter is a string indicating the key of the data being added to the cache. This key can be used later to get or invalidate the cached item.
- The second parameter is the data to be added to the cache. The data can be of any type.
- The third parameter is optional. It’s a number indicating how long (in seconds) the data should be kept in the cache.
For example, to implement this method using Memcached:
class MyCacheService implements ICacheService {
protected TTL = 60
// ...
async set(
key: string,
data: Record<string, unknown>,
ttl: number = this.TTL // or any value
): Promise<void> {
return new Promise((res, rej) =>
this.memcached.set(
key, JSON.stringify(data), ttl, (err) => {
if (err) {
rej(err)
} else {
res()
}
})
)
}
}
Implement invalidate Method#
The invalidate method removes an item from the cache using its key.
By default, items are removed from the cache when their time-to-live (ttl) expires. The invalidate method can be used to remove the item beforehand.
The method accepts a string as a first parameter, which is the key of the item to invalidate and remove from the cache.
For example, to implement this method using Memcached:
class MyCacheService implements ICacheService {
// ...
async invalidate(key: string): Promise<void> {
return new Promise((res, rej) => {
this.memcached.del(key, (err) => {
if (err) {
rej(err)
} else {
res()
}
})
})
}
}
3. Create Module Definition File#
Create the file src/modules/my-cache/index.ts with the following content:
import MyCacheService from "./service"
import { Module } from "@medusajs/framework/utils"
export default Module("my_cache", {
service: MyCacheService,
})
This exports the module's definition, indicating that the MyCacheService is the main service of the module.
4. Use Module#
To use your Cache Module, add it to the modules object exported as part of the configurations in medusa-config.ts. A Cache Module is added under the cacheService key.
For example:
import { Modules } from "@medusajs/framework/utils"
// ...
module.exports = defineConfig({
// ...
modules: [
{
resolve: "./src/modules/my-cache",
options: {
// any options
ttl: 30,
},
},
],
})