diff --git a/src/msgd/store.py b/src/msgd/store.py index 278e8b71..4dbb12e8 100644 --- a/src/msgd/store.py +++ b/src/msgd/store.py @@ -4425,23 +4425,26 @@ def _reindex_inbox(self, post_id: int) -> None: events.add((target, "reply")) text = post.title + "\n" + post.body + alias_keys: set[str] = set() for token in set(MENTION_RE.findall(text)): lowered = token.lower() - targets: set[str] = set() if AUTHOR_ID_RE.fullmatch(lowered): - targets.add(lowered) + if lowered != actor_id: + events.add((lowered, "mention")) else: - rows = self._conn.execute( - """ - SELECT author_id - FROM name_claims - WHERE name_key = ? - """, - (self.normalize_identity_name(token),), - ).fetchall() - targets.update(str(item["author_id"]) for item in rows) + alias_keys.add(self.normalize_identity_name(token)) - for target in targets: + if alias_keys: + rows = self._conn.execute( + """ + SELECT author_id + FROM name_claims + WHERE name_key IN (SELECT value FROM json_each(?)) + """, + (json.dumps(sorted(alias_keys), separators=(",", ":")),), + ).fetchall() + for item in rows: + target = str(item["author_id"]) if target != actor_id: events.add((target, "mention")) diff --git a/tests/test_msgd.py b/tests/test_msgd.py index c8ee0394..25a76b80 100644 --- a/tests/test_msgd.py +++ b/tests/test_msgd.py @@ -1874,6 +1874,33 @@ def test_private_inbox_collects_replies_and_mentions(self) -> None: self.assertIn(f"[mention] #{direct_id}", inbox) self.assertIn("latest_id=", inbox) + def test_alias_mentions_are_resolved_in_one_query(self) -> None: + alice = Ed25519PrivateKey.generate() + self.issue_member(alice) + self.signed_create(alice, "hello", name="Alice") + + statements: list[str] = [] + self.server.board.store._conn.set_trace_callback(statements.append) + try: + status, body = self.c.post( + "/publish", + board="main", + text="ping @Alice " + " ".join(f"@missing{index}" for index in range(1_000)), + ) + finally: + self.server.board.store._conn.set_trace_callback(None) + + self.assertEqual(status, 201, body) + alias_queries = [ + statement + for statement in statements + if "FROM name_claims" in statement and "json_each" in statement + ] + self.assertEqual(len(alias_queries), 1) + status, inbox, _ = self.read_inbox(alice) + self.assertEqual(status, 200, inbox) + self.assertIn("[mention]", inbox) + def test_inbox_signature_nonce_and_cursor_are_enforced(self) -> None: alice = Ed25519PrivateKey.generate() mallory = Ed25519PrivateKey.generate()