Skip to content

Commit a101003

Browse files
chore: add additional tests
1 parent ac5fca0 commit a101003

File tree

2 files changed

+42
-11
lines changed

2 files changed

+42
-11
lines changed

README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,44 @@ with Connector(resolver=DnsResolver) as connector:
428428
# ... use SQLAlchemy engine normally
429429
```
430430

431+
### Automatic failover using DNS domain names
432+
433+
> [!NOTE]
434+
>
435+
> Usage of the `asyncpg` driver does not currently support automatic failover.
436+
437+
When the connector is configured using a domain name, the connector will
438+
periodically check if the DNS record for an instance changes. When the connector
439+
detects that the domain name refers to a different instance, the connector will
440+
close all open connections to the old instance. Subsequent connection attempts
441+
will be directed to the new instance.
442+
443+
For example: suppose application is configured to connect using the
444+
domain name `prod-db.mycompany.example.com`. Initially the private DNS
445+
zone has a TXT record with the value `my-project:region:my-instance`. The
446+
application establishes connections to the `my-project:region:my-instance`
447+
Cloud SQL instance.
448+
449+
Then, to reconfigure the application to use a different database
450+
instance, change the value of the `prod-db.mycompany.example.com` DNS record
451+
from `my-project:region:my-instance` to `my-project:other-region:my-instance-2`
452+
453+
The connector inside the application detects the change to this
454+
DNS record. Now, when the application connects to its database using the
455+
domain name `prod-db.mycompany.example.com`, it will connect to the
456+
`my-project:other-region:my-instance-2` Cloud SQL instance.
457+
458+
The connector will automatically close all existing connections to
459+
`my-project:region:my-instance`. This will force the connection pools to
460+
establish new connections. Also, it may cause database queries in progress
461+
to fail.
462+
463+
The connector will poll for changes to the DNS name every 30 seconds by default.
464+
You may configure the frequency of the connections using the Connector's
465+
`failover_period` argument (i.e. `Connector(failover_period=60`). When this is
466+
set to 0, the connector will disable polling and only check if the DNS record
467+
changed when it is creating a new connection.
468+
431469
### Using the Python Connector with Python Web Frameworks
432470

433471
The Python Connector can be used alongside popular Python web frameworks such

google/cloud/sql/connector/monitored_cache.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ def __init__(
3939
self.domain_name_ticker: Optional[asyncio.Task] = None
4040
self.sockets: list[ssl.SSLSocket] = []
4141

42-
if self.cache.conn_name.domain_name:
42+
# If domain name is configured for instance and failover period is set,
43+
# poll for DNS record changes.
44+
if self.cache.conn_name.domain_name and failover_period > 0:
4345
self.domain_name_ticker = asyncio.create_task(
4446
ticker(failover_period, self._check_domain_name)
4547
)
@@ -52,15 +54,6 @@ def __init__(
5254
def closed(self) -> bool:
5355
return self.cache.closed
5456

55-
async def _purge_closed_sockets(self) -> None:
56-
open_sockets = []
57-
for socket in self.sockets:
58-
# Check fileno as method to check if socket is closed. Will return
59-
# -1 on failure, which will be used to signal socket closed.
60-
if socket.fileno() != -1:
61-
open_sockets.append(socket)
62-
self.sockets = open_sockets
63-
6457
async def _check_domain_name(self) -> None:
6558
try:
6659
# Resolve domain name and see if Cloud SQL instance connection name
@@ -109,7 +102,7 @@ async def close(self) -> None:
109102

110103
# Close any still open sockets
111104
for socket in self.sockets:
112-
# Check fileno as method to check if socket is closed. Will return
105+
# Check fileno for if socket is closed. Will return
113106
# -1 on failure, which will be used to signal socket closed.
114107
if socket.fileno() != -1:
115108
socket.close()

0 commit comments

Comments
 (0)