Repository: edgedb/edgedb

Issue:
EdgeDB server doesn't always correctly recognize PostgreSQL server startup
<!-- Please search existing issues to avoid creating duplicates. -->
- EdgeDB Version: 1.0-rc.2+dev6093.d2021102414.gec7d60ef3.cv202110240000
- OS Version: Arch Linux under WSL2

When the EdgeDB server starts up during `edb server` or `edb test` commands and tries to read the `postmaster.pid` file, sometimes it doesn't do it quite correctly, as it seems to me. 

I printed the content of the file and parsed host and port in `_connection_addr_from_pidfile` method and got the following:
```
157186
/home/nik/.local/share/edgedb/_localdev
1635094601
5432


    27256    262160

('', 5432)
```

This results in parsing the host to an empty string, trying to connect to it in `pgcon._connect` and and getting a `ConnectionRefusedError` in the process. I suspect that the `postmaster.pid` file itself did not have time to initialize fully because when I ran `edgedb-server --botstrap-only` my computer already had almost 100% CPU/memory load. Also, the problem disappeared when I tried to repeat the steps, but my PC had free resources. But perhaps the `edb.server.pgcluster` module itself should have a check that the `postmaster.pid` file hasn't been fully loaded or something like that anyway.

Steps to Reproduce:

1. Load PC resources to the limit (?)
2. Run `edgedb-server --bootstrap-only`

Full logs of server startup:
```
INFO 159251 2021-10-24T20:04:35.317 edb.server: EdgeDB server (version: 1.0-rc.2+dev6093.d2021102414.gec7d60ef3.cv202110240000) is starting in DEV mode.
INFO 159251 2021-10-24T20:04:36.056 edb.server: Using 127 max backend connections based on total memory.
159273
/home/nik/.local/share/edgedb/_localdev
1635095076
5432


    27256    262207

('', 5432)
INFO 159273 2021-10-24T20:04:36.229 postgres: starting PostgreSQL 13.4 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 11.1.0, 64-bit
INFO 159273 2021-10-24T20:04:37.240 postgres: listening on Unix socket "/home/nik/.local/share/edgedb/_localdev/.s.PGSQL.5432"
INFO 159273 2021-10-24T20:04:37.240 postgres: database system was shut down at 2021-10-24 20:04:33 MSK
INFO 159273 2021-10-24T20:04:37.241 postgres: database system is ready to accept connections
INFO 159273 2021-10-24T20:05:37.071 postgres: received fast shutdown request
INFO 159273 2021-10-24T20:05:37.106 postgres: aborting any active transactions
INFO 159273 2021-10-24T20:05:37.107 postgres: background worker "logical replication launcher" (PID 159284) exited with exit code 1
INFO 159273 2021-10-24T20:05:37.107 postgres: shutting down
INFO 159273 2021-10-24T20:05:37.239 postgres: database system is shut down
======================================================== Exception occurred: [Errno 111] Connection refused =========================================================

1. ConnectionRefusedError: [Errno 111] Connection refused

----------------------------------------------------------------------------- Traceback -----------------------------------------------------------------------------

    /home/nik/.virtualenvs/edgedb/bin/edb, line 33, in <module>
        > sys.exit(load_entry_point('edgedb-server', 'console_scripts', 'edb')())
    /home/nik/.virtualenvs/edgedb/lib/python3.10/site-packages/click/core.py, line 829, in __call__
        > return self.main(*args, **kwargs)
    /home/nik/.virtualenvs/edgedb/lib/python3.10/site-packages/click/core.py, line 782, in main
        > rv = self.invoke(ctx)
    /home/nik/.virtualenvs/edgedb/lib/python3.10/site-packages/click/core.py, line 1259, in invoke
        > return _process_result(sub_ctx.command.invoke(sub_ctx))
    /home/nik/.virtualenvs/edgedb/lib/python3.10/site-packages/click/core.py, line 1066, in invoke
        > return ctx.invoke(self.callback, **ctx.params)
    /home/nik/.virtualenvs/edgedb/lib/python3.10/site-packages/click/core.py, line 610, in invoke
        > return callback(*args, **kwargs)
    /home/nik/projects/edgedb/edgedb/edb/tools/edb.py, line 55, in server
        > srv_main.server_main(**kwargs)
    /home/nik/projects/edgedb/edgedb/edb/server/main.py, line 556, in server_main
        > asyncio.run(run_server(server_args))
    /home/nik/.asdf/installs/python/3.10.0/lib/python3.10/asyncio/runners.py, line 44, in run
        > return loop.run_until_complete(main)
    uvloop/loop.pyx, line 1501, in uvloop.loop.Loop.run_until_complete
        
    /home/nik/projects/edgedb/edgedb/edb/server/main.py, line 459, in run_server
        > need_cluster_restart = await _init_cluster(cluster, args)
    /home/nik/projects/edgedb/edgedb/edb/server/main.py, line 141, in _init_cluster
        > need_restart = await bootstrap.ensure_bootstrapped(cluster, args)
    /home/nik/projects/edgedb/edgedb/edb/server/bootstrap.py, line 1386, in ensure_bootstrapped
        > pgconn = await cluster.connect()
    /home/nik/projects/edgedb/edgedb/edb/server/pgcluster.py, line 184, in connect
        > conn = await asyncpg.connect(**conn_info)
    /home/nik/.virtualenvs/edgedb/lib/python3.10/site-packages/asyncpg/connection.py, line 2045, in connect
        > return await connect_utils._connect(
    /home/nik/.virtualenvs/edgedb/lib/python3.10/site-packages/asyncpg/connect_utils.py, line 790, in _connect
        > raise last_error
    /home/nik/.virtualenvs/edgedb/lib/python3.10/site-packages/asyncpg/connect_utils.py, line 776, in _connect
        > return await _connect_addr(
    /home/nik/.virtualenvs/edgedb/lib/python3.10/site-packages/asyncpg/connect_utils.py, line 676, in _connect_addr
        > return await __connect_addr(params, timeout, True, *args)
    /home/nik/.virtualenvs/edgedb/lib/python3.10/site-packages/asyncpg/connect_utils.py, line 720, in __connect_addr
        > tr, pr = await compat.wait_for(connector, timeout=timeout)
    /home/nik/.virtualenvs/edgedb/lib/python3.10/site-packages/asyncpg/compat.py, line 66, in wait_for
        > return await asyncio.wait_for(fut, timeout)
    /home/nik/.asdf/installs/python/3.10.0/lib/python3.10/asyncio/tasks.py, line 447, in wait_for
        > return fut.result()
    /home/nik/.virtualenvs/edgedb/lib/python3.10/site-packages/asyncpg/connect_utils.py, line 586, in _create_ssl_connection
        > tr, pr = await loop.create_connection(
    uvloop/loop.pyx, line 2024, in create_connection
        
    uvloop/loop.pyx, line 2001, in uvloop.loop.Loop.create_connection
        

ConnectionRefusedError: [Errno 111] Connection refused
```


Discussion:

Resolving patch:
diff --git a/edb/server/pgcluster.py b/edb/server/pgcluster.py
--- a/edb/server/pgcluster.py
+++ b/edb/server/pgcluster.py
@@ -678,8 +678,10 @@ def _connection_addr_from_pidfile(self) -> Tuple[str, int]:
                 sockdir = os.path.normpath(
                     os.path.join(self._data_dir, sockdir))
             host_str = sockdir
-        else:
+        elif hostaddr:
             host_str = hostaddr
+        else:
+            raise PostgresPidFileNotReadyError
 
         if host_str == '*':
             host_str = 'localhost'


Test patch: