nsqio / go-diskqueue

A Go package providing a filesystem-backed FIFO queue
MIT License
464 stars 103 forks source link

Consistent EOF error when reading immediately after write rolls files #42

Open jonasfreyr opened 10 months ago

jonasfreyr commented 10 months ago

Consistent EOF error happens if the reading position is keeping up with the writing position and if the write rolls a file, then read will throw an EOF error since it missed its chance to roll.

It is to do with how the reader rolls, it checks after it has read a message if it should roll to the next file and when it checks it uses a variable that is called maxBytesPerFileRead. The variable is either the files size if the file is complete or the maxBytesPerFile which is configured (e.g 100 MB).

Say readFileNum = d.writeFileNum and maxBytesPerFile = 100 MB Say we read Msg-1 and after which the nextReadPos is at 96 MB, this is under maxBytesPerFile (100 MB) so we don’t roll. Then say we write Msg-2 which is 10 MB. It doesn’t fit so we roll the write file and write the message in the new file. Then we set maxBytesPerFileRead = 96 MB Now when we read we get an EOF error as there is no more data in the file and we missed our chance to roll when we read Msg-1.

Because we hit an EOF we will mark the file as bad and roll to the next file, so we are not missing any messages but we accumulate a lot of unnecessary bad files.

This problem however doesn’t present itself if the reader is more than a message behind the writer, because after the writer has rolled there are still messages in the previous file for the reader to read. He will then be able to use the updated maxBytesPerFileRead value when reading those messages.

A fix is to move the check for roll at the start of the readOne function and roll before we read if necessary.

Flowchart below hopefully helps with the text above. image

mreiferson commented 10 months ago

thanks for this. Possibly also explains #38?

I don't remember where I was at with #41, but I'll bring the test you added from #43 and make sure it addresses that as well.