feat(medusa): Cache modules (#3187)
This commit is contained in:
1 parent
f43f03badb
commit
f97b3d7cce
42 files changed
+783
-186
No files matched your search
@@ -1,66 +0,0 @@
|
||||
import { Redis } from "ioredis"
|
||||
import { ICacheService } from "../interfaces"
|
||||
|
||||
const DEFAULT_CACHE_TIME = 30 // 30 seconds
|
||||
const EXPIRY_MODE = "EX" // "EX" stands for an expiry time in second
|
||||
|
||||
export default class CacheService implements ICacheService {
|
||||
protected readonly redis_: Redis
|
||||
|
||||
constructor({ redisClient }) {
|
||||
this.redis_ = redisClient
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a key/value pair to the cache.
|
||||
* It is also possible to manage the ttl through environment variable using CACHE_TTL. If the ttl is 0 it will
|
||||
* act like the value should not be cached at all.
|
||||
* @param key
|
||||
* @param data
|
||||
* @param ttl
|
||||
*/
|
||||
async set(
|
||||
key: string,
|
||||
data: Record<string, unknown>,
|
||||
ttl: number = DEFAULT_CACHE_TIME
|
||||
): Promise<void> {
|
||||
ttl = Number(process.env.CACHE_TTL ?? ttl)
|
||||
if (ttl === 0) {
|
||||
// No need to call redis set without expiry time
|
||||
return
|
||||
}
|
||||
|
||||
await this.redis_.set(key, JSON.stringify(data), EXPIRY_MODE, ttl)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a cached value belonging to the given key.
|
||||
* @param cacheKey
|
||||
*/
|
||||
async get<T>(cacheKey: string): Promise<T | null> {
|
||||
try {
|
||||
const cached = await this.redis_.get(cacheKey)
|
||||
if (cached) {
|
||||
return JSON.parse(cached)
|
||||
}
|
||||
} catch (err) {
|
||||
await this.redis_.del(cacheKey)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate cache for a specific key. a key can be either a specific key or more global such as "ps:*".
|
||||
* @param key
|
||||
*/
|
||||
async invalidate(key: string): Promise<void> {
|
||||
const keys = await this.redis_.keys(key)
|
||||
const pipeline = this.redis_.pipeline()
|
||||
|
||||
keys.forEach(function (key) {
|
||||
pipeline.del(key)
|
||||
})
|
||||
|
||||
await pipeline.exec()
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ export { default as AnalyticsConfigService } from "./analytics-config"
|
||||
export { default as AuthService } from "./auth"
|
||||
export { default as BatchJobService } from "./batch-job"
|
||||
export { default as CartService } from "./cart"
|
||||
export { default as CacheService } from "./cache"
|
||||
export { default as ClaimService } from "./claim"
|
||||
export { default as ClaimItemService } from "./claim-item"
|
||||
export { default as CurrencyService } from "./currency"
|
||||
|
||||
@@ -57,7 +57,7 @@ class PricingService extends TransactionBaseService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects additional information neccessary for completing the price
|
||||
* Collects additional information necessary for completing the price
|
||||
* selection.
|
||||
* @param context - the price selection context to use
|
||||
* @return The pricing context
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
||||
import { EntityManager, In } from "typeorm"
|
||||
import {
|
||||
ICacheService,
|
||||
IInventoryService,
|
||||
IStockLocationService,
|
||||
TransactionBaseService,
|
||||
@@ -14,7 +15,6 @@ import {
|
||||
} from "../types/inventory"
|
||||
import { PricedProduct, PricedVariant } from "../types/pricing"
|
||||
import {
|
||||
CacheService,
|
||||
ProductVariantService,
|
||||
SalesChannelInventoryService,
|
||||
SalesChannelLocationService,
|
||||
@@ -35,7 +35,7 @@ class ProductVariantInventoryService extends TransactionBaseService {
|
||||
protected readonly productVariantService_: ProductVariantService
|
||||
protected readonly stockLocationService_: IStockLocationService
|
||||
protected readonly inventoryService_: IInventoryService
|
||||
protected readonly cacheService_: CacheService
|
||||
protected readonly cacheService_: ICacheService
|
||||
|
||||
constructor({
|
||||
stockLocationService,
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import {
|
||||
CacheService,
|
||||
EventBusService,
|
||||
ProductVariantService,
|
||||
} from "../services"
|
||||
import { EventBusService, ProductVariantService } from "../services"
|
||||
import { ICacheService } from "../interfaces"
|
||||
|
||||
type ProductVariantUpdatedEventData = {
|
||||
id: string
|
||||
@@ -12,7 +9,7 @@ type ProductVariantUpdatedEventData = {
|
||||
|
||||
class PricingSubscriber {
|
||||
protected readonly eventBus_: EventBusService
|
||||
protected readonly cacheService_: CacheService
|
||||
protected readonly cacheService_: ICacheService
|
||||
|
||||
constructor({ eventBusService, cacheService }) {
|
||||
this.eventBus_ = eventBusService
|
||||
@@ -23,7 +20,7 @@ class PricingSubscriber {
|
||||
async (data) => {
|
||||
const { id, fields } = data as ProductVariantUpdatedEventData
|
||||
if (fields.includes("prices")) {
|
||||
await this.cacheService_.invalidate(`ps:${id}*`)
|
||||
await this.cacheService_.invalidate(`ps:${id}:*`)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user