@@ -33,9 +33,10 @@ class AikidoSession(object):
3333 """
3434
3535 class Holder (object ):
36- def __init__ (self , fct , auth , verify = True ):
36+ def __init__ (self , fct , auth , max_conflict_retries = 5 , verify = True ):
3737 self .fct = fct
3838 self .auth = auth
39+ self .max_conflict_retries = max_conflict_retries
3940 if not isinstance (verify , bool ) and not isinstance (verify , CA_Certificate ) and not not isinstance (verify , str ) :
4041 raise ValueError ("'verify' argument can only be of type: bool, CA_Certificate or str " )
4142 self .verify = verify
@@ -49,7 +50,12 @@ def __call__(self, *args, **kwargs):
4950 kwargs ["verify" ] = self .verify
5051
5152 try :
52- ret = self .fct (* args , ** kwargs )
53+ status_code = 1200
54+ retry = 0
55+ while status_code == 1200 and retry < self .max_conflict_retries :
56+ ret = self .fct (* args , ** kwargs )
57+ status_code = ret .status_code
58+ retry += 1
5359 except :
5460 print ("===\n Unable to establish connection, perhaps arango is not running.\n ===" )
5561 raise
@@ -62,7 +68,7 @@ def __call__(self, *args, **kwargs):
6268 ret .json = JsonHook (ret )
6369 return ret
6470
65- def __init__ (self , username , password , verify = True , max_retries = 5 , log_requests = False ):
71+ def __init__ (self , username , password , verify = True , max_conflict_retries = 5 , max_retries = 5 , single_session = True , log_requests = False ):
6672 if username :
6773 self .auth = (username , password )
6874 else :
@@ -71,19 +77,33 @@ def __init__(self, username, password, verify=True, max_retries=5, log_requests=
7177 self .verify = verify
7278 self .max_retries = max_retries
7379 self .log_requests = log_requests
80+ self .max_conflict_retries = max_conflict_retries
81+
82+ self .session = None
83+ if single_session :
84+ self .session = self ._make_session ()
7485
7586 if log_requests :
7687 self .log = {}
7788 self .log ["nb_request" ] = 0
7889 self .log ["requests" ] = {}
7990
91+ def _make_session (self ):
92+ session = requests .Session ()
93+ http = requests .adapters .HTTPAdapter (max_retries = self .max_retries )
94+ https = requests .adapters .HTTPAdapter (max_retries = self .max_retries )
95+ session .mount ('http://' , http )
96+ session .mount ('https://' , https )
97+
98+ return session
99+
80100 def __getattr__ (self , request_function_name ):
101+ if self .session is not None :
102+ session = self .session
103+ else :
104+ session = self ._make_session ()
105+
81106 try :
82- session = requests .Session ()
83- http = requests .adapters .HTTPAdapter (max_retries = self .max_retries )
84- https = requests .adapters .HTTPAdapter (max_retries = self .max_retries )
85- session .mount ('http://' , http )
86- session .mount ('https://' , https )
87107 request_function = getattr (session , request_function_name )
88108 except AttributeError :
89109 raise AttributeError ("Attribute '%s' not found (no Aikido move available)" % request_function_name )
@@ -95,15 +115,46 @@ def __getattr__(self, request_function_name):
95115 log ["nb_request" ] += 1
96116 log ["requests" ][request_function .__name__ ] += 1
97117
98- return AikidoSession .Holder (request_function , auth , verify )
118+ return AikidoSession .Holder (request_function , auth , max_conflict_retries = self . max_conflict_retries , verify = verify )
99119
100120 def disconnect (self ):
101121 pass
102122
103123class Connection (object ):
104124 """This is the entry point in pyArango and directly handles databases.
105125 @param arangoURL: can be either a string url or a list of string urls to different coordinators
106- @param use_grequests: allows for running concurent requets."""
126+ @param use_grequests: allows for running concurent requets.
127+
128+ Parameters
129+ ----------
130+ arangoURL: list or str
131+ list of urls or url for connecting to the db
132+
133+ username: str
134+ for credentials
135+ password: str
136+ for credentials
137+ verify: bool
138+ check the validity of the CA certificate
139+ verbose: bool
140+ flag for addictional prints during run
141+ statsdClient: instance
142+ statsd instance
143+ reportFileName: str
144+ where to save statsd report
145+ loadBalancing: str
146+ type of load balancing between collections
147+ use_grequests: bool
148+ parallelise requests using gevents. Use with care as gevents monkey patches python, this could have unintended concequences on other packages
149+ use_jwt_authentication: bool
150+ use JWT authentication
151+ use_lock_for_reseting_jwt: bool
152+ use lock for reseting gevents authentication
153+ max_retries: int
154+ max number of retries for a request
155+ max_conflict_retries: int
156+ max number of requests for a conflict error (1200 arangodb error). Does not work with gevents (grequests),
157+ """
107158
108159 LOAD_BLANCING_METHODS = {'round-robin' , 'random' }
109160
@@ -120,6 +171,7 @@ def __init__(self,
120171 use_jwt_authentication = False ,
121172 use_lock_for_reseting_jwt = True ,
122173 max_retries = 5 ,
174+ max_conflict_retries = 5
123175 ):
124176
125177 if loadBalancing not in Connection .LOAD_BLANCING_METHODS :
@@ -132,6 +184,7 @@ def __init__(self,
132184 self .use_jwt_authentication = use_jwt_authentication
133185 self .use_lock_for_reseting_jwt = use_lock_for_reseting_jwt
134186 self .max_retries = max_retries
187+ self .max_conflict_retries = max_conflict_retries
135188 self .action = ConnectionAction (self )
136189
137190 self .databases = {}
@@ -211,7 +264,16 @@ def resetSession(self, username=None, password=None, verify=True):
211264 verify
212265 )
213266 else :
214- self .session = AikidoSession (username , password , verify , self .max_retries )
267+ # self.session = AikidoSession(username, password, verify, self.max_retries)
268+ self .session = AikidoSession (
269+ username = username ,
270+ password = password ,
271+ verify = verify ,
272+ single_session = True ,
273+ max_conflict_retries = self .max_conflict_retries ,
274+ max_retries = self .max_retries ,
275+ log_requests = False
276+ )
215277
216278 def reload (self ):
217279 """Reloads the database list.
0 commit comments