# Buggy code
def delete_pusher_txn(txn, stream_id):
    self._invalidate_cache_and_stream(  # type: ignore
        txn, self.get_if_user_has_pusher, (user_id,)
    )

    self.db_pool.simple_delete_one_txn(
        txn,
        "pushers",
        {"app_id": app_id, "pushkey": pushkey, "user_name": user_id},
    )

    # it's possible for us to end up with duplicate rows for
    # (app_id, pushkey, user_id) at different stream_ids, but that
    # doesn't really matter.
    self.db_pool.simple_insert_txn(
        txn,
        table="deleted_pushers",
        values={
            "stream_id": stream_id,
            "app_id": app_id,
            "pushkey": pushkey,
            "user_id": user_id,
        },
    )


# Traceback (synapse.api.errors.StoreError)
2019-04-26 13:17:52,980 - synapse.push.httppusher - 144 - ERROR - httppush.process-34525- Exception processing notifs
Traceback (most recent call last):
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/synapse/push/httppusher.py", line 142, in _process
yield self._unsafe_process()
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/twisted/internet/defer.py", line 1416, in _inlineCallbacks
result = result.throwExceptionIntoGenerator(g)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/twisted/python/failure.py", line 491, in throwExceptionIntoGenerator
return g.throw(self.type, self.value, self.tb)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/synapse/push/httppusher.py", line 178, in _unsafe_process
self.clock.time_msec()
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/twisted/internet/defer.py", line 1416, in _inlineCallbacks
result = result.throwExceptionIntoGenerator(g)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/twisted/python/failure.py", line 491, in throwExceptionIntoGenerator
return g.throw(self.type, self.value, self.tb)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/synapse/storage/pusher.py", line 307, in update_pusher_last_stream_ordering_and_success
desc="update_pusher_last_stream_ordering_and_success",
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/twisted/internet/defer.py", line 1416, in _inlineCallbacks
result = result.throwExceptionIntoGenerator(g)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/twisted/python/failure.py", line 491, in throwExceptionIntoGenerator
return g.throw(self.type, self.value, self.tb)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/synapse/storage/_base.py", line 393, in runInteraction
*args, **kwargs
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/twisted/internet/defer.py", line 1416, in _inlineCallbacks
result = result.throwExceptionIntoGenerator(g)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/twisted/python/failure.py", line 491, in throwExceptionIntoGenerator
return g.throw(self.type, self.value, self.tb)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/synapse/storage/_base.py", line 442, in runWithConnection
inner_func, *args, **kwargs
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/twisted/python/threadpool.py", line 250, in inContext
result = inContext.theWork()
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/twisted/python/threadpool.py", line 266, in <lambda>
inContext.theWork = lambda: context.call(ctx, func, *args, **kw)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/twisted/python/context.py", line 122, in callWithContext
return self.currentContext().callWithContext(ctx, func, *args, **kw)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/twisted/python/context.py", line 85, in callWithContext
return func(*args,**kw)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/twisted/enterprise/adbapi.py", line 306, in _runWithConnection
compat.reraise(excValue, excTraceback)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/twisted/python/compat.py", line 464, in reraise
raise exception.with_traceback(traceback)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/twisted/enterprise/adbapi.py", line 297, in _runWithConnection
result = func(conn, *args, **kw)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/synapse/storage/_base.py", line 438, in inner_func
return func(conn, *args, **kwargs)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/synapse/storage/_base.py", line 314, in _new_transaction
r = func(txn, *args, **kwargs)
File "/opt/venvs/matrix-synapse/lib/python3.5/site-packages/synapse/storage/_base.py", line 1031, in _simple_update_one_txn
raise StoreError(404, "No row found (%s)" % (table,))
synapse.api.errors.StoreError: 404: No row found (pushers)

# Fixed code
def delete_pusher_txn(txn, stream_id):
    self._invalidate_cache_and_stream(  # type: ignore
        txn, self.get_if_user_has_pusher, (user_id,)
    )

    # It is expected that there is exactly one pusher to delete, but
    # if it isn't there (or there are multiple) delete them all.
    self.db_pool.simple_delete_txn(
        txn,
        "pushers",
        {"app_id": app_id, "pushkey": pushkey, "user_name": user_id},
    )

    # it's possible for us to end up with duplicate rows for
    # (app_id, pushkey, user_id) at different stream_ids, but that
    # doesn't really matter.
    self.db_pool.simple_insert_txn(
        txn,
        table="deleted_pushers",
        values={
            "stream_id": stream_id,
            "app_id": app_id,
            "pushkey": pushkey,
            "user_id": user_id,
        },
    )