Skip to content

Commit 960293d

Browse files
authored
Merge pull request #17 from dapper91/hooks-example
- hooks usage example added.
2 parents 263de40 + 2ca3a8e commit 960293d

File tree

5 files changed

+63
-6
lines changed

5 files changed

+63
-6
lines changed

docs/source/pages/api.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ _______
3535

3636
.. automodule:: generic_connection_pool.contrib.unix
3737
:members:
38+
39+
.. automodule:: generic_connection_pool.contrib.unix_async
40+
:members:

docs/source/pages/quickstart.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,14 @@ The following example illustrate how to implement a custom connection manager fo
125125
:language: python
126126

127127

128+
Connection manager allows to define methods to be called on connection acquire, release or when
129+
a connection determined to be dead. That helps to log pool actions or collect metrics.
130+
The following examples illustrate how to collect pool metrics and export them to prometheus.
131+
132+
.. literalinclude:: ../../../examples/manager_hooks.py
133+
:language: python
134+
135+
128136
Examples
129137
________
130138

examples/manager_hooks.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import ssl
2+
import time
3+
from ssl import SSLSocket
4+
from typing import Any, Dict, Tuple
5+
6+
import prometheus_client as prom
7+
8+
from generic_connection_pool.contrib.socket import SslSocketConnectionManager
9+
from generic_connection_pool.threading import ConnectionPool
10+
11+
Hostname = str
12+
Port = int
13+
Endpoint = Tuple[Hostname, Port]
14+
15+
acquire_latency_hist = prom.Histogram('acquire_latency', 'Connections acquire latency', labelnames=['hostname'])
16+
acquire_total = prom.Counter('acquire_total', 'Connections acquire count', labelnames=['hostname'])
17+
dead_conn_total = prom.Counter('dead_conn_total', 'Dead connections count', labelnames=['hostname'])
18+
19+
20+
class ObservableConnectionManager(SslSocketConnectionManager):
21+
22+
def __init__(self, *args: Any, **kwargs: Any):
23+
super().__init__(*args, **kwargs)
24+
self._acquires: Dict[SSLSocket, float] = {}
25+
26+
def on_acquire(self, endpoint: Endpoint, conn: SSLSocket) -> None:
27+
hostname, port = endpoint
28+
29+
acquire_total.labels(hostname).inc()
30+
self._acquires[conn] = time.time()
31+
32+
def on_release(self, endpoint: Endpoint, conn: SSLSocket) -> None:
33+
hostname, port = endpoint
34+
35+
acquired_at = self._acquires.pop(conn)
36+
acquire_latency_hist.labels(hostname).observe(time.time() - acquired_at)
37+
38+
def on_connection_dead(self, endpoint: Endpoint, conn: SSLSocket) -> None:
39+
hostname, port = endpoint
40+
41+
dead_conn_total.labels(hostname).inc()
42+
43+
44+
http_pool = ConnectionPool[Endpoint, SSLSocket](
45+
ObservableConnectionManager(ssl.create_default_context()),
46+
)

examples/ssl_pool.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import socket
21
import ssl
32
import urllib.parse
43
from http.client import HTTPResponse
@@ -10,7 +9,7 @@
109
Hostname = str
1110
Port = int
1211
Endpoint = Tuple[Hostname, Port]
13-
Connection = socket.socket
12+
Connection = ssl.SSLSocket
1413

1514

1615
http_pool = ConnectionPool[Endpoint, Connection](

examples/tcp_pool.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import socket
2-
from ipaddress import IPv4Address
3-
from typing import Tuple
2+
from ipaddress import IPv4Address, IPv6Address
3+
from typing import Tuple, Union
44

55
from generic_connection_pool.contrib.socket import TcpSocketConnectionManager
66
from generic_connection_pool.threading import ConnectionPool
77

88
Port = int
9-
Endpoint = Tuple[IPv4Address, Port]
9+
IpAddress = Union[IPv4Address, IPv6Address]
10+
Endpoint = Tuple[IpAddress, Port]
1011
Connection = socket.socket
1112

1213

@@ -21,7 +22,7 @@
2122
)
2223

2324

24-
def command(addr: IPv4Address, port: int, cmd: str) -> None:
25+
def command(addr: IpAddress, port: int, cmd: str) -> None:
2526
with redis_pool.connection(endpoint=(addr, port), timeout=5.0) as sock:
2627
sock.sendall(cmd.encode() + b'\n')
2728
response = sock.recv(1024)

0 commit comments

Comments
 (0)