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

Commit e8dbbcb

Browse files
authored
Fix get|set_type_stream_id_for_appservice store functions (#8648)
1 parent 73d8209 commit e8dbbcb

File tree

4 files changed

+85
-13
lines changed

4 files changed

+85
-13
lines changed

changelog.d/8648.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a bug introduced in v1.22.0rc1 which would cause ephemeral events to not be sent to appservices.

synapse/handlers/appservice.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,16 +236,16 @@ async def _notify_interested_services_ephemeral(
236236
events = await self._handle_receipts(service)
237237
if events:
238238
self.scheduler.submit_ephemeral_events_for_as(service, events)
239-
await self.store.set_type_stream_id_for_appservice(
240-
service, "read_receipt", new_token
241-
)
239+
await self.store.set_type_stream_id_for_appservice(
240+
service, "read_receipt", new_token
241+
)
242242
elif stream_key == "presence_key":
243243
events = await self._handle_presence(service, users)
244244
if events:
245245
self.scheduler.submit_ephemeral_events_for_as(service, events)
246-
await self.store.set_type_stream_id_for_appservice(
247-
service, "presence", new_token
248-
)
246+
await self.store.set_type_stream_id_for_appservice(
247+
service, "presence", new_token
248+
)
249249

250250
async def _handle_typing(self, service: ApplicationService, new_token: int):
251251
typing_source = self.event_sources.sources["typing"]

synapse/storage/databases/main/appservice.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -369,17 +369,25 @@ def get_new_events_for_appservice_txn(txn):
369369
async def get_type_stream_id_for_appservice(
370370
self, service: ApplicationService, type: str
371371
) -> int:
372+
if type not in ("read_receipt", "presence"):
373+
raise ValueError(
374+
"Expected type to be a valid application stream id type, got %s"
375+
% (type,)
376+
)
377+
372378
def get_type_stream_id_for_appservice_txn(txn):
373379
stream_id_type = "%s_stream_id" % type
374380
txn.execute(
375-
"SELECT ? FROM application_services_state WHERE as_id=?",
376-
(stream_id_type, service.id,),
381+
# We do NOT want to escape `stream_id_type`.
382+
"SELECT %s FROM application_services_state WHERE as_id=?"
383+
% stream_id_type,
384+
(service.id,),
377385
)
378-
last_txn_id = txn.fetchone()
379-
if last_txn_id is None or last_txn_id[0] is None: # no row exists
386+
last_stream_id = txn.fetchone()
387+
if last_stream_id is None or last_stream_id[0] is None: # no row exists
380388
return 0
381389
else:
382-
return int(last_txn_id[0])
390+
return int(last_stream_id[0])
383391

384392
return await self.db_pool.runInteraction(
385393
"get_type_stream_id_for_appservice", get_type_stream_id_for_appservice_txn
@@ -388,11 +396,18 @@ def get_type_stream_id_for_appservice_txn(txn):
388396
async def set_type_stream_id_for_appservice(
389397
self, service: ApplicationService, type: str, pos: int
390398
) -> None:
399+
if type not in ("read_receipt", "presence"):
400+
raise ValueError(
401+
"Expected type to be a valid application stream id type, got %s"
402+
% (type,)
403+
)
404+
391405
def set_type_stream_id_for_appservice_txn(txn):
392406
stream_id_type = "%s_stream_id" % type
393407
txn.execute(
394-
"UPDATE ? SET device_list_stream_id = ? WHERE as_id=?",
395-
(stream_id_type, pos, service.id),
408+
"UPDATE application_services_state SET %s = ? WHERE as_id=?"
409+
% stream_id_type,
410+
(pos, service.id),
396411
)
397412

398413
await self.db_pool.runInteraction(

tests/storage/test_appservice.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,62 @@ def test_get_appservices_by_state_multiple(self):
410410
)
411411

412412

413+
class ApplicationServiceStoreTypeStreamIds(unittest.HomeserverTestCase):
414+
def make_homeserver(self, reactor, clock):
415+
hs = self.setup_test_homeserver()
416+
return hs
417+
418+
def prepare(self, hs, reactor, clock):
419+
self.service = Mock(id="foo")
420+
self.store = self.hs.get_datastore()
421+
self.get_success(self.store.set_appservice_state(self.service, "up"))
422+
423+
def test_get_type_stream_id_for_appservice_no_value(self):
424+
value = self.get_success(
425+
self.store.get_type_stream_id_for_appservice(self.service, "read_receipt")
426+
)
427+
self.assertEquals(value, 0)
428+
429+
value = self.get_success(
430+
self.store.get_type_stream_id_for_appservice(self.service, "presence")
431+
)
432+
self.assertEquals(value, 0)
433+
434+
def test_get_type_stream_id_for_appservice_invalid_type(self):
435+
self.get_failure(
436+
self.store.get_type_stream_id_for_appservice(self.service, "foobar"),
437+
ValueError,
438+
)
439+
440+
def test_set_type_stream_id_for_appservice(self):
441+
read_receipt_value = 1024
442+
self.get_success(
443+
self.store.set_type_stream_id_for_appservice(
444+
self.service, "read_receipt", read_receipt_value
445+
)
446+
)
447+
result = self.get_success(
448+
self.store.get_type_stream_id_for_appservice(self.service, "read_receipt")
449+
)
450+
self.assertEqual(result, read_receipt_value)
451+
452+
self.get_success(
453+
self.store.set_type_stream_id_for_appservice(
454+
self.service, "presence", read_receipt_value
455+
)
456+
)
457+
result = self.get_success(
458+
self.store.get_type_stream_id_for_appservice(self.service, "presence")
459+
)
460+
self.assertEqual(result, read_receipt_value)
461+
462+
def test_set_type_stream_id_for_appservice_invalid_type(self):
463+
self.get_failure(
464+
self.store.set_type_stream_id_for_appservice(self.service, "foobar", 1024),
465+
ValueError,
466+
)
467+
468+
413469
# required for ApplicationServiceTransactionStoreTestCase tests
414470
class TestTransactionStore(ApplicationServiceTransactionStore, ApplicationServiceStore):
415471
def __init__(self, database: DatabasePool, db_conn, hs):

0 commit comments

Comments
 (0)