-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Mario edited this page Sep 23, 2026
·
2 revisions
Vyra is an asynchronous, type-safe messaging framework for Java. It gives you the ergonomics of a local method call with the semantics of distributed messaging, over whatever broker you choose.
┌─────────────────┐ request("billing", req, ...) ┌─────────────────┐
│ API Gateway │ ───────────────────────────────────────▶ │ Billing Service │
│ (Vyra Client A) │ ◀─────────────────────────────────────── │ (Vyra Worker B) │
└─────────────────┘ typed response └─────────────────┘
│ ▲
│ publish("orders", orderEvent) │
└────────────────────────────────────────────────────────────┘
- Typed contracts: requests, responses and events are plain Java records. No JSON bodies, no manual casting, no reflection magic.
- Small API: eight core methods, five builder options. The whole framework fits in an afternoon.
-
Asynchronous: every operation returns a standard
CompletionStage. -
Zero-dependency core:
vyra-corehas no third-party runtime dependencies. You plug in exactly what you need. - Worker load balancing: requests to a service target are distributed across the instances listening on it.
- Predictable failures: timeouts, error propagation, and delivery guarantees are explicit and documented.
Connecting two services looks like this:
// 1. Define immutable records for your wire contract
record GetPlayerRequest(String playerId) {}
record PlayerResponse(String playerId, String name, int score) {}
// 2. Spin up instances (InMemory for local testing, a broker transport in production)
Vyra backend = InMemoryVyra.inMemory().serializer(JacksonSerializer.jackson()).build();
Vyra client = InMemoryVyra.inMemory().serializer(JacksonSerializer.jackson()).build();
// 3. Register stable message identifiers (these travel on the wire, not class names)
backend.register("player.get", GetPlayerRequest.class);
backend.register("player.info", PlayerResponse.class);
client.register("player.get", GetPlayerRequest.class);
client.register("player.info", PlayerResponse.class);
// 4. Register a request handler (automatically starts listening)
backend.handle("backend", GetPlayerRequest.class, req ->
CompletableFuture.completedFuture(new PlayerResponse(req.playerId(), "Mario", 1200)));
// 5. Send an asynchronous request with an explicit timeout
client.request("backend", new GetPlayerRequest("p-100"), PlayerResponse.class, Duration.ofSeconds(3))
.thenAccept(player -> System.out.println("Player: " + player.name() + " (Score: " + player.score() + ")"))
.exceptionally(err -> {
System.err.println("Request failed: " + err.getMessage());
return null;
});- Getting started: setting up Vyra, registering message types, implementing request handlers.
- Request / response: two-way communication, correlation IDs, worker queues, broadcast requests, timeouts.
- Events: one-way communication, broadcasting, at-most-once delivery.
- Transports: Redis in production, in-memory for testing, custom transports.
- Serialization: Gson, Jackson, Smile, CBOR, and the uniform network constraint.
- Configuration: node IDs, timeouts, thread pools, builder options.
- Concurrency: the three-layer threading model.
- Timeouts & errors: the exception hierarchy and error codes.
- Best practices: making Vyra instances production-ready.
Vyra documentation