--
You received this message because you are subscribed to the Google Groups "Java Chronicle" group.
To unsubscribe from this group and stop receiving emails from it, send an email to java-chronicl...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
A technique that works really well for us is to have the writer, appending to the chronicle, write out a flag as part of the message to the stream, e.g. "processed".
Our "reader" (that logs to the database) then processes each entry, and when the database insert is successful, we go to the flag's position, write it as true, and then call finish.
When the system restarts, the reader can simply reads up to the next unprocessed entry and starts logging again.
This means we don't have any external tracking of the chronicle progress.
It does mean you have effectively two writers in different threads, but this is okay, as only one is appending, the other is just updating some data in an existing entry. At least, it works well with IndexedChronicle.
Kieron
try {tailer.writeBoolean(tailer.position() - 1, true);} catch (Exception e) {e.printStackTrace();} finally {tailer.finish();}
Hi Vijay,
I assume that would work, but you probably want to use a Excerpt rather than a ExcerptTailer if you're modifying the stream. Peter can correct me on this, but my understanding is that the trailer has some optimisations for appending, and so it doesn't seem right to use it to modify previous excerpts.
I now remember what I did was a bit more involved because I wanted to have a "consuming" reader that provides these core features:
1) A "next()" method to read the next item. Repeated calls to "next()" will return the same item until it is "consumed". This allows you to read an item, and try to process it, but allow reprocessing of the item to allow for retries.
2) A "consume()" method that marks the last read item as finished with (either successfully processed, or skipped).
3) A "resume()" method, that reads through the Chronicle stream from the start until it reaches the next unprocessed transaction. This is slightly naïve perhaps, but it's simple, and since it only reads a flag at the beginning of each index to see if it has been processed yet, it is super fast (at least for my purposes).
I think this might be generally useful, so I'll see if I can find some time to blog the details, as I've seen various people asking about how to do the same sort of thing. I'll post back with a link, but may take a couple of days.
Kieron
--
You received this message because you are subscribed to a topic in the Google Groups "Java Chronicle" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/java-chronicle/CctzhN6tc9o/unsubscribe.
To unsubscribe from this group and all its topics, send an email to java-chronicl...@googlegroups.com.
I suspect what you really want is a CAS operation which has the advantage of being thread safe (although uses an int)
You can do
if(excerpt.compareAndSwap(0L 0, 1)) // did i set from 0 to 1
This has the benefit of exclusively updating the record. To make the field more useful you can add the time. E.g.
static final int SENT_OFFSET = 0;
static final int RECV_OFFSET = 8;
static final int MSG_STARTS = 16;
On the reading side you can do
if (tailer.compareAndSwap(RECV_OFFSET, 0L, System.nanoTime()) {
// Updated with the processing time
}
Tailer can update a record but only the last record it is reading, not random access. Excerpt can access any record but is more heavy weight to do the move between records. 3-4x the cost. Given reading the next record only, is a common usecase , the Tailer was added to optimise this usage.
Once moved, they behave the same.
The thread safety work for one machine ie across processes but not replication. The change is only guarenteed to be visible on the machine you performed the change.
(Programmed on my phone so you might have to correct a couple of things ;)
--
You received this message because you are subscribed to the Google Groups "Java Chronicle" group.
To unsubscribe from this group and stop receiving emails from it, send an email to java-chronicl...@googlegroups.com.
if(unprocessed) {try {
}
--
You received this message because you are subscribed to the Google Groups "Java Chronicle" group.
To unsubscribe from this group and stop receiving emails from it, send an email to java-chronicl...@googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "Java Chronicle" group.
To unsubscribe from this group and stop receiving emails from it, send an email to java-chronicl...@googlegroups.com.
Instead of zeroing out the whole record you can add a byte which determines if a record has been processed. If you use an int, you can do a CAS to allocate the message to one of multiple consumers.
If you use position 0L you can do
if(excerpt.compareAndSwapInt(0L, 0, myid)) {
processMessage(excerpt);
The cool thing about approach is it works even if you have multiple readers and you can see which reader read the message.
The writer has to write some padding for the reader to over write. The CAS will fail if the value is not 0 already.
It is clearer if you write out your padding with a write of 0. You could just move the position but this is not as clear unless you have a lot of padding.
Correct though you can put the readInt after the CAS is successful. Or you can move the excerpt.position(4)