Inter-Procedure Calling
Procedures in Actyx RPC can invoke each other directly as standard functions. This design makes it easy to compose complex backend actions without incurring network round-trip overhead.
const getAuditLog = procedure
.input(z.object({ userId: z.string() }))
.query(async ({ input }) => {
return await db.auditLog.findMany({ where: { userId: input.userId } });
});
export const getUserDetails = procedure
.input(z.object({ id: z.string() }))
.query(async ({ input }) => {
const user = await db.user.findUnique({ where: { id: input.id } });
// 1. Call getAuditLog procedure directly as a function!
const [logs, err] = await getAuditLog({ userId: input.id });
if (err) throw err;
return { ...user, logs };
});How It Works: Context Bypass
Actyx RPC leverages AsyncLocalStorage to track the context of active queries and mutations.
- Context Sharing: When a procedure calls another procedure, the target procedure automatically checks for an active context.
- Context Creation Bypass: If a parent context exists, the child procedure skips its own
createContext()execution, preventing duplicate database sessions or token checks. - Execution Integrity: Even with context bypass, the child’s
.authorize()and custom middlewares are still executed to preserve security. - Zero Overhead: Calls compile to direct function calls. There is no payload serialization/deserialization or network round-tripping.
Last updated on