From 3db07bca5f0729825306aed683758104ed63fa60 Mon Sep 17 00:00:00 2001 From: kimth Date: Mon, 13 Aug 2012 19:42:08 -0400 Subject: [PATCH 1/6] Frontend polling rate aware of queue length at time of submission --- .../lib/xmodule/xmodule/js/src/capa/display.coffee | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/common/lib/xmodule/xmodule/js/src/capa/display.coffee b/common/lib/xmodule/xmodule/js/src/capa/display.coffee index 6b39805d1a..9af48cce64 100644 --- a/common/lib/xmodule/xmodule/js/src/capa/display.coffee +++ b/common/lib/xmodule/xmodule/js/src/capa/display.coffee @@ -35,8 +35,18 @@ class @Problem if @queued_items.length > 0 if window.queuePollerID # Only one poller 'thread' per Problem window.clearTimeout(window.queuePollerID) - window.queuePollerID = window.setTimeout(@poll, 100) + queuelen = @get_queuelen() + window.queuePollerID = window.setTimeout(@poll, queuelen*10) + # Retrieves the minimum queue length of all queued items + get_queuelen: => + minlen = Infinity + @queued_items.each (index, qitem) -> + len = parseInt($.text(qitem)) + if len < minlen + minlen = len + return minlen + poll: => $.postWithPrefix "#{@url}/problem_get", (response) => @queued_items = $(response.html).find(".xqueue") @@ -47,7 +57,7 @@ class @Problem @bind() delete window.queuePollerID else - # TODO: Dynamically adjust timeout interval based on @queued_items.value + # TODO: Some logic to dynamically adjust polling rate based on queuelen window.queuePollerID = window.setTimeout(@poll, 1000) render: (content) -> From a4e283e975bceeff574baa706698e6af9a8c141e Mon Sep 17 00:00:00 2001 From: kimth Date: Mon, 13 Aug 2012 20:20:19 -0400 Subject: [PATCH 2/6] File submission frontend checks for filesize --- common/lib/xmodule/xmodule/js/src/capa/display.coffee | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/common/lib/xmodule/xmodule/js/src/capa/display.coffee b/common/lib/xmodule/xmodule/js/src/capa/display.coffee index 9af48cce64..9fe6f5e80e 100644 --- a/common/lib/xmodule/xmodule/js/src/capa/display.coffee +++ b/common/lib/xmodule/xmodule/js/src/capa/display.coffee @@ -151,9 +151,16 @@ class @Problem fd = new FormData() + # Sanity check of file size + file_too_large = false + max_filesize = 10*1000*1000 # 10 MB + @inputs.each (index, element) -> if element.type is 'file' if element.files[0] instanceof File + if element.files[0].size > max_filesize + file_too_large = true + alert 'Submission aborted! Your file "' + element.files[0].name + '" is too large (max size: ' + max_filesize/(1000*1000) + ' MB)' fd.append(element.id, element.files[0]) else fd.append(element.id, '') @@ -173,7 +180,8 @@ class @Problem else alert(response.success) - $.ajaxWithPrefix("#{@url}/problem_check", settings) + if not file_too_large + $.ajaxWithPrefix("#{@url}/problem_check", settings) check: => Logger.log 'problem_check', @answers From d19244c48b9b669ac2c6365205fec98e119ae828 Mon Sep 17 00:00:00 2001 From: kimth Date: Mon, 13 Aug 2012 20:41:16 -0400 Subject: [PATCH 3/6] Polling rerenders problem when individual queued items return --- common/lib/xmodule/xmodule/js/src/capa/display.coffee | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/common/lib/xmodule/xmodule/js/src/capa/display.coffee b/common/lib/xmodule/xmodule/js/src/capa/display.coffee index 9fe6f5e80e..9d725a67ee 100644 --- a/common/lib/xmodule/xmodule/js/src/capa/display.coffee +++ b/common/lib/xmodule/xmodule/js/src/capa/display.coffee @@ -32,7 +32,8 @@ class @Problem queueing: => @queued_items = @$(".xqueue") - if @queued_items.length > 0 + @num_queued_items = @queued_items.length + if @num_queued_items > 0 if window.queuePollerID # Only one poller 'thread' per Problem window.clearTimeout(window.queuePollerID) queuelen = @get_queuelen() @@ -49,12 +50,16 @@ class @Problem poll: => $.postWithPrefix "#{@url}/problem_get", (response) => - @queued_items = $(response.html).find(".xqueue") - if @queued_items.length == 0 + # If queueing status changed, then render + @new_queued_items = $(response.html).find(".xqueue") + if @new_queued_items.length isnt @num_queued_items @el.html(response.html) @executeProblemScripts () => @setupInputTypes() @bind() + + @num_queued_items = @new_queued_items.length + if @num_queued_items == 0 delete window.queuePollerID else # TODO: Some logic to dynamically adjust polling rate based on queuelen From 936f2c49f5b9ccaf401e569c3ec94cda201b4eb3 Mon Sep 17 00:00:00 2001 From: kimth Date: Mon, 13 Aug 2012 21:00:29 -0400 Subject: [PATCH 4/6] Server-side (LMS) checking of uploaded filesize --- lms/djangoapps/courseware/module_render.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index 3bb1c477cb..bb69dfcc6f 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -336,11 +336,20 @@ def modx_dispatch(request, dispatch=None, id=None, course_id=None): - id -- the module id. Used to look up the XModule instance ''' # ''' (fix emacs broken parsing) + + # TODO: Should be in settings.py + MAX_UPLOAD_FILE_SIZE = 4*1000*1000 # 4 MB + # Check for submitted files p = request.POST.copy() if request.FILES: for inputfile_id in request.FILES.keys(): - p[inputfile_id] = request.FILES[inputfile_id] + inputfile = request.FILES[inputfile_id] + if inputfile.size > MAX_UPLOAD_FILE_SIZE: + file_too_big_msg = 'Submission aborted! Your file "%s" is too large (max size: %d MB)' %\ + (inputfile.name, MAX_UPLOAD_FILE_SIZE/(1000**2)) + return HttpResponse(json.dumps({'success': file_too_big_msg})) + p[inputfile_id] = inputfile student_module_cache = StudentModuleCache.cache_for_descriptor_descendents(request.user, modulestore().get_item(id)) instance = get_module(request.user, request, id, student_module_cache) From 1c2d034283816f2e2d496d4167599da9f4d1e5c8 Mon Sep 17 00:00:00 2001 From: kimth Date: Mon, 13 Aug 2012 21:17:47 -0400 Subject: [PATCH 5/6] LMS-side MAX_FILESIZE set in settings.py --- lms/djangoapps/courseware/module_render.py | 9 +++------ lms/envs/common.py | 1 + 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index bb69dfcc6f..85eeb72c24 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -337,17 +337,14 @@ def modx_dispatch(request, dispatch=None, id=None, course_id=None): ''' # ''' (fix emacs broken parsing) - # TODO: Should be in settings.py - MAX_UPLOAD_FILE_SIZE = 4*1000*1000 # 4 MB - - # Check for submitted files + # Check for submitted files and basic file size checks p = request.POST.copy() if request.FILES: for inputfile_id in request.FILES.keys(): inputfile = request.FILES[inputfile_id] - if inputfile.size > MAX_UPLOAD_FILE_SIZE: + if inputfile.size > settings.STUDENT_FILEUPLOAD_MAX_SIZE: # Bytes file_too_big_msg = 'Submission aborted! Your file "%s" is too large (max size: %d MB)' %\ - (inputfile.name, MAX_UPLOAD_FILE_SIZE/(1000**2)) + (inputfile.name, settings.STUDENT_FILEUPLOAD_MAX_SIZE/(1000**2)) return HttpResponse(json.dumps({'success': file_too_big_msg})) p[inputfile_id] = inputfile diff --git a/lms/envs/common.py b/lms/envs/common.py index 8ebf72f22a..24a70e3e45 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -128,6 +128,7 @@ TEMPLATE_CONTEXT_PROCESSORS = ( 'django.core.context_processors.csrf', #necessary for csrf protection ) +STUDENT_FILEUPLOAD_MAX_SIZE = 4*1000*1000 # 4 MB # FIXME: # We should have separate S3 staged URLs in case we need to make changes to From 895cf2c2ed941df877e1b6080d8c1e60d47ef3a9 Mon Sep 17 00:00:00 2001 From: kimth Date: Mon, 13 Aug 2012 21:18:49 -0400 Subject: [PATCH 6/6] Front end file size limit matches server-end limit --- common/lib/xmodule/xmodule/js/src/capa/display.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/lib/xmodule/xmodule/js/src/capa/display.coffee b/common/lib/xmodule/xmodule/js/src/capa/display.coffee index 9d725a67ee..c00b680eba 100644 --- a/common/lib/xmodule/xmodule/js/src/capa/display.coffee +++ b/common/lib/xmodule/xmodule/js/src/capa/display.coffee @@ -158,7 +158,7 @@ class @Problem # Sanity check of file size file_too_large = false - max_filesize = 10*1000*1000 # 10 MB + max_filesize = 4*1000*1000 # 4 MB @inputs.each (index, element) -> if element.type is 'file'