update_database 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Copyright 2019 The Matrix.org Foundation C.I.C.
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. import argparse
  17. import logging
  18. import sys
  19. import yaml
  20. from twisted.internet import defer, reactor
  21. import synapse
  22. from synapse.config.homeserver import HomeServerConfig
  23. from synapse.metrics.background_process_metrics import run_as_background_process
  24. from synapse.server import HomeServer
  25. from synapse.storage import DataStore
  26. from synapse.util.versionstring import get_version_string
  27. logger = logging.getLogger("update_database")
  28. class MockHomeserver(HomeServer):
  29. DATASTORE_CLASS = DataStore
  30. def __init__(self, config, **kwargs):
  31. super(MockHomeserver, self).__init__(
  32. config.server_name, reactor=reactor, config=config, **kwargs
  33. )
  34. self.version_string = "Synapse/" + get_version_string(synapse)
  35. if __name__ == "__main__":
  36. parser = argparse.ArgumentParser(
  37. description=(
  38. "Updates a synapse database to the latest schema and runs background updates"
  39. " on it."
  40. )
  41. )
  42. parser.add_argument("-v", action="store_true")
  43. parser.add_argument(
  44. "--database-config",
  45. type=argparse.FileType("r"),
  46. required=True,
  47. help="A database config file for either a SQLite3 database or a PostgreSQL one.",
  48. )
  49. args = parser.parse_args()
  50. logging_config = {
  51. "level": logging.DEBUG if args.v else logging.INFO,
  52. "format": "%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(message)s",
  53. }
  54. logging.basicConfig(**logging_config)
  55. # Load, process and sanity-check the config.
  56. hs_config = yaml.safe_load(args.database_config)
  57. if "database" not in hs_config:
  58. sys.stderr.write("The configuration file must have a 'database' section.\n")
  59. sys.exit(4)
  60. config = HomeServerConfig()
  61. config.parse_config_dict(hs_config, "", "")
  62. # Instantiate and initialise the homeserver object.
  63. hs = MockHomeserver(config)
  64. # Setup instantiates the store within the homeserver object and updates the
  65. # DB.
  66. hs.setup()
  67. store = hs.get_datastore()
  68. async def run_background_updates():
  69. await store.db_pool.updates.run_background_updates(sleep=False)
  70. # Stop the reactor to exit the script once every background update is run.
  71. reactor.stop()
  72. def run():
  73. # Apply all background updates on the database.
  74. defer.ensureDeferred(
  75. run_as_background_process("background_updates", run_background_updates)
  76. )
  77. reactor.callWhenRunning(run)
  78. reactor.run()