chore(): Reorganize modules (#7210)
**What** Move all modules to the modules directory
This commit is contained in:
committed by
GitHub
parent
7a351eef09
commit
4eae25e1ef
15
packages/modules/cache-redis/src/index.ts
Normal file
15
packages/modules/cache-redis/src/index.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { ModuleExports } from "@medusajs/modules-sdk"
|
||||
import Loader from "./loaders"
|
||||
import { RedisCacheService } from "./services"
|
||||
|
||||
const service = RedisCacheService
|
||||
const loaders = [Loader]
|
||||
|
||||
const moduleDefinition: ModuleExports = {
|
||||
service,
|
||||
loaders,
|
||||
}
|
||||
|
||||
export default moduleDefinition
|
||||
export * from "./initialize"
|
||||
export * from "./types"
|
||||
23
packages/modules/cache-redis/src/initialize/index.ts
Normal file
23
packages/modules/cache-redis/src/initialize/index.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import {
|
||||
ExternalModuleDeclaration,
|
||||
InternalModuleDeclaration,
|
||||
MedusaModule,
|
||||
Modules,
|
||||
} from "@medusajs/modules-sdk"
|
||||
import { ICacheService } from "@medusajs/types"
|
||||
import { RedisCacheModuleOptions } from "../types"
|
||||
|
||||
export const initialize = async (
|
||||
options?: RedisCacheModuleOptions | ExternalModuleDeclaration
|
||||
): Promise<ICacheService> => {
|
||||
const serviceKey = Modules.CACHE
|
||||
const loaded = await MedusaModule.bootstrap<ICacheService>({
|
||||
moduleKey: serviceKey,
|
||||
defaultPath: "@medusajs/cache-redis",
|
||||
declaration: options as
|
||||
| InternalModuleDeclaration
|
||||
| ExternalModuleDeclaration,
|
||||
})
|
||||
|
||||
return loaded[serviceKey]
|
||||
}
|
||||
37
packages/modules/cache-redis/src/loaders/index.ts
Normal file
37
packages/modules/cache-redis/src/loaders/index.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { LoaderOptions } from "@medusajs/modules-sdk"
|
||||
import { asValue } from "awilix"
|
||||
import Redis from "ioredis"
|
||||
import { RedisCacheModuleOptions } from "../types"
|
||||
|
||||
export default async ({
|
||||
container,
|
||||
logger,
|
||||
options,
|
||||
}: LoaderOptions): Promise<void> => {
|
||||
const { redisUrl, redisOptions } = options as RedisCacheModuleOptions
|
||||
|
||||
if (!redisUrl) {
|
||||
throw Error(
|
||||
"No `redisUrl` provided in `cacheService` module options. It is required for the Redis Cache Module."
|
||||
)
|
||||
}
|
||||
|
||||
const connection = new Redis(redisUrl, {
|
||||
// Lazy connect to properly handle connection errors
|
||||
lazyConnect: true,
|
||||
...(redisOptions ?? {}),
|
||||
})
|
||||
|
||||
try {
|
||||
await connection.connect()
|
||||
logger?.info(`Connection to Redis in module 'cache-redis' established`)
|
||||
} catch (err) {
|
||||
logger?.error(
|
||||
`An error occurred while connecting to Redis in module 'cache-redis': ${err}`
|
||||
)
|
||||
}
|
||||
|
||||
container.register({
|
||||
cacheRedisConnection: asValue(connection),
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { RedisCacheService } from "../index"
|
||||
|
||||
const redisClientMock = {
|
||||
set: jest.fn(),
|
||||
get: jest.fn(),
|
||||
}
|
||||
|
||||
describe("RedisCacheService", () => {
|
||||
let cacheService
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("Underlying client methods are called", async () => {
|
||||
cacheService = new RedisCacheService(
|
||||
{
|
||||
cacheRedisConnection: redisClientMock,
|
||||
},
|
||||
{}
|
||||
)
|
||||
|
||||
await cacheService.set("test-key", "value")
|
||||
expect(redisClientMock.set).toBeCalled()
|
||||
|
||||
await cacheService.get("test-key")
|
||||
expect(redisClientMock.get).toBeCalled()
|
||||
})
|
||||
})
|
||||
1
packages/modules/cache-redis/src/services/index.ts
Normal file
1
packages/modules/cache-redis/src/services/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as RedisCacheService } from "./redis-cache"
|
||||
98
packages/modules/cache-redis/src/services/redis-cache.ts
Normal file
98
packages/modules/cache-redis/src/services/redis-cache.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import { ICacheService } from "@medusajs/types"
|
||||
import { Redis } from "ioredis"
|
||||
import { RedisCacheModuleOptions } from "../types"
|
||||
|
||||
const DEFAULT_NAMESPACE = "medusa"
|
||||
const DEFAULT_CACHE_TIME = 30 // 30 seconds
|
||||
const EXPIRY_MODE = "EX" // "EX" stands for an expiry time in second
|
||||
|
||||
type InjectedDependencies = {
|
||||
cacheRedisConnection: Redis
|
||||
}
|
||||
|
||||
class RedisCacheService implements ICacheService {
|
||||
protected readonly TTL: number
|
||||
protected readonly redis: Redis
|
||||
private readonly namespace: string
|
||||
|
||||
constructor(
|
||||
{ cacheRedisConnection }: InjectedDependencies,
|
||||
options: RedisCacheModuleOptions = {}
|
||||
) {
|
||||
this.redis = cacheRedisConnection
|
||||
this.TTL = options.ttl ?? DEFAULT_CACHE_TIME
|
||||
this.namespace = options.namespace || DEFAULT_NAMESPACE
|
||||
}
|
||||
|
||||
__hooks = {
|
||||
onApplicationShutdown: async () => {
|
||||
this.redis.disconnect()
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a key/value pair to the cache.
|
||||
* 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 = this.TTL
|
||||
): Promise<void> {
|
||||
if (ttl === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
await this.redis.set(
|
||||
this.getCacheKey(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> {
|
||||
cacheKey = this.getCacheKey(cacheKey)
|
||||
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(this.getCacheKey(key))
|
||||
const pipeline = this.redis.pipeline()
|
||||
|
||||
keys.forEach(function (key) {
|
||||
pipeline.del(key)
|
||||
})
|
||||
|
||||
await pipeline.exec()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns namespaced cache key
|
||||
* @param key
|
||||
*/
|
||||
private getCacheKey(key: string) {
|
||||
return this.namespace ? `${this.namespace}:${key}` : key
|
||||
}
|
||||
}
|
||||
|
||||
export default RedisCacheService
|
||||
27
packages/modules/cache-redis/src/types/index.ts
Normal file
27
packages/modules/cache-redis/src/types/index.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { RedisOptions } from "ioredis"
|
||||
|
||||
/**
|
||||
* Module config type
|
||||
*/
|
||||
export type RedisCacheModuleOptions = {
|
||||
/**
|
||||
* Time to keep data in cache (in seconds)
|
||||
*/
|
||||
ttl?: number
|
||||
|
||||
/**
|
||||
* Redis connection string
|
||||
*/
|
||||
redisUrl?: string
|
||||
|
||||
/**
|
||||
* Redis client options
|
||||
*/
|
||||
redisOptions?: RedisOptions
|
||||
|
||||
/**
|
||||
* Prefix for event keys
|
||||
* @default `medusa:`
|
||||
*/
|
||||
namespace?: string
|
||||
}
|
||||
Reference in New Issue
Block a user