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

Improve database configuration docs #6988

Merged
merged 3 commits into from
Mar 20, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/6988.doc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improve the documentation for database configuration.
42 changes: 32 additions & 10 deletions docs/postgres.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,19 +105,41 @@ of free memory the database host has available.
When you are ready to start using PostgreSQL, edit the `database`
section in your config file to match the following lines:

database:
name: psycopg2
args:
user: <user>
password: <pass>
database: <db>
host: <host>
cp_min: 5
cp_max: 10
```yaml
database:
name: psycopg2
args:
user: <user>
password: <pass>
database: <db>
host: <host>
cp_min: 5
cp_max: 10
```

All key, values in `args` are passed to the `psycopg2.connect(..)`
function, except keys beginning with `cp_`, which are consumed by the
twisted adbapi connection pool.
twisted adbapi connection pool. See the [libpq
documentation](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS)
for a list of options which can be passed.

You should consider tuning the `keepalives_*` options if there is any danger of
richvdh marked this conversation as resolved.
Show resolved Hide resolved
the connection between your homeserver and database dropping, otherwise Synapse
may block for an extended period while it waits for a response from the
database server. Example values might be:

```yaml
# seconds of inactivity after which TCP should send a keepalive message to the server
keepalives_idle: 10

# the number of seconds after which a TCP keepalive message that is not
# acknowledged by the server should be retransmitted
keepalives_interval: 10

# the number of TCP keepalives that can be lost before the client's connection
# to the server is considered dead
keepalives_count: 3
```
richvdh marked this conversation as resolved.
Show resolved Hide resolved

## Porting from SQLite

Expand Down
43 changes: 38 additions & 5 deletions docs/sample_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -578,13 +578,46 @@ acme:

## Database ##

# The 'database' setting defines the database that synapse uses to store all of
# its data.
#
# 'name' gives the database engine to use: either 'sqlite3' (for SQLite) or
# 'psycopg2' (for PostgreSQL).
#
# 'args' gives options which are passed through to the database engine,
# except for options starting 'cp_', which are used to configure the Twisted
# connection pool. For a reference to valid arguments, see:
# * for sqlite: https://docs.python.org/3/library/sqlite3.html#sqlite3.connect
# * for postgres: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS
# * for the connection pool: https://twistedmatrix.com/documents/current/api/twisted.enterprise.adbapi.ConnectionPool.html#__init__
#
#
# Example SQLite configuration:
#
#database:
# name: sqlite3
# args:
# database: /path/to/homeserver.db
#
#
# Example Postgres configuration:
#
#database:
# name: psycopg2
# args:
# user: synapse
# password: secretpassword
# database: synapse
# host: localhost
# cp_min: 5
# cp_max: 10
#
# For more information on using Synapse with Postgres, see `docs/postgres.md`.
#
database:
# The database engine name
name: "sqlite3"
# Arguments to pass to the engine
name: sqlite3
args:
# Path to the database
database: "DATADIR/homeserver.db"
database: DATADIR/homeserver.db

# Number of events to cache in memory.
#
Expand Down
2 changes: 0 additions & 2 deletions synapse/config/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,6 @@ def generate_config(
report_stats=None,
open_private_ports=False,
listeners=None,
database_conf=None,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was never set, outside of tests.

tls_certificate_path=None,
tls_private_key_path=None,
acme_domain=None,
Expand Down Expand Up @@ -367,7 +366,6 @@ def generate_config(
report_stats=report_stats,
open_private_ports=open_private_ports,
listeners=listeners,
database_conf=database_conf,
tls_certificate_path=tls_certificate_path,
tls_private_key_path=tls_private_key_path,
acme_domain=acme_domain,
Expand Down
93 changes: 59 additions & 34 deletions synapse/config/database.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright 2014-2016 OpenMarket Ltd
# Copyright 2020 The Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -14,14 +15,60 @@
# limitations under the License.
import logging
import os
from textwrap import indent

import yaml

from synapse.config._base import Config, ConfigError

logger = logging.getLogger(__name__)

DEFAULT_CONFIG = """\
## Database ##

# The 'database' setting defines the database that synapse uses to store all of
# its data.
#
# 'name' gives the database engine to use: either 'sqlite3' (for SQLite) or
# 'psycopg2' (for PostgreSQL).
#
# 'args' gives options which are passed through to the database engine,
# except for options starting 'cp_', which are used to configure the Twisted
# connection pool. For a reference to valid arguments, see:
# * for sqlite: https://docs.python.org/3/library/sqlite3.html#sqlite3.connect
# * for postgres: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS
# * for the connection pool: https://twistedmatrix.com/documents/current/api/twisted.enterprise.adbapi.ConnectionPool.html#__init__
#
#
# Example SQLite configuration:
#
#database:
# name: sqlite3
# args:
# database: /path/to/homeserver.db
#
#
# Example Postgres configuration:
#
#database:
# name: psycopg2
# args:
# user: synapse
# password: secretpassword
# database: synapse
# host: localhost
# cp_min: 5
# cp_max: 10
#
# For more information on using Synapse with Postgres, see `docs/postgres.md`.
#
database:
name: sqlite3
args:
database: %(database_path)s

# Number of events to cache in memory.
#
#event_cache_size: 10K
"""


class DatabaseConnectionConfig:
"""Contains the connection config for a particular database.
Expand All @@ -36,10 +83,12 @@ class DatabaseConnectionConfig:
"""

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"],))
db_engine = db_config.get("name", "sqlite3")

if db_config["name"] == "sqlite3":
if db_engine not in ("sqlite3", "psycopg2"):
raise ConfigError("Unsupported database type %r" % (db_engine,))

if db_engine == "sqlite3":
db_config.setdefault("args", {}).update(
{"cp_min": 1, "cp_max": 1, "check_same_thread": False}
)
Expand Down Expand Up @@ -97,34 +146,10 @@ def read_config(self, config, **kwargs):

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

def generate_config_section(self, data_dir_path, database_conf, **kwargs):
if not database_conf:
database_path = os.path.join(data_dir_path, "homeserver.db")
database_conf = (
"""# The database engine name
name: "sqlite3"
# Arguments to pass to the engine
args:
# Path to the database
database: "%(database_path)s"
"""
% locals()
)
else:
database_conf = indent(yaml.dump(database_conf), " " * 10).lstrip()

return (
"""\
## Database ##

database:
%(database_conf)s
# Number of events to cache in memory.
#
#event_cache_size: 10K
"""
% locals()
)
def generate_config_section(self, data_dir_path, **kwargs):
return DEFAULT_CONFIG % {
"database_path": os.path.join(data_dir_path, "homeserver.db")
}

def read_arguments(self, args):
self.set_databasepath(args.database_path)
Expand Down
22 changes: 2 additions & 20 deletions tests/config/test_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@


class DatabaseConfigTestCase(unittest.TestCase):
def test_database_configured_correctly_no_database_conf_param(self):
def test_database_configured_correctly(self):
conf = yaml.safe_load(
DatabaseConfig().generate_config_section("/data_dir_path", None)
DatabaseConfig().generate_config_section(data_dir_path="/data_dir_path")
)

expected_database_conf = {
Expand All @@ -32,21 +32,3 @@ def test_database_configured_correctly_no_database_conf_param(self):
}

self.assertEqual(conf["database"], expected_database_conf)

def test_database_configured_correctly_database_conf_param(self):

database_conf = {
"name": "my super fast datastore",
"args": {
"user": "matrix",
"password": "synapse_database_password",
"host": "synapse_database_host",
"database": "matrix",
},
}

conf = yaml.safe_load(
DatabaseConfig().generate_config_section("/data_dir_path", database_conf)
)

self.assertEqual(conf["database"], database_conf)