Chronicle Queue: How to read excepts/documents with different WireKey?

125 views Asked by At

Assume a chronicle queue, and a producer that writes 2 types of messages into the queue. Each type of message is written with a different "WireKey".

// Writes: {key1: TestMessage}
appender.writeDocument(w -> w.write("key1").text("TestMessage"));

// Writes: {key2: AnotherTextMessage}
appender.writeDocument(w -> w.write("key2").text("AnotherTextMessage"));

Question:

How can I write a single-threaded consumer that can read both types of messages and handle them differently?

What I've tried:

// This can read both types of messages, but cannot
// tell which type a message belongs to.
tailer.readDocument(wire -> {
    wire.read().text();
});
// This only reads type "key1" messages, skips all "key2" messages.
tailer.readDocument(wire -> {
    wire.read("key1").text();
});
// This crashes. (because it advances the read position illegally?)
tailer.readDocument(wire -> {
    wire.read("key1").text();
    wire.read("key2").text();
});

I was hoping I can do something like wire.readKey() and get the WireKey of a document, then proceed to read the document and handle it dynamically. How can I do this?

Note: I'm aware this can be accomplished using methodReader and methodWriter, and it seems like documentation/demo recommends this approach (?) But I'd prefer not to use that API, and be explicit about reading and writing messages. I assume there has to be a way to accomplish this use case.

Thank you.

1

There are 1 answers

5
Peter Lawrey On BEST ANSWER

You are correct, e.g. MethodReader accomplishes it.

You can do it two ways

// a reused StringBuilder
StringBuilder sb = new StringBuilder();
wire.read(sb); // populate the StringBuilder

or a more convenient method is

String name = wire.readEvent(String.class);
switch(name) {
    case "key1":
        String text1 = wire.getValueIn().text();
        // do something with text1
        break;

    case "key2":
        String text2 = wire.getValueIn().text();
        // do something with text1
        break;

    default:
        // log unexpected key
}

For other readers who don't know about MethodReader, the same messages can be accomplished with

interface MyEvents {
    void key1(String text1);
    void key2(String text2);
}

MyEvents me = wire.methodWriter(MyEvents.class);
me.key1("text1");
me.key2("text2");

MyEvents me2 = new MyEvents() {
    public void key1(String text1) {
        // handle text1
    }
    public void key2(String text2) {
        // handle text2
    }
};

Reader reader = wire.methodReader(me2;
do {
} while(reader.readeOne());

NOTE: The content is the same, so you can mix and match the two options

You can use a Chronicle Queue instead of a Wire to persist this information