matrix-synapse 1.145.0rc2__cp310-abi3-manylinux_2_28_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of matrix-synapse might be problematic. Click here for more details.

Files changed (1636) hide show
  1. AUTHORS.rst +51 -0
  2. CHANGES.md +1732 -0
  3. CONTRIBUTING.md +3 -0
  4. Cargo.lock +1923 -0
  5. Cargo.toml +6 -0
  6. INSTALL.md +7 -0
  7. LICENSE-AGPL-3.0 +661 -0
  8. LICENSE-COMMERCIAL +6 -0
  9. UPGRADE.rst +7 -0
  10. book.toml +47 -0
  11. changelog.d/.gitignore +1 -0
  12. demo/.gitignore +4 -0
  13. demo/clean.sh +22 -0
  14. demo/start.sh +173 -0
  15. demo/stop.sh +14 -0
  16. docs/.sample_config_header.yaml +12 -0
  17. docs/CAPTCHA_SETUP.md +37 -0
  18. docs/README.md +86 -0
  19. docs/SUMMARY.md +126 -0
  20. docs/admin_api/README.rst +13 -0
  21. docs/admin_api/account_validity.md +47 -0
  22. docs/admin_api/client_server_api_extensions.md +67 -0
  23. docs/admin_api/event_reports.md +185 -0
  24. docs/admin_api/experimental_features.md +52 -0
  25. docs/admin_api/fetch_event.md +53 -0
  26. docs/admin_api/media_admin_api.md +372 -0
  27. docs/admin_api/purge_history_api.md +77 -0
  28. docs/admin_api/register_api.md +92 -0
  29. docs/admin_api/room_membership.md +35 -0
  30. docs/admin_api/rooms.md +1190 -0
  31. docs/admin_api/scheduled_tasks.md +54 -0
  32. docs/admin_api/server_notices.md +48 -0
  33. docs/admin_api/statistics.md +132 -0
  34. docs/admin_api/user_admin_api.md +1602 -0
  35. docs/admin_api/version_api.md +23 -0
  36. docs/ancient_architecture_notes.md +81 -0
  37. docs/application_services.md +36 -0
  38. docs/architecture.md +65 -0
  39. docs/auth_chain_diff.dot +32 -0
  40. docs/auth_chain_diff.dot.png +0 -0
  41. docs/auth_chain_difference_algorithm.md +141 -0
  42. docs/changelogs/CHANGES-2019.md +1039 -0
  43. docs/changelogs/CHANGES-2020.md +2145 -0
  44. docs/changelogs/CHANGES-2021.md +2573 -0
  45. docs/changelogs/CHANGES-2022.md +2766 -0
  46. docs/changelogs/CHANGES-2023.md +2202 -0
  47. docs/changelogs/CHANGES-2024.md +1586 -0
  48. docs/changelogs/CHANGES-pre-1.0.md +3641 -0
  49. docs/changelogs/README.md +1 -0
  50. docs/code_style.md +119 -0
  51. docs/consent_tracking.md +197 -0
  52. docs/delegate.md +111 -0
  53. docs/deprecation_policy.md +89 -0
  54. docs/development/cas.md +64 -0
  55. docs/development/contributing_guide.md +554 -0
  56. docs/development/database_schema.md +404 -0
  57. docs/development/demo.md +42 -0
  58. docs/development/dependencies.md +326 -0
  59. docs/development/experimental_features.md +37 -0
  60. docs/development/git.md +148 -0
  61. docs/development/img/git/branches.jpg +0 -0
  62. docs/development/img/git/clean.png +0 -0
  63. docs/development/img/git/squash.png +0 -0
  64. docs/development/internal_documentation/README.md +12 -0
  65. docs/development/internal_documentation/release_notes_review_checklist.md +12 -0
  66. docs/development/releases.md +37 -0
  67. docs/development/reviews.md +41 -0
  68. docs/development/room-dag-concepts.md +115 -0
  69. docs/development/saml.md +40 -0
  70. docs/development/synapse_architecture/cancellation.md +392 -0
  71. docs/development/synapse_architecture/faster_joins.md +375 -0
  72. docs/development/synapse_architecture/streams.md +198 -0
  73. docs/element_logo_white_bg.svg +94 -0
  74. docs/favicon.png +0 -0
  75. docs/favicon.svg +58 -0
  76. docs/federate.md +67 -0
  77. docs/jwt.md +105 -0
  78. docs/log_contexts.md +566 -0
  79. docs/manhole.md +101 -0
  80. docs/media_repository.md +78 -0
  81. docs/message_retention_policies.md +207 -0
  82. docs/metrics-howto.md +315 -0
  83. docs/modules/account_data_callbacks.md +106 -0
  84. docs/modules/account_validity_callbacks.md +57 -0
  85. docs/modules/add_extra_fields_to_client_events_unsigned.md +32 -0
  86. docs/modules/background_update_controller_callbacks.md +71 -0
  87. docs/modules/index.md +53 -0
  88. docs/modules/media_repository_callbacks.md +131 -0
  89. docs/modules/password_auth_provider_callbacks.md +270 -0
  90. docs/modules/porting_legacy_module.md +20 -0
  91. docs/modules/presence_router_callbacks.md +112 -0
  92. docs/modules/ratelimit_callbacks.md +43 -0
  93. docs/modules/spam_checker_callbacks.md +517 -0
  94. docs/modules/third_party_rules_callbacks.md +350 -0
  95. docs/modules/writing_a_module.md +141 -0
  96. docs/openid.md +783 -0
  97. docs/opentracing.md +99 -0
  98. docs/other/running_synapse_on_single_board_computers.md +75 -0
  99. docs/password_auth_providers.md +129 -0
  100. docs/postgres.md +269 -0
  101. docs/presence_router_module.md +247 -0
  102. docs/privacy_policy_templates/en/1.0.html +26 -0
  103. docs/privacy_policy_templates/en/success.html +11 -0
  104. docs/replication.md +36 -0
  105. docs/reverse_proxy.md +327 -0
  106. docs/room_and_user_statistics.md +22 -0
  107. docs/sample_config.yaml +47 -0
  108. docs/sample_log_config.yaml +75 -0
  109. docs/server_notices.md +66 -0
  110. docs/setup/forward_proxy.md +89 -0
  111. docs/setup/installation.md +656 -0
  112. docs/setup/security.md +41 -0
  113. docs/setup/turn/coturn.md +197 -0
  114. docs/setup/turn/eturnal.md +170 -0
  115. docs/spam_checker.md +122 -0
  116. docs/sso_mapping_providers.md +208 -0
  117. docs/structured_logging.md +80 -0
  118. docs/synctl_workers.md +36 -0
  119. docs/systemd-with-workers/README.md +101 -0
  120. docs/systemd-with-workers/system/matrix-synapse-worker@.service +26 -0
  121. docs/systemd-with-workers/system/matrix-synapse.service +23 -0
  122. docs/systemd-with-workers/system/matrix-synapse.target +6 -0
  123. docs/systemd-with-workers/workers/background_worker.yaml +4 -0
  124. docs/systemd-with-workers/workers/event_persister.yaml +20 -0
  125. docs/systemd-with-workers/workers/federation_sender.yaml +4 -0
  126. docs/systemd-with-workers/workers/generic_worker.yaml +11 -0
  127. docs/systemd-with-workers/workers/media_worker.yaml +11 -0
  128. docs/systemd-with-workers/workers/pusher_worker.yaml +4 -0
  129. docs/tcp_replication.md +258 -0
  130. docs/templates.md +254 -0
  131. docs/turn-howto.md +168 -0
  132. docs/upgrade.md +2876 -0
  133. docs/usage/administration/README.md +7 -0
  134. docs/usage/administration/admin_api/README.md +47 -0
  135. docs/usage/administration/admin_api/background_updates.md +109 -0
  136. docs/usage/administration/admin_api/federation.md +212 -0
  137. docs/usage/administration/admin_api/registration_tokens.md +298 -0
  138. docs/usage/administration/admin_faq.md +294 -0
  139. docs/usage/administration/backups.md +125 -0
  140. docs/usage/administration/database_maintenance_tools.md +18 -0
  141. docs/usage/administration/monitoring/reporting_homeserver_usage_statistics.md +77 -0
  142. docs/usage/administration/monthly_active_users.md +84 -0
  143. docs/usage/administration/request_log.md +44 -0
  144. docs/usage/administration/state_groups.md +25 -0
  145. docs/usage/administration/understanding_synapse_through_grafana_graphs.md +83 -0
  146. docs/usage/administration/useful_sql_for_admins.md +216 -0
  147. docs/usage/configuration/README.md +4 -0
  148. docs/usage/configuration/config_documentation.md +4768 -0
  149. docs/usage/configuration/homeserver_sample_config.md +17 -0
  150. docs/usage/configuration/logging_sample_config.md +19 -0
  151. docs/usage/configuration/user_authentication/README.md +15 -0
  152. docs/usage/configuration/user_authentication/refresh_tokens.md +139 -0
  153. docs/usage/configuration/user_authentication/single_sign_on/README.md +5 -0
  154. docs/usage/configuration/user_authentication/single_sign_on/cas.md +8 -0
  155. docs/usage/configuration/user_authentication/single_sign_on/saml.md +8 -0
  156. docs/user_directory.md +130 -0
  157. docs/website_files/README.md +35 -0
  158. docs/website_files/indent-section-headers.css +7 -0
  159. docs/website_files/remove-nav-buttons.css +8 -0
  160. docs/website_files/table-of-contents.css +47 -0
  161. docs/website_files/table-of-contents.js +148 -0
  162. docs/website_files/theme/index.hbs +324 -0
  163. docs/website_files/version-picker.css +78 -0
  164. docs/website_files/version-picker.js +147 -0
  165. docs/website_files/version.js +1 -0
  166. docs/welcome_and_overview.md +67 -0
  167. docs/workers.md +897 -0
  168. matrix_synapse-1.145.0rc2.dist-info/METADATA +260 -0
  169. matrix_synapse-1.145.0rc2.dist-info/RECORD +1636 -0
  170. matrix_synapse-1.145.0rc2.dist-info/WHEEL +5 -0
  171. matrix_synapse-1.145.0rc2.dist-info/entry_points.txt +13 -0
  172. matrix_synapse-1.145.0rc2.dist-info/licenses/AUTHORS.rst +51 -0
  173. matrix_synapse-1.145.0rc2.dist-info/licenses/LICENSE-AGPL-3.0 +661 -0
  174. matrix_synapse-1.145.0rc2.dist-info/licenses/LICENSE-COMMERCIAL +6 -0
  175. mypy.ini +115 -0
  176. rust/Cargo.toml +63 -0
  177. rust/build.rs +45 -0
  178. scripts-dev/build_debian_packages.py +228 -0
  179. scripts-dev/check-newsfragment.sh +62 -0
  180. scripts-dev/check_line_terminators.sh +29 -0
  181. scripts-dev/check_locked_deps_have_sdists.py +64 -0
  182. scripts-dev/check_schema_delta.py +240 -0
  183. scripts-dev/complement.sh +332 -0
  184. scripts-dev/config-lint.sh +15 -0
  185. scripts-dev/database-save.sh +15 -0
  186. scripts-dev/docker_update_debian_changelog.sh +70 -0
  187. scripts-dev/dump_macaroon.py +25 -0
  188. scripts-dev/federation_client.py +428 -0
  189. scripts-dev/gen_config_documentation.py +510 -0
  190. scripts-dev/generate_sample_config.sh +28 -0
  191. scripts-dev/lint.sh +141 -0
  192. scripts-dev/make_full_schema.sh +310 -0
  193. scripts-dev/mypy_synapse_plugin.py +918 -0
  194. scripts-dev/next_github_number.sh +9 -0
  195. scripts-dev/release.py +986 -0
  196. scripts-dev/schema_versions.py +182 -0
  197. scripts-dev/sign_json.py +172 -0
  198. synapse/__init__.py +97 -0
  199. synapse/_scripts/__init__.py +0 -0
  200. synapse/_scripts/export_signing_key.py +109 -0
  201. synapse/_scripts/generate_config.py +83 -0
  202. synapse/_scripts/generate_log_config.py +56 -0
  203. synapse/_scripts/generate_signing_key.py +55 -0
  204. synapse/_scripts/generate_workers_map.py +318 -0
  205. synapse/_scripts/hash_password.py +95 -0
  206. synapse/_scripts/move_remote_media_to_new_store.py +128 -0
  207. synapse/_scripts/register_new_matrix_user.py +402 -0
  208. synapse/_scripts/review_recent_signups.py +212 -0
  209. synapse/_scripts/synapse_port_db.py +1604 -0
  210. synapse/_scripts/synctl.py +365 -0
  211. synapse/_scripts/update_synapse_database.py +130 -0
  212. synapse/api/__init__.py +20 -0
  213. synapse/api/auth/__init__.py +207 -0
  214. synapse/api/auth/base.py +406 -0
  215. synapse/api/auth/internal.py +299 -0
  216. synapse/api/auth/mas.py +436 -0
  217. synapse/api/auth/msc3861_delegated.py +617 -0
  218. synapse/api/auth_blocking.py +144 -0
  219. synapse/api/constants.py +379 -0
  220. synapse/api/errors.py +913 -0
  221. synapse/api/filtering.py +537 -0
  222. synapse/api/presence.py +102 -0
  223. synapse/api/ratelimiting.py +481 -0
  224. synapse/api/room_versions.py +535 -0
  225. synapse/api/urls.py +118 -0
  226. synapse/app/__init__.py +62 -0
  227. synapse/app/_base.py +906 -0
  228. synapse/app/admin_cmd.py +388 -0
  229. synapse/app/appservice.py +30 -0
  230. synapse/app/client_reader.py +30 -0
  231. synapse/app/complement_fork_starter.py +206 -0
  232. synapse/app/event_creator.py +29 -0
  233. synapse/app/federation_reader.py +30 -0
  234. synapse/app/federation_sender.py +30 -0
  235. synapse/app/frontend_proxy.py +30 -0
  236. synapse/app/generic_worker.py +475 -0
  237. synapse/app/homeserver.py +505 -0
  238. synapse/app/media_repository.py +30 -0
  239. synapse/app/phone_stats_home.py +292 -0
  240. synapse/app/pusher.py +30 -0
  241. synapse/app/synchrotron.py +30 -0
  242. synapse/app/user_dir.py +31 -0
  243. synapse/appservice/__init__.py +458 -0
  244. synapse/appservice/api.py +567 -0
  245. synapse/appservice/scheduler.py +565 -0
  246. synapse/config/__init__.py +27 -0
  247. synapse/config/__main__.py +62 -0
  248. synapse/config/_base.py +1154 -0
  249. synapse/config/_base.pyi +216 -0
  250. synapse/config/_util.py +99 -0
  251. synapse/config/account_validity.py +116 -0
  252. synapse/config/api.py +141 -0
  253. synapse/config/appservice.py +210 -0
  254. synapse/config/auth.py +80 -0
  255. synapse/config/auto_accept_invites.py +43 -0
  256. synapse/config/background_updates.py +44 -0
  257. synapse/config/cache.py +231 -0
  258. synapse/config/captcha.py +90 -0
  259. synapse/config/cas.py +116 -0
  260. synapse/config/consent.py +73 -0
  261. synapse/config/database.py +184 -0
  262. synapse/config/emailconfig.py +367 -0
  263. synapse/config/experimental.py +601 -0
  264. synapse/config/federation.py +114 -0
  265. synapse/config/homeserver.py +141 -0
  266. synapse/config/jwt.py +55 -0
  267. synapse/config/key.py +447 -0
  268. synapse/config/logger.py +390 -0
  269. synapse/config/mas.py +192 -0
  270. synapse/config/matrixrtc.py +66 -0
  271. synapse/config/metrics.py +93 -0
  272. synapse/config/modules.py +40 -0
  273. synapse/config/oembed.py +185 -0
  274. synapse/config/oidc.py +509 -0
  275. synapse/config/password_auth_providers.py +82 -0
  276. synapse/config/push.py +64 -0
  277. synapse/config/ratelimiting.py +260 -0
  278. synapse/config/redis.py +74 -0
  279. synapse/config/registration.py +296 -0
  280. synapse/config/repository.py +311 -0
  281. synapse/config/retention.py +162 -0
  282. synapse/config/room.py +88 -0
  283. synapse/config/room_directory.py +165 -0
  284. synapse/config/saml2.py +251 -0
  285. synapse/config/server.py +1139 -0
  286. synapse/config/server_notices.py +84 -0
  287. synapse/config/spam_checker.py +66 -0
  288. synapse/config/sso.py +121 -0
  289. synapse/config/stats.py +54 -0
  290. synapse/config/third_party_event_rules.py +40 -0
  291. synapse/config/tls.py +192 -0
  292. synapse/config/tracer.py +71 -0
  293. synapse/config/user_directory.py +47 -0
  294. synapse/config/user_types.py +42 -0
  295. synapse/config/voip.py +59 -0
  296. synapse/config/workers.py +642 -0
  297. synapse/crypto/__init__.py +20 -0
  298. synapse/crypto/context_factory.py +278 -0
  299. synapse/crypto/event_signing.py +194 -0
  300. synapse/crypto/keyring.py +980 -0
  301. synapse/event_auth.py +1266 -0
  302. synapse/events/__init__.py +667 -0
  303. synapse/events/auto_accept_invites.py +216 -0
  304. synapse/events/builder.py +387 -0
  305. synapse/events/presence_router.py +243 -0
  306. synapse/events/snapshot.py +559 -0
  307. synapse/events/utils.py +924 -0
  308. synapse/events/validator.py +305 -0
  309. synapse/federation/__init__.py +22 -0
  310. synapse/federation/federation_base.py +382 -0
  311. synapse/federation/federation_client.py +2133 -0
  312. synapse/federation/federation_server.py +1543 -0
  313. synapse/federation/persistence.py +70 -0
  314. synapse/federation/send_queue.py +532 -0
  315. synapse/federation/sender/__init__.py +1165 -0
  316. synapse/federation/sender/per_destination_queue.py +886 -0
  317. synapse/federation/sender/transaction_manager.py +210 -0
  318. synapse/federation/transport/__init__.py +28 -0
  319. synapse/federation/transport/client.py +1199 -0
  320. synapse/federation/transport/server/__init__.py +334 -0
  321. synapse/federation/transport/server/_base.py +429 -0
  322. synapse/federation/transport/server/federation.py +910 -0
  323. synapse/federation/units.py +133 -0
  324. synapse/handlers/__init__.py +20 -0
  325. synapse/handlers/account.py +162 -0
  326. synapse/handlers/account_data.py +360 -0
  327. synapse/handlers/account_validity.py +362 -0
  328. synapse/handlers/admin.py +615 -0
  329. synapse/handlers/appservice.py +989 -0
  330. synapse/handlers/auth.py +2482 -0
  331. synapse/handlers/cas.py +413 -0
  332. synapse/handlers/deactivate_account.py +363 -0
  333. synapse/handlers/delayed_events.py +607 -0
  334. synapse/handlers/device.py +1869 -0
  335. synapse/handlers/devicemessage.py +399 -0
  336. synapse/handlers/directory.py +545 -0
  337. synapse/handlers/e2e_keys.py +1835 -0
  338. synapse/handlers/e2e_room_keys.py +455 -0
  339. synapse/handlers/event_auth.py +390 -0
  340. synapse/handlers/events.py +203 -0
  341. synapse/handlers/federation.py +2042 -0
  342. synapse/handlers/federation_event.py +2420 -0
  343. synapse/handlers/identity.py +812 -0
  344. synapse/handlers/initial_sync.py +528 -0
  345. synapse/handlers/jwt.py +120 -0
  346. synapse/handlers/message.py +2357 -0
  347. synapse/handlers/oidc.py +1801 -0
  348. synapse/handlers/pagination.py +811 -0
  349. synapse/handlers/password_policy.py +102 -0
  350. synapse/handlers/presence.py +2634 -0
  351. synapse/handlers/profile.py +656 -0
  352. synapse/handlers/push_rules.py +164 -0
  353. synapse/handlers/read_marker.py +79 -0
  354. synapse/handlers/receipts.py +351 -0
  355. synapse/handlers/register.py +1059 -0
  356. synapse/handlers/relations.py +623 -0
  357. synapse/handlers/reports.py +98 -0
  358. synapse/handlers/room.py +2449 -0
  359. synapse/handlers/room_list.py +632 -0
  360. synapse/handlers/room_member.py +2366 -0
  361. synapse/handlers/room_member_worker.py +146 -0
  362. synapse/handlers/room_policy.py +186 -0
  363. synapse/handlers/room_summary.py +1057 -0
  364. synapse/handlers/saml.py +524 -0
  365. synapse/handlers/search.py +723 -0
  366. synapse/handlers/send_email.py +209 -0
  367. synapse/handlers/set_password.py +71 -0
  368. synapse/handlers/sliding_sync/__init__.py +1961 -0
  369. synapse/handlers/sliding_sync/extensions.py +969 -0
  370. synapse/handlers/sliding_sync/room_lists.py +2317 -0
  371. synapse/handlers/sliding_sync/store.py +126 -0
  372. synapse/handlers/sso.py +1291 -0
  373. synapse/handlers/state_deltas.py +82 -0
  374. synapse/handlers/stats.py +322 -0
  375. synapse/handlers/sync.py +3096 -0
  376. synapse/handlers/thread_subscriptions.py +190 -0
  377. synapse/handlers/typing.py +612 -0
  378. synapse/handlers/ui_auth/__init__.py +48 -0
  379. synapse/handlers/ui_auth/checkers.py +332 -0
  380. synapse/handlers/user_directory.py +786 -0
  381. synapse/handlers/worker_lock.py +371 -0
  382. synapse/http/__init__.py +105 -0
  383. synapse/http/additional_resource.py +62 -0
  384. synapse/http/client.py +1377 -0
  385. synapse/http/connectproxyclient.py +316 -0
  386. synapse/http/federation/__init__.py +19 -0
  387. synapse/http/federation/matrix_federation_agent.py +490 -0
  388. synapse/http/federation/srv_resolver.py +196 -0
  389. synapse/http/federation/well_known_resolver.py +368 -0
  390. synapse/http/matrixfederationclient.py +1874 -0
  391. synapse/http/proxy.py +290 -0
  392. synapse/http/proxyagent.py +497 -0
  393. synapse/http/replicationagent.py +203 -0
  394. synapse/http/request_metrics.py +309 -0
  395. synapse/http/server.py +1111 -0
  396. synapse/http/servlet.py +1018 -0
  397. synapse/http/site.py +952 -0
  398. synapse/http/types.py +27 -0
  399. synapse/logging/__init__.py +31 -0
  400. synapse/logging/_remote.py +261 -0
  401. synapse/logging/_terse_json.py +95 -0
  402. synapse/logging/context.py +1209 -0
  403. synapse/logging/formatter.py +62 -0
  404. synapse/logging/handlers.py +99 -0
  405. synapse/logging/loggers.py +25 -0
  406. synapse/logging/opentracing.py +1132 -0
  407. synapse/logging/scopecontextmanager.py +160 -0
  408. synapse/media/_base.py +831 -0
  409. synapse/media/filepath.py +417 -0
  410. synapse/media/media_repository.py +1595 -0
  411. synapse/media/media_storage.py +703 -0
  412. synapse/media/oembed.py +277 -0
  413. synapse/media/preview_html.py +556 -0
  414. synapse/media/storage_provider.py +195 -0
  415. synapse/media/thumbnailer.py +833 -0
  416. synapse/media/url_previewer.py +884 -0
  417. synapse/metrics/__init__.py +748 -0
  418. synapse/metrics/_gc.py +219 -0
  419. synapse/metrics/_reactor_metrics.py +171 -0
  420. synapse/metrics/_types.py +38 -0
  421. synapse/metrics/background_process_metrics.py +555 -0
  422. synapse/metrics/common_usage_metrics.py +95 -0
  423. synapse/metrics/jemalloc.py +248 -0
  424. synapse/module_api/__init__.py +2131 -0
  425. synapse/module_api/callbacks/__init__.py +50 -0
  426. synapse/module_api/callbacks/account_validity_callbacks.py +106 -0
  427. synapse/module_api/callbacks/media_repository_callbacks.py +157 -0
  428. synapse/module_api/callbacks/ratelimit_callbacks.py +78 -0
  429. synapse/module_api/callbacks/spamchecker_callbacks.py +991 -0
  430. synapse/module_api/callbacks/third_party_event_rules_callbacks.py +592 -0
  431. synapse/module_api/errors.py +42 -0
  432. synapse/notifier.py +969 -0
  433. synapse/push/__init__.py +212 -0
  434. synapse/push/bulk_push_rule_evaluator.py +635 -0
  435. synapse/push/clientformat.py +126 -0
  436. synapse/push/emailpusher.py +334 -0
  437. synapse/push/httppusher.py +565 -0
  438. synapse/push/mailer.py +1009 -0
  439. synapse/push/presentable_names.py +216 -0
  440. synapse/push/push_tools.py +114 -0
  441. synapse/push/push_types.py +141 -0
  442. synapse/push/pusher.py +87 -0
  443. synapse/push/pusherpool.py +501 -0
  444. synapse/push/rulekinds.py +33 -0
  445. synapse/py.typed +0 -0
  446. synapse/replication/__init__.py +20 -0
  447. synapse/replication/http/__init__.py +68 -0
  448. synapse/replication/http/_base.py +469 -0
  449. synapse/replication/http/account_data.py +297 -0
  450. synapse/replication/http/deactivate_account.py +81 -0
  451. synapse/replication/http/delayed_events.py +62 -0
  452. synapse/replication/http/devices.py +254 -0
  453. synapse/replication/http/federation.py +334 -0
  454. synapse/replication/http/login.py +106 -0
  455. synapse/replication/http/membership.py +364 -0
  456. synapse/replication/http/presence.py +133 -0
  457. synapse/replication/http/push.py +156 -0
  458. synapse/replication/http/register.py +172 -0
  459. synapse/replication/http/send_events.py +182 -0
  460. synapse/replication/http/state.py +82 -0
  461. synapse/replication/http/streams.py +101 -0
  462. synapse/replication/tcp/__init__.py +56 -0
  463. synapse/replication/tcp/client.py +553 -0
  464. synapse/replication/tcp/commands.py +569 -0
  465. synapse/replication/tcp/context.py +41 -0
  466. synapse/replication/tcp/external_cache.py +156 -0
  467. synapse/replication/tcp/handler.py +922 -0
  468. synapse/replication/tcp/protocol.py +611 -0
  469. synapse/replication/tcp/redis.py +510 -0
  470. synapse/replication/tcp/resource.py +349 -0
  471. synapse/replication/tcp/streams/__init__.py +96 -0
  472. synapse/replication/tcp/streams/_base.py +765 -0
  473. synapse/replication/tcp/streams/events.py +287 -0
  474. synapse/replication/tcp/streams/federation.py +92 -0
  475. synapse/replication/tcp/streams/partial_state.py +80 -0
  476. synapse/res/providers.json +29 -0
  477. synapse/res/templates/_base.html +29 -0
  478. synapse/res/templates/account_previously_renewed.html +6 -0
  479. synapse/res/templates/account_renewed.html +6 -0
  480. synapse/res/templates/add_threepid.html +8 -0
  481. synapse/res/templates/add_threepid.txt +6 -0
  482. synapse/res/templates/add_threepid_failure.html +7 -0
  483. synapse/res/templates/add_threepid_success.html +6 -0
  484. synapse/res/templates/already_in_use.html +12 -0
  485. synapse/res/templates/already_in_use.txt +10 -0
  486. synapse/res/templates/auth_success.html +21 -0
  487. synapse/res/templates/invalid_token.html +6 -0
  488. synapse/res/templates/mail-Element.css +7 -0
  489. synapse/res/templates/mail-Vector.css +7 -0
  490. synapse/res/templates/mail-expiry.css +4 -0
  491. synapse/res/templates/mail.css +156 -0
  492. synapse/res/templates/notice_expiry.html +46 -0
  493. synapse/res/templates/notice_expiry.txt +7 -0
  494. synapse/res/templates/notif.html +51 -0
  495. synapse/res/templates/notif.txt +22 -0
  496. synapse/res/templates/notif_mail.html +59 -0
  497. synapse/res/templates/notif_mail.txt +10 -0
  498. synapse/res/templates/password_reset.html +10 -0
  499. synapse/res/templates/password_reset.txt +7 -0
  500. synapse/res/templates/password_reset_confirmation.html +15 -0
  501. synapse/res/templates/password_reset_failure.html +7 -0
  502. synapse/res/templates/password_reset_success.html +6 -0
  503. synapse/res/templates/recaptcha.html +42 -0
  504. synapse/res/templates/registration.html +12 -0
  505. synapse/res/templates/registration.txt +10 -0
  506. synapse/res/templates/registration_failure.html +6 -0
  507. synapse/res/templates/registration_success.html +6 -0
  508. synapse/res/templates/registration_token.html +18 -0
  509. synapse/res/templates/room.html +33 -0
  510. synapse/res/templates/room.txt +9 -0
  511. synapse/res/templates/sso.css +129 -0
  512. synapse/res/templates/sso_account_deactivated.html +25 -0
  513. synapse/res/templates/sso_auth_account_details.html +186 -0
  514. synapse/res/templates/sso_auth_account_details.js +116 -0
  515. synapse/res/templates/sso_auth_bad_user.html +26 -0
  516. synapse/res/templates/sso_auth_confirm.html +27 -0
  517. synapse/res/templates/sso_auth_success.html +26 -0
  518. synapse/res/templates/sso_error.html +71 -0
  519. synapse/res/templates/sso_footer.html +19 -0
  520. synapse/res/templates/sso_login_idp_picker.html +60 -0
  521. synapse/res/templates/sso_new_user_consent.html +30 -0
  522. synapse/res/templates/sso_partial_profile.html +19 -0
  523. synapse/res/templates/sso_redirect_confirm.html +39 -0
  524. synapse/res/templates/style.css +33 -0
  525. synapse/res/templates/terms.html +27 -0
  526. synapse/rest/__init__.py +197 -0
  527. synapse/rest/admin/__init__.py +395 -0
  528. synapse/rest/admin/_base.py +72 -0
  529. synapse/rest/admin/background_updates.py +171 -0
  530. synapse/rest/admin/devices.py +221 -0
  531. synapse/rest/admin/event_reports.py +173 -0
  532. synapse/rest/admin/events.py +69 -0
  533. synapse/rest/admin/experimental_features.py +137 -0
  534. synapse/rest/admin/federation.py +243 -0
  535. synapse/rest/admin/media.py +540 -0
  536. synapse/rest/admin/registration_tokens.py +358 -0
  537. synapse/rest/admin/rooms.py +1092 -0
  538. synapse/rest/admin/scheduled_tasks.py +70 -0
  539. synapse/rest/admin/server_notice_servlet.py +132 -0
  540. synapse/rest/admin/statistics.py +132 -0
  541. synapse/rest/admin/username_available.py +58 -0
  542. synapse/rest/admin/users.py +1634 -0
  543. synapse/rest/client/__init__.py +20 -0
  544. synapse/rest/client/_base.py +113 -0
  545. synapse/rest/client/account.py +937 -0
  546. synapse/rest/client/account_data.py +319 -0
  547. synapse/rest/client/account_validity.py +103 -0
  548. synapse/rest/client/appservice_ping.py +125 -0
  549. synapse/rest/client/auth.py +218 -0
  550. synapse/rest/client/auth_metadata.py +122 -0
  551. synapse/rest/client/capabilities.py +121 -0
  552. synapse/rest/client/delayed_events.py +165 -0
  553. synapse/rest/client/devices.py +587 -0
  554. synapse/rest/client/directory.py +211 -0
  555. synapse/rest/client/events.py +116 -0
  556. synapse/rest/client/filter.py +112 -0
  557. synapse/rest/client/initial_sync.py +65 -0
  558. synapse/rest/client/keys.py +678 -0
  559. synapse/rest/client/knock.py +104 -0
  560. synapse/rest/client/login.py +750 -0
  561. synapse/rest/client/login_token_request.py +127 -0
  562. synapse/rest/client/logout.py +93 -0
  563. synapse/rest/client/matrixrtc.py +52 -0
  564. synapse/rest/client/media.py +307 -0
  565. synapse/rest/client/mutual_rooms.py +145 -0
  566. synapse/rest/client/notifications.py +137 -0
  567. synapse/rest/client/openid.py +109 -0
  568. synapse/rest/client/password_policy.py +69 -0
  569. synapse/rest/client/presence.py +131 -0
  570. synapse/rest/client/profile.py +291 -0
  571. synapse/rest/client/push_rule.py +331 -0
  572. synapse/rest/client/pusher.py +181 -0
  573. synapse/rest/client/read_marker.py +104 -0
  574. synapse/rest/client/receipts.py +165 -0
  575. synapse/rest/client/register.py +1072 -0
  576. synapse/rest/client/relations.py +138 -0
  577. synapse/rest/client/rendezvous.py +76 -0
  578. synapse/rest/client/reporting.py +207 -0
  579. synapse/rest/client/room.py +1763 -0
  580. synapse/rest/client/room_keys.py +426 -0
  581. synapse/rest/client/room_upgrade_rest_servlet.py +112 -0
  582. synapse/rest/client/sendtodevice.py +85 -0
  583. synapse/rest/client/sync.py +1131 -0
  584. synapse/rest/client/tags.py +129 -0
  585. synapse/rest/client/thirdparty.py +130 -0
  586. synapse/rest/client/thread_subscriptions.py +247 -0
  587. synapse/rest/client/tokenrefresh.py +52 -0
  588. synapse/rest/client/transactions.py +150 -0
  589. synapse/rest/client/user_directory.py +99 -0
  590. synapse/rest/client/versions.py +193 -0
  591. synapse/rest/client/voip.py +88 -0
  592. synapse/rest/consent/__init__.py +0 -0
  593. synapse/rest/consent/consent_resource.py +210 -0
  594. synapse/rest/health.py +38 -0
  595. synapse/rest/key/__init__.py +20 -0
  596. synapse/rest/key/v2/__init__.py +40 -0
  597. synapse/rest/key/v2/local_key_resource.py +125 -0
  598. synapse/rest/key/v2/remote_key_resource.py +302 -0
  599. synapse/rest/media/__init__.py +0 -0
  600. synapse/rest/media/config_resource.py +53 -0
  601. synapse/rest/media/create_resource.py +90 -0
  602. synapse/rest/media/download_resource.py +110 -0
  603. synapse/rest/media/media_repository_resource.py +113 -0
  604. synapse/rest/media/preview_url_resource.py +77 -0
  605. synapse/rest/media/thumbnail_resource.py +142 -0
  606. synapse/rest/media/upload_resource.py +187 -0
  607. synapse/rest/media/v1/__init__.py +39 -0
  608. synapse/rest/media/v1/_base.py +23 -0
  609. synapse/rest/media/v1/media_storage.py +23 -0
  610. synapse/rest/media/v1/storage_provider.py +23 -0
  611. synapse/rest/synapse/__init__.py +20 -0
  612. synapse/rest/synapse/client/__init__.py +93 -0
  613. synapse/rest/synapse/client/federation_whitelist.py +66 -0
  614. synapse/rest/synapse/client/jwks.py +77 -0
  615. synapse/rest/synapse/client/new_user_consent.py +115 -0
  616. synapse/rest/synapse/client/oidc/__init__.py +45 -0
  617. synapse/rest/synapse/client/oidc/backchannel_logout_resource.py +42 -0
  618. synapse/rest/synapse/client/oidc/callback_resource.py +48 -0
  619. synapse/rest/synapse/client/password_reset.py +129 -0
  620. synapse/rest/synapse/client/pick_idp.py +107 -0
  621. synapse/rest/synapse/client/pick_username.py +153 -0
  622. synapse/rest/synapse/client/rendezvous.py +58 -0
  623. synapse/rest/synapse/client/saml2/__init__.py +42 -0
  624. synapse/rest/synapse/client/saml2/metadata_resource.py +46 -0
  625. synapse/rest/synapse/client/saml2/response_resource.py +52 -0
  626. synapse/rest/synapse/client/sso_register.py +56 -0
  627. synapse/rest/synapse/client/unsubscribe.py +88 -0
  628. synapse/rest/synapse/mas/__init__.py +71 -0
  629. synapse/rest/synapse/mas/_base.py +55 -0
  630. synapse/rest/synapse/mas/devices.py +239 -0
  631. synapse/rest/synapse/mas/users.py +469 -0
  632. synapse/rest/well_known.py +148 -0
  633. synapse/server.py +1279 -0
  634. synapse/server_notices/__init__.py +0 -0
  635. synapse/server_notices/consent_server_notices.py +136 -0
  636. synapse/server_notices/resource_limits_server_notices.py +215 -0
  637. synapse/server_notices/server_notices_manager.py +388 -0
  638. synapse/server_notices/server_notices_sender.py +67 -0
  639. synapse/server_notices/worker_server_notices_sender.py +46 -0
  640. synapse/spam_checker_api/__init__.py +31 -0
  641. synapse/state/__init__.py +1023 -0
  642. synapse/state/v1.py +369 -0
  643. synapse/state/v2.py +985 -0
  644. synapse/static/client/login/index.html +47 -0
  645. synapse/static/client/login/js/jquery-3.4.1.min.js +2 -0
  646. synapse/static/client/login/js/login.js +291 -0
  647. synapse/static/client/login/spinner.gif +0 -0
  648. synapse/static/client/login/style.css +79 -0
  649. synapse/static/index.html +63 -0
  650. synapse/storage/__init__.py +43 -0
  651. synapse/storage/_base.py +245 -0
  652. synapse/storage/admin_client_config.py +25 -0
  653. synapse/storage/background_updates.py +1189 -0
  654. synapse/storage/controllers/__init__.py +57 -0
  655. synapse/storage/controllers/persist_events.py +1237 -0
  656. synapse/storage/controllers/purge_events.py +456 -0
  657. synapse/storage/controllers/state.py +950 -0
  658. synapse/storage/controllers/stats.py +119 -0
  659. synapse/storage/database.py +2720 -0
  660. synapse/storage/databases/__init__.py +175 -0
  661. synapse/storage/databases/main/__init__.py +420 -0
  662. synapse/storage/databases/main/account_data.py +1073 -0
  663. synapse/storage/databases/main/appservice.py +473 -0
  664. synapse/storage/databases/main/cache.py +912 -0
  665. synapse/storage/databases/main/censor_events.py +226 -0
  666. synapse/storage/databases/main/client_ips.py +816 -0
  667. synapse/storage/databases/main/delayed_events.py +577 -0
  668. synapse/storage/databases/main/deviceinbox.py +1272 -0
  669. synapse/storage/databases/main/devices.py +2579 -0
  670. synapse/storage/databases/main/directory.py +212 -0
  671. synapse/storage/databases/main/e2e_room_keys.py +689 -0
  672. synapse/storage/databases/main/end_to_end_keys.py +1894 -0
  673. synapse/storage/databases/main/event_federation.py +2511 -0
  674. synapse/storage/databases/main/event_push_actions.py +1936 -0
  675. synapse/storage/databases/main/events.py +3765 -0
  676. synapse/storage/databases/main/events_bg_updates.py +2910 -0
  677. synapse/storage/databases/main/events_forward_extremities.py +126 -0
  678. synapse/storage/databases/main/events_worker.py +2787 -0
  679. synapse/storage/databases/main/experimental_features.py +130 -0
  680. synapse/storage/databases/main/filtering.py +231 -0
  681. synapse/storage/databases/main/keys.py +291 -0
  682. synapse/storage/databases/main/lock.py +554 -0
  683. synapse/storage/databases/main/media_repository.py +1068 -0
  684. synapse/storage/databases/main/metrics.py +461 -0
  685. synapse/storage/databases/main/monthly_active_users.py +443 -0
  686. synapse/storage/databases/main/openid.py +60 -0
  687. synapse/storage/databases/main/presence.py +509 -0
  688. synapse/storage/databases/main/profile.py +539 -0
  689. synapse/storage/databases/main/purge_events.py +521 -0
  690. synapse/storage/databases/main/push_rule.py +970 -0
  691. synapse/storage/databases/main/pusher.py +793 -0
  692. synapse/storage/databases/main/receipts.py +1341 -0
  693. synapse/storage/databases/main/registration.py +3071 -0
  694. synapse/storage/databases/main/rejections.py +37 -0
  695. synapse/storage/databases/main/relations.py +1116 -0
  696. synapse/storage/databases/main/room.py +2779 -0
  697. synapse/storage/databases/main/roommember.py +2132 -0
  698. synapse/storage/databases/main/search.py +939 -0
  699. synapse/storage/databases/main/session.py +152 -0
  700. synapse/storage/databases/main/signatures.py +94 -0
  701. synapse/storage/databases/main/sliding_sync.py +842 -0
  702. synapse/storage/databases/main/state.py +1002 -0
  703. synapse/storage/databases/main/state_deltas.py +360 -0
  704. synapse/storage/databases/main/stats.py +789 -0
  705. synapse/storage/databases/main/stream.py +2589 -0
  706. synapse/storage/databases/main/tags.py +360 -0
  707. synapse/storage/databases/main/task_scheduler.py +225 -0
  708. synapse/storage/databases/main/thread_subscriptions.py +589 -0
  709. synapse/storage/databases/main/transactions.py +676 -0
  710. synapse/storage/databases/main/ui_auth.py +420 -0
  711. synapse/storage/databases/main/user_directory.py +1330 -0
  712. synapse/storage/databases/main/user_erasure_store.py +117 -0
  713. synapse/storage/databases/state/__init__.py +22 -0
  714. synapse/storage/databases/state/bg_updates.py +497 -0
  715. synapse/storage/databases/state/deletion.py +557 -0
  716. synapse/storage/databases/state/store.py +948 -0
  717. synapse/storage/engines/__init__.py +70 -0
  718. synapse/storage/engines/_base.py +154 -0
  719. synapse/storage/engines/postgres.py +261 -0
  720. synapse/storage/engines/sqlite.py +199 -0
  721. synapse/storage/invite_rule.py +152 -0
  722. synapse/storage/keys.py +40 -0
  723. synapse/storage/prepare_database.py +730 -0
  724. synapse/storage/push_rule.py +28 -0
  725. synapse/storage/roommember.py +88 -0
  726. synapse/storage/schema/README.md +4 -0
  727. synapse/storage/schema/__init__.py +186 -0
  728. synapse/storage/schema/common/delta/25/00background_updates.sql +40 -0
  729. synapse/storage/schema/common/delta/35/00background_updates_add_col.sql +36 -0
  730. synapse/storage/schema/common/delta/58/00background_update_ordering.sql +38 -0
  731. synapse/storage/schema/common/full_schemas/72/full.sql.postgres +8 -0
  732. synapse/storage/schema/common/full_schemas/72/full.sql.sqlite +6 -0
  733. synapse/storage/schema/common/schema_version.sql +60 -0
  734. synapse/storage/schema/main/delta/12/v12.sql +82 -0
  735. synapse/storage/schema/main/delta/13/v13.sql +38 -0
  736. synapse/storage/schema/main/delta/14/v14.sql +42 -0
  737. synapse/storage/schema/main/delta/15/appservice_txns.sql +50 -0
  738. synapse/storage/schema/main/delta/15/presence_indices.sql +2 -0
  739. synapse/storage/schema/main/delta/15/v15.sql +24 -0
  740. synapse/storage/schema/main/delta/16/events_order_index.sql +4 -0
  741. synapse/storage/schema/main/delta/16/remote_media_cache_index.sql +2 -0
  742. synapse/storage/schema/main/delta/16/remove_duplicates.sql +9 -0
  743. synapse/storage/schema/main/delta/16/room_alias_index.sql +3 -0
  744. synapse/storage/schema/main/delta/16/unique_constraints.sql +72 -0
  745. synapse/storage/schema/main/delta/16/users.sql +56 -0
  746. synapse/storage/schema/main/delta/17/drop_indexes.sql +37 -0
  747. synapse/storage/schema/main/delta/17/server_keys.sql +43 -0
  748. synapse/storage/schema/main/delta/17/user_threepids.sql +9 -0
  749. synapse/storage/schema/main/delta/18/server_keys_bigger_ints.sql +51 -0
  750. synapse/storage/schema/main/delta/19/event_index.sql +38 -0
  751. synapse/storage/schema/main/delta/20/dummy.sql +1 -0
  752. synapse/storage/schema/main/delta/20/pushers.py +93 -0
  753. synapse/storage/schema/main/delta/21/end_to_end_keys.sql +53 -0
  754. synapse/storage/schema/main/delta/21/receipts.sql +57 -0
  755. synapse/storage/schema/main/delta/22/receipts_index.sql +41 -0
  756. synapse/storage/schema/main/delta/22/user_threepids_unique.sql +19 -0
  757. synapse/storage/schema/main/delta/24/stats_reporting.sql +37 -0
  758. synapse/storage/schema/main/delta/25/fts.py +81 -0
  759. synapse/storage/schema/main/delta/25/guest_access.sql +44 -0
  760. synapse/storage/schema/main/delta/25/history_visibility.sql +44 -0
  761. synapse/storage/schema/main/delta/25/tags.sql +57 -0
  762. synapse/storage/schema/main/delta/26/account_data.sql +36 -0
  763. synapse/storage/schema/main/delta/27/account_data.sql +55 -0
  764. synapse/storage/schema/main/delta/27/forgotten_memberships.sql +45 -0
  765. synapse/storage/schema/main/delta/27/ts.py +61 -0
  766. synapse/storage/schema/main/delta/28/event_push_actions.sql +46 -0
  767. synapse/storage/schema/main/delta/28/events_room_stream.sql +39 -0
  768. synapse/storage/schema/main/delta/28/public_roms_index.sql +39 -0
  769. synapse/storage/schema/main/delta/28/receipts_user_id_index.sql +41 -0
  770. synapse/storage/schema/main/delta/28/upgrade_times.sql +40 -0
  771. synapse/storage/schema/main/delta/28/users_is_guest.sql +41 -0
  772. synapse/storage/schema/main/delta/29/push_actions.sql +54 -0
  773. synapse/storage/schema/main/delta/30/alias_creator.sql +35 -0
  774. synapse/storage/schema/main/delta/30/as_users.py +82 -0
  775. synapse/storage/schema/main/delta/30/deleted_pushers.sql +44 -0
  776. synapse/storage/schema/main/delta/30/presence_stream.sql +49 -0
  777. synapse/storage/schema/main/delta/30/public_rooms.sql +42 -0
  778. synapse/storage/schema/main/delta/30/push_rule_stream.sql +57 -0
  779. synapse/storage/schema/main/delta/30/threepid_guest_access_tokens.sql +43 -0
  780. synapse/storage/schema/main/delta/31/invites.sql +61 -0
  781. synapse/storage/schema/main/delta/31/local_media_repository_url_cache.sql +46 -0
  782. synapse/storage/schema/main/delta/31/pushers_0.py +92 -0
  783. synapse/storage/schema/main/delta/31/pushers_index.sql +41 -0
  784. synapse/storage/schema/main/delta/31/search_update.py +65 -0
  785. synapse/storage/schema/main/delta/32/events.sql +35 -0
  786. synapse/storage/schema/main/delta/32/openid.sql +9 -0
  787. synapse/storage/schema/main/delta/32/pusher_throttle.sql +42 -0
  788. synapse/storage/schema/main/delta/32/remove_indices.sql +52 -0
  789. synapse/storage/schema/main/delta/32/reports.sql +44 -0
  790. synapse/storage/schema/main/delta/33/access_tokens_device_index.sql +36 -0
  791. synapse/storage/schema/main/delta/33/devices.sql +40 -0
  792. synapse/storage/schema/main/delta/33/devices_for_e2e_keys.sql +38 -0
  793. synapse/storage/schema/main/delta/33/devices_for_e2e_keys_clear_unknown_device.sql +39 -0
  794. synapse/storage/schema/main/delta/33/event_fields.py +61 -0
  795. synapse/storage/schema/main/delta/33/remote_media_ts.py +43 -0
  796. synapse/storage/schema/main/delta/33/user_ips_index.sql +36 -0
  797. synapse/storage/schema/main/delta/34/appservice_stream.sql +42 -0
  798. synapse/storage/schema/main/delta/34/cache_stream.py +50 -0
  799. synapse/storage/schema/main/delta/34/device_inbox.sql +43 -0
  800. synapse/storage/schema/main/delta/34/push_display_name_rename.sql +39 -0
  801. synapse/storage/schema/main/delta/34/received_txn_purge.py +36 -0
  802. synapse/storage/schema/main/delta/35/contains_url.sql +36 -0
  803. synapse/storage/schema/main/delta/35/device_outbox.sql +58 -0
  804. synapse/storage/schema/main/delta/35/device_stream_id.sql +40 -0
  805. synapse/storage/schema/main/delta/35/event_push_actions_index.sql +36 -0
  806. synapse/storage/schema/main/delta/35/public_room_list_change_stream.sql +52 -0
  807. synapse/storage/schema/main/delta/35/stream_order_to_extrem.sql +56 -0
  808. synapse/storage/schema/main/delta/36/readd_public_rooms.sql +45 -0
  809. synapse/storage/schema/main/delta/37/remove_auth_idx.py +89 -0
  810. synapse/storage/schema/main/delta/37/user_threepids.sql +71 -0
  811. synapse/storage/schema/main/delta/38/postgres_fts_gist.sql +38 -0
  812. synapse/storage/schema/main/delta/39/appservice_room_list.sql +48 -0
  813. synapse/storage/schema/main/delta/39/device_federation_stream_idx.sql +35 -0
  814. synapse/storage/schema/main/delta/39/event_push_index.sql +36 -0
  815. synapse/storage/schema/main/delta/39/federation_out_position.sql +41 -0
  816. synapse/storage/schema/main/delta/39/membership_profile.sql +39 -0
  817. synapse/storage/schema/main/delta/40/current_state_idx.sql +36 -0
  818. synapse/storage/schema/main/delta/40/device_inbox.sql +40 -0
  819. synapse/storage/schema/main/delta/40/device_list_streams.sql +79 -0
  820. synapse/storage/schema/main/delta/40/event_push_summary.sql +57 -0
  821. synapse/storage/schema/main/delta/40/pushers.sql +58 -0
  822. synapse/storage/schema/main/delta/41/device_list_stream_idx.sql +36 -0
  823. synapse/storage/schema/main/delta/41/device_outbound_index.sql +35 -0
  824. synapse/storage/schema/main/delta/41/event_search_event_id_idx.sql +36 -0
  825. synapse/storage/schema/main/delta/41/ratelimit.sql +41 -0
  826. synapse/storage/schema/main/delta/42/current_state_delta.sql +48 -0
  827. synapse/storage/schema/main/delta/42/device_list_last_id.sql +52 -0
  828. synapse/storage/schema/main/delta/42/event_auth_state_only.sql +36 -0
  829. synapse/storage/schema/main/delta/42/user_dir.py +88 -0
  830. synapse/storage/schema/main/delta/43/blocked_rooms.sql +40 -0
  831. synapse/storage/schema/main/delta/43/quarantine_media.sql +36 -0
  832. synapse/storage/schema/main/delta/43/url_cache.sql +35 -0
  833. synapse/storage/schema/main/delta/43/user_share.sql +52 -0
  834. synapse/storage/schema/main/delta/44/expire_url_cache.sql +60 -0
  835. synapse/storage/schema/main/delta/45/group_server.sql +186 -0
  836. synapse/storage/schema/main/delta/45/profile_cache.sql +47 -0
  837. synapse/storage/schema/main/delta/46/drop_refresh_tokens.sql +36 -0
  838. synapse/storage/schema/main/delta/46/drop_unique_deleted_pushers.sql +54 -0
  839. synapse/storage/schema/main/delta/46/group_server.sql +51 -0
  840. synapse/storage/schema/main/delta/46/local_media_repository_url_idx.sql +43 -0
  841. synapse/storage/schema/main/delta/46/user_dir_null_room_ids.sql +54 -0
  842. synapse/storage/schema/main/delta/46/user_dir_typos.sql +43 -0
  843. synapse/storage/schema/main/delta/47/last_access_media.sql +35 -0
  844. synapse/storage/schema/main/delta/47/postgres_fts_gin.sql +36 -0
  845. synapse/storage/schema/main/delta/47/push_actions_staging.sql +47 -0
  846. synapse/storage/schema/main/delta/48/add_user_consent.sql +37 -0
  847. synapse/storage/schema/main/delta/48/add_user_ips_last_seen_index.sql +36 -0
  848. synapse/storage/schema/main/delta/48/deactivated_users.sql +44 -0
  849. synapse/storage/schema/main/delta/48/group_unique_indexes.py +67 -0
  850. synapse/storage/schema/main/delta/48/groups_joinable.sql +41 -0
  851. synapse/storage/schema/main/delta/49/add_user_consent_server_notice_sent.sql +39 -0
  852. synapse/storage/schema/main/delta/49/add_user_daily_visits.sql +40 -0
  853. synapse/storage/schema/main/delta/49/add_user_ips_last_seen_only_index.sql +36 -0
  854. synapse/storage/schema/main/delta/50/add_creation_ts_users_index.sql +38 -0
  855. synapse/storage/schema/main/delta/50/erasure_store.sql +40 -0
  856. synapse/storage/schema/main/delta/50/make_event_content_nullable.py +102 -0
  857. synapse/storage/schema/main/delta/51/e2e_room_keys.sql +58 -0
  858. synapse/storage/schema/main/delta/51/monthly_active_users.sql +46 -0
  859. synapse/storage/schema/main/delta/52/add_event_to_state_group_index.sql +38 -0
  860. synapse/storage/schema/main/delta/52/device_list_streams_unique_idx.sql +55 -0
  861. synapse/storage/schema/main/delta/52/e2e_room_keys.sql +72 -0
  862. synapse/storage/schema/main/delta/53/add_user_type_to_users.sql +38 -0
  863. synapse/storage/schema/main/delta/53/drop_sent_transactions.sql +35 -0
  864. synapse/storage/schema/main/delta/53/event_format_version.sql +35 -0
  865. synapse/storage/schema/main/delta/53/user_dir_populate.sql +49 -0
  866. synapse/storage/schema/main/delta/53/user_ips_index.sql +49 -0
  867. synapse/storage/schema/main/delta/53/user_share.sql +63 -0
  868. synapse/storage/schema/main/delta/53/user_threepid_id.sql +48 -0
  869. synapse/storage/schema/main/delta/53/users_in_public_rooms.sql +47 -0
  870. synapse/storage/schema/main/delta/54/account_validity_with_renewal.sql +49 -0
  871. synapse/storage/schema/main/delta/54/add_validity_to_server_keys.sql +42 -0
  872. synapse/storage/schema/main/delta/54/delete_forward_extremities.sql +42 -0
  873. synapse/storage/schema/main/delta/54/drop_legacy_tables.sql +49 -0
  874. synapse/storage/schema/main/delta/54/drop_presence_list.sql +35 -0
  875. synapse/storage/schema/main/delta/54/relations.sql +46 -0
  876. synapse/storage/schema/main/delta/54/stats.sql +99 -0
  877. synapse/storage/schema/main/delta/54/stats2.sql +47 -0
  878. synapse/storage/schema/main/delta/55/access_token_expiry.sql +37 -0
  879. synapse/storage/schema/main/delta/55/track_threepid_validations.sql +50 -0
  880. synapse/storage/schema/main/delta/55/users_alter_deactivated.sql +38 -0
  881. synapse/storage/schema/main/delta/56/add_spans_to_device_lists.sql +39 -0
  882. synapse/storage/schema/main/delta/56/current_state_events_membership.sql +41 -0
  883. synapse/storage/schema/main/delta/56/current_state_events_membership_mk2.sql +43 -0
  884. synapse/storage/schema/main/delta/56/delete_keys_from_deleted_backups.sql +44 -0
  885. synapse/storage/schema/main/delta/56/destinations_failure_ts.sql +44 -0
  886. synapse/storage/schema/main/delta/56/destinations_retry_interval_type.sql.postgres +18 -0
  887. synapse/storage/schema/main/delta/56/device_stream_id_insert.sql +39 -0
  888. synapse/storage/schema/main/delta/56/devices_last_seen.sql +43 -0
  889. synapse/storage/schema/main/delta/56/drop_unused_event_tables.sql +39 -0
  890. synapse/storage/schema/main/delta/56/event_expiry.sql +40 -0
  891. synapse/storage/schema/main/delta/56/event_labels.sql +49 -0
  892. synapse/storage/schema/main/delta/56/event_labels_background_update.sql +36 -0
  893. synapse/storage/schema/main/delta/56/fix_room_keys_index.sql +37 -0
  894. synapse/storage/schema/main/delta/56/hidden_devices.sql +37 -0
  895. synapse/storage/schema/main/delta/56/hidden_devices_fix.sql.sqlite +42 -0
  896. synapse/storage/schema/main/delta/56/nuke_empty_communities_from_db.sql +48 -0
  897. synapse/storage/schema/main/delta/56/public_room_list_idx.sql +35 -0
  898. synapse/storage/schema/main/delta/56/redaction_censor.sql +35 -0
  899. synapse/storage/schema/main/delta/56/redaction_censor2.sql +41 -0
  900. synapse/storage/schema/main/delta/56/redaction_censor3_fix_update.sql.postgres +25 -0
  901. synapse/storage/schema/main/delta/56/redaction_censor4.sql +35 -0
  902. synapse/storage/schema/main/delta/56/remove_tombstoned_rooms_from_directory.sql +38 -0
  903. synapse/storage/schema/main/delta/56/room_key_etag.sql +36 -0
  904. synapse/storage/schema/main/delta/56/room_membership_idx.sql +37 -0
  905. synapse/storage/schema/main/delta/56/room_retention.sql +52 -0
  906. synapse/storage/schema/main/delta/56/signing_keys.sql +75 -0
  907. synapse/storage/schema/main/delta/56/signing_keys_nonunique_signatures.sql +41 -0
  908. synapse/storage/schema/main/delta/56/stats_separated.sql +175 -0
  909. synapse/storage/schema/main/delta/56/unique_user_filter_index.py +46 -0
  910. synapse/storage/schema/main/delta/56/user_external_ids.sql +43 -0
  911. synapse/storage/schema/main/delta/56/users_in_public_rooms_idx.sql +36 -0
  912. synapse/storage/schema/main/delta/57/delete_old_current_state_events.sql +41 -0
  913. synapse/storage/schema/main/delta/57/device_list_remote_cache_stale.sql +44 -0
  914. synapse/storage/schema/main/delta/57/local_current_membership.py +111 -0
  915. synapse/storage/schema/main/delta/57/remove_sent_outbound_pokes.sql +40 -0
  916. synapse/storage/schema/main/delta/57/rooms_version_column.sql +43 -0
  917. synapse/storage/schema/main/delta/57/rooms_version_column_2.sql.postgres +35 -0
  918. synapse/storage/schema/main/delta/57/rooms_version_column_2.sql.sqlite +22 -0
  919. synapse/storage/schema/main/delta/57/rooms_version_column_3.sql.postgres +39 -0
  920. synapse/storage/schema/main/delta/57/rooms_version_column_3.sql.sqlite +23 -0
  921. synapse/storage/schema/main/delta/58/02remove_dup_outbound_pokes.sql +41 -0
  922. synapse/storage/schema/main/delta/58/03persist_ui_auth.sql +55 -0
  923. synapse/storage/schema/main/delta/58/05cache_instance.sql.postgres +30 -0
  924. synapse/storage/schema/main/delta/58/06dlols_unique_idx.py +83 -0
  925. synapse/storage/schema/main/delta/58/07add_method_to_thumbnail_constraint.sql.postgres +33 -0
  926. synapse/storage/schema/main/delta/58/07add_method_to_thumbnail_constraint.sql.sqlite +44 -0
  927. synapse/storage/schema/main/delta/58/07persist_ui_auth_ips.sql +44 -0
  928. synapse/storage/schema/main/delta/58/08_media_safe_from_quarantine.sql.postgres +18 -0
  929. synapse/storage/schema/main/delta/58/08_media_safe_from_quarantine.sql.sqlite +18 -0
  930. synapse/storage/schema/main/delta/58/09shadow_ban.sql +37 -0
  931. synapse/storage/schema/main/delta/58/10_pushrules_enabled_delete_obsolete.sql +47 -0
  932. synapse/storage/schema/main/delta/58/10drop_local_rejections_stream.sql +41 -0
  933. synapse/storage/schema/main/delta/58/10federation_pos_instance_name.sql +41 -0
  934. synapse/storage/schema/main/delta/58/11dehydration.sql +39 -0
  935. synapse/storage/schema/main/delta/58/11fallback.sql +43 -0
  936. synapse/storage/schema/main/delta/58/11user_id_seq.py +38 -0
  937. synapse/storage/schema/main/delta/58/12room_stats.sql +51 -0
  938. synapse/storage/schema/main/delta/58/13remove_presence_allow_inbound.sql +36 -0
  939. synapse/storage/schema/main/delta/58/14events_instance_name.sql +35 -0
  940. synapse/storage/schema/main/delta/58/14events_instance_name.sql.postgres +28 -0
  941. synapse/storage/schema/main/delta/58/15_catchup_destination_rooms.sql +61 -0
  942. synapse/storage/schema/main/delta/58/15unread_count.sql +45 -0
  943. synapse/storage/schema/main/delta/58/16populate_stats_process_rooms_fix.sql +41 -0
  944. synapse/storage/schema/main/delta/58/17_catchup_last_successful.sql +40 -0
  945. synapse/storage/schema/main/delta/58/18stream_positions.sql +41 -0
  946. synapse/storage/schema/main/delta/58/19instance_map.sql.postgres +25 -0
  947. synapse/storage/schema/main/delta/58/19txn_id.sql +59 -0
  948. synapse/storage/schema/main/delta/58/20instance_name_event_tables.sql +36 -0
  949. synapse/storage/schema/main/delta/58/20user_daily_visits.sql +37 -0
  950. synapse/storage/schema/main/delta/58/21as_device_stream.sql +36 -0
  951. synapse/storage/schema/main/delta/58/21drop_device_max_stream_id.sql +1 -0
  952. synapse/storage/schema/main/delta/58/22puppet_token.sql +36 -0
  953. synapse/storage/schema/main/delta/58/22users_have_local_media.sql +2 -0
  954. synapse/storage/schema/main/delta/58/23e2e_cross_signing_keys_idx.sql +36 -0
  955. synapse/storage/schema/main/delta/58/24drop_event_json_index.sql +38 -0
  956. synapse/storage/schema/main/delta/58/25user_external_ids_user_id_idx.sql +36 -0
  957. synapse/storage/schema/main/delta/58/26access_token_last_validated.sql +37 -0
  958. synapse/storage/schema/main/delta/58/27local_invites.sql +37 -0
  959. synapse/storage/schema/main/delta/58/28drop_last_used_column.sql.postgres +16 -0
  960. synapse/storage/schema/main/delta/58/28drop_last_used_column.sql.sqlite +62 -0
  961. synapse/storage/schema/main/delta/59/01ignored_user.py +85 -0
  962. synapse/storage/schema/main/delta/59/02shard_send_to_device.sql +37 -0
  963. synapse/storage/schema/main/delta/59/03shard_send_to_device_sequence.sql.postgres +25 -0
  964. synapse/storage/schema/main/delta/59/04_event_auth_chains.sql +71 -0
  965. synapse/storage/schema/main/delta/59/04_event_auth_chains.sql.postgres +16 -0
  966. synapse/storage/schema/main/delta/59/04drop_account_data.sql +36 -0
  967. synapse/storage/schema/main/delta/59/05cache_invalidation.sql +36 -0
  968. synapse/storage/schema/main/delta/59/06chain_cover_index.sql +36 -0
  969. synapse/storage/schema/main/delta/59/06shard_account_data.sql +39 -0
  970. synapse/storage/schema/main/delta/59/06shard_account_data.sql.postgres +32 -0
  971. synapse/storage/schema/main/delta/59/07shard_account_data_fix.sql +37 -0
  972. synapse/storage/schema/main/delta/59/08delete_pushers_for_deactivated_accounts.sql +39 -0
  973. synapse/storage/schema/main/delta/59/08delete_stale_pushers.sql +39 -0
  974. synapse/storage/schema/main/delta/59/09rejected_events_metadata.sql +45 -0
  975. synapse/storage/schema/main/delta/59/10delete_purged_chain_cover.sql +36 -0
  976. synapse/storage/schema/main/delta/59/11add_knock_members_to_stats.sql +39 -0
  977. synapse/storage/schema/main/delta/59/11drop_thumbnail_constraint.sql.postgres +22 -0
  978. synapse/storage/schema/main/delta/59/12account_validity_token_used_ts_ms.sql +37 -0
  979. synapse/storage/schema/main/delta/59/12presence_stream_instance.sql +37 -0
  980. synapse/storage/schema/main/delta/59/12presence_stream_instance_seq.sql.postgres +20 -0
  981. synapse/storage/schema/main/delta/59/13users_to_send_full_presence_to.sql +53 -0
  982. synapse/storage/schema/main/delta/59/14refresh_tokens.sql +53 -0
  983. synapse/storage/schema/main/delta/59/15locks.sql +56 -0
  984. synapse/storage/schema/main/delta/59/16federation_inbound_staging.sql +51 -0
  985. synapse/storage/schema/main/delta/60/01recreate_stream_ordering.sql.postgres +45 -0
  986. synapse/storage/schema/main/delta/60/02change_stream_ordering_columns.sql.postgres +30 -0
  987. synapse/storage/schema/main/delta/61/01change_appservices_txns.sql.postgres +23 -0
  988. synapse/storage/schema/main/delta/61/01insertion_event_lookups.sql +68 -0
  989. synapse/storage/schema/main/delta/61/02drop_redundant_room_depth_index.sql +37 -0
  990. synapse/storage/schema/main/delta/61/03recreate_min_depth.py +74 -0
  991. synapse/storage/schema/main/delta/62/01insertion_event_extremities.sql +43 -0
  992. synapse/storage/schema/main/delta/63/01create_registration_tokens.sql +42 -0
  993. synapse/storage/schema/main/delta/63/02delete_unlinked_email_pushers.sql +39 -0
  994. synapse/storage/schema/main/delta/63/02populate-rooms-creator.sql +36 -0
  995. synapse/storage/schema/main/delta/63/03session_store.sql +42 -0
  996. synapse/storage/schema/main/delta/63/04add_presence_stream_not_offline_index.sql +37 -0
  997. synapse/storage/schema/main/delta/64/01msc2716_chunk_to_batch_rename.sql.postgres +23 -0
  998. synapse/storage/schema/main/delta/64/01msc2716_chunk_to_batch_rename.sql.sqlite +37 -0
  999. synapse/storage/schema/main/delta/65/01msc2716_insertion_event_edges.sql +38 -0
  1000. synapse/storage/schema/main/delta/65/03remove_hidden_devices_from_device_inbox.sql +41 -0
  1001. synapse/storage/schema/main/delta/65/04_local_group_updates.sql +37 -0
  1002. synapse/storage/schema/main/delta/65/05_remove_room_stats_historical_and_user_stats_historical.sql +38 -0
  1003. synapse/storage/schema/main/delta/65/06remove_deleted_devices_from_device_inbox.sql +53 -0
  1004. synapse/storage/schema/main/delta/65/07_arbitrary_relations.sql +37 -0
  1005. synapse/storage/schema/main/delta/65/08_device_inbox_background_updates.sql +37 -0
  1006. synapse/storage/schema/main/delta/65/10_expirable_refresh_tokens.sql +47 -0
  1007. synapse/storage/schema/main/delta/65/11_devices_auth_provider_session.sql +46 -0
  1008. synapse/storage/schema/main/delta/67/01drop_public_room_list_stream.sql +37 -0
  1009. synapse/storage/schema/main/delta/68/01event_columns.sql +45 -0
  1010. synapse/storage/schema/main/delta/68/02_msc2409_add_device_id_appservice_stream_type.sql +40 -0
  1011. synapse/storage/schema/main/delta/68/03_delete_account_data_for_deactivated_accounts.sql +39 -0
  1012. synapse/storage/schema/main/delta/68/04_refresh_tokens_index_next_token_id.sql +47 -0
  1013. synapse/storage/schema/main/delta/68/04partial_state_rooms.sql +60 -0
  1014. synapse/storage/schema/main/delta/68/05_delete_non_strings_from_event_search.sql.sqlite +22 -0
  1015. synapse/storage/schema/main/delta/68/05partial_state_rooms_triggers.py +80 -0
  1016. synapse/storage/schema/main/delta/68/06_msc3202_add_device_list_appservice_stream_type.sql +42 -0
  1017. synapse/storage/schema/main/delta/69/01as_txn_seq.py +54 -0
  1018. synapse/storage/schema/main/delta/69/01device_list_oubound_by_room.sql +57 -0
  1019. synapse/storage/schema/main/delta/69/02cache_invalidation_index.sql +37 -0
  1020. synapse/storage/schema/main/delta/70/01clean_table_purged_rooms.sql +39 -0
  1021. synapse/storage/schema/main/delta/71/01rebuild_event_edges.sql.postgres +43 -0
  1022. synapse/storage/schema/main/delta/71/01rebuild_event_edges.sql.sqlite +47 -0
  1023. synapse/storage/schema/main/delta/71/01remove_noop_background_updates.sql +80 -0
  1024. synapse/storage/schema/main/delta/71/02event_push_summary_unique.sql +37 -0
  1025. synapse/storage/schema/main/delta/72/01add_room_type_to_state_stats.sql +38 -0
  1026. synapse/storage/schema/main/delta/72/01event_push_summary_receipt.sql +54 -0
  1027. synapse/storage/schema/main/delta/72/02event_push_actions_index.sql +38 -0
  1028. synapse/storage/schema/main/delta/72/03bg_populate_events_columns.py +57 -0
  1029. synapse/storage/schema/main/delta/72/03drop_event_reference_hashes.sql +36 -0
  1030. synapse/storage/schema/main/delta/72/03remove_groups.sql +50 -0
  1031. synapse/storage/schema/main/delta/72/04drop_column_application_services_state_last_txn.sql.postgres +17 -0
  1032. synapse/storage/schema/main/delta/72/04drop_column_application_services_state_last_txn.sql.sqlite +40 -0
  1033. synapse/storage/schema/main/delta/72/05receipts_event_stream_ordering.sql +38 -0
  1034. synapse/storage/schema/main/delta/72/05remove_unstable_private_read_receipts.sql +38 -0
  1035. synapse/storage/schema/main/delta/72/06add_consent_ts_to_users.sql +35 -0
  1036. synapse/storage/schema/main/delta/72/06thread_notifications.sql +49 -0
  1037. synapse/storage/schema/main/delta/72/07force_update_current_state_events_membership.py +67 -0
  1038. synapse/storage/schema/main/delta/72/07thread_receipts.sql.postgres +30 -0
  1039. synapse/storage/schema/main/delta/72/07thread_receipts.sql.sqlite +70 -0
  1040. synapse/storage/schema/main/delta/72/08begin_cache_invalidation_seq_at_2.sql.postgres +23 -0
  1041. synapse/storage/schema/main/delta/72/08thread_receipts.sql +39 -0
  1042. synapse/storage/schema/main/delta/72/09partial_indices.sql.sqlite +56 -0
  1043. synapse/storage/schema/main/delta/73/01event_failed_pull_attempts.sql +48 -0
  1044. synapse/storage/schema/main/delta/73/02add_pusher_enabled.sql +35 -0
  1045. synapse/storage/schema/main/delta/73/02room_id_indexes_for_purging.sql +41 -0
  1046. synapse/storage/schema/main/delta/73/03pusher_device_id.sql +39 -0
  1047. synapse/storage/schema/main/delta/73/03users_approved_column.sql +39 -0
  1048. synapse/storage/schema/main/delta/73/04partial_join_details.sql +42 -0
  1049. synapse/storage/schema/main/delta/73/04pending_device_list_updates.sql +47 -0
  1050. synapse/storage/schema/main/delta/73/05old_push_actions.sql.postgres +22 -0
  1051. synapse/storage/schema/main/delta/73/05old_push_actions.sql.sqlite +24 -0
  1052. synapse/storage/schema/main/delta/73/06thread_notifications_thread_id_idx.sql +42 -0
  1053. synapse/storage/schema/main/delta/73/08thread_receipts_non_null.sql.postgres +23 -0
  1054. synapse/storage/schema/main/delta/73/08thread_receipts_non_null.sql.sqlite +76 -0
  1055. synapse/storage/schema/main/delta/73/09partial_joined_via_destination.sql +37 -0
  1056. synapse/storage/schema/main/delta/73/09threads_table.sql +49 -0
  1057. synapse/storage/schema/main/delta/73/10_update_sqlite_fts4_tokenizer.py +71 -0
  1058. synapse/storage/schema/main/delta/73/10login_tokens.sql +54 -0
  1059. synapse/storage/schema/main/delta/73/11event_search_room_id_n_distinct.sql.postgres +33 -0
  1060. synapse/storage/schema/main/delta/73/12refactor_device_list_outbound_pokes.sql +72 -0
  1061. synapse/storage/schema/main/delta/73/13add_device_lists_index.sql +39 -0
  1062. synapse/storage/schema/main/delta/73/20_un_partial_stated_room_stream.sql +51 -0
  1063. synapse/storage/schema/main/delta/73/21_un_partial_stated_room_stream_seq.sql.postgres +20 -0
  1064. synapse/storage/schema/main/delta/73/22_rebuild_user_dir_stats.sql +48 -0
  1065. synapse/storage/schema/main/delta/73/22_un_partial_stated_event_stream.sql +53 -0
  1066. synapse/storage/schema/main/delta/73/23_fix_thread_index.sql +52 -0
  1067. synapse/storage/schema/main/delta/73/23_un_partial_stated_room_stream_seq.sql.postgres +20 -0
  1068. synapse/storage/schema/main/delta/73/24_events_jump_to_date_index.sql +36 -0
  1069. synapse/storage/schema/main/delta/73/25drop_presence.sql +36 -0
  1070. synapse/storage/schema/main/delta/74/01_user_directory_stale_remote_users.sql +58 -0
  1071. synapse/storage/schema/main/delta/74/02_set_device_id_for_pushers_bg_update.sql +38 -0
  1072. synapse/storage/schema/main/delta/74/03_membership_tables_event_stream_ordering.sql.postgres +29 -0
  1073. synapse/storage/schema/main/delta/74/03_membership_tables_event_stream_ordering.sql.sqlite +23 -0
  1074. synapse/storage/schema/main/delta/74/03_room_membership_index.sql +38 -0
  1075. synapse/storage/schema/main/delta/74/04_delete_e2e_backup_keys_for_deactivated_users.sql +36 -0
  1076. synapse/storage/schema/main/delta/74/04_membership_tables_event_stream_ordering_triggers.py +87 -0
  1077. synapse/storage/schema/main/delta/74/05_events_txn_id_device_id.sql +72 -0
  1078. synapse/storage/schema/main/delta/74/90COMMENTS_destinations.sql.postgres +52 -0
  1079. synapse/storage/schema/main/delta/76/01_add_profiles_full_user_id_column.sql +39 -0
  1080. synapse/storage/schema/main/delta/76/02_add_user_filters_full_user_id_column.sql +39 -0
  1081. synapse/storage/schema/main/delta/76/03_per_user_experimental_features.sql +46 -0
  1082. synapse/storage/schema/main/delta/76/04_add_room_forgetter.sql +43 -0
  1083. synapse/storage/schema/main/delta/77/01_add_profiles_not_valid_check.sql.postgres +16 -0
  1084. synapse/storage/schema/main/delta/77/02_add_user_filters_not_valid_check.sql.postgres +16 -0
  1085. synapse/storage/schema/main/delta/77/03bg_populate_full_user_id_profiles.sql +35 -0
  1086. synapse/storage/schema/main/delta/77/04bg_populate_full_user_id_user_filters.sql +35 -0
  1087. synapse/storage/schema/main/delta/77/05thread_notifications_backfill.sql +67 -0
  1088. synapse/storage/schema/main/delta/77/06thread_notifications_not_null.sql.sqlite +102 -0
  1089. synapse/storage/schema/main/delta/77/06thread_notifications_not_null_event_push_actions.sql.postgres +27 -0
  1090. synapse/storage/schema/main/delta/77/06thread_notifications_not_null_event_push_actions_staging.sql.postgres +27 -0
  1091. synapse/storage/schema/main/delta/77/06thread_notifications_not_null_event_push_summary.sql.postgres +29 -0
  1092. synapse/storage/schema/main/delta/77/14bg_indices_event_stream_ordering.sql +39 -0
  1093. synapse/storage/schema/main/delta/78/01_validate_and_update_profiles.py +99 -0
  1094. synapse/storage/schema/main/delta/78/02_validate_and_update_user_filters.py +100 -0
  1095. synapse/storage/schema/main/delta/78/03_remove_unused_indexes_user_filters.py +72 -0
  1096. synapse/storage/schema/main/delta/78/03event_extremities_constraints.py +65 -0
  1097. synapse/storage/schema/main/delta/78/04_add_full_user_id_index_user_filters.py +32 -0
  1098. synapse/storage/schema/main/delta/79/03_read_write_locks_triggers.sql.postgres +102 -0
  1099. synapse/storage/schema/main/delta/79/03_read_write_locks_triggers.sql.sqlite +72 -0
  1100. synapse/storage/schema/main/delta/79/04_mitigate_stream_ordering_update_race.py +70 -0
  1101. synapse/storage/schema/main/delta/79/05_read_write_locks_triggers.sql.postgres +69 -0
  1102. synapse/storage/schema/main/delta/79/05_read_write_locks_triggers.sql.sqlite +65 -0
  1103. synapse/storage/schema/main/delta/80/01_users_alter_locked.sql +35 -0
  1104. synapse/storage/schema/main/delta/80/02_read_write_locks_unlogged.sql.postgres +30 -0
  1105. synapse/storage/schema/main/delta/80/02_scheduled_tasks.sql +47 -0
  1106. synapse/storage/schema/main/delta/80/03_read_write_locks_triggers.sql.postgres +37 -0
  1107. synapse/storage/schema/main/delta/80/04_read_write_locks_deadlock.sql.postgres +71 -0
  1108. synapse/storage/schema/main/delta/82/02_scheduled_tasks_index.sql +35 -0
  1109. synapse/storage/schema/main/delta/82/04_add_indices_for_purging_rooms.sql +39 -0
  1110. synapse/storage/schema/main/delta/82/05gaps.sql +44 -0
  1111. synapse/storage/schema/main/delta/83/01_drop_old_tables.sql +43 -0
  1112. synapse/storage/schema/main/delta/83/03_instance_name_receipts.sql.sqlite +17 -0
  1113. synapse/storage/schema/main/delta/83/05_cross_signing_key_update_grant.sql +34 -0
  1114. synapse/storage/schema/main/delta/83/06_event_push_summary_room.sql +36 -0
  1115. synapse/storage/schema/main/delta/84/01_auth_links_stats.sql.postgres +20 -0
  1116. synapse/storage/schema/main/delta/84/02_auth_links_index.sql +16 -0
  1117. synapse/storage/schema/main/delta/84/03_auth_links_analyze.sql.postgres +16 -0
  1118. synapse/storage/schema/main/delta/84/04_access_token_index.sql +15 -0
  1119. synapse/storage/schema/main/delta/85/01_add_suspended.sql +14 -0
  1120. synapse/storage/schema/main/delta/85/02_add_instance_names.sql +27 -0
  1121. synapse/storage/schema/main/delta/85/03_new_sequences.sql.postgres +54 -0
  1122. synapse/storage/schema/main/delta/85/04_cleanup_device_federation_outbox.sql +15 -0
  1123. synapse/storage/schema/main/delta/85/05_add_instance_names_converted_pos.sql +16 -0
  1124. synapse/storage/schema/main/delta/85/06_add_room_reports.sql +20 -0
  1125. synapse/storage/schema/main/delta/86/01_authenticate_media.sql +15 -0
  1126. synapse/storage/schema/main/delta/86/02_receipts_event_id_index.sql +15 -0
  1127. synapse/storage/schema/main/delta/87/01_sliding_sync_memberships.sql +169 -0
  1128. synapse/storage/schema/main/delta/87/02_per_connection_state.sql +81 -0
  1129. synapse/storage/schema/main/delta/87/03_current_state_index.sql +19 -0
  1130. synapse/storage/schema/main/delta/88/01_add_delayed_events.sql +43 -0
  1131. synapse/storage/schema/main/delta/88/01_custom_profile_fields.sql +15 -0
  1132. synapse/storage/schema/main/delta/88/02_fix_sliding_sync_membership_snapshots_forgotten_column.sql +21 -0
  1133. synapse/storage/schema/main/delta/88/03_add_otk_ts_added_index.sql +18 -0
  1134. synapse/storage/schema/main/delta/88/04_current_state_delta_index.sql +18 -0
  1135. synapse/storage/schema/main/delta/88/05_drop_old_otks.sql.postgres +19 -0
  1136. synapse/storage/schema/main/delta/88/05_drop_old_otks.sql.sqlite +19 -0
  1137. synapse/storage/schema/main/delta/88/05_sliding_sync_room_config_index.sql +20 -0
  1138. synapse/storage/schema/main/delta/88/06_events_received_ts_index.sql +17 -0
  1139. synapse/storage/schema/main/delta/89/01_sliding_sync_membership_snapshot_index.sql +15 -0
  1140. synapse/storage/schema/main/delta/90/01_add_column_participant_room_memberships_table.sql +16 -0
  1141. synapse/storage/schema/main/delta/91/01_media_hash.sql +28 -0
  1142. synapse/storage/schema/main/delta/92/01_remove_trigger.sql.postgres +16 -0
  1143. synapse/storage/schema/main/delta/92/01_remove_trigger.sql.sqlite +16 -0
  1144. synapse/storage/schema/main/delta/92/02_remove_populate_participant_bg_update.sql +17 -0
  1145. synapse/storage/schema/main/delta/92/04_ss_membership_snapshot_idx.sql +16 -0
  1146. synapse/storage/schema/main/delta/92/04_thread_subscriptions.sql +59 -0
  1147. synapse/storage/schema/main/delta/92/04_thread_subscriptions_seq.sql.postgres +19 -0
  1148. synapse/storage/schema/main/delta/92/05_fixup_max_depth_cap.sql +17 -0
  1149. synapse/storage/schema/main/delta/92/05_thread_subscriptions_comments.sql.postgres +18 -0
  1150. synapse/storage/schema/main/delta/92/06_device_federation_inbox_index.sql +16 -0
  1151. synapse/storage/schema/main/delta/92/06_threads_last_sent_stream_ordering_comments.sql.postgres +24 -0
  1152. synapse/storage/schema/main/delta/92/07_add_user_reports.sql +22 -0
  1153. synapse/storage/schema/main/delta/92/07_event_txn_id_device_id_txn_id2.sql +15 -0
  1154. synapse/storage/schema/main/delta/92/08_room_ban_redactions.sql +21 -0
  1155. synapse/storage/schema/main/delta/92/08_thread_subscriptions_seq_fixup.sql.postgres +19 -0
  1156. synapse/storage/schema/main/delta/92/09_thread_subscriptions_update.sql +20 -0
  1157. synapse/storage/schema/main/delta/92/09_thread_subscriptions_update.sql.postgres +18 -0
  1158. synapse/storage/schema/main/delta/93/01_add_delayed_events.sql +15 -0
  1159. synapse/storage/schema/main/delta/93/02_sliding_sync_members.sql +60 -0
  1160. synapse/storage/schema/main/delta/93/03_sss_pos_last_used.sql +27 -0
  1161. synapse/storage/schema/main/full_schemas/72/full.sql.postgres +1344 -0
  1162. synapse/storage/schema/main/full_schemas/72/full.sql.sqlite +646 -0
  1163. synapse/storage/schema/state/delta/23/drop_state_index.sql +35 -0
  1164. synapse/storage/schema/state/delta/32/remove_state_indices.sql +38 -0
  1165. synapse/storage/schema/state/delta/35/add_state_index.sql +36 -0
  1166. synapse/storage/schema/state/delta/35/state.sql +41 -0
  1167. synapse/storage/schema/state/delta/35/state_dedupe.sql +36 -0
  1168. synapse/storage/schema/state/delta/47/state_group_seq.py +38 -0
  1169. synapse/storage/schema/state/delta/56/state_group_room_idx.sql +36 -0
  1170. synapse/storage/schema/state/delta/61/02state_groups_state_n_distinct.sql.postgres +34 -0
  1171. synapse/storage/schema/state/delta/70/08_state_group_edges_unique.sql +36 -0
  1172. synapse/storage/schema/state/delta/89/01_state_groups_deletion.sql +39 -0
  1173. synapse/storage/schema/state/delta/90/02_delete_unreferenced_state_groups.sql +16 -0
  1174. synapse/storage/schema/state/delta/90/03_remove_old_deletion_bg_update.sql +15 -0
  1175. synapse/storage/schema/state/full_schemas/72/full.sql.postgres +30 -0
  1176. synapse/storage/schema/state/full_schemas/72/full.sql.sqlite +20 -0
  1177. synapse/storage/types.py +183 -0
  1178. synapse/storage/util/__init__.py +20 -0
  1179. synapse/storage/util/id_generators.py +928 -0
  1180. synapse/storage/util/partial_state_events_tracker.py +194 -0
  1181. synapse/storage/util/sequence.py +315 -0
  1182. synapse/streams/__init__.py +43 -0
  1183. synapse/streams/config.py +91 -0
  1184. synapse/streams/events.py +203 -0
  1185. synapse/synapse_rust/__init__.pyi +3 -0
  1186. synapse/synapse_rust/acl.pyi +20 -0
  1187. synapse/synapse_rust/events.pyi +136 -0
  1188. synapse/synapse_rust/http_client.pyi +32 -0
  1189. synapse/synapse_rust/push.pyi +86 -0
  1190. synapse/synapse_rust/rendezvous.pyi +30 -0
  1191. synapse/synapse_rust/segmenter.pyi +1 -0
  1192. synapse/synapse_rust.abi3.so +0 -0
  1193. synapse/types/__init__.py +1600 -0
  1194. synapse/types/handlers/__init__.py +93 -0
  1195. synapse/types/handlers/policy_server.py +16 -0
  1196. synapse/types/handlers/sliding_sync.py +1004 -0
  1197. synapse/types/rest/__init__.py +25 -0
  1198. synapse/types/rest/client/__init__.py +413 -0
  1199. synapse/types/state.py +634 -0
  1200. synapse/types/storage/__init__.py +66 -0
  1201. synapse/util/__init__.py +160 -0
  1202. synapse/util/async_helpers.py +1048 -0
  1203. synapse/util/background_queue.py +142 -0
  1204. synapse/util/batching_queue.py +203 -0
  1205. synapse/util/caches/__init__.py +300 -0
  1206. synapse/util/caches/cached_call.py +143 -0
  1207. synapse/util/caches/deferred_cache.py +530 -0
  1208. synapse/util/caches/descriptors.py +692 -0
  1209. synapse/util/caches/dictionary_cache.py +346 -0
  1210. synapse/util/caches/expiringcache.py +250 -0
  1211. synapse/util/caches/lrucache.py +976 -0
  1212. synapse/util/caches/response_cache.py +323 -0
  1213. synapse/util/caches/stream_change_cache.py +370 -0
  1214. synapse/util/caches/treecache.py +189 -0
  1215. synapse/util/caches/ttlcache.py +197 -0
  1216. synapse/util/cancellation.py +63 -0
  1217. synapse/util/check_dependencies.py +335 -0
  1218. synapse/util/clock.py +592 -0
  1219. synapse/util/daemonize.py +165 -0
  1220. synapse/util/distributor.py +157 -0
  1221. synapse/util/duration.py +117 -0
  1222. synapse/util/events.py +134 -0
  1223. synapse/util/file_consumer.py +164 -0
  1224. synapse/util/frozenutils.py +57 -0
  1225. synapse/util/gai_resolver.py +178 -0
  1226. synapse/util/hash.py +38 -0
  1227. synapse/util/httpresourcetree.py +108 -0
  1228. synapse/util/iterutils.py +190 -0
  1229. synapse/util/json.py +56 -0
  1230. synapse/util/linked_list.py +156 -0
  1231. synapse/util/logcontext.py +46 -0
  1232. synapse/util/logformatter.py +28 -0
  1233. synapse/util/macaroons.py +325 -0
  1234. synapse/util/manhole.py +191 -0
  1235. synapse/util/metrics.py +339 -0
  1236. synapse/util/module_loader.py +116 -0
  1237. synapse/util/msisdn.py +51 -0
  1238. synapse/util/patch_inline_callbacks.py +250 -0
  1239. synapse/util/pydantic_models.py +63 -0
  1240. synapse/util/ratelimitutils.py +422 -0
  1241. synapse/util/retryutils.py +339 -0
  1242. synapse/util/rlimit.py +42 -0
  1243. synapse/util/rust.py +164 -0
  1244. synapse/util/sentinel.py +21 -0
  1245. synapse/util/stringutils.py +293 -0
  1246. synapse/util/task_scheduler.py +494 -0
  1247. synapse/util/templates.py +126 -0
  1248. synapse/util/threepids.py +123 -0
  1249. synapse/util/wheel_timer.py +112 -0
  1250. synapse/visibility.py +869 -0
  1251. synmark/__init__.py +47 -0
  1252. synmark/__main__.py +128 -0
  1253. synmark/suites/__init__.py +9 -0
  1254. synmark/suites/logging.py +154 -0
  1255. synmark/suites/lrucache.py +48 -0
  1256. synmark/suites/lrucache_evict.py +49 -0
  1257. sytest-blacklist +33 -0
  1258. tests/__init__.py +29 -0
  1259. tests/api/__init__.py +0 -0
  1260. tests/api/test_auth.py +548 -0
  1261. tests/api/test_errors.py +46 -0
  1262. tests/api/test_filtering.py +622 -0
  1263. tests/api/test_ratelimiting.py +505 -0
  1264. tests/api/test_urls.py +81 -0
  1265. tests/app/__init__.py +0 -0
  1266. tests/app/test_homeserver_shutdown.py +271 -0
  1267. tests/app/test_homeserver_start.py +49 -0
  1268. tests/app/test_openid_listener.py +139 -0
  1269. tests/app/test_phone_stats_home.py +248 -0
  1270. tests/appservice/__init__.py +20 -0
  1271. tests/appservice/test_api.py +253 -0
  1272. tests/appservice/test_appservice.py +259 -0
  1273. tests/appservice/test_scheduler.py +477 -0
  1274. tests/config/__init__.py +20 -0
  1275. tests/config/test___main__.py +38 -0
  1276. tests/config/test_api.py +146 -0
  1277. tests/config/test_appservice.py +48 -0
  1278. tests/config/test_background_update.py +65 -0
  1279. tests/config/test_base.py +151 -0
  1280. tests/config/test_cache.py +193 -0
  1281. tests/config/test_database.py +42 -0
  1282. tests/config/test_generate.py +72 -0
  1283. tests/config/test_load.py +322 -0
  1284. tests/config/test_oauth_delegation.py +454 -0
  1285. tests/config/test_ratelimiting.py +77 -0
  1286. tests/config/test_registration_config.py +203 -0
  1287. tests/config/test_room_directory.py +203 -0
  1288. tests/config/test_server.py +248 -0
  1289. tests/config/test_tls.py +209 -0
  1290. tests/config/test_util.py +59 -0
  1291. tests/config/test_workers.py +332 -0
  1292. tests/config/utils.py +66 -0
  1293. tests/crypto/__init__.py +20 -0
  1294. tests/crypto/test_event_signing.py +109 -0
  1295. tests/crypto/test_keyring.py +737 -0
  1296. tests/events/__init__.py +0 -0
  1297. tests/events/test_auto_accept_invites.py +827 -0
  1298. tests/events/test_presence_router.py +540 -0
  1299. tests/events/test_snapshot.py +121 -0
  1300. tests/events/test_utils.py +986 -0
  1301. tests/federation/__init__.py +0 -0
  1302. tests/federation/test_complexity.py +257 -0
  1303. tests/federation/test_federation_catch_up.py +585 -0
  1304. tests/federation/test_federation_client.py +316 -0
  1305. tests/federation/test_federation_devices.py +161 -0
  1306. tests/federation/test_federation_media.py +295 -0
  1307. tests/federation/test_federation_out_of_band_membership.py +671 -0
  1308. tests/federation/test_federation_sender.py +956 -0
  1309. tests/federation/test_federation_server.py +631 -0
  1310. tests/federation/transport/__init__.py +0 -0
  1311. tests/federation/transport/server/__init__.py +20 -0
  1312. tests/federation/transport/server/test__base.py +156 -0
  1313. tests/federation/transport/test_client.py +157 -0
  1314. tests/federation/transport/test_knocking.py +323 -0
  1315. tests/federation/transport/test_server.py +74 -0
  1316. tests/handlers/__init__.py +0 -0
  1317. tests/handlers/oidc_test_key.p8 +5 -0
  1318. tests/handlers/oidc_test_key.pub.pem +4 -0
  1319. tests/handlers/test_admin.py +361 -0
  1320. tests/handlers/test_appservice.py +1336 -0
  1321. tests/handlers/test_auth.py +248 -0
  1322. tests/handlers/test_cas.py +239 -0
  1323. tests/handlers/test_deactivate_account.py +485 -0
  1324. tests/handlers/test_device.py +665 -0
  1325. tests/handlers/test_directory.py +613 -0
  1326. tests/handlers/test_e2e_keys.py +2025 -0
  1327. tests/handlers/test_e2e_room_keys.py +569 -0
  1328. tests/handlers/test_federation.py +794 -0
  1329. tests/handlers/test_federation_event.py +1181 -0
  1330. tests/handlers/test_message.py +322 -0
  1331. tests/handlers/test_oauth_delegation.py +1314 -0
  1332. tests/handlers/test_oidc.py +1688 -0
  1333. tests/handlers/test_password_providers.py +987 -0
  1334. tests/handlers/test_presence.py +2144 -0
  1335. tests/handlers/test_profile.py +401 -0
  1336. tests/handlers/test_receipts.py +342 -0
  1337. tests/handlers/test_register.py +880 -0
  1338. tests/handlers/test_room.py +108 -0
  1339. tests/handlers/test_room_list.py +93 -0
  1340. tests/handlers/test_room_member.py +764 -0
  1341. tests/handlers/test_room_policy.py +468 -0
  1342. tests/handlers/test_room_summary.py +1248 -0
  1343. tests/handlers/test_saml.py +427 -0
  1344. tests/handlers/test_send_email.py +230 -0
  1345. tests/handlers/test_sliding_sync.py +5065 -0
  1346. tests/handlers/test_sso.py +152 -0
  1347. tests/handlers/test_stats.py +594 -0
  1348. tests/handlers/test_sync.py +1275 -0
  1349. tests/handlers/test_typing.py +557 -0
  1350. tests/handlers/test_user_directory.py +1435 -0
  1351. tests/handlers/test_worker_lock.py +126 -0
  1352. tests/http/__init__.py +196 -0
  1353. tests/http/ca.crt +19 -0
  1354. tests/http/ca.key +27 -0
  1355. tests/http/federation/__init__.py +19 -0
  1356. tests/http/federation/test_matrix_federation_agent.py +1855 -0
  1357. tests/http/federation/test_srv_resolver.py +220 -0
  1358. tests/http/server/__init__.py +20 -0
  1359. tests/http/server/_base.py +621 -0
  1360. tests/http/server.key +27 -0
  1361. tests/http/test_additional_resource.py +76 -0
  1362. tests/http/test_client.py +422 -0
  1363. tests/http/test_endpoint.py +62 -0
  1364. tests/http/test_matrixfederationclient.py +1092 -0
  1365. tests/http/test_proxy.py +75 -0
  1366. tests/http/test_proxyagent.py +1008 -0
  1367. tests/http/test_servlet.py +145 -0
  1368. tests/http/test_simple_client.py +188 -0
  1369. tests/http/test_site.py +247 -0
  1370. tests/logging/__init__.py +42 -0
  1371. tests/logging/test_loggers.py +127 -0
  1372. tests/logging/test_opentracing.py +524 -0
  1373. tests/logging/test_remote_handler.py +184 -0
  1374. tests/logging/test_terse_json.py +253 -0
  1375. tests/media/__init__.py +20 -0
  1376. tests/media/test_base.py +88 -0
  1377. tests/media/test_filepath.py +602 -0
  1378. tests/media/test_html_preview.py +565 -0
  1379. tests/media/test_media_retention.py +299 -0
  1380. tests/media/test_media_storage.py +1401 -0
  1381. tests/media/test_oembed.py +172 -0
  1382. tests/media/test_url_previewer.py +120 -0
  1383. tests/metrics/__init__.py +0 -0
  1384. tests/metrics/test_background_process_metrics.py +21 -0
  1385. tests/metrics/test_metrics.py +407 -0
  1386. tests/metrics/test_phone_home_stats.py +263 -0
  1387. tests/module_api/__init__.py +0 -0
  1388. tests/module_api/test_account_data_manager.py +171 -0
  1389. tests/module_api/test_api.py +1035 -0
  1390. tests/module_api/test_event_unsigned_addition.py +66 -0
  1391. tests/module_api/test_spamchecker.py +286 -0
  1392. tests/push/__init__.py +0 -0
  1393. tests/push/test_bulk_push_rule_evaluator.py +652 -0
  1394. tests/push/test_email.py +570 -0
  1395. tests/push/test_http.py +1247 -0
  1396. tests/push/test_presentable_names.py +238 -0
  1397. tests/push/test_push_rule_evaluator.py +1069 -0
  1398. tests/replication/__init__.py +20 -0
  1399. tests/replication/_base.py +619 -0
  1400. tests/replication/http/__init__.py +20 -0
  1401. tests/replication/http/test__base.py +113 -0
  1402. tests/replication/storage/__init__.py +20 -0
  1403. tests/replication/storage/_base.py +85 -0
  1404. tests/replication/storage/test_events.py +299 -0
  1405. tests/replication/tcp/__init__.py +19 -0
  1406. tests/replication/tcp/streams/__init__.py +19 -0
  1407. tests/replication/tcp/streams/test_account_data.py +133 -0
  1408. tests/replication/tcp/streams/test_events.py +565 -0
  1409. tests/replication/tcp/streams/test_federation.py +117 -0
  1410. tests/replication/tcp/streams/test_partial_state.py +72 -0
  1411. tests/replication/tcp/streams/test_receipts.py +110 -0
  1412. tests/replication/tcp/streams/test_thread_subscriptions.py +157 -0
  1413. tests/replication/tcp/streams/test_to_device.py +112 -0
  1414. tests/replication/tcp/streams/test_typing.py +223 -0
  1415. tests/replication/tcp/test_commands.py +50 -0
  1416. tests/replication/tcp/test_handler.py +211 -0
  1417. tests/replication/test_auth.py +120 -0
  1418. tests/replication/test_client_reader_shard.py +101 -0
  1419. tests/replication/test_federation_ack.py +88 -0
  1420. tests/replication/test_federation_sender_shard.py +352 -0
  1421. tests/replication/test_module_cache_invalidation.py +89 -0
  1422. tests/replication/test_multi_media_repo.py +496 -0
  1423. tests/replication/test_pusher_shard.py +192 -0
  1424. tests/replication/test_sharded_event_persister.py +332 -0
  1425. tests/replication/test_sharded_receipts.py +250 -0
  1426. tests/rest/__init__.py +20 -0
  1427. tests/rest/admin/__init__.py +19 -0
  1428. tests/rest/admin/test_admin.py +614 -0
  1429. tests/rest/admin/test_background_updates.py +375 -0
  1430. tests/rest/admin/test_device.py +600 -0
  1431. tests/rest/admin/test_event.py +74 -0
  1432. tests/rest/admin/test_event_reports.py +781 -0
  1433. tests/rest/admin/test_federation.py +863 -0
  1434. tests/rest/admin/test_jwks.py +106 -0
  1435. tests/rest/admin/test_media.py +1091 -0
  1436. tests/rest/admin/test_registration_tokens.py +729 -0
  1437. tests/rest/admin/test_room.py +3626 -0
  1438. tests/rest/admin/test_scheduled_tasks.py +192 -0
  1439. tests/rest/admin/test_server_notice.py +753 -0
  1440. tests/rest/admin/test_statistics.py +523 -0
  1441. tests/rest/admin/test_user.py +6061 -0
  1442. tests/rest/admin/test_username_available.py +82 -0
  1443. tests/rest/client/__init__.py +20 -0
  1444. tests/rest/client/sliding_sync/__init__.py +13 -0
  1445. tests/rest/client/sliding_sync/test_connection_tracking.py +505 -0
  1446. tests/rest/client/sliding_sync/test_extension_account_data.py +1056 -0
  1447. tests/rest/client/sliding_sync/test_extension_e2ee.py +459 -0
  1448. tests/rest/client/sliding_sync/test_extension_receipts.py +934 -0
  1449. tests/rest/client/sliding_sync/test_extension_thread_subscriptions.py +497 -0
  1450. tests/rest/client/sliding_sync/test_extension_to_device.py +294 -0
  1451. tests/rest/client/sliding_sync/test_extension_typing.py +500 -0
  1452. tests/rest/client/sliding_sync/test_extensions.py +306 -0
  1453. tests/rest/client/sliding_sync/test_lists_filters.py +1975 -0
  1454. tests/rest/client/sliding_sync/test_room_subscriptions.py +303 -0
  1455. tests/rest/client/sliding_sync/test_rooms_invites.py +528 -0
  1456. tests/rest/client/sliding_sync/test_rooms_meta.py +1338 -0
  1457. tests/rest/client/sliding_sync/test_rooms_required_state.py +2247 -0
  1458. tests/rest/client/sliding_sync/test_rooms_timeline.py +718 -0
  1459. tests/rest/client/sliding_sync/test_sliding_sync.py +1688 -0
  1460. tests/rest/client/test_account.py +1543 -0
  1461. tests/rest/client/test_account_data.py +81 -0
  1462. tests/rest/client/test_auth.py +1508 -0
  1463. tests/rest/client/test_auth_metadata.py +145 -0
  1464. tests/rest/client/test_capabilities.py +318 -0
  1465. tests/rest/client/test_consent.py +138 -0
  1466. tests/rest/client/test_delayed_events.py +553 -0
  1467. tests/rest/client/test_devices.py +634 -0
  1468. tests/rest/client/test_directory.py +249 -0
  1469. tests/rest/client/test_ephemeral_message.py +113 -0
  1470. tests/rest/client/test_events.py +165 -0
  1471. tests/rest/client/test_filter.py +124 -0
  1472. tests/rest/client/test_identity.py +67 -0
  1473. tests/rest/client/test_keys.py +516 -0
  1474. tests/rest/client/test_login.py +1881 -0
  1475. tests/rest/client/test_login_token_request.py +175 -0
  1476. tests/rest/client/test_matrixrtc.py +105 -0
  1477. tests/rest/client/test_media.py +3156 -0
  1478. tests/rest/client/test_models.py +83 -0
  1479. tests/rest/client/test_mutual_rooms.py +235 -0
  1480. tests/rest/client/test_notifications.py +231 -0
  1481. tests/rest/client/test_owned_state.py +308 -0
  1482. tests/rest/client/test_password_policy.py +186 -0
  1483. tests/rest/client/test_power_levels.py +295 -0
  1484. tests/rest/client/test_presence.py +149 -0
  1485. tests/rest/client/test_profile.py +925 -0
  1486. tests/rest/client/test_push_rule_attrs.py +510 -0
  1487. tests/rest/client/test_read_marker.py +151 -0
  1488. tests/rest/client/test_receipts.py +287 -0
  1489. tests/rest/client/test_redactions.py +657 -0
  1490. tests/rest/client/test_register.py +1314 -0
  1491. tests/rest/client/test_relations.py +1954 -0
  1492. tests/rest/client/test_rendezvous.py +468 -0
  1493. tests/rest/client/test_reporting.py +324 -0
  1494. tests/rest/client/test_retention.py +389 -0
  1495. tests/rest/client/test_rooms.py +5486 -0
  1496. tests/rest/client/test_sendtodevice.py +271 -0
  1497. tests/rest/client/test_shadow_banned.py +335 -0
  1498. tests/rest/client/test_sync.py +1147 -0
  1499. tests/rest/client/test_tags.py +161 -0
  1500. tests/rest/client/test_third_party_rules.py +1076 -0
  1501. tests/rest/client/test_thread_subscriptions.py +351 -0
  1502. tests/rest/client/test_transactions.py +204 -0
  1503. tests/rest/client/test_typing.py +114 -0
  1504. tests/rest/client/test_upgrade_room.py +433 -0
  1505. tests/rest/client/utils.py +985 -0
  1506. tests/rest/key/__init__.py +0 -0
  1507. tests/rest/key/v2/__init__.py +0 -0
  1508. tests/rest/key/v2/test_remote_key_resource.py +282 -0
  1509. tests/rest/media/__init__.py +19 -0
  1510. tests/rest/media/test_domain_blocking.py +148 -0
  1511. tests/rest/media/test_url_preview.py +1445 -0
  1512. tests/rest/synapse/__init__.py +12 -0
  1513. tests/rest/synapse/client/__init__.py +12 -0
  1514. tests/rest/synapse/client/test_federation_whitelist.py +118 -0
  1515. tests/rest/synapse/mas/__init__.py +12 -0
  1516. tests/rest/synapse/mas/_base.py +43 -0
  1517. tests/rest/synapse/mas/test_devices.py +693 -0
  1518. tests/rest/synapse/mas/test_users.py +1399 -0
  1519. tests/rest/test_health.py +35 -0
  1520. tests/rest/test_well_known.py +155 -0
  1521. tests/scripts/__init__.py +0 -0
  1522. tests/scripts/test_new_matrix_user.py +172 -0
  1523. tests/server.py +1374 -0
  1524. tests/server_notices/__init__.py +241 -0
  1525. tests/server_notices/test_consent.py +111 -0
  1526. tests/server_notices/test_resource_limits_server_notices.py +409 -0
  1527. tests/state/__init__.py +0 -0
  1528. tests/state/test_v2.py +1096 -0
  1529. tests/state/test_v21.py +506 -0
  1530. tests/storage/__init__.py +0 -0
  1531. tests/storage/databases/__init__.py +20 -0
  1532. tests/storage/databases/main/__init__.py +20 -0
  1533. tests/storage/databases/main/test_cache.py +124 -0
  1534. tests/storage/databases/main/test_deviceinbox.py +323 -0
  1535. tests/storage/databases/main/test_end_to_end_keys.py +127 -0
  1536. tests/storage/databases/main/test_events_worker.py +594 -0
  1537. tests/storage/databases/main/test_lock.py +499 -0
  1538. tests/storage/databases/main/test_metrics.py +88 -0
  1539. tests/storage/databases/main/test_receipts.py +218 -0
  1540. tests/storage/databases/main/test_room.py +192 -0
  1541. tests/storage/test__base.py +178 -0
  1542. tests/storage/test_account_data.py +186 -0
  1543. tests/storage/test_appservice.py +568 -0
  1544. tests/storage/test_background_update.py +671 -0
  1545. tests/storage/test_base.py +813 -0
  1546. tests/storage/test_cleanup_extrems.py +396 -0
  1547. tests/storage/test_client_ips.py +788 -0
  1548. tests/storage/test_database.py +288 -0
  1549. tests/storage/test_devices.py +353 -0
  1550. tests/storage/test_directory.py +74 -0
  1551. tests/storage/test_e2e_room_keys.py +87 -0
  1552. tests/storage/test_end_to_end_keys.py +120 -0
  1553. tests/storage/test_event_chain.py +826 -0
  1554. tests/storage/test_event_federation.py +1433 -0
  1555. tests/storage/test_event_push_actions.py +809 -0
  1556. tests/storage/test_events.py +591 -0
  1557. tests/storage/test_events_bg_updates.py +156 -0
  1558. tests/storage/test_id_generators.py +791 -0
  1559. tests/storage/test_invite_rule.py +171 -0
  1560. tests/storage/test_main.py +56 -0
  1561. tests/storage/test_monthly_active_users.py +500 -0
  1562. tests/storage/test_profile.py +134 -0
  1563. tests/storage/test_purge.py +459 -0
  1564. tests/storage/test_receipts.py +309 -0
  1565. tests/storage/test_redaction.py +462 -0
  1566. tests/storage/test_registration.py +277 -0
  1567. tests/storage/test_relations.py +118 -0
  1568. tests/storage/test_rollback_worker.py +132 -0
  1569. tests/storage/test_room.py +69 -0
  1570. tests/storage/test_room_search.py +383 -0
  1571. tests/storage/test_roommember.py +812 -0
  1572. tests/storage/test_sliding_sync_tables.py +5187 -0
  1573. tests/storage/test_state.py +959 -0
  1574. tests/storage/test_state_deletion.py +475 -0
  1575. tests/storage/test_stream.py +1533 -0
  1576. tests/storage/test_thread_subscriptions.py +369 -0
  1577. tests/storage/test_transactions.py +77 -0
  1578. tests/storage/test_txn_limit.py +49 -0
  1579. tests/storage/test_unsafe_locale.py +67 -0
  1580. tests/storage/test_user_directory.py +691 -0
  1581. tests/storage/test_user_filters.py +101 -0
  1582. tests/storage/util/__init__.py +20 -0
  1583. tests/storage/util/test_partial_state_events_tracker.py +181 -0
  1584. tests/synapse_rust/__init__.py +11 -0
  1585. tests/synapse_rust/test_http_client.py +225 -0
  1586. tests/test_distributor.py +74 -0
  1587. tests/test_event_auth.py +921 -0
  1588. tests/test_mau.py +347 -0
  1589. tests/test_phone_home.py +102 -0
  1590. tests/test_rust.py +11 -0
  1591. tests/test_server.py +557 -0
  1592. tests/test_state.py +902 -0
  1593. tests/test_terms_auth.py +128 -0
  1594. tests/test_types.py +201 -0
  1595. tests/test_utils/__init__.py +161 -0
  1596. tests/test_utils/event_injection.py +150 -0
  1597. tests/test_utils/html_parsers.py +59 -0
  1598. tests/test_utils/logging_setup.py +74 -0
  1599. tests/test_utils/oidc.py +370 -0
  1600. tests/test_visibility.py +712 -0
  1601. tests/types/__init__.py +0 -0
  1602. tests/types/test_init.py +51 -0
  1603. tests/types/test_state.py +627 -0
  1604. tests/unittest.py +1108 -0
  1605. tests/util/__init__.py +20 -0
  1606. tests/util/caches/__init__.py +20 -0
  1607. tests/util/caches/test_cached_call.py +168 -0
  1608. tests/util/caches/test_deferred_cache.py +317 -0
  1609. tests/util/caches/test_descriptors.py +1110 -0
  1610. tests/util/caches/test_response_cache.py +225 -0
  1611. tests/util/caches/test_ttlcache.py +90 -0
  1612. tests/util/test_async_helpers.py +808 -0
  1613. tests/util/test_background_queue.py +117 -0
  1614. tests/util/test_batching_queue.py +252 -0
  1615. tests/util/test_check_dependencies.py +243 -0
  1616. tests/util/test_dict_cache.py +130 -0
  1617. tests/util/test_events.py +118 -0
  1618. tests/util/test_expiring_cache.py +113 -0
  1619. tests/util/test_file_consumer.py +199 -0
  1620. tests/util/test_itertools.py +190 -0
  1621. tests/util/test_linearizer.py +264 -0
  1622. tests/util/test_logcontext.py +715 -0
  1623. tests/util/test_logformatter.py +44 -0
  1624. tests/util/test_lrucache.py +479 -0
  1625. tests/util/test_macaroons.py +126 -0
  1626. tests/util/test_mutable_overlay_mapping.py +189 -0
  1627. tests/util/test_ratelimitutils.py +146 -0
  1628. tests/util/test_retryutils.py +314 -0
  1629. tests/util/test_rwlock.py +401 -0
  1630. tests/util/test_stream_change_cache.py +304 -0
  1631. tests/util/test_stringutils.py +86 -0
  1632. tests/util/test_task_scheduler.py +227 -0
  1633. tests/util/test_threepids.py +55 -0
  1634. tests/util/test_treecache.py +93 -0
  1635. tests/util/test_wheel_timer.py +82 -0
  1636. tests/utils.py +342 -0
@@ -0,0 +1,2511 @@
1
+ #
2
+ # This file is licensed under the Affero General Public License (AGPL) version 3.
3
+ #
4
+ # Copyright 2014-2016 OpenMarket Ltd
5
+ # Copyright (C) 2023 New Vector, Ltd
6
+ #
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Affero General Public License as
9
+ # published by the Free Software Foundation, either version 3 of the
10
+ # License, or (at your option) any later version.
11
+ #
12
+ # See the GNU Affero General Public License for more details:
13
+ # <https://www.gnu.org/licenses/agpl-3.0.html>.
14
+ #
15
+ # Originally licensed under the Apache License, Version 2.0:
16
+ # <http://www.apache.org/licenses/LICENSE-2.0>.
17
+ #
18
+ # [This file includes modifications made by New Vector Limited]
19
+ #
20
+ #
21
+ import datetime
22
+ import itertools
23
+ import logging
24
+ from queue import Empty, PriorityQueue
25
+ from typing import (
26
+ TYPE_CHECKING,
27
+ Collection,
28
+ Generator,
29
+ Iterable,
30
+ Sequence,
31
+ cast,
32
+ )
33
+
34
+ import attr
35
+ from prometheus_client import Counter, Gauge
36
+
37
+ from synapse.api.constants import MAX_DEPTH
38
+ from synapse.api.errors import StoreError
39
+ from synapse.api.room_versions import EventFormatVersions, RoomVersion
40
+ from synapse.events import EventBase, make_event_from_dict
41
+ from synapse.logging.opentracing import tag_args, trace
42
+ from synapse.metrics import SERVER_NAME_LABEL
43
+ from synapse.metrics.background_process_metrics import wrap_as_background_process
44
+ from synapse.storage._base import db_to_json, make_in_list_sql_clause
45
+ from synapse.storage.background_updates import ForeignKeyConstraint
46
+ from synapse.storage.database import (
47
+ DatabasePool,
48
+ LoggingDatabaseConnection,
49
+ LoggingTransaction,
50
+ )
51
+ from synapse.storage.databases.main.cache import CacheInvalidationWorkerStore
52
+ from synapse.storage.databases.main.events_worker import EventsWorkerStore
53
+ from synapse.storage.databases.main.signatures import SignatureWorkerStore
54
+ from synapse.storage.engines import PostgresEngine, Sqlite3Engine
55
+ from synapse.types import JsonDict, StrCollection
56
+ from synapse.util.caches.descriptors import cached
57
+ from synapse.util.caches.lrucache import LruCache
58
+ from synapse.util.cancellation import cancellable
59
+ from synapse.util.duration import Duration
60
+ from synapse.util.iterutils import batch_iter
61
+ from synapse.util.json import json_encoder
62
+
63
+ if TYPE_CHECKING:
64
+ from synapse.server import HomeServer
65
+
66
+ oldest_pdu_in_federation_staging = Gauge(
67
+ "synapse_federation_server_oldest_inbound_pdu_in_staging",
68
+ "The age in seconds since we received the oldest pdu in the federation staging area",
69
+ labelnames=[SERVER_NAME_LABEL],
70
+ )
71
+
72
+ number_pdus_in_federation_queue = Gauge(
73
+ "synapse_federation_server_number_inbound_pdu_in_staging",
74
+ "The total number of events in the inbound federation staging",
75
+ labelnames=[SERVER_NAME_LABEL],
76
+ )
77
+
78
+ pdus_pruned_from_federation_queue = Counter(
79
+ "synapse_federation_server_number_inbound_pdu_pruned",
80
+ "The number of events in the inbound federation staging that have been "
81
+ "pruned due to the queue getting too long",
82
+ labelnames=[SERVER_NAME_LABEL],
83
+ )
84
+
85
+ logger = logging.getLogger(__name__)
86
+
87
+ # Parameters controlling exponential backoff between backfill failures.
88
+ # After the first failure to backfill, we wait 2 hours before trying again. If the
89
+ # second attempt fails, we wait 4 hours before trying again. If the third attempt fails,
90
+ # we wait 8 hours before trying again, ... and so on.
91
+ #
92
+ # Each successive backoff period is twice as long as the last. However we cap this
93
+ # period at a maximum of 2^8 = 256 hours: a little over 10 days. (This is the smallest
94
+ # power of 2 which yields a maximum backoff period of at least 7 days---which was the
95
+ # original maximum backoff period.) Even when we hit this cap, we will continue to
96
+ # make backfill attempts once every 10 days.
97
+ BACKFILL_EVENT_EXPONENTIAL_BACKOFF_MAXIMUM_DOUBLING_STEPS = 8
98
+ BACKFILL_EVENT_EXPONENTIAL_BACKOFF_STEP_MILLISECONDS = int(
99
+ datetime.timedelta(hours=1).total_seconds() * 1000
100
+ )
101
+
102
+ # We need a cap on the power of 2 or else the backoff period
103
+ # 2^N * (milliseconds per hour)
104
+ # will overflow when calcuated within the database. We ensure overflow does not occur
105
+ # by checking that the largest backoff period fits in a 32-bit signed integer.
106
+ _LONGEST_BACKOFF_PERIOD_MILLISECONDS = (
107
+ 2**BACKFILL_EVENT_EXPONENTIAL_BACKOFF_MAXIMUM_DOUBLING_STEPS
108
+ ) * BACKFILL_EVENT_EXPONENTIAL_BACKOFF_STEP_MILLISECONDS
109
+ assert 0 < _LONGEST_BACKOFF_PERIOD_MILLISECONDS <= ((2**31) - 1)
110
+
111
+
112
+ # We use 2^53-1 as a "very large number", it has no particular
113
+ # importance other than knowing synapse can support it (given canonical json
114
+ # requires it).
115
+ MAX_CHAIN_LENGTH = (2**53) - 1
116
+
117
+
118
+ # All the info we need while iterating the DAG while backfilling
119
+ @attr.s(frozen=True, slots=True, auto_attribs=True)
120
+ class BackfillQueueNavigationItem:
121
+ depth: int
122
+ stream_ordering: int
123
+ event_id: str
124
+ type: str
125
+
126
+
127
+ @attr.s(frozen=True, slots=True, auto_attribs=True)
128
+ class StateDifference:
129
+ # The event IDs in the auth difference.
130
+ auth_difference: set[str]
131
+ # The event IDs in the conflicted state subgraph. Used in v2.1 only.
132
+ conflicted_subgraph: set[str] | None
133
+
134
+
135
+ class _NoChainCoverIndex(Exception):
136
+ def __init__(self, room_id: str):
137
+ super().__init__("Unexpectedly no chain cover for events in %s" % (room_id,))
138
+
139
+
140
+ class EventFederationWorkerStore(
141
+ SignatureWorkerStore, EventsWorkerStore, CacheInvalidationWorkerStore
142
+ ):
143
+ # TODO: this attribute comes from EventPushActionWorkerStore. Should we inherit from
144
+ # that store so that mypy can deduce this for itself?
145
+ stream_ordering_month_ago: int | None
146
+
147
+ def __init__(
148
+ self,
149
+ database: DatabasePool,
150
+ db_conn: LoggingDatabaseConnection,
151
+ hs: "HomeServer",
152
+ ):
153
+ super().__init__(database, db_conn, hs)
154
+
155
+ self.hs = hs
156
+
157
+ if hs.config.worker.run_background_tasks:
158
+ hs.get_clock().looping_call(
159
+ self._delete_old_forward_extrem_cache, Duration(hours=1)
160
+ )
161
+
162
+ # Cache of event ID to list of auth event IDs and their depths.
163
+ self._event_auth_cache: LruCache[str, list[tuple[str, int]]] = LruCache(
164
+ max_size=500000,
165
+ clock=self.hs.get_clock(),
166
+ server_name=self.server_name,
167
+ cache_name="_event_auth_cache",
168
+ size_callback=len,
169
+ )
170
+
171
+ # Flag used by unit tests to disable fallback when there is no chain cover
172
+ # index.
173
+ self.tests_allow_no_chain_cover_index = True
174
+
175
+ self.clock.looping_call(
176
+ self._get_stats_for_federation_staging, Duration(seconds=30)
177
+ )
178
+
179
+ if isinstance(self.database_engine, PostgresEngine):
180
+ self.db_pool.updates.register_background_validate_constraint_and_delete_rows(
181
+ update_name="event_forward_extremities_event_id_foreign_key_constraint_update",
182
+ table="event_forward_extremities",
183
+ constraint_name="event_forward_extremities_event_id",
184
+ constraint=ForeignKeyConstraint(
185
+ "events", [("event_id", "event_id")], deferred=True
186
+ ),
187
+ unique_columns=("event_id", "room_id"),
188
+ )
189
+
190
+ self.db_pool.updates.register_background_index_update(
191
+ update_name="event_auth_chain_links_origin_index",
192
+ index_name="event_auth_chain_links_origin_index",
193
+ table="event_auth_chain_links",
194
+ columns=("origin_chain_id", "origin_sequence_number"),
195
+ )
196
+
197
+ async def get_auth_chain(
198
+ self, room_id: str, event_ids: Collection[str], include_given: bool = False
199
+ ) -> list[EventBase]:
200
+ """Get auth events for given event_ids. The events *must* be state events.
201
+
202
+ Args:
203
+ room_id: The room the event is in.
204
+ event_ids: state events
205
+ include_given: include the given events in result
206
+
207
+ Returns:
208
+ list of events
209
+ """
210
+ event_ids = await self.get_auth_chain_ids(
211
+ room_id, event_ids, include_given=include_given
212
+ )
213
+ return await self.get_events_as_list(event_ids)
214
+
215
+ @trace
216
+ @tag_args
217
+ async def get_auth_chain_ids(
218
+ self,
219
+ room_id: str,
220
+ event_ids: Collection[str],
221
+ include_given: bool = False,
222
+ ) -> set[str]:
223
+ """Get auth events for given event_ids. The events *must* be state events.
224
+
225
+ Args:
226
+ room_id: The room the event is in.
227
+ event_ids: state events
228
+ include_given: include the given events in result
229
+
230
+ Returns:
231
+ set of event_ids
232
+ """
233
+
234
+ # Check if we have indexed the room so we can use the chain cover
235
+ # algorithm.
236
+ room = await self.get_room(room_id) # type: ignore[attr-defined]
237
+ # If the room has an auth chain index.
238
+ if room[1]:
239
+ try:
240
+ return await self.db_pool.runInteraction(
241
+ "get_auth_chain_ids_chains",
242
+ self._get_auth_chain_ids_using_cover_index_txn,
243
+ room_id,
244
+ event_ids,
245
+ include_given,
246
+ )
247
+ except _NoChainCoverIndex:
248
+ # For whatever reason we don't actually have a chain cover index
249
+ # for the events in question, so we fall back to the old method
250
+ # (except in tests)
251
+ if not self.tests_allow_no_chain_cover_index:
252
+ raise
253
+
254
+ return await self.db_pool.runInteraction(
255
+ "get_auth_chain_ids",
256
+ self._get_auth_chain_ids_txn,
257
+ event_ids,
258
+ include_given,
259
+ )
260
+
261
+ def _get_auth_chain_ids_using_cover_index_txn(
262
+ self,
263
+ txn: LoggingTransaction,
264
+ room_id: str,
265
+ event_ids: Collection[str],
266
+ include_given: bool,
267
+ ) -> set[str]:
268
+ """Calculates the auth chain IDs using the chain index."""
269
+
270
+ # First we look up the chain ID/sequence numbers for the given events.
271
+
272
+ initial_events = set(event_ids)
273
+
274
+ # All the events that we've found that are reachable from the events.
275
+ seen_events: set[str] = set()
276
+
277
+ # A map from chain ID to max sequence number of the given events.
278
+ event_chains: dict[int, int] = {}
279
+
280
+ sql = """
281
+ SELECT event_id, chain_id, sequence_number
282
+ FROM event_auth_chains
283
+ WHERE %s
284
+ """
285
+ for batch in batch_iter(initial_events, 1000):
286
+ clause, args = make_in_list_sql_clause(
287
+ txn.database_engine, "event_id", batch
288
+ )
289
+ txn.execute(sql % (clause,), args)
290
+
291
+ for event_id, chain_id, sequence_number in txn:
292
+ seen_events.add(event_id)
293
+ event_chains[chain_id] = max(
294
+ sequence_number, event_chains.get(chain_id, 0)
295
+ )
296
+
297
+ # Check that we actually have a chain ID for all the events.
298
+ events_missing_chain_info = initial_events.difference(seen_events)
299
+ if events_missing_chain_info:
300
+ # This can happen due to e.g. downgrade/upgrade of the server. We
301
+ # raise an exception and fall back to the previous algorithm.
302
+ logger.error(
303
+ "Unexpectedly found that events don't have chain IDs in room %s: %s",
304
+ room_id,
305
+ events_missing_chain_info,
306
+ )
307
+ raise _NoChainCoverIndex(room_id)
308
+
309
+ # Now we look up all links for the chains we have, adding chains that
310
+ # are reachable from any event.
311
+
312
+ # A map from chain ID to max sequence number *reachable* from any event ID.
313
+ chains: dict[int, int] = {}
314
+ for links in self._get_chain_links(txn, set(event_chains.keys())):
315
+ for chain_id in links:
316
+ if chain_id not in event_chains:
317
+ continue
318
+
319
+ _materialize(chain_id, event_chains[chain_id], links, chains)
320
+
321
+ # Add the initial set of chains, excluding the sequence corresponding to
322
+ # initial event.
323
+ for chain_id, seq_no in event_chains.items():
324
+ # Check if the initial event is the first item in the chain. If so, then
325
+ # there is nothing new to add from this chain.
326
+ if seq_no == 1:
327
+ continue
328
+
329
+ chains[chain_id] = max(seq_no - 1, chains.get(chain_id, 0))
330
+
331
+ # Now for each chain we figure out the maximum sequence number reachable
332
+ # from *any* event ID. Events with a sequence less than that are in the
333
+ # auth chain.
334
+ if include_given:
335
+ results = initial_events
336
+ else:
337
+ results = set()
338
+
339
+ if isinstance(self.database_engine, PostgresEngine):
340
+ # We can use `execute_values` to efficiently fetch the gaps when
341
+ # using postgres.
342
+ sql = """
343
+ SELECT event_id
344
+ FROM event_auth_chains AS c, (VALUES ?) AS l(chain_id, max_seq)
345
+ WHERE
346
+ c.chain_id = l.chain_id
347
+ AND sequence_number <= max_seq
348
+ """
349
+
350
+ rows = txn.execute_values(sql, chains.items())
351
+ results.update(r for (r,) in rows)
352
+ else:
353
+ # For SQLite we just fall back to doing a noddy for loop.
354
+ sql = """
355
+ SELECT event_id FROM event_auth_chains
356
+ WHERE chain_id = ? AND sequence_number <= ?
357
+ """
358
+ for chain_id, max_no in chains.items():
359
+ txn.execute(sql, (chain_id, max_no))
360
+ results.update(r for (r,) in txn)
361
+
362
+ return results
363
+
364
+ @classmethod
365
+ def _get_chain_links(
366
+ cls, txn: LoggingTransaction, chains_to_fetch: set[int]
367
+ ) -> Generator[dict[int, list[tuple[int, int, int]]], None, None]:
368
+ """Fetch all auth chain links from the given set of chains, and all
369
+ links from those chains, recursively.
370
+
371
+ Note: This may return links that are not reachable from the given
372
+ chains.
373
+
374
+ Returns a generator that produces dicts from origin chain ID to 3-tuple
375
+ of origin sequence number, target chain ID and target sequence number.
376
+ """
377
+
378
+ # This query is structured to first get all chain IDs reachable, and
379
+ # then pull out all links from those chains. This does pull out more
380
+ # rows than is strictly necessary, however there isn't a way of
381
+ # structuring the recursive part of query to pull out the links without
382
+ # also returning large quantities of redundant data (which can make it a
383
+ # lot slower).
384
+ sql = """
385
+ WITH RECURSIVE links(chain_id) AS (
386
+ SELECT
387
+ DISTINCT origin_chain_id
388
+ FROM event_auth_chain_links WHERE %s
389
+ UNION
390
+ SELECT
391
+ target_chain_id
392
+ FROM event_auth_chain_links
393
+ INNER JOIN links ON (chain_id = origin_chain_id)
394
+ )
395
+ SELECT
396
+ origin_chain_id, origin_sequence_number,
397
+ target_chain_id, target_sequence_number
398
+ FROM links
399
+ INNER JOIN event_auth_chain_links ON (chain_id = origin_chain_id)
400
+ """
401
+
402
+ while chains_to_fetch:
403
+ batch2 = tuple(itertools.islice(chains_to_fetch, 1000))
404
+ chains_to_fetch.difference_update(batch2)
405
+ clause, args = make_in_list_sql_clause(
406
+ txn.database_engine, "origin_chain_id", batch2
407
+ )
408
+ txn.execute(sql % (clause,), args)
409
+
410
+ links: dict[int, list[tuple[int, int, int]]] = {}
411
+
412
+ for (
413
+ origin_chain_id,
414
+ origin_sequence_number,
415
+ target_chain_id,
416
+ target_sequence_number,
417
+ ) in txn:
418
+ links.setdefault(origin_chain_id, []).append(
419
+ (origin_sequence_number, target_chain_id, target_sequence_number)
420
+ )
421
+
422
+ chains_to_fetch.difference_update(links)
423
+
424
+ yield links
425
+
426
+ def _get_auth_chain_ids_txn(
427
+ self, txn: LoggingTransaction, event_ids: Collection[str], include_given: bool
428
+ ) -> set[str]:
429
+ """Calculates the auth chain IDs.
430
+
431
+ This is used when we don't have a cover index for the room.
432
+ """
433
+ if include_given:
434
+ results = set(event_ids)
435
+ else:
436
+ results = set()
437
+
438
+ # We pull out the depth simply so that we can populate the
439
+ # `_event_auth_cache` cache.
440
+ base_sql = """
441
+ SELECT a.event_id, auth_id, depth
442
+ FROM event_auth AS a
443
+ INNER JOIN events AS e ON (e.event_id = a.auth_id)
444
+ WHERE
445
+ """
446
+
447
+ front = set(event_ids)
448
+ while front:
449
+ new_front: set[str] = set()
450
+ for chunk in batch_iter(front, 100):
451
+ # Pull the auth events either from the cache or DB.
452
+ to_fetch: list[str] = [] # Event IDs to fetch from DB
453
+ for event_id in chunk:
454
+ res = self._event_auth_cache.get(event_id)
455
+ if res is None:
456
+ to_fetch.append(event_id)
457
+ else:
458
+ new_front.update(auth_id for auth_id, depth in res)
459
+
460
+ if to_fetch:
461
+ clause, args = make_in_list_sql_clause(
462
+ txn.database_engine, "a.event_id", to_fetch
463
+ )
464
+ txn.execute(base_sql + clause, args)
465
+
466
+ # Note we need to batch up the results by event ID before
467
+ # adding to the cache.
468
+ to_cache: dict[str, list[tuple[str, int]]] = {}
469
+ for event_id, auth_event_id, auth_event_depth in txn:
470
+ to_cache.setdefault(event_id, []).append(
471
+ (auth_event_id, auth_event_depth)
472
+ )
473
+ new_front.add(auth_event_id)
474
+
475
+ for event_id, auth_events in to_cache.items():
476
+ self._event_auth_cache.set(event_id, auth_events)
477
+
478
+ new_front -= results
479
+
480
+ front = new_front
481
+ results.update(front)
482
+
483
+ return results
484
+
485
+ async def get_auth_chain_difference(
486
+ self,
487
+ room_id: str,
488
+ state_sets: list[set[str]],
489
+ ) -> set[str]:
490
+ state_diff = await self.get_auth_chain_difference_extended(
491
+ room_id, state_sets, None, None
492
+ )
493
+ return state_diff.auth_difference
494
+
495
+ async def get_auth_chain_difference_extended(
496
+ self,
497
+ room_id: str,
498
+ state_sets: list[set[str]],
499
+ conflicted_set: set[str] | None,
500
+ additional_backwards_reachable_conflicted_events: set[str] | None,
501
+ ) -> StateDifference:
502
+ """ "Given sets of state events figure out the auth chain difference (as
503
+ per state res v2 algorithm).
504
+
505
+ This is equivalent to fetching the full auth chain for each set of state
506
+ and returning the events that don't appear in each and every auth
507
+ chain.
508
+
509
+ If conflicted_set is not None, calculate and return the conflicted sub-graph as per
510
+ state res v2.1. The event IDs in the conflicted set MUST be a subset of the event IDs in
511
+ state_sets.
512
+
513
+ If additional_backwards_reachable_conflicted_events is set, the provided events are included
514
+ when calculating the conflicted subgraph. This is primarily useful for calculating the
515
+ subgraph across a combination of persisted and unpersisted events. The event IDs in this set
516
+ MUST be a subset of the event IDs in state_sets.
517
+
518
+ Returns:
519
+ information on the auth chain difference, and also the conflicted subgraph if
520
+ conflicted_set is not None
521
+ """
522
+
523
+ # Check if we have indexed the room so we can use the chain cover
524
+ # algorithm.
525
+ room = await self.get_room(room_id) # type: ignore[attr-defined]
526
+ # If the room has an auth chain index.
527
+ if room[1]:
528
+ try:
529
+ return await self.db_pool.runInteraction(
530
+ "get_auth_chain_difference_chains",
531
+ self._get_auth_chain_difference_using_cover_index_txn,
532
+ room_id,
533
+ state_sets,
534
+ conflicted_set,
535
+ additional_backwards_reachable_conflicted_events,
536
+ )
537
+ except _NoChainCoverIndex:
538
+ # For whatever reason we don't actually have a chain cover index
539
+ # for the events in question, so we fall back to the old method
540
+ # (except in tests)
541
+ if not self.tests_allow_no_chain_cover_index:
542
+ raise
543
+
544
+ # It's been 4 years since we added chain cover, so we expect all rooms to have it.
545
+ # If they don't, we will error out when trying to do state res v2.1
546
+ if conflicted_set is not None:
547
+ raise _NoChainCoverIndex(room_id)
548
+
549
+ auth_diff = await self.db_pool.runInteraction(
550
+ "get_auth_chain_difference",
551
+ self._get_auth_chain_difference_txn,
552
+ state_sets,
553
+ )
554
+ return StateDifference(auth_difference=auth_diff, conflicted_subgraph=None)
555
+
556
+ def _get_auth_chain_difference_using_cover_index_txn(
557
+ self,
558
+ txn: LoggingTransaction,
559
+ room_id: str,
560
+ state_sets: list[set[str]],
561
+ conflicted_set: set[str] | None = None,
562
+ additional_backwards_reachable_conflicted_events: set[str] | None = None,
563
+ ) -> StateDifference:
564
+ """Calculates the auth chain difference using the chain index.
565
+
566
+ See docs/auth_chain_difference_algorithm.md for details
567
+ """
568
+ is_state_res_v21 = conflicted_set is not None
569
+
570
+ # First we look up the chain ID/sequence numbers for all the events, and
571
+ # work out the chain/sequence numbers reachable from each state set.
572
+
573
+ initial_events = set(state_sets[0]).union(*state_sets[1:])
574
+
575
+ if is_state_res_v21:
576
+ # Sanity check v2.1 fields
577
+ assert conflicted_set is not None
578
+ assert conflicted_set.issubset(initial_events)
579
+ # It's possible for the conflicted_set to be empty if all the conflicts are in
580
+ # unpersisted events, so we don't assert that conflicted_set has len > 0
581
+ if additional_backwards_reachable_conflicted_events:
582
+ assert additional_backwards_reachable_conflicted_events.issubset(
583
+ initial_events
584
+ )
585
+
586
+ # Map from event_id -> (chain ID, seq no)
587
+ chain_info: dict[str, tuple[int, int]] = {}
588
+
589
+ # Map from chain ID -> seq no -> event Id
590
+ chain_to_event: dict[int, dict[int, str]] = {}
591
+
592
+ # All the chains that we've found that are reachable from the state
593
+ # sets.
594
+ seen_chains: set[int] = set()
595
+
596
+ # Fetch the chain cover index for the initial set of events we're
597
+ # considering.
598
+ def fetch_chain_info(events_to_fetch: Collection[str]) -> None:
599
+ sql = """
600
+ SELECT event_id, chain_id, sequence_number
601
+ FROM event_auth_chains
602
+ WHERE %s
603
+ """
604
+ for batch in batch_iter(events_to_fetch, 1000):
605
+ clause, args = make_in_list_sql_clause(
606
+ txn.database_engine, "event_id", batch
607
+ )
608
+ txn.execute(sql % (clause,), args)
609
+
610
+ for event_id, chain_id, sequence_number in txn:
611
+ chain_info[event_id] = (chain_id, sequence_number)
612
+ seen_chains.add(chain_id)
613
+ chain_to_event.setdefault(chain_id, {})[sequence_number] = event_id
614
+
615
+ fetch_chain_info(initial_events)
616
+
617
+ # Check that we actually have a chain ID for all the events.
618
+ events_missing_chain_info = initial_events.difference(chain_info)
619
+
620
+ # The result set to return, i.e. the auth chain difference.
621
+ auth_difference_result: set[str] = set()
622
+
623
+ if events_missing_chain_info:
624
+ # For some reason we have events we haven't calculated the chain
625
+ # index for, so we need to handle those separately. This should only
626
+ # happen for older rooms where the server doesn't have all the auth
627
+ # events.
628
+ auth_difference_result = self._fixup_auth_chain_difference_sets(
629
+ txn,
630
+ room_id,
631
+ state_sets=state_sets,
632
+ events_missing_chain_info=events_missing_chain_info,
633
+ events_that_have_chain_index=chain_info,
634
+ )
635
+
636
+ # We now need to refetch any events that we have added to the state
637
+ # sets.
638
+ new_events_to_fetch = {
639
+ event_id
640
+ for state_set in state_sets
641
+ for event_id in state_set
642
+ if event_id not in initial_events
643
+ }
644
+
645
+ fetch_chain_info(new_events_to_fetch)
646
+
647
+ # State Res v2.1 needs extra data structures to calculate the conflicted subgraph which
648
+ # are outlined below.
649
+
650
+ # A subset of chain_info for conflicted events only, as we need to
651
+ # loop all conflicted chain positions. Map from event_id -> (chain ID, seq no)
652
+ conflicted_chain_positions: dict[str, tuple[int, int]] = {}
653
+ # For each chain, remember the positions where conflicted events are.
654
+ # We need this for calculating the forward reachable events.
655
+ conflicted_chain_to_seq: dict[int, set[int]] = {} # chain_id => {seq_num}
656
+ # A subset of chain_info for additional backwards reachable events only, as we need to
657
+ # loop all additional backwards reachable events for calculating backwards reachable events.
658
+ additional_backwards_reachable_positions: dict[
659
+ str, tuple[int, int]
660
+ ] = {} # event_id => (chain_id, seq_num)
661
+ # These next two fields are critical as the intersection of them is the conflicted subgraph.
662
+ # We'll populate them when we walk the chain links.
663
+ # chain_id => max(seq_num) backwards reachable (e.g 4 means 1,2,3,4 are backwards reachable)
664
+ conflicted_backwards_reachable: dict[int, int] = {}
665
+ # chain_id => min(seq_num) forwards reachable (e.g 4 means 4,5,6..n are forwards reachable)
666
+ conflicted_forwards_reachable: dict[int, int] = {}
667
+
668
+ # populate the v2.1 data structures
669
+ if is_state_res_v21:
670
+ assert conflicted_set is not None
671
+ # provide chain positions for each conflicted event
672
+ for conflicted_event_id in conflicted_set:
673
+ (chain_id, seq_num) = chain_info[conflicted_event_id]
674
+ conflicted_chain_positions[conflicted_event_id] = (chain_id, seq_num)
675
+ conflicted_chain_to_seq.setdefault(chain_id, set()).add(seq_num)
676
+ if additional_backwards_reachable_conflicted_events:
677
+ for (
678
+ additional_event_id
679
+ ) in additional_backwards_reachable_conflicted_events:
680
+ (chain_id, seq_num) = chain_info[additional_event_id]
681
+ additional_backwards_reachable_positions[additional_event_id] = (
682
+ chain_id,
683
+ seq_num,
684
+ )
685
+
686
+ # Corresponds to `state_sets`, except as a map from chain ID to max
687
+ # sequence number reachable from the state set.
688
+ set_to_chain: list[dict[int, int]] = []
689
+ for state_set in state_sets:
690
+ chains: dict[int, int] = {}
691
+ set_to_chain.append(chains)
692
+
693
+ for state_id in state_set:
694
+ chain_id, seq_no = chain_info[state_id]
695
+
696
+ chains[chain_id] = max(seq_no, chains.get(chain_id, 0))
697
+
698
+ # Now we look up all links for the chains we have, adding chains that
699
+ # are reachable from any event.
700
+
701
+ # (We need to take a copy of `seen_chains` as the function mutates it)
702
+ for links in self._get_chain_links(txn, set(seen_chains)):
703
+ # `links` encodes the backwards reachable events _from a single chain_ all the way to
704
+ # the root of the graph.
705
+ for chains in set_to_chain:
706
+ for chain_id in links:
707
+ if chain_id not in chains:
708
+ continue
709
+
710
+ _materialize(chain_id, chains[chain_id], links, chains)
711
+
712
+ seen_chains.update(chains)
713
+ if is_state_res_v21:
714
+ # Apply v2.1 conflicted event reachability checks.
715
+ #
716
+ # A <-- B <-- C <-- D <-- E
717
+ #
718
+ # Backwards reachable from C = {A,B}
719
+ # Forwards reachable from C = {D,E}
720
+
721
+ # this handles calculating forwards reachable information and updates
722
+ # conflicted_forwards_reachable.
723
+ accumulate_forwards_reachable_events(
724
+ conflicted_forwards_reachable,
725
+ links,
726
+ conflicted_chain_positions,
727
+ )
728
+
729
+ # handle backwards reachable information
730
+ for (
731
+ conflicted_chain_id,
732
+ conflicted_chain_seq,
733
+ ) in conflicted_chain_positions.values():
734
+ if conflicted_chain_id not in links:
735
+ # This conflicted event does not lie on the path to the root.
736
+ continue
737
+
738
+ # The conflicted chain position itself encodes reachability information
739
+ # _within_ the chain. Set it now before walking to other links.
740
+ conflicted_backwards_reachable[conflicted_chain_id] = max(
741
+ conflicted_chain_seq,
742
+ conflicted_backwards_reachable.get(conflicted_chain_id, 0),
743
+ )
744
+
745
+ # Build backwards reachability paths. This is the same as what the auth difference
746
+ # code does. We find which chain the conflicted event
747
+ # belongs to then walk it backwards to the root. We store reachability info
748
+ # for all conflicted events in the same map 'conflicted_backwards_reachable'
749
+ # as we don't care about the paths themselves.
750
+ _materialize(
751
+ conflicted_chain_id,
752
+ conflicted_chain_seq,
753
+ links,
754
+ conflicted_backwards_reachable,
755
+ )
756
+ # Mark some extra events as backwards reachable. This is used when we have some
757
+ # unpersisted events and want to know the subgraph across the persisted/unpersisted
758
+ # boundary:
759
+ # |
760
+ # A <-- B <-- C <-|- D <-- E <-- F
761
+ # persisted | unpersisted
762
+ #
763
+ # Assume {B,E} are conflicted, we want to return {B,C,D,E}
764
+ #
765
+ # The unpersisted code ensures it passes C as an additional backwards reachable
766
+ # event. C is NOT a conflicted event, but we do need to consider it as part of
767
+ # the backwards reachable set. When we then calculate the forwards reachable set
768
+ # from B, C will be in both the backwards and forwards reachable sets and hence
769
+ # will be included in the conflicted subgraph.
770
+ for (
771
+ additional_chain_id,
772
+ additional_chain_seq,
773
+ ) in additional_backwards_reachable_positions.values():
774
+ if additional_chain_id not in links:
775
+ # The additional backwards reachable event does not lie on the path to the root.
776
+ continue
777
+
778
+ # the additional event chain position itself encodes reachability information.
779
+ # It means that position and all positions earlier in that chain are backwards reachable
780
+ # by some unpersisted conflicted event.
781
+ conflicted_backwards_reachable[additional_chain_id] = max(
782
+ additional_chain_seq,
783
+ conflicted_backwards_reachable.get(additional_chain_id, 0),
784
+ )
785
+
786
+ # Now walk the chains back, marking backwards reachable events.
787
+ # This is the same thing we do for auth difference / conflicted events.
788
+ _materialize(
789
+ additional_chain_id, # walk all links back, marking them as backwards reachable
790
+ additional_chain_seq,
791
+ links,
792
+ conflicted_backwards_reachable,
793
+ )
794
+
795
+ # Now for each chain we figure out the maximum sequence number reachable
796
+ # from *any* state set and the minimum sequence number reachable from
797
+ # *all* state sets. Events in that range are in the auth chain
798
+ # difference.
799
+
800
+ # Mapping from chain ID to the range of sequence numbers that should be
801
+ # pulled from the database.
802
+ auth_diff_chain_to_gap: dict[int, tuple[int, int]] = {}
803
+
804
+ for chain_id in seen_chains:
805
+ min_seq_no = min(chains.get(chain_id, 0) for chains in set_to_chain)
806
+ max_seq_no = max(chains.get(chain_id, 0) for chains in set_to_chain)
807
+
808
+ if min_seq_no < max_seq_no:
809
+ # We have a non empty gap, try and fill it from the events that
810
+ # we have, otherwise add them to the list of gaps to pull out
811
+ # from the DB.
812
+ for seq_no in range(min_seq_no + 1, max_seq_no + 1):
813
+ event_id = chain_to_event.get(chain_id, {}).get(seq_no)
814
+ if event_id:
815
+ auth_difference_result.add(event_id)
816
+ else:
817
+ auth_diff_chain_to_gap[chain_id] = (min_seq_no, max_seq_no)
818
+ break
819
+
820
+ conflicted_subgraph_result: set[str] = set()
821
+ # Mapping from chain ID to the range of sequence numbers that should be
822
+ # pulled from the database.
823
+ conflicted_subgraph_chain_to_gap: dict[int, tuple[int, int]] = {}
824
+ if is_state_res_v21:
825
+ # also include the conflicted subgraph using backward/forward reachability info from all
826
+ # the conflicted events. To calculate this, we want to extract the intersection between
827
+ # the backwards and forwards reachability sets, e.g:
828
+ # A <- B <- C <- D <- E
829
+ # Assume B and D are conflicted so we want {C} as the conflicted subgraph.
830
+ # B_backwards={A}, B_forwards={C,D,E}
831
+ # D_backwards={A,B,C} D_forwards={E}
832
+ # ALL_backwards={A,B,C} ALL_forwards={C,D,E}
833
+ # Intersection(ALL_backwards, ALL_forwards) = {C}
834
+ #
835
+ # It's worth noting that once we have the ALL_ sets, we no longer care about the paths.
836
+ # We're dealing with chains and not singular events, but we've already got the ALL_ sets.
837
+ # As such, we can inspect each chain in isolation and check for overlapping sequence
838
+ # numbers:
839
+ # 1,2,3,4,5 Seq Num
840
+ # Chain N [A,B,C,D,E]
841
+ #
842
+ # if (N,4) is in the backwards set and (N,2) is in the forwards set, then the
843
+ # intersection is events between 2 < 4. We will include the conflicted events themselves
844
+ # in the subgraph, but they will already be, hence the full set of events is {B,C,D}.
845
+ for chain_id, backwards_seq_num in conflicted_backwards_reachable.items():
846
+ forwards_seq_num = conflicted_forwards_reachable.get(chain_id)
847
+ if forwards_seq_num is None:
848
+ continue # this chain isn't in both sets so can't intersect
849
+ if forwards_seq_num > backwards_seq_num:
850
+ continue # this chain is in both sets but they don't overap
851
+ for seq_no in range(
852
+ forwards_seq_num, backwards_seq_num + 1
853
+ ): # inclusive of both
854
+ event_id = chain_to_event.get(chain_id, {}).get(seq_no)
855
+ if event_id:
856
+ conflicted_subgraph_result.add(event_id)
857
+ else:
858
+ conflicted_subgraph_chain_to_gap[chain_id] = (
859
+ # _fetch_event_ids_from_chains_txn is exclusive of the min value
860
+ forwards_seq_num - 1,
861
+ backwards_seq_num,
862
+ )
863
+ break
864
+
865
+ if auth_diff_chain_to_gap:
866
+ auth_difference_result.update(
867
+ self._fetch_event_ids_from_chains_txn(txn, auth_diff_chain_to_gap)
868
+ )
869
+ if conflicted_subgraph_chain_to_gap:
870
+ conflicted_subgraph_result.update(
871
+ self._fetch_event_ids_from_chains_txn(
872
+ txn, conflicted_subgraph_chain_to_gap
873
+ )
874
+ )
875
+
876
+ return StateDifference(
877
+ auth_difference=auth_difference_result,
878
+ conflicted_subgraph=conflicted_subgraph_result,
879
+ )
880
+
881
+ def _fetch_event_ids_from_chains_txn(
882
+ self, txn: LoggingTransaction, chains: dict[int, tuple[int, int]]
883
+ ) -> set[str]:
884
+ result: set[str] = set()
885
+ if isinstance(self.database_engine, PostgresEngine):
886
+ # We can use `execute_values` to efficiently fetch the gaps when
887
+ # using postgres.
888
+ sql = """
889
+ SELECT event_id
890
+ FROM event_auth_chains AS c, (VALUES ?) AS l(chain_id, min_seq, max_seq)
891
+ WHERE
892
+ c.chain_id = l.chain_id
893
+ AND min_seq < sequence_number AND sequence_number <= max_seq
894
+ """
895
+
896
+ args = [
897
+ (chain_id, min_no, max_no)
898
+ for chain_id, (min_no, max_no) in chains.items()
899
+ ]
900
+
901
+ rows = txn.execute_values(sql, args)
902
+ result.update(r for (r,) in rows)
903
+ else:
904
+ # For SQLite we just fall back to doing a noddy for loop.
905
+ sql = """
906
+ SELECT event_id FROM event_auth_chains
907
+ WHERE chain_id = ? AND ? < sequence_number AND sequence_number <= ?
908
+ """
909
+ for chain_id, (min_no, max_no) in chains.items():
910
+ txn.execute(sql, (chain_id, min_no, max_no))
911
+ result.update(r for (r,) in txn)
912
+ return result
913
+
914
+ def _fixup_auth_chain_difference_sets(
915
+ self,
916
+ txn: LoggingTransaction,
917
+ room_id: str,
918
+ state_sets: list[set[str]],
919
+ events_missing_chain_info: set[str],
920
+ events_that_have_chain_index: Collection[str],
921
+ ) -> set[str]:
922
+ """Helper for `_get_auth_chain_difference_using_cover_index_txn` to
923
+ handle the case where we haven't calculated the chain cover index for
924
+ all events.
925
+
926
+ This modifies `state_sets` so that they only include events that have a
927
+ chain cover index, and returns a set of event IDs that are part of the
928
+ auth difference.
929
+ """
930
+
931
+ # This works similarly to the handling of unpersisted events in
932
+ # `synapse.state.v2_get_auth_chain_difference`. We uses the observation
933
+ # that if you can split the set of events into two classes X and Y,
934
+ # where no events in Y have events in X in their auth chain, then we can
935
+ # calculate the auth difference by considering X and Y separately.
936
+ #
937
+ # We do this in three steps:
938
+ # 1. Compute the set of events without chain cover index belonging to
939
+ # the auth difference.
940
+ # 2. Replacing the un-indexed events in the state_sets with their auth
941
+ # events, recursively, until the state_sets contain only indexed
942
+ # events. We can then calculate the auth difference of those state
943
+ # sets using the chain cover index.
944
+ # 3. Add the results of 1 and 2 together.
945
+
946
+ # By construction we know that all events that we haven't persisted the
947
+ # chain cover index for are contained in
948
+ # `event_auth_chain_to_calculate`, so we pull out the events from those
949
+ # rather than doing recursive queries to walk the auth chain.
950
+ #
951
+ # We pull out those events with their auth events, which gives us enough
952
+ # information to construct the auth chain of an event up to auth events
953
+ # that have the chain cover index.
954
+ sql = """
955
+ SELECT tc.event_id, ea.auth_id, eac.chain_id IS NOT NULL
956
+ FROM event_auth_chain_to_calculate AS tc
957
+ LEFT JOIN event_auth AS ea USING (event_id)
958
+ LEFT JOIN event_auth_chains AS eac ON (ea.auth_id = eac.event_id)
959
+ WHERE tc.room_id = ?
960
+ """
961
+ txn.execute(sql, (room_id,))
962
+ event_to_auth_ids: dict[str, set[str]] = {}
963
+ events_that_have_chain_index = set(events_that_have_chain_index)
964
+ for event_id, auth_id, auth_id_has_chain in txn:
965
+ s = event_to_auth_ids.setdefault(event_id, set())
966
+ if auth_id is not None:
967
+ s.add(auth_id)
968
+ if auth_id_has_chain:
969
+ events_that_have_chain_index.add(auth_id)
970
+
971
+ if events_missing_chain_info - event_to_auth_ids.keys():
972
+ # Uh oh, we somehow haven't correctly done the chain cover index,
973
+ # bail and fall back to the old method.
974
+ logger.error(
975
+ "Unexpectedly found that events don't have chain IDs in room %s: %s",
976
+ room_id,
977
+ events_missing_chain_info - event_to_auth_ids.keys(),
978
+ )
979
+ raise _NoChainCoverIndex(room_id)
980
+
981
+ # Create a map from event IDs we care about to their partial auth chain.
982
+ event_id_to_partial_auth_chain: dict[str, set[str]] = {}
983
+ for event_id, auth_ids in event_to_auth_ids.items():
984
+ if not any(event_id in state_set for state_set in state_sets):
985
+ continue
986
+
987
+ processing = set(auth_ids)
988
+ to_add = set()
989
+ while processing:
990
+ auth_id = processing.pop()
991
+ to_add.add(auth_id)
992
+
993
+ sub_auth_ids = event_to_auth_ids.get(auth_id)
994
+ if sub_auth_ids is None:
995
+ continue
996
+
997
+ processing.update(sub_auth_ids - to_add)
998
+
999
+ event_id_to_partial_auth_chain[event_id] = to_add
1000
+
1001
+ # Now we do two things:
1002
+ # 1. Update the state sets to only include indexed events; and
1003
+ # 2. Create a new list containing the auth chains of the un-indexed
1004
+ # events
1005
+ unindexed_state_sets: list[set[str]] = []
1006
+ for state_set in state_sets:
1007
+ unindexed_state_set = set()
1008
+ for event_id, auth_chain in event_id_to_partial_auth_chain.items():
1009
+ if event_id not in state_set:
1010
+ continue
1011
+
1012
+ unindexed_state_set.add(event_id)
1013
+
1014
+ state_set.discard(event_id)
1015
+ state_set.difference_update(auth_chain)
1016
+ for auth_id in auth_chain:
1017
+ if auth_id in events_that_have_chain_index:
1018
+ state_set.add(auth_id)
1019
+ else:
1020
+ unindexed_state_set.add(auth_id)
1021
+
1022
+ unindexed_state_sets.append(unindexed_state_set)
1023
+
1024
+ # Calculate and return the auth difference of the un-indexed events.
1025
+ union = unindexed_state_sets[0].union(*unindexed_state_sets[1:])
1026
+ intersection = unindexed_state_sets[0].intersection(*unindexed_state_sets[1:])
1027
+
1028
+ return union - intersection
1029
+
1030
+ def _get_auth_chain_difference_txn(
1031
+ self, txn: LoggingTransaction, state_sets: list[set[str]]
1032
+ ) -> set[str]:
1033
+ """Calculates the auth chain difference using a breadth first search.
1034
+
1035
+ This is used when we don't have a cover index for the room.
1036
+ """
1037
+
1038
+ # Algorithm Description
1039
+ # ~~~~~~~~~~~~~~~~~~~~~
1040
+ #
1041
+ # The idea here is to basically walk the auth graph of each state set in
1042
+ # tandem, keeping track of which auth events are reachable by each state
1043
+ # set. If we reach an auth event we've already visited (via a different
1044
+ # state set) then we mark that auth event and all ancestors as reachable
1045
+ # by the state set. This requires that we keep track of the auth chains
1046
+ # in memory.
1047
+ #
1048
+ # Doing it in a such a way means that we can stop early if all auth
1049
+ # events we're currently walking are reachable by all state sets.
1050
+ #
1051
+ # *Note*: We can't stop walking an event's auth chain if it is reachable
1052
+ # by all state sets. This is because other auth chains we're walking
1053
+ # might be reachable only via the original auth chain. For example,
1054
+ # given the following auth chain:
1055
+ #
1056
+ # A -> C -> D -> E
1057
+ # / /
1058
+ # B -´---------´
1059
+ #
1060
+ # and state sets {A} and {B} then walking the auth chains of A and B
1061
+ # would immediately show that C is reachable by both. However, if we
1062
+ # stopped at C then we'd only reach E via the auth chain of B and so E
1063
+ # would erroneously get included in the returned difference.
1064
+ #
1065
+ # The other thing that we do is limit the number of auth chains we walk
1066
+ # at once, due to practical limits (i.e. we can only query the database
1067
+ # with a limited set of parameters). We pick the auth chains we walk
1068
+ # each iteration based on their depth, in the hope that events with a
1069
+ # lower depth are likely reachable by those with higher depths.
1070
+ #
1071
+ # We could use any ordering that we believe would give a rough
1072
+ # topological ordering, e.g. origin server timestamp. If the ordering
1073
+ # chosen is not topological then the algorithm still produces the right
1074
+ # result, but perhaps a bit more inefficiently. This is why it is safe
1075
+ # to use "depth" here.
1076
+
1077
+ initial_events = set(state_sets[0]).union(*state_sets[1:])
1078
+
1079
+ # Dict from events in auth chains to which sets *cannot* reach them.
1080
+ # I.e. if the set is empty then all sets can reach the event.
1081
+ event_to_missing_sets = {
1082
+ event_id: {i for i, a in enumerate(state_sets) if event_id not in a}
1083
+ for event_id in initial_events
1084
+ }
1085
+
1086
+ # The sorted list of events whose auth chains we should walk.
1087
+ search: list[tuple[int, str]] = []
1088
+
1089
+ # We need to get the depth of the initial events for sorting purposes.
1090
+ sql = """
1091
+ SELECT depth, event_id FROM events
1092
+ WHERE %s
1093
+ """
1094
+ # the list can be huge, so let's avoid looking them all up in one massive
1095
+ # query.
1096
+ for batch in batch_iter(initial_events, 1000):
1097
+ clause, args = make_in_list_sql_clause(
1098
+ txn.database_engine, "event_id", batch
1099
+ )
1100
+ txn.execute(sql % (clause,), args)
1101
+
1102
+ # I think building a temporary list with fetchall is more efficient than
1103
+ # just `search.extend(txn)`, but this is unconfirmed
1104
+ search.extend(cast(list[tuple[int, str]], txn.fetchall()))
1105
+
1106
+ # sort by depth
1107
+ search.sort()
1108
+
1109
+ # Map from event to its auth events
1110
+ event_to_auth_events: dict[str, set[str]] = {}
1111
+
1112
+ base_sql = """
1113
+ SELECT a.event_id, auth_id, depth
1114
+ FROM event_auth AS a
1115
+ INNER JOIN events AS e ON (e.event_id = a.auth_id)
1116
+ WHERE
1117
+ """
1118
+
1119
+ while search:
1120
+ # Check whether all our current walks are reachable by all state
1121
+ # sets. If so we can bail.
1122
+ if all(not event_to_missing_sets[eid] for _, eid in search):
1123
+ break
1124
+
1125
+ # Fetch the auth events and their depths of the N last events we're
1126
+ # currently walking, either from cache or DB.
1127
+ search, chunk = search[:-100], search[-100:]
1128
+
1129
+ found: list[tuple[str, str, int]] = [] # Results found
1130
+ to_fetch: list[str] = [] # Event IDs to fetch from DB
1131
+ for _, event_id in chunk:
1132
+ res = self._event_auth_cache.get(event_id)
1133
+ if res is None:
1134
+ to_fetch.append(event_id)
1135
+ else:
1136
+ found.extend((event_id, auth_id, depth) for auth_id, depth in res)
1137
+
1138
+ if to_fetch:
1139
+ clause, args = make_in_list_sql_clause(
1140
+ txn.database_engine, "a.event_id", to_fetch
1141
+ )
1142
+ txn.execute(base_sql + clause, args)
1143
+
1144
+ # We parse the results and add the to the `found` set and the
1145
+ # cache (note we need to batch up the results by event ID before
1146
+ # adding to the cache).
1147
+ to_cache: dict[str, list[tuple[str, int]]] = {}
1148
+ for event_id, auth_event_id, auth_event_depth in txn:
1149
+ to_cache.setdefault(event_id, []).append(
1150
+ (auth_event_id, auth_event_depth)
1151
+ )
1152
+ found.append((event_id, auth_event_id, auth_event_depth))
1153
+
1154
+ for event_id, auth_events in to_cache.items():
1155
+ self._event_auth_cache.set(event_id, auth_events)
1156
+
1157
+ for event_id, auth_event_id, auth_event_depth in found:
1158
+ event_to_auth_events.setdefault(event_id, set()).add(auth_event_id)
1159
+
1160
+ sets = event_to_missing_sets.get(auth_event_id)
1161
+ if sets is None:
1162
+ # First time we're seeing this event, so we add it to the
1163
+ # queue of things to fetch.
1164
+ search.append((auth_event_depth, auth_event_id))
1165
+
1166
+ # Assume that this event is unreachable from any of the
1167
+ # state sets until proven otherwise
1168
+ sets = event_to_missing_sets[auth_event_id] = set(
1169
+ range(len(state_sets))
1170
+ )
1171
+ else:
1172
+ # We've previously seen this event, so look up its auth
1173
+ # events and recursively mark all ancestors as reachable
1174
+ # by the current event's state set.
1175
+ a_ids = event_to_auth_events.get(auth_event_id)
1176
+ while a_ids:
1177
+ new_aids = set()
1178
+ for a_id in a_ids:
1179
+ event_to_missing_sets[a_id].intersection_update(
1180
+ event_to_missing_sets[event_id]
1181
+ )
1182
+
1183
+ b = event_to_auth_events.get(a_id)
1184
+ if b:
1185
+ new_aids.update(b)
1186
+
1187
+ a_ids = new_aids
1188
+
1189
+ # Mark that the auth event is reachable by the appropriate sets.
1190
+ sets.intersection_update(event_to_missing_sets[event_id])
1191
+
1192
+ search.sort()
1193
+
1194
+ # Return all events where not all sets can reach them.
1195
+ return {eid for eid, n in event_to_missing_sets.items() if n}
1196
+
1197
+ @trace
1198
+ @tag_args
1199
+ async def get_backfill_points_in_room(
1200
+ self,
1201
+ room_id: str,
1202
+ current_depth: int,
1203
+ limit: int,
1204
+ ) -> list[tuple[str, int]]:
1205
+ """
1206
+ Get the backward extremities to backfill from in the room along with the
1207
+ approximate depth.
1208
+
1209
+ Only returns events that are at a depth lower than or
1210
+ equal to the `current_depth`. Sorted by depth, highest to lowest (descending)
1211
+ so the closest events to the `current_depth` are first in the list.
1212
+
1213
+ We ignore extremities that are newer than the user's current scroll position
1214
+ (ie, those with depth greater than `current_depth`) as:
1215
+ 1. we don't really care about getting events that have happened
1216
+ after our current position; and
1217
+ 2. by the nature of paginating and scrolling back, we have likely
1218
+ previously tried and failed to backfill from that extremity, so
1219
+ to avoid getting "stuck" requesting the same backfill repeatedly
1220
+ we drop those extremities.
1221
+
1222
+ Args:
1223
+ room_id: Room where we want to find the oldest events
1224
+ current_depth: The depth at the user's current scrollback position
1225
+ limit: The max number of backfill points to return
1226
+
1227
+ Returns:
1228
+ List of (event_id, depth) tuples. Sorted by depth, highest to lowest
1229
+ (descending) so the closest events to the `current_depth` are first
1230
+ in the list.
1231
+ """
1232
+
1233
+ def get_backfill_points_in_room_txn(
1234
+ txn: LoggingTransaction, room_id: str
1235
+ ) -> list[tuple[str, int]]:
1236
+ # Assemble a tuple lookup of event_id -> depth for the oldest events
1237
+ # we know of in the room. Backwards extremeties are the oldest
1238
+ # events we know of in the room but we only know of them because
1239
+ # some other event referenced them by prev_event and aren't
1240
+ # persisted in our database yet (meaning we don't know their depth
1241
+ # specifically). So we need to look for the approximate depth from
1242
+ # the events connected to the current backwards extremeties.
1243
+
1244
+ if isinstance(self.database_engine, PostgresEngine):
1245
+ least_function = "LEAST"
1246
+ elif isinstance(self.database_engine, Sqlite3Engine):
1247
+ least_function = "MIN"
1248
+ else:
1249
+ raise RuntimeError("Unknown database engine")
1250
+
1251
+ sql = f"""
1252
+ SELECT backward_extrem.event_id, event.depth FROM events AS event
1253
+ /**
1254
+ * Get the edge connections from the event_edges table
1255
+ * so we can see whether this event's prev_events points
1256
+ * to a backward extremity in the next join.
1257
+ */
1258
+ INNER JOIN event_edges AS edge
1259
+ ON edge.event_id = event.event_id
1260
+ /**
1261
+ * We find the "oldest" events in the room by looking for
1262
+ * events connected to backwards extremeties (oldest events
1263
+ * in the room that we know of so far).
1264
+ */
1265
+ INNER JOIN event_backward_extremities AS backward_extrem
1266
+ ON edge.prev_event_id = backward_extrem.event_id
1267
+ /**
1268
+ * We use this info to make sure we don't retry to use a backfill point
1269
+ * if we've already attempted to backfill from it recently.
1270
+ */
1271
+ LEFT JOIN event_failed_pull_attempts AS failed_backfill_attempt_info
1272
+ ON
1273
+ failed_backfill_attempt_info.room_id = backward_extrem.room_id
1274
+ AND failed_backfill_attempt_info.event_id = backward_extrem.event_id
1275
+ WHERE
1276
+ backward_extrem.room_id = ?
1277
+ /* We only care about non-state edges because we used to use
1278
+ * `event_edges` for two different sorts of "edges" (the current
1279
+ * event DAG, but also a link to the previous state, for state
1280
+ * events). These legacy state event edges can be distinguished by
1281
+ * `is_state` and are removed from the codebase and schema but
1282
+ * because the schema change is in a background update, it's not
1283
+ * necessarily safe to assume that it will have been completed.
1284
+ */
1285
+ AND edge.is_state is FALSE
1286
+ /**
1287
+ * We only want backwards extremities that are older than or at
1288
+ * the same position of the given `current_depth` (where older
1289
+ * means less than the given depth) because we're looking backwards
1290
+ * from the `current_depth` when backfilling.
1291
+ *
1292
+ * current_depth (ignore events that come after this, ignore 2-4)
1293
+ * |
1294
+ * ▼
1295
+ * <oldest-in-time> [0]<--[1]<--[2]<--[3]<--[4] <newest-in-time>
1296
+ */
1297
+ AND event.depth <= ? /* current_depth */
1298
+ /**
1299
+ * Exponential back-off (up to the upper bound) so we don't retry the
1300
+ * same backfill point over and over. ex. 2hr, 4hr, 8hr, 16hr, etc.
1301
+ *
1302
+ * We use `1 << n` as a power of 2 equivalent for compatibility
1303
+ * with older SQLites. The left shift equivalent only works with
1304
+ * powers of 2 because left shift is a binary operation (base-2).
1305
+ * Otherwise, we would use `power(2, n)` or the power operator, `2^n`.
1306
+ */
1307
+ AND (
1308
+ failed_backfill_attempt_info.event_id IS NULL
1309
+ OR ? /* current_time */ >= failed_backfill_attempt_info.last_attempt_ts + (
1310
+ (1 << {least_function}(failed_backfill_attempt_info.num_attempts, ? /* max doubling steps */))
1311
+ * ? /* step */
1312
+ )
1313
+ )
1314
+ /**
1315
+ * Sort from highest (closest to the `current_depth`) to the lowest depth
1316
+ * because the closest are most relevant to backfill from first.
1317
+ * Then tie-break on alphabetical order of the event_ids so we get a
1318
+ * consistent ordering which is nice when asserting things in tests.
1319
+ */
1320
+ ORDER BY event.depth DESC, backward_extrem.event_id DESC
1321
+ LIMIT ?
1322
+ """
1323
+
1324
+ txn.execute(
1325
+ sql,
1326
+ (
1327
+ room_id,
1328
+ current_depth,
1329
+ self.clock.time_msec(),
1330
+ BACKFILL_EVENT_EXPONENTIAL_BACKOFF_MAXIMUM_DOUBLING_STEPS,
1331
+ BACKFILL_EVENT_EXPONENTIAL_BACKOFF_STEP_MILLISECONDS,
1332
+ limit,
1333
+ ),
1334
+ )
1335
+
1336
+ return cast(list[tuple[str, int]], txn.fetchall())
1337
+
1338
+ return await self.db_pool.runInteraction(
1339
+ "get_backfill_points_in_room",
1340
+ get_backfill_points_in_room_txn,
1341
+ room_id,
1342
+ )
1343
+
1344
+ async def get_max_depth_of(
1345
+ self, event_ids: Collection[str]
1346
+ ) -> tuple[str | None, int]:
1347
+ """Returns the event ID and depth for the event that has the max depth from a set of event IDs
1348
+
1349
+ Args:
1350
+ event_ids: The event IDs to calculate the max depth of.
1351
+ """
1352
+ rows = cast(
1353
+ list[tuple[str, int]],
1354
+ await self.db_pool.simple_select_many_batch(
1355
+ table="events",
1356
+ column="event_id",
1357
+ iterable=event_ids,
1358
+ retcols=(
1359
+ "event_id",
1360
+ "depth",
1361
+ ),
1362
+ desc="get_max_depth_of",
1363
+ ),
1364
+ )
1365
+
1366
+ if not rows:
1367
+ return None, 0
1368
+ else:
1369
+ max_depth_event_id = ""
1370
+ current_max_depth = 0
1371
+ for event_id, depth in rows:
1372
+ if depth > current_max_depth:
1373
+ max_depth_event_id = event_id
1374
+ current_max_depth = depth
1375
+
1376
+ return max_depth_event_id, current_max_depth
1377
+
1378
+ async def get_min_depth_of(self, event_ids: list[str]) -> tuple[str | None, int]:
1379
+ """Returns the event ID and depth for the event that has the min depth from a set of event IDs
1380
+
1381
+ Args:
1382
+ event_ids: The event IDs to calculate the max depth of.
1383
+ """
1384
+ rows = cast(
1385
+ list[tuple[str, int]],
1386
+ await self.db_pool.simple_select_many_batch(
1387
+ table="events",
1388
+ column="event_id",
1389
+ iterable=event_ids,
1390
+ retcols=(
1391
+ "event_id",
1392
+ "depth",
1393
+ ),
1394
+ desc="get_min_depth_of",
1395
+ ),
1396
+ )
1397
+
1398
+ if not rows:
1399
+ return None, 0
1400
+ else:
1401
+ min_depth_event_id = ""
1402
+ current_min_depth = MAX_DEPTH
1403
+ for event_id, depth in rows:
1404
+ if depth < current_min_depth:
1405
+ min_depth_event_id = event_id
1406
+ current_min_depth = depth
1407
+
1408
+ return min_depth_event_id, current_min_depth
1409
+
1410
+ async def get_prev_events_for_room(self, room_id: str) -> list[str]:
1411
+ """
1412
+ Gets a subset of the current forward extremities in the given room.
1413
+
1414
+ Limits the result to 10 extremities, so that we can avoid creating
1415
+ events which refer to hundreds of prev_events.
1416
+
1417
+ Args:
1418
+ room_id: room_id
1419
+
1420
+ Returns:
1421
+ The event ids of the forward extremities.
1422
+
1423
+ """
1424
+
1425
+ return await self.db_pool.runInteraction(
1426
+ "get_prev_events_for_room", self._get_prev_events_for_room_txn, room_id
1427
+ )
1428
+
1429
+ def _get_prev_events_for_room_txn(
1430
+ self, txn: LoggingTransaction, room_id: str
1431
+ ) -> list[str]:
1432
+ # we just use the 10 newest events. Older events will become
1433
+ # prev_events of future events.
1434
+
1435
+ sql = """
1436
+ SELECT e.event_id FROM event_forward_extremities AS f
1437
+ INNER JOIN events AS e USING (event_id)
1438
+ WHERE f.room_id = ?
1439
+ ORDER BY e.depth DESC
1440
+ LIMIT 10
1441
+ """
1442
+
1443
+ txn.execute(sql, (room_id,))
1444
+
1445
+ return [row[0] for row in txn]
1446
+
1447
+ async def get_rooms_with_many_extremities(
1448
+ self, min_count: int, limit: int, room_id_filter: Iterable[str]
1449
+ ) -> list[str]:
1450
+ """Get the top rooms with at least N extremities.
1451
+
1452
+ Args:
1453
+ min_count: The minimum number of extremities
1454
+ limit: The maximum number of rooms to return.
1455
+ room_id_filter: room_ids to exclude from the results
1456
+
1457
+ Returns:
1458
+ At most `limit` room IDs that have at least `min_count` extremities,
1459
+ sorted by extremity count.
1460
+ """
1461
+
1462
+ def _get_rooms_with_many_extremities_txn(txn: LoggingTransaction) -> list[str]:
1463
+ where_clause = "1=1"
1464
+ if room_id_filter:
1465
+ where_clause = "room_id NOT IN (%s)" % (
1466
+ ",".join("?" for _ in room_id_filter),
1467
+ )
1468
+
1469
+ sql = """
1470
+ SELECT room_id FROM event_forward_extremities
1471
+ WHERE %s
1472
+ GROUP BY room_id
1473
+ HAVING count(*) > ?
1474
+ ORDER BY count(*) DESC
1475
+ LIMIT ?
1476
+ """ % (where_clause,)
1477
+
1478
+ query_args = list(itertools.chain(room_id_filter, [min_count, limit]))
1479
+ txn.execute(sql, query_args)
1480
+ return [room_id for (room_id,) in txn]
1481
+
1482
+ return await self.db_pool.runInteraction(
1483
+ "get_rooms_with_many_extremities", _get_rooms_with_many_extremities_txn
1484
+ )
1485
+
1486
+ @cached(max_entries=5000, iterable=True)
1487
+ async def get_latest_event_ids_in_room(self, room_id: str) -> frozenset[str]:
1488
+ event_ids = await self.db_pool.simple_select_onecol(
1489
+ table="event_forward_extremities",
1490
+ keyvalues={"room_id": room_id},
1491
+ retcol="event_id",
1492
+ desc="get_latest_event_ids_in_room",
1493
+ )
1494
+ return frozenset(event_ids)
1495
+
1496
+ async def get_min_depth(self, room_id: str) -> int | None:
1497
+ """For the given room, get the minimum depth we have seen for it."""
1498
+ return await self.db_pool.runInteraction(
1499
+ "get_min_depth", self._get_min_depth_interaction, room_id
1500
+ )
1501
+
1502
+ def _get_min_depth_interaction(
1503
+ self, txn: LoggingTransaction, room_id: str
1504
+ ) -> int | None:
1505
+ min_depth = self.db_pool.simple_select_one_onecol_txn(
1506
+ txn,
1507
+ table="room_depth",
1508
+ keyvalues={"room_id": room_id},
1509
+ retcol="min_depth",
1510
+ allow_none=True,
1511
+ )
1512
+
1513
+ return int(min_depth) if min_depth is not None else None
1514
+
1515
+ async def have_room_forward_extremities_changed_since(
1516
+ self,
1517
+ room_id: str,
1518
+ stream_ordering: int,
1519
+ ) -> bool:
1520
+ """Check if the forward extremities in a room have changed since the
1521
+ given stream ordering
1522
+
1523
+ Throws a StoreError if we have since purged the index for
1524
+ stream_orderings from that point.
1525
+ """
1526
+ assert self.stream_ordering_month_ago is not None
1527
+ if stream_ordering <= self.stream_ordering_month_ago:
1528
+ raise StoreError(400, f"stream_ordering too old {stream_ordering}")
1529
+
1530
+ sql = """
1531
+ SELECT 1 FROM stream_ordering_to_exterm
1532
+ WHERE stream_ordering > ? AND room_id = ?
1533
+ LIMIT 1
1534
+ """
1535
+
1536
+ def have_room_forward_extremities_changed_since_txn(
1537
+ txn: LoggingTransaction,
1538
+ ) -> bool:
1539
+ txn.execute(sql, (stream_ordering, room_id))
1540
+ return txn.fetchone() is not None
1541
+
1542
+ return await self.db_pool.runInteraction(
1543
+ "have_room_forward_extremities_changed_since",
1544
+ have_room_forward_extremities_changed_since_txn,
1545
+ )
1546
+
1547
+ @cancellable
1548
+ async def get_forward_extremities_for_room_at_stream_ordering(
1549
+ self, room_id: str, stream_ordering: int
1550
+ ) -> Sequence[str]:
1551
+ """For a given room_id and stream_ordering, return the forward
1552
+ extremeties of the room at that point in "time".
1553
+
1554
+ Throws a StoreError if we have since purged the index for
1555
+ stream_orderings from that point.
1556
+
1557
+ Args:
1558
+ room_id:
1559
+ stream_ordering:
1560
+
1561
+ Returns:
1562
+ A list of event_ids
1563
+ """
1564
+ # We want to make the cache more effective, so we clamp to the last
1565
+ # change before the given ordering.
1566
+ last_change = self._events_stream_cache.get_max_pos_of_last_change(room_id) # type: ignore[attr-defined]
1567
+ if last_change is None:
1568
+ # If the room isn't in the cache we know that the last change was
1569
+ # somewhere before the earliest known position of the cache, so we
1570
+ # can clamp to that.
1571
+ last_change = self._events_stream_cache.get_earliest_known_position() # type: ignore[attr-defined]
1572
+
1573
+ # We don't always have a full stream_to_exterm_id table, e.g. after
1574
+ # the upgrade that introduced it, so we make sure we never ask for a
1575
+ # stream_ordering from before a restart
1576
+ last_change = max(self._stream_order_on_start, last_change) # type: ignore[attr-defined]
1577
+
1578
+ # provided the last_change is recent enough, we now clamp the requested
1579
+ # stream_ordering to it.
1580
+ assert self.stream_ordering_month_ago is not None
1581
+ if last_change > self.stream_ordering_month_ago:
1582
+ stream_ordering = min(last_change, stream_ordering)
1583
+
1584
+ return await self._get_forward_extremeties_for_room(room_id, stream_ordering)
1585
+
1586
+ @cached(max_entries=5000, num_args=2)
1587
+ async def _get_forward_extremeties_for_room(
1588
+ self, room_id: str, stream_ordering: int
1589
+ ) -> Sequence[str]:
1590
+ """For a given room_id and stream_ordering, return the forward
1591
+ extremeties of the room at that point in "time".
1592
+
1593
+ Throws a StoreError if we have since purged the index for
1594
+ stream_orderings from that point.
1595
+ """
1596
+ assert self.stream_ordering_month_ago is not None
1597
+ if stream_ordering <= self.stream_ordering_month_ago:
1598
+ raise StoreError(400, "stream_ordering too old %s" % (stream_ordering,))
1599
+
1600
+ sql = """
1601
+ SELECT event_id FROM stream_ordering_to_exterm
1602
+ INNER JOIN (
1603
+ SELECT room_id, MAX(stream_ordering) AS stream_ordering
1604
+ FROM stream_ordering_to_exterm
1605
+ WHERE stream_ordering <= ? GROUP BY room_id
1606
+ ) AS rms USING (room_id, stream_ordering)
1607
+ WHERE room_id = ?
1608
+ """
1609
+
1610
+ def get_forward_extremeties_for_room_txn(txn: LoggingTransaction) -> list[str]:
1611
+ txn.execute(sql, (stream_ordering, room_id))
1612
+ return [event_id for (event_id,) in txn]
1613
+
1614
+ event_ids = await self.db_pool.runInteraction(
1615
+ "get_forward_extremeties_for_room", get_forward_extremeties_for_room_txn
1616
+ )
1617
+
1618
+ # If we didn't find any IDs, then we must have cleared out the
1619
+ # associated `stream_ordering_to_exterm`.
1620
+ if not event_ids:
1621
+ raise StoreError(400, "stream_ordering too old %s" % (stream_ordering,))
1622
+
1623
+ return event_ids
1624
+
1625
+ def _get_connected_prev_event_backfill_results_txn(
1626
+ self, txn: LoggingTransaction, event_id: str, limit: int
1627
+ ) -> list[BackfillQueueNavigationItem]:
1628
+ """
1629
+ Find any events connected by prev_event the specified event_id.
1630
+
1631
+ Args:
1632
+ txn: The database transaction to use
1633
+ event_id: The event ID to navigate from
1634
+ limit: Max number of event ID's to query for and return
1635
+
1636
+ Returns:
1637
+ List of prev events that the backfill queue can process
1638
+ """
1639
+ # Look for the prev_event_id connected to the given event_id
1640
+ connected_prev_event_query = """
1641
+ SELECT depth, stream_ordering, prev_event_id, events.type FROM event_edges
1642
+ /* Get the depth and stream_ordering of the prev_event_id from the events table */
1643
+ INNER JOIN events
1644
+ ON prev_event_id = events.event_id
1645
+
1646
+ /* exclude outliers from the results (we don't have the state, so cannot
1647
+ * verify if the requesting server can see them).
1648
+ */
1649
+ WHERE NOT events.outlier
1650
+
1651
+ /* Look for an edge which matches the given event_id */
1652
+ AND event_edges.event_id = ? AND NOT event_edges.is_state
1653
+
1654
+ /* Because we can have many events at the same depth,
1655
+ * we want to also tie-break and sort on stream_ordering */
1656
+ ORDER BY depth DESC, stream_ordering DESC
1657
+ LIMIT ?
1658
+ """
1659
+
1660
+ txn.execute(
1661
+ connected_prev_event_query,
1662
+ (event_id, limit),
1663
+ )
1664
+ return [
1665
+ BackfillQueueNavigationItem(
1666
+ depth=row[0],
1667
+ stream_ordering=row[1],
1668
+ event_id=row[2],
1669
+ type=row[3],
1670
+ )
1671
+ for row in txn
1672
+ ]
1673
+
1674
+ async def get_backfill_events(
1675
+ self, room_id: str, seed_event_id_list: list[str], limit: int
1676
+ ) -> list[EventBase]:
1677
+ """Get a list of Events for a given topic that occurred before (and
1678
+ including) the events in seed_event_id_list. Return a list of max size `limit`
1679
+
1680
+ Args:
1681
+ room_id
1682
+ seed_event_id_list
1683
+ limit
1684
+ """
1685
+ event_ids = await self.db_pool.runInteraction(
1686
+ "get_backfill_events",
1687
+ self._get_backfill_events,
1688
+ room_id,
1689
+ seed_event_id_list,
1690
+ limit,
1691
+ )
1692
+ events = await self.get_events_as_list(event_ids)
1693
+ return sorted(
1694
+ # type-ignore: mypy doesn't like negating the int | None stream_ordering.
1695
+ # But it's never None, because these events were previously persisted to the DB.
1696
+ events,
1697
+ key=lambda e: (-e.depth, -e.internal_metadata.stream_ordering), # type: ignore[operator]
1698
+ )
1699
+
1700
+ def _get_backfill_events(
1701
+ self,
1702
+ txn: LoggingTransaction,
1703
+ room_id: str,
1704
+ seed_event_id_list: list[str],
1705
+ limit: int,
1706
+ ) -> set[str]:
1707
+ """
1708
+ We want to make sure that we do a breadth-first, "depth" ordered search.
1709
+ We also handle navigating historical branches of history connected by
1710
+ insertion and batch events.
1711
+ """
1712
+ logger.debug(
1713
+ "_get_backfill_events(room_id=%s): seeding backfill with seed_event_id_list=%s limit=%s",
1714
+ room_id,
1715
+ seed_event_id_list,
1716
+ limit,
1717
+ )
1718
+
1719
+ event_id_results: set[str] = set()
1720
+
1721
+ # In a PriorityQueue, the lowest valued entries are retrieved first.
1722
+ # We're using depth as the priority in the queue and tie-break based on
1723
+ # stream_ordering. Depth is lowest at the oldest-in-time message and
1724
+ # highest and newest-in-time message. We add events to the queue with a
1725
+ # negative depth so that we process the newest-in-time messages first
1726
+ # going backwards in time. stream_ordering follows the same pattern.
1727
+ queue: "PriorityQueue[tuple[int, int, str, str]]" = PriorityQueue()
1728
+
1729
+ for seed_event_id in seed_event_id_list:
1730
+ event_lookup_result = self.db_pool.simple_select_one_txn(
1731
+ txn,
1732
+ table="events",
1733
+ keyvalues={"event_id": seed_event_id, "room_id": room_id},
1734
+ retcols=(
1735
+ "type",
1736
+ "depth",
1737
+ "stream_ordering",
1738
+ ),
1739
+ allow_none=True,
1740
+ )
1741
+
1742
+ if event_lookup_result is not None:
1743
+ event_type, depth, stream_ordering = event_lookup_result
1744
+ logger.debug(
1745
+ "_get_backfill_events(room_id=%s): seed_event_id=%s depth=%s stream_ordering=%s type=%s",
1746
+ room_id,
1747
+ seed_event_id,
1748
+ depth,
1749
+ stream_ordering,
1750
+ event_type,
1751
+ )
1752
+
1753
+ if depth:
1754
+ queue.put((-depth, -stream_ordering, seed_event_id, event_type))
1755
+
1756
+ while not queue.empty() and len(event_id_results) < limit:
1757
+ try:
1758
+ _, _, event_id, event_type = queue.get_nowait()
1759
+ except Empty:
1760
+ break
1761
+
1762
+ if event_id in event_id_results:
1763
+ continue
1764
+
1765
+ event_id_results.add(event_id)
1766
+
1767
+ # Now we just look up the DAG by prev_events as normal
1768
+ connected_prev_event_backfill_results = (
1769
+ self._get_connected_prev_event_backfill_results_txn(
1770
+ txn, event_id, limit - len(event_id_results)
1771
+ )
1772
+ )
1773
+ logger.debug(
1774
+ "_get_backfill_events(room_id=%s): connected_prev_event_backfill_results=%s",
1775
+ room_id,
1776
+ connected_prev_event_backfill_results,
1777
+ )
1778
+ for (
1779
+ connected_prev_event_backfill_item
1780
+ ) in connected_prev_event_backfill_results:
1781
+ if connected_prev_event_backfill_item.event_id not in event_id_results:
1782
+ queue.put(
1783
+ (
1784
+ -connected_prev_event_backfill_item.depth,
1785
+ -connected_prev_event_backfill_item.stream_ordering,
1786
+ connected_prev_event_backfill_item.event_id,
1787
+ connected_prev_event_backfill_item.type,
1788
+ )
1789
+ )
1790
+
1791
+ return event_id_results
1792
+
1793
+ @trace
1794
+ async def record_event_failed_pull_attempt(
1795
+ self, room_id: str, event_id: str, cause: str
1796
+ ) -> None:
1797
+ """
1798
+ Record when we fail to pull an event over federation.
1799
+
1800
+ This information allows us to be more intelligent when we decide to
1801
+ retry (we don't need to fail over and over) and we can process that
1802
+ event in the background so we don't block on it each time.
1803
+
1804
+ Args:
1805
+ room_id: The room where the event failed to pull from
1806
+ event_id: The event that failed to be fetched or processed
1807
+ cause: The error message or reason that we failed to pull the event
1808
+ """
1809
+ logger.debug(
1810
+ "record_event_failed_pull_attempt room_id=%s, event_id=%s, cause=%s",
1811
+ room_id,
1812
+ event_id,
1813
+ cause,
1814
+ )
1815
+ await self.db_pool.runInteraction(
1816
+ "record_event_failed_pull_attempt",
1817
+ self._record_event_failed_pull_attempt_upsert_txn,
1818
+ room_id,
1819
+ event_id,
1820
+ cause,
1821
+ db_autocommit=True, # Safe as it's a single upsert
1822
+ )
1823
+
1824
+ def _record_event_failed_pull_attempt_upsert_txn(
1825
+ self,
1826
+ txn: LoggingTransaction,
1827
+ room_id: str,
1828
+ event_id: str,
1829
+ cause: str,
1830
+ ) -> None:
1831
+ sql = """
1832
+ INSERT INTO event_failed_pull_attempts (
1833
+ room_id, event_id, num_attempts, last_attempt_ts, last_cause
1834
+ )
1835
+ VALUES (?, ?, ?, ?, ?)
1836
+ ON CONFLICT (room_id, event_id) DO UPDATE SET
1837
+ num_attempts=event_failed_pull_attempts.num_attempts + 1,
1838
+ last_attempt_ts=EXCLUDED.last_attempt_ts,
1839
+ last_cause=EXCLUDED.last_cause;
1840
+ """
1841
+
1842
+ txn.execute(sql, (room_id, event_id, 1, self.clock.time_msec(), cause))
1843
+
1844
+ @trace
1845
+ async def get_event_ids_with_failed_pull_attempts(
1846
+ self, event_ids: StrCollection
1847
+ ) -> set[str]:
1848
+ """
1849
+ Filter the given list of `event_ids` and return events which have any failed
1850
+ pull attempts.
1851
+
1852
+ Args:
1853
+ event_ids: A list of events to filter down.
1854
+
1855
+ Returns:
1856
+ A filtered down list of `event_ids` that have previous failed pull attempts.
1857
+ """
1858
+
1859
+ rows = cast(
1860
+ list[tuple[str]],
1861
+ await self.db_pool.simple_select_many_batch(
1862
+ table="event_failed_pull_attempts",
1863
+ column="event_id",
1864
+ iterable=event_ids,
1865
+ keyvalues={},
1866
+ retcols=("event_id",),
1867
+ desc="get_event_ids_with_failed_pull_attempts",
1868
+ ),
1869
+ )
1870
+ return {row[0] for row in rows}
1871
+
1872
+ @trace
1873
+ async def get_event_ids_to_not_pull_from_backoff(
1874
+ self,
1875
+ room_id: str,
1876
+ event_ids: Collection[str],
1877
+ ) -> dict[str, int]:
1878
+ """
1879
+ Filter down the events to ones that we've failed to pull before recently. Uses
1880
+ exponential backoff.
1881
+
1882
+ Args:
1883
+ room_id: The room that the events belong to
1884
+ event_ids: A list of events to filter down
1885
+
1886
+ Returns:
1887
+ A dictionary of event_ids that should not be attempted to be pulled and the
1888
+ next timestamp at which we may try pulling them again.
1889
+ """
1890
+ event_failed_pull_attempts = cast(
1891
+ list[tuple[str, int, int]],
1892
+ await self.db_pool.simple_select_many_batch(
1893
+ table="event_failed_pull_attempts",
1894
+ column="event_id",
1895
+ iterable=event_ids,
1896
+ keyvalues={},
1897
+ retcols=(
1898
+ "event_id",
1899
+ "last_attempt_ts",
1900
+ "num_attempts",
1901
+ ),
1902
+ desc="get_event_ids_to_not_pull_from_backoff",
1903
+ ),
1904
+ )
1905
+
1906
+ current_time = self.clock.time_msec()
1907
+
1908
+ event_ids_with_backoff = {}
1909
+ for event_id, last_attempt_ts, num_attempts in event_failed_pull_attempts:
1910
+ # Exponential back-off (up to the upper bound) so we don't try to
1911
+ # pull the same event over and over. ex. 2hr, 4hr, 8hr, 16hr, etc.
1912
+ backoff_end_time = (
1913
+ last_attempt_ts
1914
+ + (
1915
+ 2
1916
+ ** min(
1917
+ num_attempts,
1918
+ BACKFILL_EVENT_EXPONENTIAL_BACKOFF_MAXIMUM_DOUBLING_STEPS,
1919
+ )
1920
+ )
1921
+ * BACKFILL_EVENT_EXPONENTIAL_BACKOFF_STEP_MILLISECONDS
1922
+ )
1923
+
1924
+ if current_time < backoff_end_time: # `backoff_end_time` is exclusive
1925
+ event_ids_with_backoff[event_id] = backoff_end_time
1926
+
1927
+ return event_ids_with_backoff
1928
+
1929
+ async def get_missing_events(
1930
+ self,
1931
+ room_id: str,
1932
+ earliest_events: list[str],
1933
+ latest_events: list[str],
1934
+ limit: int,
1935
+ ) -> list[EventBase]:
1936
+ ids = await self.db_pool.runInteraction(
1937
+ "get_missing_events",
1938
+ self._get_missing_events,
1939
+ room_id,
1940
+ earliest_events,
1941
+ latest_events,
1942
+ limit,
1943
+ )
1944
+ return await self.get_events_as_list(ids)
1945
+
1946
+ def _get_missing_events(
1947
+ self,
1948
+ txn: LoggingTransaction,
1949
+ room_id: str,
1950
+ earliest_events: list[str],
1951
+ latest_events: list[str],
1952
+ limit: int,
1953
+ ) -> list[str]:
1954
+ seen_events = set(earliest_events)
1955
+ front = set(latest_events) - seen_events
1956
+ event_results: list[str] = []
1957
+
1958
+ query = (
1959
+ "SELECT prev_event_id FROM event_edges "
1960
+ "WHERE event_id = ? AND NOT is_state "
1961
+ "LIMIT ?"
1962
+ )
1963
+
1964
+ while front and len(event_results) < limit:
1965
+ new_front = set()
1966
+ for event_id in front:
1967
+ txn.execute(query, (event_id, limit - len(event_results)))
1968
+ new_results = {t[0] for t in txn} - seen_events
1969
+
1970
+ new_front |= new_results
1971
+ seen_events |= new_results
1972
+ event_results.extend(new_results)
1973
+
1974
+ front = new_front
1975
+
1976
+ # we built the list working backwards from latest_events; we now need to
1977
+ # reverse it so that the events are approximately chronological.
1978
+ event_results.reverse()
1979
+ return event_results
1980
+
1981
+ @trace
1982
+ @tag_args
1983
+ async def get_successor_events(self, event_id: str) -> list[str]:
1984
+ """Fetch all events that have the given event as a prev event
1985
+
1986
+ Args:
1987
+ event_id: The event to search for as a prev_event.
1988
+ """
1989
+ return await self.db_pool.simple_select_onecol(
1990
+ table="event_edges",
1991
+ keyvalues={"prev_event_id": event_id},
1992
+ retcol="event_id",
1993
+ desc="get_successor_events",
1994
+ )
1995
+
1996
+ @wrap_as_background_process("delete_old_forward_extrem_cache")
1997
+ async def _delete_old_forward_extrem_cache(self) -> None:
1998
+ def _delete_old_forward_extrem_cache_txn(txn: LoggingTransaction) -> None:
1999
+ sql = """
2000
+ DELETE FROM stream_ordering_to_exterm
2001
+ WHERE stream_ordering < ?
2002
+ """
2003
+ txn.execute(sql, (self.stream_ordering_month_ago,))
2004
+
2005
+ await self.db_pool.runInteraction(
2006
+ "_delete_old_forward_extrem_cache",
2007
+ _delete_old_forward_extrem_cache_txn,
2008
+ )
2009
+
2010
+ async def insert_received_event_to_staging(
2011
+ self, origin: str, event: EventBase
2012
+ ) -> None:
2013
+ """Insert a newly received event from federation into the staging area."""
2014
+
2015
+ # We use an upsert here to handle the case where we see the same event
2016
+ # from the same server multiple times.
2017
+ await self.db_pool.simple_upsert(
2018
+ table="federation_inbound_events_staging",
2019
+ keyvalues={
2020
+ "origin": origin,
2021
+ "event_id": event.event_id,
2022
+ },
2023
+ values={},
2024
+ insertion_values={
2025
+ "room_id": event.room_id,
2026
+ "received_ts": self.clock.time_msec(),
2027
+ "event_json": json_encoder.encode(event.get_dict()),
2028
+ "internal_metadata": json_encoder.encode(
2029
+ event.internal_metadata.get_dict()
2030
+ ),
2031
+ },
2032
+ desc="insert_received_event_to_staging",
2033
+ )
2034
+
2035
+ async def remove_received_event_from_staging(
2036
+ self,
2037
+ origin: str,
2038
+ event_id: str,
2039
+ ) -> int | None:
2040
+ """Remove the given event from the staging area.
2041
+
2042
+ Returns:
2043
+ The received_ts of the row that was deleted, if any.
2044
+ """
2045
+
2046
+ def _remove_received_event_from_staging_txn(
2047
+ txn: LoggingTransaction,
2048
+ ) -> int | None:
2049
+ sql = """
2050
+ DELETE FROM federation_inbound_events_staging
2051
+ WHERE origin = ? AND event_id = ?
2052
+ RETURNING received_ts
2053
+ """
2054
+
2055
+ txn.execute(sql, (origin, event_id))
2056
+ row = cast(tuple[int] | None, txn.fetchone())
2057
+
2058
+ if row is None:
2059
+ return None
2060
+
2061
+ return row[0]
2062
+
2063
+ return await self.db_pool.runInteraction(
2064
+ "remove_received_event_from_staging",
2065
+ _remove_received_event_from_staging_txn,
2066
+ db_autocommit=True,
2067
+ )
2068
+
2069
+ async def get_next_staged_event_id_for_room(
2070
+ self,
2071
+ room_id: str,
2072
+ ) -> tuple[str, str] | None:
2073
+ """
2074
+ Get the next event ID in the staging area for the given room.
2075
+
2076
+ Returns:
2077
+ Tuple of the `origin` and `event_id`
2078
+ """
2079
+
2080
+ def _get_next_staged_event_id_for_room_txn(
2081
+ txn: LoggingTransaction,
2082
+ ) -> tuple[str, str] | None:
2083
+ sql = """
2084
+ SELECT origin, event_id
2085
+ FROM federation_inbound_events_staging
2086
+ WHERE room_id = ?
2087
+ ORDER BY received_ts ASC
2088
+ LIMIT 1
2089
+ """
2090
+
2091
+ txn.execute(sql, (room_id,))
2092
+
2093
+ return cast(tuple[str, str] | None, txn.fetchone())
2094
+
2095
+ return await self.db_pool.runInteraction(
2096
+ "get_next_staged_event_id_for_room", _get_next_staged_event_id_for_room_txn
2097
+ )
2098
+
2099
+ async def get_next_staged_event_for_room(
2100
+ self,
2101
+ room_id: str,
2102
+ room_version: RoomVersion,
2103
+ ) -> tuple[str, EventBase] | None:
2104
+ """Get the next event in the staging area for the given room."""
2105
+
2106
+ def _get_next_staged_event_for_room_txn(
2107
+ txn: LoggingTransaction,
2108
+ ) -> tuple[str, str, str] | None:
2109
+ sql = """
2110
+ SELECT event_json, internal_metadata, origin
2111
+ FROM federation_inbound_events_staging
2112
+ WHERE room_id = ?
2113
+ ORDER BY received_ts ASC
2114
+ LIMIT 1
2115
+ """
2116
+ txn.execute(sql, (room_id,))
2117
+
2118
+ return cast(tuple[str, str, str] | None, txn.fetchone())
2119
+
2120
+ row = await self.db_pool.runInteraction(
2121
+ "get_next_staged_event_for_room", _get_next_staged_event_for_room_txn
2122
+ )
2123
+
2124
+ if not row:
2125
+ return None
2126
+
2127
+ event_d = db_to_json(row[0])
2128
+ internal_metadata_d = db_to_json(row[1])
2129
+ origin = row[2]
2130
+
2131
+ event = make_event_from_dict(
2132
+ event_dict=event_d,
2133
+ room_version=room_version,
2134
+ internal_metadata_dict=internal_metadata_d,
2135
+ )
2136
+
2137
+ return origin, event
2138
+
2139
+ async def prune_staged_events_in_room(
2140
+ self,
2141
+ room_id: str,
2142
+ room_version: RoomVersion,
2143
+ ) -> bool:
2144
+ """Checks if there are lots of staged events for the room, and if so
2145
+ prune them down.
2146
+
2147
+ Returns:
2148
+ Whether any events were pruned
2149
+ """
2150
+
2151
+ # First check the size of the queue.
2152
+ count = await self.db_pool.simple_select_one_onecol(
2153
+ table="federation_inbound_events_staging",
2154
+ keyvalues={"room_id": room_id},
2155
+ retcol="COUNT(*)",
2156
+ desc="prune_staged_events_in_room_count",
2157
+ )
2158
+
2159
+ if count < 100:
2160
+ return False
2161
+
2162
+ # If the queue is too large, then we want clear the entire queue,
2163
+ # keeping only the forward extremities (i.e. the events not referenced
2164
+ # by other events in the queue). We do this so that we can always
2165
+ # backpaginate in all the events we have dropped.
2166
+ rows = cast(
2167
+ list[tuple[str, str]],
2168
+ await self.db_pool.simple_select_list(
2169
+ table="federation_inbound_events_staging",
2170
+ keyvalues={"room_id": room_id},
2171
+ retcols=("event_id", "event_json"),
2172
+ desc="prune_staged_events_in_room_fetch",
2173
+ ),
2174
+ )
2175
+
2176
+ # Find the set of events referenced by those in the queue, as well as
2177
+ # collecting all the event IDs in the queue.
2178
+ referenced_events: set[str] = set()
2179
+ seen_events: set[str] = set()
2180
+ for event_id, event_json in rows:
2181
+ seen_events.add(event_id)
2182
+ event_d = db_to_json(event_json)
2183
+
2184
+ # We don't bother parsing the dicts into full blown event objects,
2185
+ # as that is needlessly expensive.
2186
+
2187
+ # We haven't checked that the `prev_events` have the right format
2188
+ # yet, so we check as we go.
2189
+ prev_events = event_d.get("prev_events", [])
2190
+ if not isinstance(prev_events, list):
2191
+ logger.info("Invalid prev_events for %s", event_id)
2192
+ continue
2193
+
2194
+ if room_version.event_format == EventFormatVersions.ROOM_V1_V2:
2195
+ for prev_event_tuple in prev_events:
2196
+ if (
2197
+ not isinstance(prev_event_tuple, list)
2198
+ or len(prev_event_tuple) != 2
2199
+ ):
2200
+ logger.info("Invalid prev_events for %s", event_id)
2201
+ break
2202
+
2203
+ prev_event_id = prev_event_tuple[0]
2204
+ if not isinstance(prev_event_id, str):
2205
+ logger.info("Invalid prev_events for %s", event_id)
2206
+ break
2207
+
2208
+ referenced_events.add(prev_event_id)
2209
+ else:
2210
+ for prev_event_id in prev_events:
2211
+ if not isinstance(prev_event_id, str):
2212
+ logger.info("Invalid prev_events for %s", event_id)
2213
+ break
2214
+
2215
+ referenced_events.add(prev_event_id)
2216
+
2217
+ to_delete = referenced_events & seen_events
2218
+ if not to_delete:
2219
+ return False
2220
+
2221
+ pdus_pruned_from_federation_queue.labels(
2222
+ **{SERVER_NAME_LABEL: self.server_name}
2223
+ ).inc(len(to_delete))
2224
+ logger.info(
2225
+ "Pruning %d events in room %s from federation queue",
2226
+ len(to_delete),
2227
+ room_id,
2228
+ )
2229
+
2230
+ await self.db_pool.simple_delete_many(
2231
+ table="federation_inbound_events_staging",
2232
+ keyvalues={"room_id": room_id},
2233
+ iterable=to_delete,
2234
+ column="event_id",
2235
+ desc="prune_staged_events_in_room_delete",
2236
+ )
2237
+
2238
+ return True
2239
+
2240
+ async def get_all_rooms_with_staged_incoming_events(self) -> list[str]:
2241
+ """Get the room IDs of all events currently staged."""
2242
+ return await self.db_pool.simple_select_onecol(
2243
+ table="federation_inbound_events_staging",
2244
+ keyvalues={},
2245
+ retcol="DISTINCT room_id",
2246
+ desc="get_all_rooms_with_staged_incoming_events",
2247
+ )
2248
+
2249
+ @wrap_as_background_process("_get_stats_for_federation_staging")
2250
+ async def _get_stats_for_federation_staging(self) -> None:
2251
+ """Update the prometheus metrics for the inbound federation staging area."""
2252
+
2253
+ def _get_stats_for_federation_staging_txn(
2254
+ txn: LoggingTransaction,
2255
+ ) -> tuple[int, int]:
2256
+ txn.execute("SELECT count(*) FROM federation_inbound_events_staging")
2257
+ (count,) = cast(tuple[int], txn.fetchone())
2258
+
2259
+ txn.execute(
2260
+ "SELECT min(received_ts) FROM federation_inbound_events_staging"
2261
+ )
2262
+
2263
+ (received_ts,) = cast(tuple[int | None], txn.fetchone())
2264
+
2265
+ # If there is nothing in the staging area default it to 0.
2266
+ age = 0
2267
+ if received_ts is not None:
2268
+ age = self.clock.time_msec() - received_ts
2269
+
2270
+ return count, age
2271
+
2272
+ count, age = await self.db_pool.runInteraction(
2273
+ "_get_stats_for_federation_staging", _get_stats_for_federation_staging_txn
2274
+ )
2275
+
2276
+ number_pdus_in_federation_queue.labels(
2277
+ **{SERVER_NAME_LABEL: self.server_name}
2278
+ ).set(count)
2279
+ oldest_pdu_in_federation_staging.labels(
2280
+ **{SERVER_NAME_LABEL: self.server_name}
2281
+ ).set(age)
2282
+
2283
+ async def clean_room_for_join(self, room_id: str) -> None:
2284
+ await self.db_pool.runInteraction(
2285
+ "clean_room_for_join", self._clean_room_for_join_txn, room_id
2286
+ )
2287
+
2288
+ def _clean_room_for_join_txn(self, txn: LoggingTransaction, room_id: str) -> None:
2289
+ query = "DELETE FROM event_forward_extremities WHERE room_id = ?"
2290
+
2291
+ txn.execute(query, (room_id,))
2292
+ self._invalidate_cache_and_stream(
2293
+ txn, self.get_latest_event_ids_in_room, (room_id,)
2294
+ )
2295
+
2296
+
2297
+ class EventFederationStore(EventFederationWorkerStore):
2298
+ """Responsible for storing and serving up the various graphs associated
2299
+ with an event. Including the main event graph and the auth chains for an
2300
+ event.
2301
+
2302
+ Also has methods for getting the front (latest) and back (oldest) edges
2303
+ of the event graphs. These are used to generate the parents for new events
2304
+ and backfilling from another server respectively.
2305
+ """
2306
+
2307
+ EVENT_AUTH_STATE_ONLY = "event_auth_state_only"
2308
+
2309
+ def __init__(
2310
+ self,
2311
+ database: DatabasePool,
2312
+ db_conn: LoggingDatabaseConnection,
2313
+ hs: "HomeServer",
2314
+ ):
2315
+ super().__init__(database, db_conn, hs)
2316
+
2317
+ self.db_pool.updates.register_background_update_handler(
2318
+ self.EVENT_AUTH_STATE_ONLY, self._background_delete_non_state_event_auth
2319
+ )
2320
+
2321
+ async def _background_delete_non_state_event_auth(
2322
+ self, progress: JsonDict, batch_size: int
2323
+ ) -> int:
2324
+ def delete_event_auth(txn: LoggingTransaction) -> bool:
2325
+ target_min_stream_id = progress.get("target_min_stream_id_inclusive")
2326
+ max_stream_id = progress.get("max_stream_id_exclusive")
2327
+
2328
+ if not target_min_stream_id or not max_stream_id:
2329
+ txn.execute("SELECT COALESCE(MIN(stream_ordering), 0) FROM events")
2330
+ rows = txn.fetchall()
2331
+ target_min_stream_id = rows[0][0]
2332
+
2333
+ txn.execute("SELECT COALESCE(MAX(stream_ordering), 0) FROM events")
2334
+ rows = txn.fetchall()
2335
+ max_stream_id = rows[0][0]
2336
+
2337
+ min_stream_id = max_stream_id - batch_size
2338
+
2339
+ sql = """
2340
+ DELETE FROM event_auth
2341
+ WHERE event_id IN (
2342
+ SELECT event_id FROM events
2343
+ LEFT JOIN state_events AS se USING (room_id, event_id)
2344
+ WHERE ? <= stream_ordering AND stream_ordering < ?
2345
+ AND se.state_key IS null
2346
+ )
2347
+ """
2348
+
2349
+ txn.execute(sql, (min_stream_id, max_stream_id))
2350
+
2351
+ new_progress = {
2352
+ "target_min_stream_id_inclusive": target_min_stream_id,
2353
+ "max_stream_id_exclusive": min_stream_id,
2354
+ }
2355
+
2356
+ self.db_pool.updates._background_update_progress_txn(
2357
+ txn, self.EVENT_AUTH_STATE_ONLY, new_progress
2358
+ )
2359
+
2360
+ return min_stream_id >= target_min_stream_id
2361
+
2362
+ result = await self.db_pool.runInteraction(
2363
+ self.EVENT_AUTH_STATE_ONLY, delete_event_auth
2364
+ )
2365
+
2366
+ if not result:
2367
+ await self.db_pool.updates._end_background_update(
2368
+ self.EVENT_AUTH_STATE_ONLY
2369
+ )
2370
+
2371
+ return batch_size
2372
+
2373
+
2374
+ def _materialize(
2375
+ origin_chain_id: int,
2376
+ origin_sequence_number: int,
2377
+ links: dict[int, list[tuple[int, int, int]]],
2378
+ materialized: dict[int, int],
2379
+ backwards: bool = True,
2380
+ ) -> None:
2381
+ """Helper function for fetching auth chain links. For a given origin chain
2382
+ ID / sequence number and a dictionary of links, updates the materialized
2383
+ dict with the reachable chains.
2384
+
2385
+ To get a dict of all chains reachable from a set of chains this function can
2386
+ be called in a loop, once per origin chain with the same links and
2387
+ materialized args. The materialized dict will the result.
2388
+
2389
+ Args:
2390
+ origin_chain_id, origin_sequence_number
2391
+ links: map of the links between chains as a dict from origin chain ID
2392
+ to list of 3-tuples of origin sequence number, target chain ID and
2393
+ target sequence number.
2394
+ materialized: dict to update with new reachability information, as a
2395
+ map from chain ID to max sequence number reachable.
2396
+ backwards: If True, walks backwards down the chains. If False, walks forwards from the chains.
2397
+ """
2398
+
2399
+ # Do a standard graph traversal.
2400
+ stack = [(origin_chain_id, origin_sequence_number)]
2401
+
2402
+ while stack:
2403
+ c, s = stack.pop()
2404
+
2405
+ chain_links = links.get(c, [])
2406
+ for (
2407
+ sequence_number,
2408
+ target_chain_id,
2409
+ target_sequence_number,
2410
+ ) in chain_links:
2411
+ if backwards:
2412
+ # Ignore any links that are higher up the chain
2413
+ if sequence_number > s:
2414
+ continue
2415
+
2416
+ # Check if we have already visited the target chain before, if so we
2417
+ # can skip it.
2418
+ if materialized.get(target_chain_id, 0) < target_sequence_number:
2419
+ stack.append((target_chain_id, target_sequence_number))
2420
+ materialized[target_chain_id] = target_sequence_number
2421
+ else:
2422
+ # Ignore any links that are lower down the chain.
2423
+ if sequence_number < s:
2424
+ continue
2425
+ # Check if we have already visited the target chain before, if so we
2426
+ # can skip it.
2427
+ if (
2428
+ materialized.get(target_chain_id, MAX_CHAIN_LENGTH)
2429
+ > target_sequence_number
2430
+ ):
2431
+ stack.append((target_chain_id, target_sequence_number))
2432
+ materialized[target_chain_id] = target_sequence_number
2433
+
2434
+
2435
+ def _generate_forward_links(
2436
+ links: dict[int, list[tuple[int, int, int]]],
2437
+ ) -> dict[int, list[tuple[int, int, int]]]:
2438
+ """Reverse the input links from the given backwards links"""
2439
+ new_links: dict[int, list[tuple[int, int, int]]] = {}
2440
+ for origin_chain_id, chain_links in links.items():
2441
+ for origin_seq_num, target_chain_id, target_seq_num in chain_links:
2442
+ new_links.setdefault(target_chain_id, []).append(
2443
+ (target_seq_num, origin_chain_id, origin_seq_num)
2444
+ )
2445
+ return new_links
2446
+
2447
+
2448
+ def accumulate_forwards_reachable_events(
2449
+ conflicted_forwards_reachable: dict[int, int],
2450
+ back_links: dict[int, list[tuple[int, int, int]]],
2451
+ conflicted_chain_positions: dict[str, tuple[int, int]],
2452
+ ) -> None:
2453
+ """Accumulate new forwards reachable events using the back_links provided.
2454
+
2455
+ Accumulating forwards reachable information is quite different from backwards reachable information
2456
+ because _get_chain_links returns the entire linkage information for backwards reachable events,
2457
+ but not _forwards_ reachable events. We are only interested in the forwards reachable information
2458
+ that is encoded in the backwards reachable links, so we can just invert all the operations we do
2459
+ for backwards reachable events to calculate a subset of forwards reachable information. The
2460
+ caveat with this approach is that it is a _subset_. This means new back_links may encode new
2461
+ forwards reachable information which we also need. Consider this scenario:
2462
+
2463
+ A <-- B <-- C <--- D <-- E <-- F Chain 1
2464
+ |
2465
+ `----- G <-- H <-- I Chain 2
2466
+ |
2467
+ `---- J <-- K Chain 3
2468
+
2469
+ Now consider what happens when B is a conflicted event. _get_chain_links returns the conflicted
2470
+ chain and ALL links heading towards the root of the graph. This means we will know the
2471
+ Chain 1 to Chain 2 link via C (as all links for the chain are returned, not strictly ones with
2472
+ a lower sequence number), but we will NOT know the Chain 2 to Chain 3 link via H. We can be
2473
+ blissfully unaware of Chain 3 entirely, if and only if there isn't some other conflicted event
2474
+ on that chain. Consider what happens when K is /also/ conflicted. _get_chain_links will generate
2475
+ two iterations: one for B and one for K. It's important that we re-evaluate the forwards reachable
2476
+ information for B to include Chain 3 when we process the K iteration, hence we are "accumulating"
2477
+ forwards reachability information.
2478
+
2479
+ NB: We don't consider 'additional backwards reachable events' here because they have no effect
2480
+ on forwards reachability calculations, only backwards.
2481
+
2482
+ Args:
2483
+ conflicted_forwards_reachable: The materialised dict of forwards reachable information.
2484
+ The output to this function are stored here.
2485
+ back_links: One iteration of _get_chain_links which encodes backwards reachable information.
2486
+ conflicted_chain_positions: The conflicted events.
2487
+ """
2488
+ # links go backwards but we want them to go forwards as well for v2.1
2489
+ fwd_links = _generate_forward_links(back_links)
2490
+
2491
+ # for each conflicted event, accumulate forwards reachability information
2492
+ for (
2493
+ conflicted_chain_id,
2494
+ conflicted_chain_seq,
2495
+ ) in conflicted_chain_positions.values():
2496
+ # the conflicted event itself encodes reachability information
2497
+ # e.g if D was conflicted, it encodes E,F as forwards reachable.
2498
+ conflicted_forwards_reachable[conflicted_chain_id] = min(
2499
+ conflicted_chain_seq,
2500
+ conflicted_forwards_reachable.get(conflicted_chain_id, MAX_CHAIN_LENGTH),
2501
+ )
2502
+ # Walk from the conflicted event forwards to explore the links.
2503
+ # This function checks if we've visited the chain before and skips reprocessing, so this
2504
+ # does not repeatedly traverse the graph.
2505
+ _materialize(
2506
+ conflicted_chain_id,
2507
+ conflicted_chain_seq,
2508
+ fwd_links,
2509
+ conflicted_forwards_reachable,
2510
+ backwards=False,
2511
+ )