|
@@ -863,9 +863,24 @@ class FederationSenderHandler(object):
|
|
|
a FEDERATION_ACK back to the master, and stores the token that we have processed
|
|
|
in `federation_stream_position` so that we can restart where we left off.
|
|
|
"""
|
|
|
- try:
|
|
|
- self.federation_position = token
|
|
|
+ self.federation_position = token
|
|
|
+
|
|
|
+ # We save and send the ACK to master asynchronously, so we don't block
|
|
|
+ # processing on persistence. We don't need to do this operation for
|
|
|
+ # every single RDATA we receive, we just need to do it periodically.
|
|
|
+
|
|
|
+ if self._fed_position_linearizer.is_queued(None):
|
|
|
+ # There is already a task queued up to save and send the token, so
|
|
|
+ # no need to queue up another task.
|
|
|
+ return
|
|
|
|
|
|
+ run_as_background_process("_save_and_send_ack", self._save_and_send_ack)
|
|
|
+
|
|
|
+ async def _save_and_send_ack(self):
|
|
|
+ """Save the current federation position in the database and send an ACK
|
|
|
+ to master with where we're up to.
|
|
|
+ """
|
|
|
+ try:
|
|
|
# We linearize here to ensure we don't have races updating the token
|
|
|
#
|
|
|
# XXX this appears to be redundant, since the ReplicationCommandHandler
|