Claude-skill-registry kv-store-grpc
Guidance for building gRPC-based key-value store services in Python. This skill should be used when tasks involve creating gRPC servers, defining protocol buffer schemas, or implementing key-value storage APIs with gRPC. Covers proto file creation, code generation, server implementation, and verification strategies.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/kv-store-grpc" ~/.claude/skills/majiayu000-claude-skill-registry-kv-store-grpc && rm -rf "$T"
skills/data/kv-store-grpc/SKILL.mdgRPC Key-Value Store Implementation
Overview
This skill provides procedural knowledge for implementing gRPC-based key-value store services in Python. It covers the complete workflow from proto file definition through server implementation and verification.
Workflow
Step 1: Environment Setup
Install the required gRPC packages with specific versions if provided:
pip install grpcio==<version> grpcio-tools==<version>
If no versions are specified, install the latest:
pip install grpcio grpcio-tools
Verification: Run
pip show grpcio grpcio-tools to confirm installation.
Step 2: Define the Protocol Buffer Schema
Create a
.proto file defining the service and messages.
Key elements to include:
declarationsyntax = "proto3";
declaration (best practice for larger projects)package- Service definition with RPC methods
- Message definitions for requests and responses
Common proto patterns for key-value stores:
syntax = "proto3"; package kvstore; service KVStore { rpc SetVal(SetRequest) returns (SetResponse); rpc GetVal(GetRequest) returns (GetResponse); } message SetRequest { string key = 1; int32 value = 2; } message SetResponse { bool success = 1; } message GetRequest { string key = 1; } message GetResponse { int32 value = 1; }
Common pitfall: Forgetting the package declaration - while not strictly required, it prevents naming conflicts in larger projects.
Step 3: Generate Python gRPC Code
Run the protobuf compiler to generate Python code:
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. <service_name>.proto
This generates two files:
- Message classes<service_name>_pb2.py
- Service stubs and base classes<service_name>_pb2_grpc.py
Verification: Confirm both files exist and contain the expected classes by reading them.
Important: Examine the generated
*_pb2_grpc.py file to understand:
- The servicer base class to inherit from
- Method signatures to implement
- How to add the servicer to the server
Step 4: Implement the Server
Create a server file that:
- Imports the generated modules
- Implements the servicer class
- Sets up and starts the gRPC server
Key implementation details:
import grpc from concurrent import futures import <service_name>_pb2 import <service_name>_pb2_grpc class KVStoreServicer(<service_name>_pb2_grpc.<ServiceName>Servicer): def __init__(self): self.store = {} def SetVal(self, request, context): self.store[request.key] = request.value return <service_name>_pb2.SetResponse(success=True) def GetVal(self, request, context): value = self.store.get(request.key, 0) # Default to 0 for missing keys return <service_name>_pb2.GetResponse(value=value) def serve(): server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) <service_name>_pb2_grpc.add_<ServiceName>Servicer_to_server( KVStoreServicer(), server ) server.add_insecure_port('[::]:50051') server.start() print("Server started on port 50051", flush=True) # flush=True is important! server.wait_for_termination() if __name__ == '__main__': serve()
Critical pitfall - Output buffering: When running the server in the background, Python buffers stdout by default. To see output:
- Use
for all print statementsprint(..., flush=True) - Or run Python with
flag:-upython -u server.py - Or use the
module instead of printlogging
Step 5: Start the Server
Run the server in the background:
python server.py &
Or with unbuffered output:
python -u server.py &
Step 6: Verify the Server
Preferred approach: Write and run a test client. This is more reliable than system tools.
Common mistake: Attempting to use system tools like
netstat, ss, lsof, or ps to verify the server. These tools may not be available in all environments. Instead, test the server directly with a client.
Test client template:
import grpc import <service_name>_pb2 import <service_name>_pb2_grpc def test_kv_store(): channel = grpc.insecure_channel('localhost:50051') stub = <service_name>_pb2_grpc.<ServiceName>Stub(channel) # Test SetVal set_response = stub.SetVal(<service_name>_pb2.SetRequest(key="test_key", value=42)) print(f"SetVal response: success={set_response.success}") # Test GetVal get_response = stub.GetVal(<service_name>_pb2.GetRequest(key="test_key")) print(f"GetVal response: value={get_response.value}") # Test non-existent key (should return default value) get_missing = stub.GetVal(<service_name>_pb2.GetRequest(key="missing_key")) print(f"GetVal missing key: value={get_missing.value}") if __name__ == '__main__': test_kv_store()
Comprehensive testing should verify:
- Setting and retrieving values
- Retrieving non-existent keys (verify default behavior)
- Overwriting existing keys
- Multiple different keys
Common Pitfalls
| Pitfall | Solution |
|---|---|
| Print statements not appearing when server runs in background | Use or run with |
| Trying to use netstat/ss/lsof to verify server | Write a test client instead - more reliable |
| Missing package declaration in proto | Add after syntax declaration |
| Not examining generated code before implementing | Read to understand the servicer interface |
| Incomplete verification | Test all operations including edge cases |
| No default value for missing keys | Use pattern |
Edge Cases to Consider
- Missing keys: Return a sensible default (often 0 or empty string)
- Empty keys: Consider whether to validate or allow
- Type boundaries: Protobuf enforces int32 bounds automatically
- Connection failures: Client should handle gRPC exceptions
- Server shutdown: Consider implementing graceful shutdown for production
Efficiency Tips
- Verification strategy: Go directly to application-level testing with a client rather than system-level inspection tools
- Examine generated code: Read the generated
file before implementing to understand method signatures*_pb2_grpc.py - Test incrementally: Verify each step works before moving to the next
- Keep test clients: Do not delete test clients - they serve as useful debugging tools