diff options
author | David Robertson <davidr@element.io> | 2022-06-09 19:21:18 +0100 |
---|---|---|
committer | David Robertson <davidr@element.io> | 2022-06-15 17:23:26 +0100 |
commit | 087aa366a6c29788fde4ef14a80d638bcf523f74 (patch) | |
tree | 4baa34467e07af3115022aeab3b09fc7ae814e2f | |
parent | Sort failing jobs in Complement CI to the top of the logs to make them easier... (diff) | |
download | synapse-087aa366a6c29788fde4ef14a80d638bcf523f74.tar.xz |
Quick and dirty stateres script
-rwxr-xr-x | synapse/_scripts/debug_state_res.py | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/synapse/_scripts/debug_state_res.py b/synapse/_scripts/debug_state_res.py new file mode 100755 index 0000000000..39eae5d3c1 --- /dev/null +++ b/synapse/_scripts/debug_state_res.py @@ -0,0 +1,121 @@ +#! /usr/bin/env python +import argparse +import logging +import sys +from pprint import pformat +from unittest.mock import MagicMock, patch + +import yaml + +from twisted.internet import task + +from synapse.config._base import RootConfig +from synapse.config.cache import CacheConfig +from synapse.config.database import DatabaseConfig +from synapse.config.homeserver import HomeServerConfig +from synapse.config.workers import WorkerConfig +from synapse.server import HomeServer +from synapse.state import StateResolutionStore +from synapse.storage.databases.main.event_federation import EventFederationWorkerStore +from synapse.storage.databases.main.events_worker import EventsWorkerStore +from synapse.storage.databases.main.room import RoomWorkerStore +from synapse.storage.databases.main.state import StateGroupWorkerStore +from synapse.types import ISynapseReactor + +logger = logging.getLogger(sys.argv[0]) + + +class Config(RootConfig): + config_classes = [DatabaseConfig, WorkerConfig, CacheConfig] + + +def load_config(source: str) -> Config: + data = yaml.safe_load(source) + data["worker_name"] = "stateres-debug" + + config = Config() + config.parse_config_dict(data, "DUMMYPATH", "DUMMYPATH") + config.key = MagicMock() # Don't bother creating signing keys + return config + + +class DataStore( + StateGroupWorkerStore, + EventFederationWorkerStore, + EventsWorkerStore, + RoomWorkerStore, +): + pass + + +class MockHomeserver(HomeServer): + DATASTORE_CLASS = DataStore # type: ignore [assignment] + + def __init__(self, config: HomeServerConfig): + super(MockHomeserver, self).__init__( + hostname="stateres-debug", + config=config, + ) + + +async def main(reactor: ISynapseReactor, args: argparse.Namespace) -> None: + config = load_config(args.config_file) + hs = MockHomeserver(config) + with patch("synapse.storage.databases.prepare_database"), patch( + "synapse.storage.database.BackgroundUpdater" + ), patch("synapse.storage.databases.main.events_worker.MultiWriterIdGenerator"): + hs.setup() + + # Fetch the event in question. + event = await hs.get_datastores().main.get_event(args.event_id) + assert event is not None + logger.info("event %s has %d parents", event.event_id, len(event.prev_event_ids())) + + state_after_parents = [] + for i, prev_event_id in enumerate(event.prev_event_ids()): + logger.info("parent %d: %s", i, prev_event_id) + state_after_parents.append( + await hs.get_storage_controllers().state.get_state_ids_for_event( + prev_event_id + ) + ) + + result = await hs.get_state_resolution_handler().resolve_events_with_store( + event.room_id, + event.room_version.identifier, + state_after_parents, + event_map=None, + state_res_store=StateResolutionStore(hs.get_datastores().main), + ) + + logger.info("State resolved at %s:", event.event_id) + logger.info(pformat(result)) + + if args.debug: + print( + f"see state_after_parents[i] for i in range({len(state_after_parents)}" + " and result", + file=sys.stderr, + ) + breakpoint() + + +parser = argparse.ArgumentParser( + description="Explain the calculation which resolves state prior before an event" +) +parser.add_argument("event_id", help="the event ID to be resolved") +parser.add_argument( + "config_file", help="Synapse config file", type=argparse.FileType("r") +) +parser.add_argument("--verbose", "-v", help="Log verbosely", action="store_true") +parser.add_argument( + "--debug", "-d", help="Enter debugger after state is resolved", action="store_true" +) + + +if __name__ == "__main__": + args = parser.parse_args() + logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO) + logging.getLogger("synapse.util").setLevel(logging.ERROR) + logging.getLogger("synapse.storage").setLevel(logging.ERROR) + task.react(main, [parser.parse_args()]) |