@aurora/runtime-rpc (0.3.3)
Published 2025-12-27 10:44:42 +00:00 by vlad
Installation
@aurora:registry=npm install @aurora/runtime-rpc@0.3.3"@aurora/runtime-rpc": "0.3.3"About this package
@aurora/runtime-rpc
RPC (Remote Procedure Call) for inter-node communication in Aurora sharded deployments.
Overview
Aurora's RPC package provides:
- NATS-based request/response
- Type-safe client/server
- Automatic serialization
- Timeout handling
- Error propagation
Installation
bun add @aurora/runtime-rpc
Quick Start
Server
import { Server } from "@aurora/runtime-rpc";
const rpc = new Server({
natsUrl: "nats://localhost:4222",
});
// Register handler
rpc.handle("getOrder", async ({ orderId }, context) => {
const order = await database.findOrder(orderId);
return order;
});
// Start server
await rpc.start();
Client
import { Client } from "@aurora/runtime-rpc";
const client = new Client({
natsUrl: "nats://localhost:4222",
timeout: 5000, // 5 second timeout
});
// Call remote procedure
const order = await client.call("getOrder", { orderId: "123" });
Server
Creating Server
import { Server } from "@aurora/runtime-rpc";
const server = new Server({
natsUrl: "nats://localhost:4222",
queueGroup: "order-service", // Load balancing
timeout: 10000, // Default timeout
});
// Register handlers
server.handle("getOrder", getOrderHandler);
server.handle("createOrder", createOrderHandler);
// Start server
await server.start();
// Stop server
await server.stop();
Handler Context
interface Context {
correlationId: string;
tenantId: string;
logger: Logger;
}
interface GetOrderInput {
orderId: string;
}
interface GetOrderOutput {
orderId: string;
amount: number;
status: string;
}
const getOrderHandler = async (
input: GetOrderInput,
context: Context
): Promise<GetOrderOutput> => {
context.logger.info("Getting order", {
correlationId: context.correlationId,
orderId: input.orderId,
});
const order = await database.findOrder(input.orderId);
if (!order) {
throw new NotFoundError("Order not found");
}
return order;
};
Error Handling
import { RpcError } from "@aurora/runtime-rpc";
server.handle("getOrder", async ({ orderId }) => {
const order = await database.findOrder(orderId);
if (!order) {
throw new RpcError("ORDER_NOT_FOUND", "Order not found", 404);
}
return order;
});
Client
Creating Client
import { Client } from "@aurora/runtime-rpc";
const client = new Client({
natsUrl: "nats://localhost:4222",
timeout: 5000,
defaultHeaders: {
"X-Node-ID": process.env.NODE_ID,
},
});
Calling Procedures
// Simple call
const order = await client.call("getOrder", { orderId: "123" });
// With options
const order = await client.call(
"getOrder",
{ orderId: "123" },
{
timeout: 10000,
headers: {
"X-Tenant-ID": "tenant-1",
},
}
);
Error Handling
import { RpcError } from "@aurora/runtime-rpc";
try {
const order = await client.call("getOrder", { orderId: "123" });
} catch (error) {
if (error instanceof RpcError) {
if (error.code === "ORDER_NOT_FOUND") {
console.log("Order not found");
} else if (error.status === 503) {
console.log("Service unavailable");
}
} else {
console.error("Unexpected error:", error);
}
}
Codec
Custom Serialization
import { Codec } from "@aurora/runtime-rpc";
const jsonCodec: Codec = {
encode(data: unknown): Uint8Array {
return new TextEncoder().encode(JSON.stringify(data));
},
decode(bytes: Uint8Array): unknown {
return JSON.parse(new TextDecoder().decode(bytes));
},
};
const server = new Server({
natsUrl: "nats://localhost:4222",
codec: jsonCodec,
});
Middleware
Server Middleware
import { Middleware } from "@aurora/runtime-rpc";
const loggingMiddleware: Middleware = async (req, next) => {
const start = Date.now();
console.log(`RPC call: ${req.method}`, { params: req.params });
const response = await next(req);
const duration = Date.now() - start;
console.log(`RPC response: ${req.method}`, { duration });
return response;
};
server.use(loggingMiddleware);
Authentication Middleware
const authMiddleware: Middleware = async (req, next) => {
const token = req.headers.get("Authorization");
if (!token) {
throw new RpcError("UNAUTHORIZED", "Missing token", 401);
}
const user = await verifyToken(token);
if (!user) {
throw new RpcError("UNAUTHORIZED", "Invalid token", 401);
}
// Add to context
(req as any).user = user;
return next(req);
};
server.use(authMiddleware);
Batch Calls
// Call multiple RPCs in parallel
const [order, user, payment] = await Promise.all([
client.call("getOrder", { orderId: "123" }),
client.call("getUser", { userId: "456" }),
client.call("getPayment", { paymentId: "789" }),
]);
Streaming RPCs
// Server - streaming response
server.handle("streamOrders", async function* (input) {
for (const order of await database.scanOrders(input.tenantId)) {
yield order;
}
});
// Client - consume stream
const orderStream = client.stream("streamOrders", { tenantId: "tenant-1" });
for await (const order of orderStream) {
console.log("Order:", order);
}
Testing
import { test, expect } from "bun:test";
import { Server, Client } from "@aurora/runtime-rpc";
test("RPC call works", async () => {
const server = new Server({ natsUrl: "nats://localhost:4222" });
server.handle("add", async ({ a, b }) => a + b);
await server.start();
const client = new Client({ natsUrl: "nats://localhost:4222" });
const result = await client.call("add", { a: 2, b: 3 });
expect(result).toBe(5);
await server.stop();
});
License
MIT
Dependencies
Dependencies
| ID | Version |
|---|---|
| @aurora/runtime-effect | 0.3.3 |
| nats | ^2.15.1 |
Details
2025-12-27 10:44:42 +00:00
Assets (1)
Versions (3)
View all
npm
3
latest
4.9 KiB
runtime-rpc-0.3.3.tgz
4.9 KiB