Commit 110637c0 by kimth

XqueueInterface is a singleton instantiated object

parent 6c875206
......@@ -29,6 +29,8 @@ import xqueue_interface
log = logging.getLogger('mitx.' + __name__)
qinterface = xqueue_interface.XqueueInterface()
#-----------------------------------------------------------------------------
# Exceptions
......@@ -809,7 +811,6 @@ class CodeResponse(LoncapaResponse):
def setup_response(self):
xml = self.xml
self.url = xml.get('url')
self.queue_name = xml.get('queuename', self.system.xqueue_default_queuename)
answer = xml.find('answer')
......@@ -877,16 +878,17 @@ class CodeResponse(LoncapaResponse):
# Submit request
if hasattr(submission, 'read'): # Test for whether submission is a file
error = xqueue_interface.send_to_queue(header=xheader,
body=json.dumps(contents),
file_to_upload=submission)
(error, msg) = qinterface.send_to_queue(header=xheader,
body=json.dumps(contents),
file_to_upload=submission)
else:
error = xqueue_interface.send_to_queue(header=xheader,
body=json.dumps(contents))
(error, msg) = qinterface.send_to_queue(header=xheader,
body=json.dumps(contents))
cmap = CorrectMap()
if error:
cmap.set(self.answer_id, queuekey=None, msg='Unable to deliver your submission to grader! Please try again later')
cmap.set(self.answer_id, queuekey=None,
msg='Unable to deliver your submission to grader. (Reason: %s.) Please try again later.' % msg)
else:
# Non-null CorrectMap['queuekey'] indicates that the problem has been queued
cmap.set(self.answer_id, queuekey=queuekey, msg='Submitted to grader')
......
......@@ -3,6 +3,7 @@
#
import hashlib
import json
import logging
import requests
import time
......@@ -11,6 +12,8 @@ XQUEUE_LMS_AUTH = { 'username': 'LMS',
'password': 'PaloAltoCA' }
XQUEUE_URL = 'http://xqueue.edx.org'
log = logging.getLogger('mitx.' + __name__)
def make_hashkey(seed=None):
'''
Generate a string key by hashing
......@@ -37,61 +40,10 @@ def make_xheader(lms_callback_url, lms_key, queue_name):
'queue_name': queue_name })
def send_to_queue(header, body, file_to_upload=None, xqueue_url=XQUEUE_URL):
'''
Submit a request to xqueue.
header: JSON-serialized dict in the format described in 'xqueue_interface.make_xheader'
body: Serialized data for the receipient behind the queueing service. The operation of
xqueue is agnostic to the contents of 'body'
file_to_upload: File object to be uploaded to xqueue along with queue request
Returns an 'error' flag indicating error in xqueue transaction
'''
# First, we login with our credentials
#------------------------------------------------------------
s = requests.session()
try:
r = s.post(xqueue_url+'/xqueue/login/', data={ 'username': XQUEUE_LMS_AUTH['username'],
'password': XQUEUE_LMS_AUTH['password'] })
except Exception as err:
msg = 'Error in xqueue_interface.send_to_queue %s: Cannot connect to server url=%s' % (err, xqueue_url)
raise Exception(msg)
# Xqueue responses are JSON-serialized dicts
(return_code, msg) = parse_xreply(r.text)
if return_code: # Nonzero return code from xqueue indicates error
print ' Error in queue_interface.send_to_queue: %s' % msg
return 1 # Error
# Next, we can make a queueing request
#------------------------------------------------------------
payload = {'xqueue_header': header,
'xqueue_body' : body}
files = None
if file_to_upload is not None:
files = { file_to_upload.name: file_to_upload }
try:
r = s.post(xqueue_url+'/xqueue/submit/', data=payload, files=files)
except Exception as err:
msg = 'Error in xqueue_interface.send_to_queue %s: Cannot connect to server url=%s' % (err, xqueue_url)
raise Exception(msg)
(return_code, msg) = parse_xreply(r.text)
if return_code:
print ' Error in queue_interface.send_to_queue: %s' % msg
return return_code
def parse_xreply(xreply):
'''
Parse the reply from xqueue. Messages are JSON-serialized dict:
{ 'return_code': 0 (success), 1 (fail),
{ 'return_code': 0 (success), 1 (fail)
'content': Message from xqueue (string)
}
'''
......@@ -99,3 +51,64 @@ def parse_xreply(xreply):
return_code = xreply['return_code']
content = xreply['content']
return (return_code, content)
class XqueueInterface:
'''
Interface to the external grading system
'''
def __init__(self, url=XQUEUE_URL, auth=XQUEUE_LMS_AUTH):
self.url = url
self.auth = auth
self.s = requests.session()
self._login()
def send_to_queue(self, header, body, file_to_upload=None):
'''
Submit a request to xqueue.
header: JSON-serialized dict in the format described in 'xqueue_interface.make_xheader'
body: Serialized data for the receipient behind the queueing service. The operation of
xqueue is agnostic to the contents of 'body'
file_to_upload: File object to be uploaded to xqueue along with queue request
Returns (error_code, msg) where error_code != 0 indicates an error
'''
# Attempt to send to queue
(error, msg) = self._send_to_queue(header, body, file_to_upload)
if error and (msg == 'login_required'): # Log in, then try again
self._login()
(error, msg) = self._send_to_queue(header, body, file_to_upload)
return (error, msg)
def _login(self):
try:
r = self.s.post(self.url+'/xqueue/login/', data={ 'username': self.auth['username'],
'password': self.auth['password'] })
except requests.exceptions.ConnectionError, err:
log.error(err)
return (1, 'cannot connect to server')
return parse_xreply(r.text)
def _send_to_queue(self, header, body, file_to_upload=None):
payload = {'xqueue_header': header,
'xqueue_body' : body}
files = None
if file_to_upload is not None:
files = { file_to_upload.name: file_to_upload }
try:
r = self.s.post(self.url+'/xqueue/submit/', data=payload, files=files)
except requests.exceptions.ConnectionError, err:
log.error(err)
return (1, 'cannot connect to server')
return parse_xreply(r.text)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment