Async RPC framework with middleware support
Project description
linkr
Async RPC framework.
Install
pip install linkr
Quickstart
from linkr import MockTransport, RpcApp
transport = MockTransport()
app = RpcApp(transport)
@app.method("add")
def add(x: int, y: int) -> int:
return x + y
await app.init()
await app.consume()
result = await app.make("add", 2, 3).call()
print(result) # 5
await app.close()
Features
- Decorator-based handler registration
- Timeout, TTL, RTTL per call
- Fire-and-forget via publish()
- App-level middleware (
AppMiddleware) - Wire-level middleware (
WireMiddleware) — compression, encryption - Gzip compression via
GzipMiddleware - Dependency injection with
Depends[T] - Pydantic serialization
- Mock transport for testing (no broker needed)
- RabbitMQ transport
App-level Middleware
import logging
from linkr import AppMiddleware
class LoggingMiddleware(AppMiddleware):
async def dispatch(self, ctx, call_next):
if ctx.direction == "request" and ctx.role == "server":
logging.info("[%s] Calling", ctx.request.id)
result = await call_next(ctx)
if ctx.direction == "response" and ctx.role == "server" and ctx.response:
logging.info("[%s] Done", ctx.request.id)
return result
app.add_middleware(LoggingMiddleware())
Wire-level Middleware
Compression, encryption and other wire transformations use WireMiddleware:
from linkr import GzipMiddleware
app.add_middleware(GzipMiddleware())
Custom wire-level middleware inherits from WireMiddleware and works with ctx.body:
import gzip
from linkr import WireMiddleware
from linkr.models import RpcContext
class CustomCompression(WireMiddleware):
async def dispatch(self, ctx: RpcContext, call_next):
if ctx.direction == "request" and ctx.role == "client":
ctx.body = gzip.compress(ctx.body)
elif ctx.direction == "request" and ctx.role == "server":
ctx.body = gzip.decompress(ctx.body)
ctx = await call_next(ctx)
if ctx.direction == "response" and ctx.role == "server":
ctx.body = gzip.compress(ctx.body)
elif ctx.direction == "response" and ctx.role == "client":
ctx.body = gzip.decompress(ctx.body)
return ctx
Dependency Injection
from linkr import Depends
class Database:
...
app.dependencies.add_singleton(Database, lambda: Database("postgres://..."))
@app.method("ping")
def ping(db: Depends[Database]) -> str:
return db.url
Transports
| Transport | When to use |
|---|---|
| MockTransport | Unit tests, local dev |
| RmqTransport | Production (RabbitMQ) |
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
linkr-0.1.1.tar.gz
(11.7 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
linkr-0.1.1-py3-none-any.whl
(16.3 kB
view details)
File details
Details for the file linkr-0.1.1.tar.gz.
File metadata
- Download URL: linkr-0.1.1.tar.gz
- Upload date:
- Size: 11.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.2 CPython/3.11.9 Darwin/25.2.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b87050b1d5096d3e59e37084ebbd260617578ed9f50d68bb4e5af925bba0d157
|
|
| MD5 |
bffe5856c10929fad839d39fd17522a8
|
|
| BLAKE2b-256 |
a33c01c61582525c14afc8476f3eb8d1ba2fac191187c37804c1db1bdaa6e5d9
|
File details
Details for the file linkr-0.1.1-py3-none-any.whl.
File metadata
- Download URL: linkr-0.1.1-py3-none-any.whl
- Upload date:
- Size: 16.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.2 CPython/3.11.9 Darwin/25.2.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c16f044a5d3d0bfdee418ebe1a2f257f2f1d1815d15cc73ce70bc50c58ae501d
|
|
| MD5 |
84756f4676d81633c183d277c88e339a
|
|
| BLAKE2b-256 |
b130e9280793e6be7a22e77dc0bc45adadd8a7f0756ef20e31185691d3060017
|