Commit 77f928d1 by kimth

Queuestate records both secret key and time of queue request

parent f9616c6e
......@@ -202,11 +202,7 @@ class LoncapaProblem(object):
'''
Returns True if any part of the problem has been submitted to an external queue
'''
queued = False
for answer_id in self.correct_map:
if self.correct_map.is_queued(answer_id):
queued = True
return queued
return any([self.correct_map.is_queued(answer_id) for answer_id in self.correct_map])
def grade_answers(self, answers):
'''
......
......@@ -15,7 +15,8 @@ class CorrectMap(object):
- msg : string (may have HTML) giving extra message response (displayed below textline or textbox)
- hint : string (may have HTML) giving optional hint (displayed below textline or textbox, above msg)
- hintmode : one of (None,'on_request','always') criteria for displaying hint
- queuekey : a random integer for xqueue_callback verification
- queuestate : Tuple (key, time) where key is a secret string, and time is a string dump
of a DateTime object in the format '%Y%m%d%H%M%S'. Is None when not queued
Behaves as a dict.
'''
......@@ -31,14 +32,14 @@ class CorrectMap(object):
def __iter__(self):
return self.cmap.__iter__()
def set(self, answer_id=None, correctness=None, npoints=None, msg='', hint='', hintmode=None, queuekey=None):
def set(self, answer_id=None, correctness=None, npoints=None, msg='', hint='', hintmode=None, queuestate=None):
if answer_id is not None:
self.cmap[answer_id] = {'correctness': correctness,
'npoints': npoints,
'msg': msg,
'hint': hint,
'hintmode': hintmode,
'queuekey': queuekey,
'queuestate': queuestate,
}
def __repr__(self):
......@@ -67,10 +68,10 @@ class CorrectMap(object):
return None
def is_queued(self, answer_id):
return answer_id in self.cmap and self.cmap[answer_id]['queuekey'] is not None
return answer_id in self.cmap and self.cmap[answer_id]['queuestate'] is not None
def is_right_queuekey(self, answer_id, test_key):
return answer_id in self.cmap and self.cmap[answer_id]['queuekey'] == test_key
return self.is_queued(answer_id) and self.cmap[answer_id]['queuestate'][0] == test_key
def get_npoints(self, answer_id):
npoints = self.get_property(answer_id, 'npoints')
......
......@@ -26,6 +26,7 @@ import xml.sax.saxutils as saxutils
# specific library imports
from calc import evaluator, UndefinedVariable
from correctmap import CorrectMap
from datetime import datetime
from util import *
from lxml import etree
from lxml.html.soupparser import fromstring as fromstring_bs # uses Beautiful Soup!!! FIXME?
......@@ -1026,7 +1027,7 @@ class CodeResponse(LoncapaResponse):
TODO: Determines whether in synchronous or asynchronous (queued) mode
'''
xml = self.xml
self.url = xml.get('url', None) # XML can override external resource (grader/queue) URL
self.url = xml.get('url', None) # TODO: XML can override external resource (grader/queue) URL
self.queue_name = xml.get('queuename', self.system.xqueue['default_queuename'])
# VS[compat]:
......@@ -1128,7 +1129,7 @@ class CodeResponse(LoncapaResponse):
xheader = xqueue_interface.make_xheader(lms_callback_url=self.system.xqueue['callback_url'],
lms_key=queuekey,
queue_name=self.queue_name)
# Generate body
if is_list_of_files(submission):
self.context.update({'submission': queuekey}) # For tracking. TODO: May want to record something else here
......@@ -1148,16 +1149,17 @@ class CodeResponse(LoncapaResponse):
(error, msg) = qinterface.send_to_queue(header=xheader,
body=json.dumps(contents))
queuestate = (queuekey,'')
cmap = CorrectMap()
if error:
cmap.set(self.answer_id, queuekey=None,
cmap.set(self.answer_id, queuestate=None,
msg='Unable to deliver your submission to grader. (Reason: %s.) Please try again later.' % msg)
else:
# Queueing mechanism flags:
# 1) Backend: Non-null CorrectMap['queuekey'] indicates that the problem has been queued
# 1) Backend: Non-null CorrectMap['queuestate'] indicates that the problem has been queued
# 2) Frontend: correctness='incomplete' eventually trickles down through inputtypes.textbox
# and .filesubmission to inform the browser to poll the LMS
cmap.set(self.answer_id, queuekey=queuekey, correctness='incomplete', msg=msg)
cmap.set(self.answer_id, queuestate=queuestate, correctness='incomplete', msg=msg)
return cmap
......@@ -1180,7 +1182,7 @@ class CodeResponse(LoncapaResponse):
points = 0
elif points > self.maxpoints[self.answer_id]:
points = self.maxpoints[self.answer_id]
oldcmap.set(self.answer_id, npoints=points, correctness=correctness, msg=msg.replace(' ', ' '), queuekey=None) # Queuekey is consumed
oldcmap.set(self.answer_id, npoints=points, correctness=correctness, msg=msg.replace(' ', ' '), queuestate=None) # Queuestate is consumed
else:
log.debug('CodeResponse: queuekey %s does not match for answer_id=%s.' % (queuekey, self.answer_id))
......
......@@ -462,6 +462,12 @@ class CapaModule(XModule):
self.system.track_function('save_problem_check_fail', event_info)
raise NotFoundError('Problem must be reset before it can be checked again')
# Problem queued. Student should not be able to submit
'''
if self.lcp.is_queued():
return {'success': False, 'html': 'Already queued'}
'''
try:
old_state = self.lcp.get_state()
lcp_id = self.lcp.problem_id
......
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