Repository: matrix-org/synapse

Issue:
setval: value -2 is out of bounds for sequence "events_backfill_stream_seq"
When running `develop` against a host previously on 1.20.0, I see:

```
2020-09-24 15:20:02,569 - synapse.storage.prepare_database - 379 - INFO - None- Applying schema deltas for v58
2020-09-24 15:20:02,570 - synapse.storage.prepare_database - 474 - INFO - None- Applying engine-specific schema 58/07add_method_to_thumbnail_constraint.sql.postgres
2020-09-24 15:20:02,573 - synapse.storage.prepare_database - 466 - INFO - None- Applying schema 58/10_pushrules_enabled_delete_obsolete.sql
2020-09-24 15:20:02,575 - synapse.storage.prepare_database - 466 - INFO - None- Applying schema 58/14events_instance_name.sql
2020-09-24 15:20:02,578 - synapse.storage.prepare_database - 474 - INFO - None- Applying engine-specific schema 58/14events_instance_name.sql.postgres
2020-09-24 15:20:02,583 - twisted - 250 - ERROR - - Traceback (most recent call last):
2020-09-24 15:20:02,584 - twisted - 250 - ERROR - -   File "/usr/local/lib/python3.7/runpy.py", line 193, in _run_module_as_main
2020-09-24 15:20:02,584 - twisted - 250 - ERROR - -     "__main__", mod_spec)
2020-09-24 15:20:02,584 - twisted - 250 - ERROR - -   File "/usr/local/lib/python3.7/runpy.py", line 85, in _run_code
2020-09-24 15:20:02,584 - twisted - 250 - ERROR - -     exec(code, run_globals)
2020-09-24 15:20:02,584 - twisted - 250 - ERROR - -   File "/usr/local/lib/python3.7/site-packages/synapse/app/homeserver.py", line 695, in <module>
2020-09-24 15:20:02,585 - twisted - 250 - ERROR - -     main()
2020-09-24 15:20:02,585 - twisted - 250 - ERROR - -   File "/usr/local/lib/python3.7/site-packages/synapse/app/homeserver.py", line 690, in main
2020-09-24 15:20:02,586 - twisted - 250 - ERROR - -     hs = setup(sys.argv[1:])
2020-09-24 15:20:02,586 - twisted - 250 - ERROR - -   File "/usr/local/lib/python3.7/site-packages/synapse/app/homeserver.py", line 386, in setup
2020-09-24 15:20:02,586 - twisted - 250 - ERROR - -     hs.setup()
2020-09-24 15:20:02,586 - twisted - 250 - ERROR - -   File "/usr/local/lib/python3.7/site-packages/synapse/server.py", line 251, in setup
2020-09-24 15:20:02,587 - twisted - 250 - ERROR - -     self.datastores = Databases(self.DATASTORE_CLASS, self)
2020-09-24 15:20:02,587 - twisted - 250 - ERROR - -   File "/usr/local/lib/python3.7/site-packages/synapse/storage/databases/__init__.py", line 59, in __init__
2020-09-24 15:20:02,587 - twisted - 250 - ERROR - -     db_conn, engine, hs.config, databases=database_config.databases,
2020-09-24 15:20:02,587 - twisted - 250 - ERROR - -   File "/usr/local/lib/python3.7/site-packages/synapse/storage/prepare_database.py", line 135, in prepare_database
2020-09-24 15:20:02,587 - twisted - 250 - ERROR - -     databases=databases,
2020-09-24 15:20:02,588 - twisted - 250 - ERROR - -   File "/usr/local/lib/python3.7/site-packages/synapse/storage/prepare_database.py", line 475, in _upgrade_existing_database
2020-09-24 15:20:02,588 - twisted - 250 - ERROR - -     executescript(cur, absolute_path)
2020-09-24 15:20:02,588 - twisted - 250 - ERROR - -   File "/usr/local/lib/python3.7/site-packages/synapse/storage/prepare_database.py", line 610, in executescript
2020-09-24 15:20:02,589 - twisted - 250 - ERROR - -     execute_statements_from_stream(txn, f)
2020-09-24 15:20:02,589 - twisted - 250 - ERROR - -   File "/usr/local/lib/python3.7/site-packages/synapse/storage/prepare_database.py", line 615, in execute_statements_from_stream
2020-09-24 15:20:02,589 - twisted - 250 - ERROR - -     cur.execute(statement)
2020-09-24 15:20:02,589 - twisted - 250 - ERROR - - psycopg2.errors.NumericValueOutOfRange: setval: value -2 is out of bounds for sequence "events_backfill_stream_seq" (1..9223372036854775807)
2020-09-24 15:20:02,590 - twisted - 250 - ERROR - - 
```


Discussion:

Resolving patch:
diff --git a/synapse/storage/util/id_generators.py b/synapse/storage/util/id_generators.py
--- a/synapse/storage/util/id_generators.py
+++ b/synapse/storage/util/id_generators.py
@@ -287,8 +287,12 @@ def _load_current_ids(
         min_stream_id = min(self._current_positions.values(), default=None)
 
         if min_stream_id is None:
+            # We add a GREATEST here to ensure that the result is always
+            # positive. (This can be a problem for e.g. backfill streams where
+            # the server has never backfilled).
             sql = """
-                SELECT COALESCE(%(agg)s(%(id)s), 1) FROM %(table)s
+                SELECT GREATEST(COALESCE(%(agg)s(%(id)s), 1), 1)
+                FROM %(table)s
             """ % {
                 "id": id_column,
                 "table": table,


Test patch: