[FIX] reuse session between calls

This commit is contained in:
Guewen Baconnier @ Camptocamp
2012-11-26 11:09:33 +01:00
parent fbcfbb3fcc
commit 34051eb0bb
2 changed files with 153 additions and 124 deletions

View File

@@ -56,7 +56,8 @@ class Pingen(object):
def __init__(self, token, staging=True): def __init__(self, token, staging=True):
self._token = token self._token = token
self.staging = True self.staging = staging
self._session = None
super(Pingen, self).__init__() super(Pingen, self).__init__()
@property @property
@@ -65,6 +66,32 @@ class Pingen(object):
return 'https://stage-api.pingen.com' return 'https://stage-api.pingen.com'
return 'https://api.pingen.com' return 'https://api.pingen.com'
@property
def session(self):
""" Build a requests session """
if self._session is not None:
return self._session
self._session = requests.Session(
params={'token': self._token},
# with safe_mode, requests catch errors and
# returns a blank response with an error
config={'safe_mode': True},
# verify = False required for staging environment
# because the SSL certificate is wrong
verify=not self.staging)
return self._session
def __enter__(self):
return self
def __exit__(self, *args):
self.close()
def close(self):
"""Dispose of any internal state. """
if self._session:
self._session.close()
def _send(self, method, endpoint, **kwargs): def _send(self, method, endpoint, **kwargs):
""" Send a request to the pingen API using requests """ Send a request to the pingen API using requests
@@ -77,23 +104,6 @@ class Pingen(object):
""" """
complete_url = urlparse.urljoin(self.url, endpoint) complete_url = urlparse.urljoin(self.url, endpoint)
auth_param = {'token': self._token}
if 'params' in kwargs:
kwargs['params'].update(auth_param)
else:
kwargs['params'] = auth_param
# with safe_mode, requests catch errors and
# returns a blank response with an error
config = {'safe_mode': True}
if 'config' in kwargs:
kwargs['config'].update(config)
else:
kwargs['config'] = config
# verify = False required for staging environment
# because the SSL certificate is wrong
kwargs['verify'] = not self.staging
response = method(complete_url, **kwargs) response = method(complete_url, **kwargs)
if not response.ok: if not response.ok:
@@ -140,7 +150,7 @@ class Pingen(object):
multipart, content_type = encode_multipart_formdata(formdata) multipart, content_type = encode_multipart_formdata(formdata)
response = self._send( response = self._send(
requests.post, self.session.post,
'document/upload', 'document/upload',
headers={'Content-Type': content_type}, headers={'Content-Type': content_type},
data=multipart) data=multipart)
@@ -169,7 +179,7 @@ class Pingen(object):
'color': color, 'color': color,
} }
response = self._send( response = self._send(
requests.post, self.session.post,
'document/send', 'document/send',
params={'id': document_id}, params={'id': document_id},
data={'data': json.dumps(data)}) data={'data': json.dumps(data)})
@@ -183,7 +193,7 @@ class Pingen(object):
:return: dict of infos of the post :return: dict of infos of the post
""" """
response = self._send( response = self._send(
requests.get, self.session.get,
'post/get', 'post/get',
params={'id': post_id}) params={'id': post_id})

View File

@@ -25,7 +25,6 @@ from cStringIO import StringIO
from contextlib import closing from contextlib import closing
from openerp.osv import osv, orm, fields from openerp.osv import osv, orm, fields
from openerp import tools
from openerp.tools.translate import _ from openerp.tools.translate import _
from openerp import pooler from openerp import pooler
from .pingen import APIError, ConnectionError, POST_SENDING_STATUS from .pingen import APIError, ConnectionError, POST_SENDING_STATUS
@@ -91,16 +90,24 @@ class pingen_document(orm.Model):
'Only one Pingen document is allowed per attachment.'), 'Only one Pingen document is allowed per attachment.'),
] ]
def _push_to_pingen(self, cr, uid, document, context=None): def _get_pingen_session(self, cr, uid, context=None):
""" Push a document to pingen.com """ """ Returns a pingen session for a user"""
company = self.pool.get('res.users').browse(
cr, uid, uid, context=context).company_id
return self.pool.get('res.company')._pingen(cr, uid, company, context=context)
def _push_to_pingen(self, cr, uid, document, pingen=None, context=None):
""" Push a document to pingen.com
:param Pingen pingen: optional pingen object to, reuse session
"""
attachment_obj = self.pool.get('ir.attachment') attachment_obj = self.pool.get('ir.attachment')
decoded_document = attachment_obj._decoded_content( decoded_document = attachment_obj._decoded_content(
cr, uid, document.attachment_id, context=context) cr, uid, document.attachment_id, context=context)
company = self.pool.get('res.users').browse( if pingen is None:
cr, uid, uid, context=context).company_id pingen = self._get_pingen_session(cr, uid, context=context)
pingen = self.pool.get('res.company')._pingen(cr, uid, company, context=context)
try: try:
doc_id, post_id, infos = pingen.push_document( doc_id, post_id, infos = pingen.push_document(
document.datas_fname, document.datas_fname,
@@ -145,9 +152,11 @@ class pingen_document(orm.Model):
Wrapper method for multiple ids (when triggered from button for Wrapper method for multiple ids (when triggered from button for
instance) for public interface. instance) for public interface.
""" """
with self._get_pingen_session(cr, uid, context=context) as session:
for document in self.browse(cr, uid, ids, context=context): for document in self.browse(cr, uid, ids, context=context):
try: try:
self._push_to_pingen(cr, uid, document, context=context) self._push_to_pingen(
cr, uid, document, pingen=session, context=context)
except ConnectionError as e: except ConnectionError as e:
raise osv.except_osv( raise osv.except_osv(
_('Pingen Connection Error'), _('Pingen Connection Error'),
@@ -186,6 +195,7 @@ class pingen_document(orm.Model):
context=context) context=context)
with closing(pooler.get_db(cr.dbname).cursor()) as loc_cr: with closing(pooler.get_db(cr.dbname).cursor()) as loc_cr:
with self._get_pingen_session(cr, uid, context=context) as session:
for document in self.browse(loc_cr, uid, ids, context=context): for document in self.browse(loc_cr, uid, ids, context=context):
if document.state == 'error': if document.state == 'error':
@@ -194,14 +204,20 @@ class pingen_document(orm.Model):
try: try:
if document.state == 'pending': if document.state == 'pending':
self._push_to_pingen(loc_cr, uid, document, context=context) self._push_to_pingen(
loc_cr, uid, document, pingen=session, context=context)
elif document.state == 'pushed': elif document.state == 'pushed':
self._ask_pingen_send(loc_cr, uid, document, context=context) self._ask_pingen_send(
loc_cr, uid, document, pingen=session, context=context)
except ConnectionError as e: except ConnectionError as e:
document.write({'last_error_message': e, 'state': 'error'}, context=context) document.write({'last_error_message': e,
'state': 'error'},
context=context)
except APIError as e: except APIError as e:
document.write({'last_error_message': e, 'state': 'pingen_error'}, context=context) document.write({'last_error_message': e,
'state': 'pingen_error'},
context=context)
except: except:
_logger.error('Unexcepted error in pingen cron') _logger.error('Unexcepted error in pingen cron')
loc_cr.rollback() loc_cr.rollback()
@@ -227,17 +243,16 @@ class pingen_document(orm.Model):
self._resolve_error(cr, uid, document, context=context) self._resolve_error(cr, uid, document, context=context)
return True return True
def _ask_pingen_send(self, cr, uid, document, context=None): def _ask_pingen_send(self, cr, uid, document, pingen, context=None):
""" For a document already pushed to pingen, ask to send it. """ For a document already pushed to pingen, ask to send it.
:param Pingen pingen: pingen object to reuse
""" """
# sending has been explicitely asked so we change the option # sending has been explicitely asked so we change the option
# for consistency # for consistency
if not document.pingen_send: if not document.pingen_send:
document.write({'pingen_send': True}, context=context) document.write({'pingen_send': True}, context=context)
company = self.pool.get('res.users').browse(
cr, uid, uid, context=context).company_id
pingen = self.pool.get('res.company')._pingen(cr, uid, company, context=context)
try: try:
post_id = pingen.send_document( post_id = pingen.send_document(
document.pingen_id, document.pingen_id,
@@ -267,9 +282,10 @@ class pingen_document(orm.Model):
Wrapper method for multiple ids (when triggered from button for Wrapper method for multiple ids (when triggered from button for
instance) for public interface. instance) for public interface.
""" """
with self._get_pingen_session(cr, uid, context=context) as session:
for document in self.browse(cr, uid, ids, context=context): for document in self.browse(cr, uid, ids, context=context):
try: try:
self._ask_pingen_send(cr, uid, document, context=context) self._ask_pingen_send(cr, uid, document, pingen=session, context=context)
except ConnectionError as e: except ConnectionError as e:
raise osv.except_osv( raise osv.except_osv(
_('Pingen Connection Error'), _('Pingen Connection Error'),
@@ -291,15 +307,14 @@ class pingen_document(orm.Model):
_('Unexcepted Error when updating the status of Document %s') % document.name) _('Unexcepted Error when updating the status of Document %s') % document.name)
return True return True
def _update_post_infos(self, cr, uid, document, context=None): def _update_post_infos(self, cr, uid, document, pingen, context=None):
""" Update the informations from pingen of a document in the Sendcenter """ Update the informations from pingen of a document in the Sendcenter
:param Pingen pingen: pingen object to reuse
""" """
if not document.post_id: if not document.post_id:
return return
company = self.pool.get('res.users').browse(
cr, uid, uid, context=context).company_id
pingen = self.pool.get('res.company')._pingen(cr, uid, company, context=context)
try: try:
post_infos = pingen.post_infos(document.post_id) post_infos = pingen.post_infos(document.post_id)
except ConnectionError as e: except ConnectionError as e:
@@ -350,9 +365,11 @@ class pingen_document(orm.Model):
context=context) context=context)
with closing(pooler.get_db(cr.dbname).cursor()) as loc_cr: with closing(pooler.get_db(cr.dbname).cursor()) as loc_cr:
with self._get_pingen_session(cr, uid, context=context) as session:
for document in self.browse(loc_cr, uid, ids, context=context): for document in self.browse(loc_cr, uid, ids, context=context):
try: try:
self._update_post_infos(loc_cr, uid, document, context=context) self._update_post_infos(
loc_cr, uid, document, pingen=session, context=context)
except (ConnectionError, APIError): except (ConnectionError, APIError):
# will be retried the next time # will be retried the next time
# In any case, the error has been logged by _update_post_infos # In any case, the error has been logged by _update_post_infos
@@ -371,9 +388,11 @@ class pingen_document(orm.Model):
Wrapper method for multiple ids (when triggered from button for Wrapper method for multiple ids (when triggered from button for
instance) for public interface. instance) for public interface.
""" """
with self._get_pingen_session(cr, uid, context=context) as session:
for document in self.browse(cr, uid, ids, context=context): for document in self.browse(cr, uid, ids, context=context):
try: try:
self._update_post_infos(cr, uid, document, context=context) self._update_post_infos(
cr, uid, document, pingen=session, context=context)
except ConnectionError as e: except ConnectionError as e:
raise osv.except_osv( raise osv.except_osv(
_('Pingen Connection Error'), _('Pingen Connection Error'),