Generator to create a database connection without blocking.
(conninfo: str, *, timeout: float = 0.0)
| 60 | |
| 61 | |
| 62 | def _connect(conninfo: str, *, timeout: float = 0.0) -> PQGenConn[PGconn]: |
| 63 | """ |
| 64 | Generator to create a database connection without blocking. |
| 65 | """ |
| 66 | deadline = monotonic() + timeout if timeout else 0.0 |
| 67 | |
| 68 | # To debug slowdown during connection: |
| 69 | # |
| 70 | # $ PSYCOPG_IMPL=python python |
| 71 | # >>> import logging |
| 72 | # >>> logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(message)s') |
| 73 | # >>> logging.getLogger("psycopg").setLevel(logging.DEBUG) |
| 74 | |
| 75 | conn = pq.PGconn.connect_start(conninfo.encode()) |
| 76 | logger.debug("connection started: %s", conn) |
| 77 | while True: |
| 78 | if conn.status == BAD: |
| 79 | encoding = conninfo_encoding(conninfo) |
| 80 | raise e.OperationalError( |
| 81 | f"connection is bad: {conn.get_error_message(encoding)}", pgconn=conn |
| 82 | ) |
| 83 | |
| 84 | status = conn.connect_poll() |
| 85 | logger.debug("connection polled: %s", conn) |
| 86 | |
| 87 | if status == POLL_READING or status == POLL_WRITING: |
| 88 | wait = WAIT_R if status == POLL_READING else WAIT_W |
| 89 | while True: |
| 90 | ready = yield conn.socket, wait |
| 91 | if deadline and monotonic() > deadline: |
| 92 | raise e.ConnectionTimeout("connection timeout expired") |
| 93 | if ready: |
| 94 | break |
| 95 | |
| 96 | elif status == POLL_OK: |
| 97 | break |
| 98 | elif status == POLL_FAILED: |
| 99 | encoding = conninfo_encoding(conninfo) |
| 100 | raise e.OperationalError( |
| 101 | f"connection failed: {conn.get_error_message(encoding)}", |
| 102 | pgconn=e.finish_pgconn(conn), |
| 103 | ) |
| 104 | else: |
| 105 | raise e.InternalError( |
| 106 | f"unexpected poll status: {status}", pgconn=e.finish_pgconn(conn) |
| 107 | ) |
| 108 | |
| 109 | conn.nonblocking = 1 |
| 110 | return conn |
| 111 | |
| 112 | |
| 113 | def _cancel(cancel_conn: PGcancelConn, *, timeout: float = 0.0) -> PQGenConn[None]: |
nothing calls this directly
no test coverage detected