ref-changes: implement "done" functionality
commit60ab24c06a69a40b7edd0c55be6a4086d2d354f9
authorKyle J. McKay <mackyle@gmail.com>
Fri, 10 Nov 2017 04:35:12 +0000 (9 20:35 -0800)
committerKyle J. McKay <mackyle@gmail.com>
Fri, 10 Nov 2017 04:35:12 +0000 (9 20:35 -0800)
tree527905272c5edde3e7ffe902564b3122f8b0a153
parent9ba59b9b5f919efc5b76f32f1c81741e3d6f144f
ref-changes: implement "done" functionality

Since 1365e59c5697ec52 (ref updates: switch from ref-change to
ref-changes, 2015-09-21), when the post-receive hook (for pushes)
or the update.sh script (for fetches) sends ref updates they are
batched and sent all at once over a single connection to the taskd
socket.

This happens using the `nc -U` utility command.  Ideally once all
the ref changes have been written by the sending script and then
fully read by taskd, the `nc` command would immediately exit and
return with success.

Unfortunately, when using the "ref-changes" mode, taskd does not
know when the incoming list of changes has ended and keeps trying
to read more data (until EOF) without closing the connection.  This
is enough to keep the connection open and the `nc` command from
exiting until the idle timeout specified with the nc `-w <timeout_secs>`
option expires.  This in turn unnecessarily delays the remote
client's push as it will not complete until the post-receive hook
returns which will not happen until the nc command finally exits
after the idle timeout.

This was not a problem with the one-ref-change-at-a-time mode because
the connection was always closed immediately after reading a single
ref-change update line.

The many-ref-changes-at-once mode is much more parsimonious with
the system's resources so switching back to the one-ref-change-at-a-time
mode is not desirable and would also break the much improved branch
update email logic which needs to see the entire batch of ref changes
all at once in order to perform its magic.

Instead implement a new "done" command that can be appended to the
end of the list of ref-changes that will cause taskd to immediately
close the connection once it sees it.  Make the post-receive and
update.sh scripts include this new command at the end of the
ref-changes list they send to taskd.

This change is both forwards and backwards compatible since the
taskd ref-changes code conveniently ignores any incoming ref-changes
lines that do not look like valid ref update lines (it has done
this since the "ref-changes" mode was first implemented) and taskd
considers the new "done" command to be entirely optional.

In this way old scripts can talk to a new taskd and new scripts can
talk to an old taskd without any problems.  Of course unless it's
new scripts talking to a new taskd then they may still need to wait
until the nc `-w <timeout>` expires just like before this change
was made.

Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
hooks/post-receive
jobd/update.sh
taskd/taskd.pl