Is it possible to get the procedure name / id in middleware?

I want to create a caching middleware that in some routes, stores a cache key that contains the route id (example: catalog.product.findMany) and the input (example: { categories: shirts }). It's not clear to me if this is possible.
S
santi26d ago
I've noticed that the req.query contains query info, but the problem is that this is batched, so I can't cache, just one of these two requests
No description
S
santi26d ago
export default publicProcedure
.use(cacheMiddleware)
.input(GetProductsQuerySchema)
.query(async ({ input, ctx }): Promise<GetProductsQueryResultsLegacy> => {
console.log({ path: __filename })
const results = await ctx.app.get(ProductService).getProducts(input)
return {
...results,
products: results.products.map((p) => p.toLegacy()),
}
})
export default publicProcedure
.use(cacheMiddleware)
.input(GetProductsQuerySchema)
.query(async ({ input, ctx }): Promise<GetProductsQueryResultsLegacy> => {
console.log({ path: __filename })
const results = await ctx.app.get(ProductService).getProducts(input)
return {
...results,
products: results.products.map((p) => p.toLegacy()),
}
})
Trying this to get a filename/routename. I wonder if there's a better way
AK
Alex / KATT 🐱25d ago
you can use opts.path in the middleware
export default publicProcedure
.input(GetProductsQuerySchema)
.use(cacheMiddleware)
export default publicProcedure
.input(GetProductsQuerySchema)
.use(cacheMiddleware)
then in the cache middleware you'll have the parsed opts.input which is somewhat normalized
S
santi24d ago
import isNil from 'lodash.isnil'
import { RedisService } from '@centrito/api/nest/data/redis.service'
import { t } from '@centrito/api/trpc/server'

const DEFAULT_CACHE_TTL = 60 * 60 * 1 // 1 hour

export const withCaching = t.middleware(async ({ ctx, next, meta, input }) => {
const routeCacheKey = meta?.routeCacheKey
if (routeCacheKey) {
const redis = ctx.app.get(RedisService)
const cacheKey = JSON.stringify({ env: 'dev2', route: routeCacheKey, input })
const cachedData = await redis.get(cacheKey)
if (!isNil(cachedData)) {
return {
data: cachedData,
}
} else {
const result = await next({ ctx })
if (result.ok) {
// No await here, it slows down the request / the response is not needed
redis.setex(cacheKey, DEFAULT_CACHE_TTL, result.data)
}
return result
}
} else {
console.log('Caching skipped as routeCacheKey is not defined')
return next({ ctx })
}
})
import isNil from 'lodash.isnil'
import { RedisService } from '@centrito/api/nest/data/redis.service'
import { t } from '@centrito/api/trpc/server'

const DEFAULT_CACHE_TTL = 60 * 60 * 1 // 1 hour

export const withCaching = t.middleware(async ({ ctx, next, meta, input }) => {
const routeCacheKey = meta?.routeCacheKey
if (routeCacheKey) {
const redis = ctx.app.get(RedisService)
const cacheKey = JSON.stringify({ env: 'dev2', route: routeCacheKey, input })
const cachedData = await redis.get(cacheKey)
if (!isNil(cachedData)) {
return {
data: cachedData,
}
} else {
const result = await next({ ctx })
if (result.ok) {
// No await here, it slows down the request / the response is not needed
redis.setex(cacheKey, DEFAULT_CACHE_TTL, result.data)
}
return result
}
} else {
console.log('Caching skipped as routeCacheKey is not defined')
return next({ ctx })
}
})
@Alex / KATT 🐱, thanks for taking the time. I'm struggling to set up this cache middleware What should the return be when the results ARE cached? Right now I wrote the following:
return {
data: cachedData,
}
return {
data: cachedData,
}
But this is surely wrong
S
santi24d ago
https://github.com/trpc/trpc/issues/4066 <-- seems related to this feature request
GitHub
feat: Allow middlewares to intercept and override procedure result ...
Describe the feature you'd like to request Hi 👋 As I mentioned here, I'm using createCaller with Next.js /app to perform server-side queries. Because Next.js might expect to run multiple qu...
S
Sandvich23d ago
Until that feature gets implemented you might just have to do:
return {
ctx: {
cache: cachedData,
}
}
return {
ctx: {
cache: cachedData,
}
}
Then in your procedures
...
.query(({ ctx }) => {
if (ctx.cache) return ctx.cache;

...
})
...
.query(({ ctx }) => {
if (ctx.cache) return ctx.cache;

...
})
It's not ideal but it should work
More Posts
queries and mutations has wrong response type in client ( monorepo )tRPC + React Query Data Invalidation?Hey y'all, I'm working with tRPC and React Query and just trying to understand how this works. I havtrpc optimistic updates causing data flickerI'm trying to add optimistic updates to a calendar component but when the mutate function is called > Error: Invariant: headers() expects to have requestAsyncStorage, none availableHi, I use trpc v1045.1 in next 14.1 app router. I call it server side and have the following. ```js How do I exclude properties while returning data?I basically need to create a dto's that would exclude properties like access keys etc. while returniDoes anyone have an example of subscriptions implemented in CloudFlare Workers?I'm trying to use subscriptions via WebSocket in CloudFlare Workers, but it's been a real pain so faTRPCClientError: Unable to transform response from serverI am currently encountering this error occasionally in my apps. I am using a Monorepo, which includeUnexpected tokenWorks fine locally, doesn't work when deployed to AWS via sst.dev. Was working last night. RedeployeContext is not being passed correctlyI will include my setup at the end. My problem is that I am using nextauth with database sessions anHow to get the Request Body data of QStashHello everyone. I'm currently working on a client project that involves using trpc with Next.js. We'Preventing uncaught error propagation from server to clientHello guys, is there any way to create default error handler? I want to avoid leaking internal inforThrowing something other than `Unexpected token '<', "<!DOCTYPE "... is not valid JSON`I'm trying to do custom error handling but whatever I throw just ends up being `Unexpected token '<'Create client that is used in every request, without re-creating clientHi all, Consider the following ``` export const createContextInner = async ({ req, res, }: { Using TRPC Server Caller in client side.What's up TRPCer. so i'm currently working in vanilla react app with seperate backend in .NET, in pAnyone has successfully setup a websockets subscription with an input ?Hi guys, here is my environment: *** node v20.11.1 * yarn@4.1.0 * trpc 11.0.0-next-beta.294 * next 1Middleware context changes aren't applied to `responseMeta(opts)` optionsIn our middleware I extend the ctx like this: ```ts const public = t.middleware(async ({ next, ctx