Skip to content

Commit fd992b0

Browse files
author
Konstantin Belyavskiy
committed
Implement reconnection strategy class
Extend base Connection class to support a list of nodes and an optional Strategy parameter to choose next item from this list. Add built-in reconnect strategy class based on Round-Robin alg. @params: - addrs (a map of {host: HOSTNAME|IP_ADDRESS, port: PORT}) Return next connection or an error if all URIs are unavailable. Closes #106
1 parent cbb09e0 commit fd992b0

File tree

3 files changed

+111
-2
lines changed

3 files changed

+111
-2
lines changed

Diff for: tarantool/__init__.py

+25-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# pylint: disable=C0301,W0105,W0401,W0614
33

44
from tarantool.connection import Connection
5+
from tarantool.mesh_connection import MeshConnection
56
from tarantool.const import (
67
SOCKET_TIMEOUT,
78
RECONNECT_MAX_ATTEMPTS,
@@ -49,6 +50,28 @@ def connect(host="localhost", port=33013, user=None, password=None,
4950
connect_now=True,
5051
encoding=encoding)
5152

53+
def connectmesh(addrs=({'host': 'localhost', 'port': 3301},), user=None,
54+
password=None, encoding=ENCODING_DEFAULT):
55+
'''
56+
Create a connection to the mesh of Tarantool servers.
57+
58+
:param str addrs: A map of server hostname or IP-address and a port.
59+
60+
:rtype: :class:`~tarantool.mesh_connection.MeshConnection`
61+
62+
:raise: `NetworkError`
63+
'''
64+
65+
return MeshConnection(addrs=addrs,
66+
user=user,
67+
password=password,
68+
socket_timeout=SOCKET_TIMEOUT,
69+
reconnect_max_attempts=RECONNECT_MAX_ATTEMPTS,
70+
reconnect_delay=RECONNECT_DELAY,
71+
connect_now=True,
72+
encoding=encoding)
73+
5274

53-
__all__ = ['connect', 'Connection', 'Schema', 'Error', 'DatabaseError',
54-
'NetworkError', 'NetworkWarning', 'SchemaError']
75+
__all__ = ['connect', 'Connection', 'connectmesh', 'MeshConnection', 'Schema',
76+
'Error', 'DatabaseError', 'NetworkError', 'NetworkWarning',
77+
'SchemaError']

Diff for: tarantool/mesh_connection.py

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# -*- coding: utf-8 -*-
2+
'''
3+
This module provides MeshConnection class with automatic switch
4+
between tarantool instances and basic Round-Robin strategy.
5+
'''
6+
7+
from tarantool.connection import Connection
8+
from tarantool.error import NetworkError
9+
from tarantool.utils import ENCODING_DEFAULT
10+
from tarantool.const import (
11+
SOCKET_TIMEOUT,
12+
RECONNECT_MAX_ATTEMPTS,
13+
RECONNECT_DELAY
14+
)
15+
16+
class RoundRobinStrategy(object):
17+
def __init__(self, addrs):
18+
self.addrs = addrs
19+
self.pos = 0
20+
21+
def getnext(self):
22+
tmp = self.pos
23+
self.pos = (self.pos + 1) % len(self.addrs)
24+
return self.addrs[tmp]
25+
26+
class MeshConnection(Connection):
27+
def __init__(self, addrs,
28+
user=None,
29+
password=None,
30+
socket_timeout=SOCKET_TIMEOUT,
31+
reconnect_max_attempts=RECONNECT_MAX_ATTEMPTS,
32+
reconnect_delay=RECONNECT_DELAY,
33+
connect_now=True,
34+
encoding=ENCODING_DEFAULT,
35+
Strategy=RoundRobinStrategy):
36+
self.nattempts = 2 * len(addrs) + 1
37+
self.Strategy = Strategy(addrs)
38+
addr = self.Strategy.getnext()
39+
host = addrs[0]['host']
40+
port = addrs[0]['port']
41+
super(MeshConnection, self).__init__(host=host,
42+
port=port,
43+
user=user,
44+
password=password,
45+
socket_timeout=socket_timeout,
46+
reconnect_max_attempts=reconnect_max_attempts,
47+
reconnect_delay=reconnect_delay,
48+
connect_now=connect_now,
49+
encoding=encoding)
50+
51+
def _opt_reconnect(self):
52+
nattempts = self.nattempts
53+
while nattempts > 0:
54+
try:
55+
super(MeshConnection, self)._opt_reconnect()
56+
break
57+
except NetworkError:
58+
nattempts -= 1
59+
addr = self.Strategy.getnext()
60+
self.host = addr['host']
61+
self.port = addr['port']
62+
else:
63+
raise NetworkError

Diff for: testclient.py

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
from tarantool import connectmesh
5+
from tarantool.error import NetworkError
6+
import time
7+
8+
addrs=(
9+
{'host': 'localhost', 'port': 3301},
10+
{'host': 'localhost', 'port': 3304},
11+
)
12+
13+
con = connectmesh(addrs)
14+
15+
while True:
16+
try:
17+
print con.ping()
18+
except NetworkError:
19+
print 'NetworkError !'
20+
break
21+
except Exception as e:
22+
print e
23+
time.sleep(1)

0 commit comments

Comments
 (0)