Claude Code से gRPC विकास: Protobuf, स्ट्रीमिंग और संचालन
Claude Code से चलने वाली gRPC सेवा बनाएं: Protobuf, समय-सीमा, स्ट्रीमिंग, प्रमाणीकरण और निगरानी।
पहले अनुबंध तय करें, फिर कोड लिखवाएं
gRPC दूरस्थ प्रक्रिया कॉल का ढांचा है। क्लाइंट किसी दूसरे सर्वर की विधि को स्थानीय फ़ंक्शन जैसा बुलाता है, लेकिन असली संचार नेटवर्क से होता है। Protocol Buffers उस संचार का अनुबंध लिखता है: सेवा, विधि, अनुरोध, उत्तर और फ़ील्ड नंबर। Claude Code को सर्वर और क्लाइंट लिखाने से पहले यही अनुबंध साफ होना चाहिए।
काम करते समय आधिकारिक दस्तावेज़ देखें: gRPC Introduction, Core concepts, Node basics, Deadlines, Status Codes, Authentication, OpenTelemetry Metrics और Protocol Buffers proto3 guide।
संबंधित पढ़ाई के लिए प्रोडक्शन API विकास, Claude Code माइक्रोसर्विसेज, API संस्करण रणनीति और टेस्ट रणनीतियां देखें।
ठोस उपयोग के मामले
gRPC को केवल “तेज़” समझकर न चुनें। जब टाइप वाला अनुबंध, साफ़ त्रुटि स्थिति और कई भाषाओं में एक जैसी सीमा चाहिए, तब यह अधिक उपयोगी है।
| उपयोग | gRPC क्यों ठीक है | Claude Code से क्या करवाएं |
|---|---|---|
| ऑर्डर, स्टॉक, बिलिंग जैसी आंतरिक सेवाएं | अनुबंध टीमों के बीच बदलाव पकड़ता है | .proto, सर्वर, क्लाइंट और स्थिति कोड तालिका |
| बड़े निर्यात | सर्वर स्ट्रीमिंग बड़े उत्तर को छोटे हिस्सों में भेजती है | returns (stream Item) और रद्द करने का व्यवहार |
| Go, Node, Python वाली टीम | एक स्कीमा कई भाषाओं को जोड़ता है | जनरेशन कमांड, फोल्डर और CI जांच |
| आंतरिक औज़ार और AI एजेंट | स्पष्ट विधियां अस्पष्ट कॉल घटाती हैं | उदाहरण क्लाइंट, प्रमाणीकरण मेटाडेटा, समय-सीमा और लॉग |
Masa का व्यावहारिक अनुभव यह रहा कि बहुत चौड़ी Search विधि शुरुआत में आसान लगती है, लेकिन बाद में बदलना कठिन हो जाता है। पढ़ना, बनाना और स्ट्रीमिंग अलग रखें, फिर Claude Code से उसी अनुबंध के अनुसार बदलाव करवाएं।
चलने वाला Node gRPC उदाहरण
यह उदाहरण @grpc/proto-loader से .proto पढ़ता है, इसलिए पहली स्थानीय जांच के लिए protoc की जरूरत नहीं है।
mkdir claude-grpc-demo
cd claude-grpc-demo
npm init -y
npm install @grpc/grpc-js @grpc/proto-loader
mkdir proto
package.json:
{
"type": "commonjs",
"scripts": {
"server": "node server.js",
"client": "node client.js"
},
"dependencies": {
"@grpc/grpc-js": "latest",
"@grpc/proto-loader": "latest"
}
}
proto/task.proto:
syntax = "proto3";
package tasks.v1;
service TaskService {
rpc CreateTask(CreateTaskRequest) returns (Task);
rpc GetTask(GetTaskRequest) returns (Task);
rpc ListTasks(ListTasksRequest) returns (stream Task);
}
message Task {
string id = 1;
string title = 2;
string status = 3;
int64 created_at_unix = 4;
}
message CreateTaskRequest {
string title = 1;
}
message GetTaskRequest {
string id = 1;
}
message ListTasksRequest {
int32 limit = 1;
}
server.js:
const path = require("node:path");
const { randomUUID } = require("node:crypto");
const grpc = require("@grpc/grpc-js");
const protoLoader = require("@grpc/proto-loader");
const PROTO_PATH = path.join(__dirname, "proto", "task.proto");
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
keepCase: false,
longs: String,
enums: String,
defaults: true,
oneofs: true,
});
const taskProto = grpc.loadPackageDefinition(packageDefinition).tasks.v1;
const token = process.env.DEMO_TOKEN || "dev-token";
const tasks = new Map();
function grpcError(code, message) {
const error = new Error(message);
error.code = code;
return error;
}
function assertAuthenticated(call) {
const value = call.metadata.get("authorization")[0];
if (value !== `Bearer ${token}`) {
throw grpcError(grpc.status.UNAUTHENTICATED, "UNAUTHENTICATED");
}
}
function createTask(call, callback) {
try {
assertAuthenticated(call);
const title = String(call.request.title || "").trim();
if (!title) {
return callback(grpcError(grpc.status.INVALID_ARGUMENT, "INVALID_ARGUMENT: title"));
}
const task = {
id: randomUUID(),
title,
status: "OPEN",
createdAtUnix: String(Math.floor(Date.now() / 1000)),
};
tasks.set(task.id, task);
callback(null, task);
} catch (error) {
callback(error);
}
}
function getTask(call, callback) {
try {
assertAuthenticated(call);
const task = tasks.get(call.request.id);
if (!task) {
return callback(grpcError(grpc.status.NOT_FOUND, "NOT_FOUND: task"));
}
callback(null, task);
} catch (error) {
callback(error);
}
}
function listTasks(call) {
try {
assertAuthenticated(call);
const limit = Math.min(Math.max(Number(call.request.limit) || 10, 1), 100);
for (const task of Array.from(tasks.values()).slice(0, limit)) {
call.write(task);
}
call.end();
} catch (error) {
call.destroy(error);
}
}
const server = new grpc.Server();
server.addService(taskProto.TaskService.service, { createTask, getTask, listTasks });
server.bindAsync("127.0.0.1:50051", grpc.ServerCredentials.createInsecure(), (error, port) => {
if (error) throw error;
console.log(`TaskService listening on ${port}`);
});
client.js:
const path = require("node:path");
const grpc = require("@grpc/grpc-js");
const protoLoader = require("@grpc/proto-loader");
const PROTO_PATH = path.join(__dirname, "proto", "task.proto");
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
keepCase: false,
longs: String,
enums: String,
defaults: true,
oneofs: true,
});
const taskProto = grpc.loadPackageDefinition(packageDefinition).tasks.v1;
const client = new taskProto.TaskService("127.0.0.1:50051", grpc.credentials.createInsecure());
const metadata = new grpc.Metadata();
metadata.set("authorization", `Bearer ${process.env.DEMO_TOKEN || "dev-token"}`);
function deadline(ms) {
return new Date(Date.now() + ms);
}
function createTask(title) {
return new Promise((resolve, reject) => {
client.createTask({ title }, metadata, { deadline: deadline(1000) }, (error, task) => {
if (error) return reject(error);
resolve(task);
});
});
}
function getTask(id) {
return new Promise((resolve, reject) => {
client.getTask({ id }, metadata, { deadline: deadline(1000) }, (error, task) => {
if (error) return reject(error);
resolve(task);
});
});
}
function listTasks(limit) {
return new Promise((resolve, reject) => {
const rows = [];
const stream = client.listTasks({ limit }, metadata, { deadline: deadline(1000) });
stream.on("data", (task) => rows.push(task));
stream.on("error", reject);
stream.on("end", () => resolve(rows));
});
}
async function main() {
const created = await createTask("Claude Code gRPC");
const fetched = await getTask(created.id);
const rows = await listTasks(10);
console.log(JSON.stringify({ created, fetched, streamed: rows.length }, null, 2));
client.close();
}
main().catch((error) => {
console.error(error.code, error.details || error.message);
client.close();
process.exitCode = 1;
});
पहले टर्मिनल में:
npm run server
दूसरे टर्मिनल में:
npm run client
स्कीमा, सुरक्षा और विफलताएं
Protocol Buffers में सबसे गंभीर गलती फ़ील्ड नंबर दोबारा इस्तेमाल करना है। प्रकाशित नंबर न बदलें। हटाए गए फ़ील्ड का नंबर और नाम reserved में रखें।
message Task {
string id = 1;
string title = 2;
string status = 3;
int64 created_at_unix = 4;
optional string assignee_email = 5;
reserved 6, 7;
reserved "owner_email";
}
समय-सीमा जरूरी है। gRPC दस्तावेज़ बताते हैं कि समय-सीमा न होने पर क्लाइंट बहुत देर तक इंतजार कर सकता है। स्ट्रीमिंग निर्यात और प्रगति दिखाने में उपयोगी है, पर पूरे परिणाम को मेमरी में जमा करना गलत है। रद्द करना, नेटवर्क टूटना और अधूरी प्रतिक्रिया संभालें।
उदाहरण में createInsecure() केवल स्थानीय अभ्यास के लिए है। उत्पादन में TLS लगाएं: सर्वर पर grpc.ServerCredentials.createSsl(...) और क्लाइंट पर grpc.credentials.createSsl(rootCert)। बिना एन्क्रिप्शन के मेटाडेटा में टोकन भेजना सुरक्षित नहीं है।
निगरानी में विधि, स्थिति, अवधि, रद्द होना, समय-सीमा समाप्त होना और बैकएंड अनुपलब्ध होना दिखना चाहिए। OpenTelemetry के gRPC मेट्रिक अच्छी शुरुआत हैं। सभी त्रुटियों को UNKNOWN न बनाएं; INVALID_ARGUMENT, NOT_FOUND, UNAUTHENTICATED, DEADLINE_EXCEEDED, UNAVAILABLE, RESOURCE_EXHAUSTED अलग रखें। लिखने वाली कॉल को अपने-आप दोहराने से पहले idempotency key रखें।
Claude Code के लिए प्रॉम्प्ट
gRPC TaskService लागू करें।
शर्तें:
- पहले proto/task.proto बनाएं
- Node.js, @grpc/grpc-js, @grpc/proto-loader इस्तेमाल करें
- CreateTask, GetTask, ListTasks server streaming लागू करें
- हर client RPC में deadline जोड़ें
- authorization metadata जांचें
- लिखें कि production में createInsecure को TLS से बदलना है
- npm run client चलाकर output रिपोर्ट करें
बदलने योग्य फाइलें:
- proto/task.proto
- server.js
- client.js
- package.json
समीक्षा के लिए:
इस gRPC implementation की findings first समीक्षा करें।
field number reuse, schema evolution, deadline, cancellation,
status code, streaming memory behavior, TLS/auth और observability जांचें।
severity के क्रम में file references के साथ लिखें।
CTA और सत्यापित परिणाम
अकेले सीख रहे हैं तो मुफ्त Claude Code चीटशीट से दैनिक कमांड और समीक्षा आदतें शुरू करें, फिर इस उदाहरण को छोटे अभ्यास प्रोजेक्ट में बदलें। टीम को .proto संचालन, CI gates, समीक्षा प्रॉम्प्ट, TLS rollout और निगरानी चाहिए तो Claude Code प्रशिक्षण और परामर्श देखें। दोहराने योग्य सामग्री के लिए ClaudeCodeLab products उपयोगी हैं।
इस अपडेट में उदाहरण को Node v24.14.1 और npm 11.11.0 वाले अस्थायी फोल्डर में चलाया गया। npm install, node server.js, node client.js सफल रहे और क्लाइंट ने created, fetched, streamed: 1 दिखाया। इस मशीन पर go, protoc और Go के Protobuf plugin उपलब्ध नहीं थे, इसलिए लेख ने वही Node तरीका चुना जिसे यहां सत्यापित किया जा सका।
मुफ़्त PDF: Claude Code cheatsheet
Email डालें और commands, review habits तथा safe workflow वाली एक-page PDF पाएँ.
हम आपका data सुरक्षित रखते हैं और spam नहीं भेजते.
लेखक के बारे में
Masa
Claude Code workflow और team adoption पर काम करने वाला engineer.
संबंधित लेख
Claude Code Obsidian to CLAUDE.md workflow: context बार-बार न समझाएं
Obsidian notes को CLAUDE.md operating notes में बदलकर Claude Code sessions को resume करना आसान बनाएं.
Claude Code Revenue CTA Routing: article से PDF, Gumroad और consultation तक
Reader intent के आधार पर free PDF, Gumroad products और consultation तक CTA route करने वाला workflow.
Claude Code टीम हैंडऑफ नियम: review proof, permissions, rollback और revenue path
Claude Code टीम काम के लिए evidence, permission rules, rollback, free PDF, Gumroad और consultation path वाला handoff.