mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-05-07 22:44:56 -04:00
Add a linearizer on (appservice, stream) when handling ephemeral events. (#11207)
Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
This commit is contained in:
parent
af54167516
commit
a271e233e9
3 changed files with 103 additions and 18 deletions
|
@ -34,6 +34,7 @@ from synapse.metrics.background_process_metrics import (
|
|||
)
|
||||
from synapse.storage.databases.main.directory import RoomAliasMapping
|
||||
from synapse.types import JsonDict, RoomAlias, RoomStreamToken, UserID
|
||||
from synapse.util.async_helpers import Linearizer
|
||||
from synapse.util.metrics import Measure
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -58,6 +59,10 @@ class ApplicationServicesHandler:
|
|||
self.current_max = 0
|
||||
self.is_processing = False
|
||||
|
||||
self._ephemeral_events_linearizer = Linearizer(
|
||||
name="appservice_ephemeral_events"
|
||||
)
|
||||
|
||||
def notify_interested_services(self, max_token: RoomStreamToken) -> None:
|
||||
"""Notifies (pushes) all application services interested in this event.
|
||||
|
||||
|
@ -260,26 +265,37 @@ class ApplicationServicesHandler:
|
|||
events = await self._handle_typing(service, new_token)
|
||||
if events:
|
||||
self.scheduler.submit_ephemeral_events_for_as(service, events)
|
||||
continue
|
||||
|
||||
elif stream_key == "receipt_key":
|
||||
events = await self._handle_receipts(service)
|
||||
if events:
|
||||
self.scheduler.submit_ephemeral_events_for_as(service, events)
|
||||
|
||||
# Persist the latest handled stream token for this appservice
|
||||
await self.store.set_type_stream_id_for_appservice(
|
||||
service, "read_receipt", new_token
|
||||
# Since we read/update the stream position for this AS/stream
|
||||
with (
|
||||
await self._ephemeral_events_linearizer.queue(
|
||||
(service.id, stream_key)
|
||||
)
|
||||
):
|
||||
if stream_key == "receipt_key":
|
||||
events = await self._handle_receipts(service, new_token)
|
||||
if events:
|
||||
self.scheduler.submit_ephemeral_events_for_as(
|
||||
service, events
|
||||
)
|
||||
|
||||
elif stream_key == "presence_key":
|
||||
events = await self._handle_presence(service, users)
|
||||
if events:
|
||||
self.scheduler.submit_ephemeral_events_for_as(service, events)
|
||||
# Persist the latest handled stream token for this appservice
|
||||
await self.store.set_type_stream_id_for_appservice(
|
||||
service, "read_receipt", new_token
|
||||
)
|
||||
|
||||
# Persist the latest handled stream token for this appservice
|
||||
await self.store.set_type_stream_id_for_appservice(
|
||||
service, "presence", new_token
|
||||
)
|
||||
elif stream_key == "presence_key":
|
||||
events = await self._handle_presence(service, users, new_token)
|
||||
if events:
|
||||
self.scheduler.submit_ephemeral_events_for_as(
|
||||
service, events
|
||||
)
|
||||
|
||||
# Persist the latest handled stream token for this appservice
|
||||
await self.store.set_type_stream_id_for_appservice(
|
||||
service, "presence", new_token
|
||||
)
|
||||
|
||||
async def _handle_typing(
|
||||
self, service: ApplicationService, new_token: int
|
||||
|
@ -316,7 +332,9 @@ class ApplicationServicesHandler:
|
|||
)
|
||||
return typing
|
||||
|
||||
async def _handle_receipts(self, service: ApplicationService) -> List[JsonDict]:
|
||||
async def _handle_receipts(
|
||||
self, service: ApplicationService, new_token: Optional[int]
|
||||
) -> List[JsonDict]:
|
||||
"""
|
||||
Return the latest read receipts that the given application service should receive.
|
||||
|
||||
|
@ -335,6 +353,12 @@ class ApplicationServicesHandler:
|
|||
from_key = await self.store.get_type_stream_id_for_appservice(
|
||||
service, "read_receipt"
|
||||
)
|
||||
if new_token is not None and new_token <= from_key:
|
||||
logger.debug(
|
||||
"Rejecting token lower than or equal to stored: %s" % (new_token,)
|
||||
)
|
||||
return []
|
||||
|
||||
receipts_source = self.event_sources.sources.receipt
|
||||
receipts, _ = await receipts_source.get_new_events_as(
|
||||
service=service, from_key=from_key
|
||||
|
@ -342,7 +366,10 @@ class ApplicationServicesHandler:
|
|||
return receipts
|
||||
|
||||
async def _handle_presence(
|
||||
self, service: ApplicationService, users: Collection[Union[str, UserID]]
|
||||
self,
|
||||
service: ApplicationService,
|
||||
users: Collection[Union[str, UserID]],
|
||||
new_token: Optional[int],
|
||||
) -> List[JsonDict]:
|
||||
"""
|
||||
Return the latest presence updates that the given application service should receive.
|
||||
|
@ -365,6 +392,12 @@ class ApplicationServicesHandler:
|
|||
from_key = await self.store.get_type_stream_id_for_appservice(
|
||||
service, "presence"
|
||||
)
|
||||
if new_token is not None and new_token <= from_key:
|
||||
logger.debug(
|
||||
"Rejecting token lower than or equal to stored: %s" % (new_token,)
|
||||
)
|
||||
return []
|
||||
|
||||
for user in users:
|
||||
if isinstance(user, str):
|
||||
user = UserID.from_string(user)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue