Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Ensure that we never stop reconnecting to redis #9391

Merged
merged 3 commits into from
Feb 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/9391.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix bug where Synapse would occaisonally stop reconnecting after the connection was lost.
26 changes: 24 additions & 2 deletions synapse/replication/tcp/redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@

import logging
from inspect import isawaitable
from typing import TYPE_CHECKING, Optional, Type, cast
from typing import TYPE_CHECKING, Generic, Optional, Type, TypeVar, cast

import attr
import txredisapi

from synapse.logging.context import PreserveLoggingContext, make_deferred_yieldable
Expand All @@ -42,6 +43,24 @@

logger = logging.getLogger(__name__)

T = TypeVar("T")
V = TypeVar("V")


@attr.s
class ConstantProperty(Generic[T, V]):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you just use the @property decorator (or does that raise when attempting to set it?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that raises. We could do continueTrying = property(lambda _: True, lambda _a, _b: True) but eww

"""A descriptor that returns the given constant, ignoring attempts to set
it.
"""

constant = attr.ib() # type: V
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW we can now do the following I think?

Suggested change
constant = attr.ib() # type: V
constant: V = attr.ib()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought that was py3.6?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, maybe. I'm guessing this is why you need the cast() call?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it should understand descriptors enough to understand, but empirically it didn't. Possibly because of the #type: ignore (as mypy doesn't like overriding a bool attribute with a descriptor that returns a bool...)


def __get__(self, obj: Optional[T], objtype: Type[T] = None) -> V:
return self.constant

def __set__(self, obj: Optional[T], value: V):
pass


class RedisSubscriber(txredisapi.SubscriberProtocol, AbstractConnection):
"""Connection to redis subscribed to replication stream.
Expand Down Expand Up @@ -195,6 +214,10 @@ class SynapseRedisFactory(txredisapi.RedisFactory):
we detect dead connections.
"""

# We want to *always* retry connecting, txredisapi will stop if there is a
# failure during certain operations, e.g. during AUTH.
continueTrying = cast(bool, ConstantProperty(True))

def __init__(
self,
hs: "HomeServer",
Expand Down Expand Up @@ -243,7 +266,6 @@ class RedisDirectTcpReplicationClientFactory(SynapseRedisFactory):
"""

maxDelay = 5
continueTrying = True
protocol = RedisSubscriber

def __init__(
Expand Down