Quicx
§ 03.02Reference

Java Client

dev.quicx:quicx-client is a small, dependency-free Java 11+ library. Two classes carry the whole surface area: QuicxClient for producers, QuicxWorker for consumers.

Add it to your build

pom.xml
<dependency>
  <groupId>dev.quicx</groupId>
  <artifactId>quicx-client</artifactId>
  <version>1.0.0</version>
</dependency>

QuicxClient — producers

QuicxClient is stateless at the connection level: every call to submit()opens a fresh TCP connection, performs the submit request-reply, and closes. Keep the object around for the lifetime of the producer — it’s safe to reuse and share across threads.

new QuicxClient(host, port)
Construct a reusable handle. No network work is performed here.
int submit(type, byte[])
Send a MSG_SUBMIT with a raw payload. Returns the 32-bit task id assigned by the daemon. Throws QuicxException on MSG_ERROR.
int submit(type, String)
Convenience overload: UTF-8 encodes the payload for you.
close()
Idempotent. Tears down any transport resources. Use try-with-resources.
Producer.java
import dev.quicx.QuicxClient;
import dev.quicx.QuicxException;

try (QuicxClient client = new QuicxClient("localhost", 16381)) {
    int id = client.submit(
        "resize_image",
        new byte[]{ 0x01, 0x02, 0x03 /* raw bytes */ }
    );
    System.out.println("accepted id = " + id);
} catch (QuicxException e) {
    System.err.println("rejected: " + e.getMessage());
}

QuicxWorker — consumers

QuicxWorker is a long-lived connection that receives MSG_TASK frames. Register a handler per task type; the worker dispatches by string key and replies to the daemon with MSG_DONE or MSG_FAILED automatically.

new QuicxWorker(host, port)
Construct a worker. No network work happens until start().
handle(type, handler)
Register a TaskHandler for a task type. Returns this for chaining.
start()
Connect, send MSG_READY and enter the dispatch loop. Blocks forever. On an unexpected disconnect the worker sleeps for 3 s and reconnects.
close()
Flips the running flag, closes the socket and unblocks start(). Safe to call from a shutdown hook.
Worker.java
import dev.quicx.QuicxWorker;

public class Worker {
    public static void main(String[] args) throws Exception {
        QuicxWorker worker = new QuicxWorker("localhost", 16381)
            .handle("send_email", payload -> {
                String body = new String(payload, "UTF-8");
                EmailService.deliver(body);
            })
            .handle("resize_image", payload -> {
                Images.resize(payload);
            });

        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try { worker.close(); } catch (Exception ignored) {}
        }));

        worker.start();   // blocks — the dispatch loop owns this thread
    }
}
NOTEError semantics
If a handler throws, the worker sends MSG_FAILED with exception.getMessage() as the reason — the task is not retried automatically. If no handler is registered for an incoming type, the worker logs and sends MSG_FAILED with “no handler for: …”.

QuicxException

An unchecked RuntimeException thrown by QuicxClient#submiton rejection or protocol error. It wraps the daemon’s MSG_ERROR message string so the cause is visible without decoding bytes by hand.

QuicxException.java
package dev.quicx;

public class QuicxException extends RuntimeException {
    public QuicxException(String message) { super(message); }
    public QuicxException(String message, Throwable cause) {
        super(message, cause);
    }
}