The Never-Ending Patch
I’ve spent the past seven weeks on the same error logging patch. Being stuck on a patch is a new sort of purgatory; I’ll spend several days working on the next patchset, only to be sent back to the beginning when my team members discover a new error, ask for a new feature, or suggest different implementations.
Scoping is probably the biggest reason why the patch has dragged on for so long. The patch replaces every error and warning log in Parsoid with my logging function, which means that it’s used in a large number of files (23 at last count). In the beginning, this made for very slow going, since I wanted to test every call site to make sure that I was referencing the logging function properly and that it generated the desired output. Besides this, the potential for error increases along with the number of lines of code. As time goes on, my patchset gets larger and harder to review, and it’s easy for me and my reviewers to overlook important details.
A good example of this was an infinite error-logging bug that the team discovered on February 11th. It crashed the Parsoid servers by filling up the disk with identical error logs. The Parsoid web server uses Connect, which comes with its own default error handler. The web server also had its own error handler, which set HTTP headers and send an HTTP response with information about an error. If we called the custom error handler but set HTTP headers again afterwards, we ended up with a “Can’t set headers after they are sent” error that would go to Connect’s default error handler. The default error handler would try to set headers again, resulting in another “can’t set headers error”, sending Parsoid into an infinite error recursion tailspin.
It took me a couple of days of reading about Connect and talking to my mentor to even understand what had caused the error recursion in the main branch of Parsoid, and another several days to process my mentor’s suggestions for how to structure my logging function to avoid error recursion. Ten days passed before I felt confident enough about the restructured code to submit my next patch.
I’m now on my 22nd iteration of the patch and feeling (delusionally?) hopeful that the next patchset will be the last. If I were to do it all over again, I’d have kept my patch smaller and more tightly scoped; since it’s too late for that (we’re down to revising the same two files each time), I’ve devised a coping strategy to speed up the feedback cycle. I’ve been sending my mentor gists for specific files, instead of waiting for his input until I’ve submitted a patchset. I’d be curious to hear whether other people have suggestions for dealing with never-ending patches.