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

Commit

Permalink
Add experimental 'databases' config (#6580)
Browse files Browse the repository at this point in the history
  • Loading branch information
erikjohnston authored Jan 6, 2020
1 parent ab4b4ee commit 9f6c1be
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 13 deletions.
1 change: 1 addition & 0 deletions changelog.d/6580.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add experimental config option to specify multiple databases.
55 changes: 42 additions & 13 deletions synapse/config/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import logging
import os
from textwrap import indent
from typing import List

import yaml

Expand All @@ -30,16 +29,13 @@ class DatabaseConnectionConfig:
Args:
name: A label for the database, used for logging.
db_config: The config for a particular database, as per `database`
section of main config. Has two fields: `name` for database
module name, and `args` for the args to give to the database
connector.
data_stores: The list of data stores that should be provisioned on the
database. Defaults to all data stores.
section of main config. Has three fields: `name` for database
module name, `args` for the args to give to the database
connector, and optional `data_stores` that is a list of stores to
provision on this database (defaulting to all).
"""

def __init__(
self, name: str, db_config: dict, data_stores: List[str] = ["main", "state"]
):
def __init__(self, name: str, db_config: dict):
if db_config["name"] not in ("sqlite3", "psycopg2"):
raise ConfigError("Unsupported database type %r" % (db_config["name"],))

Expand All @@ -48,6 +44,10 @@ def __init__(
{"cp_min": 1, "cp_max": 1, "check_same_thread": False}
)

data_stores = db_config.get("data_stores")
if data_stores is None:
data_stores = ["main", "state"]

self.name = name
self.config = db_config
self.data_stores = data_stores
Expand All @@ -59,14 +59,43 @@ class DatabaseConfig(Config):
def read_config(self, config, **kwargs):
self.event_cache_size = self.parse_size(config.get("event_cache_size", "10K"))

# We *experimentally* support specifying multiple databases via the
# `databases` key. This is a map from a label to database config in the
# same format as the `database` config option, plus an extra
# `data_stores` key to specify which data store goes where. For example:
#
# databases:
# master:
# name: psycopg2
# data_stores: ["main"]
# args: {}
# state:
# name: psycopg2
# data_stores: ["state"]
# args: {}

multi_database_config = config.get("databases")
database_config = config.get("database")

if database_config is None:
database_config = {"name": "sqlite3", "args": {}}
if multi_database_config and database_config:
raise ConfigError("Can't specify both 'database' and 'datbases' in config")

if multi_database_config:
if config.get("database_path"):
raise ConfigError("Can't specify 'database_path' with 'databases'")

self.databases = [
DatabaseConnectionConfig(name, db_conf)
for name, db_conf in multi_database_config.items()
]

else:
if database_config is None:
database_config = {"name": "sqlite3", "args": {}}

self.databases = [DatabaseConnectionConfig("master", database_config)]
self.databases = [DatabaseConnectionConfig("master", database_config)]

self.set_databasepath(config.get("database_path"))
self.set_databasepath(config.get("database_path"))

def generate_config_section(self, data_dir_path, database_conf, **kwargs):
if not database_conf:
Expand Down
21 changes: 21 additions & 0 deletions synapse/storage/data_stores/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ def __init__(self, main_store_class, hs):
# store.

self.databases = []
self.main = None
self.state = None

for database_config in hs.config.database.databases:
db_name = database_config.name
Expand All @@ -54,14 +56,33 @@ def __init__(self, main_store_class, hs):

if "main" in database_config.data_stores:
logger.info("Starting 'main' data store")

# Sanity check we don't try and configure the main store on
# multiple databases.
if self.main:
raise Exception("'main' data store already configured")

self.main = main_store_class(database, db_conn, hs)

if "state" in database_config.data_stores:
logger.info("Starting 'state' data store")

# Sanity check we don't try and configure the state store on
# multiple databases.
if self.state:
raise Exception("'state' data store already configured")

self.state = StateGroupDataStore(database, db_conn, hs)

db_conn.commit()

self.databases.append(database)

logger.info("Database %r prepared", db_name)

# Sanity check that we have actually configured all the required stores.
if not self.main:
raise Exception("No 'main' data store configured")

if not self.state:
raise Exception("No 'main' data store configured")

0 comments on commit 9f6c1be

Please sign in to comment.