Merge branch 'feature/progress' into develop
This commit is contained in:
@@ -0,0 +1,58 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
|
import numpy as np
|
||||||
|
import time
|
||||||
|
|
||||||
|
from redis import StrictRedis,Redis
|
||||||
|
from celery import result as celery_result
|
||||||
|
import json
|
||||||
|
|
||||||
|
redis_connection = StrictRedis()
|
||||||
|
|
||||||
|
import redis
|
||||||
|
import threading
|
||||||
|
|
||||||
|
def getvalue(data):
|
||||||
|
perc = 0
|
||||||
|
total = 1
|
||||||
|
done = 0
|
||||||
|
id = 0
|
||||||
|
session_key = 'noot'
|
||||||
|
for i in data.iteritems():
|
||||||
|
if i[0] == 'total':
|
||||||
|
total = float(i[1])
|
||||||
|
if i[0] == 'done':
|
||||||
|
done = float(i[1])
|
||||||
|
if i[0] == 'id':
|
||||||
|
id = i[1]
|
||||||
|
if i[0] == 'session_key':
|
||||||
|
session_key = i[1]
|
||||||
|
|
||||||
|
return total,done,id,session_key
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def longtask(aantal,jobid=None,debug=False,
|
||||||
|
session_key=None):
|
||||||
|
counter = 0
|
||||||
|
|
||||||
|
channel = 'tasks'
|
||||||
|
for i in range(aantal):
|
||||||
|
time.sleep(1)
|
||||||
|
counter += 1
|
||||||
|
if counter > 10:
|
||||||
|
counter = 0
|
||||||
|
if debug:
|
||||||
|
progress = 100.*i/aantal
|
||||||
|
if jobid != None:
|
||||||
|
redis_connection.publish(channel,json.dumps(
|
||||||
|
{
|
||||||
|
'done':i,
|
||||||
|
'total':aantal,
|
||||||
|
'id':jobid,
|
||||||
|
'session_key':session_key,
|
||||||
|
}
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 1
|
||||||
+10
-2
@@ -35,6 +35,8 @@ from django.db.utils import OperationalError
|
|||||||
import datautils
|
import datautils
|
||||||
import utils
|
import utils
|
||||||
|
|
||||||
|
import longtask
|
||||||
|
|
||||||
# testing task
|
# testing task
|
||||||
|
|
||||||
|
|
||||||
@@ -42,9 +44,15 @@ import utils
|
|||||||
def add(x, y):
|
def add(x, y):
|
||||||
return x + y
|
return x + y
|
||||||
|
|
||||||
|
|
||||||
|
@app.task(bind=True)
|
||||||
|
def long_test_task(self,aantal,debug=False,job=None,session_key=None):
|
||||||
|
job = self.request
|
||||||
|
|
||||||
|
return longtask.longtask(aantal,jobid=job.id,debug=debug,
|
||||||
|
session_key=session_key)
|
||||||
|
|
||||||
# create workout
|
# create workout
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@app.task
|
||||||
def handle_new_workout_from_file(r, f2,
|
def handle_new_workout_from_file(r, f2,
|
||||||
workouttype='rower',
|
workouttype='rower',
|
||||||
|
|||||||
@@ -4,6 +4,53 @@
|
|||||||
|
|
||||||
{% block title %}Rowsandall - Tasks {% endblock %}
|
{% block title %}Rowsandall - Tasks {% endblock %}
|
||||||
|
|
||||||
|
{% block meta %}
|
||||||
|
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
|
||||||
|
<style type="text/css">
|
||||||
|
.progressBar div {
|
||||||
|
border-radius:5px;
|
||||||
|
height: 100%;
|
||||||
|
/* padding: 4px 10px; */
|
||||||
|
font-size: 15px;
|
||||||
|
color: #fff;
|
||||||
|
text-align: right;
|
||||||
|
line-height: 22px;
|
||||||
|
width: 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-color: #0099ff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script type='text/javascript'
|
||||||
|
src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'>
|
||||||
|
</script>
|
||||||
|
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
$('.progressBar').each(function() {
|
||||||
|
var bar = $(this);
|
||||||
|
var maxvalue = $(this).attr('data');
|
||||||
|
maxvalue = 0;
|
||||||
|
var text = $(this).children('div').data('show');
|
||||||
|
progress1(maxvalue, bar, text);
|
||||||
|
});
|
||||||
|
$('.progressBar').each(function() {
|
||||||
|
var bar = $(this);
|
||||||
|
var maxvalue = $(this).attr('data');
|
||||||
|
maxvalue = maxvalue.substring(3);
|
||||||
|
var text = $(this).children('div').data('show');
|
||||||
|
progress(maxvalue, bar, text);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function progress1(percent, element, text) {
|
||||||
|
element.find('div').animate({ width: percent+'%' }, 1).html(text +" "+ percent + "% ");
|
||||||
|
}
|
||||||
|
function progress(percent, element, text) {
|
||||||
|
element.find('div').animate({ width: percent+'%' }, 'slow').html(text +" "+ percent + "% ");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
|
||||||
@@ -16,7 +63,8 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
<th style="width:180">Task</th>
|
<th>Task</th>
|
||||||
|
<th>Progress</th>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<th>Action</th>
|
<th>Action</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -31,6 +79,12 @@
|
|||||||
{{ task|lookup:'verbose' }}
|
{{ task|lookup:'verbose' }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
<div class="progressBar" data="max{{ task|lookup:'progress' }}" style="width: 100%;">
|
||||||
|
<div data-show=""> {{ task|lookup:'progress' }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
{{ task|lookup:'status' }}
|
{{ task|lookup:'status' }}
|
||||||
</td>
|
</td>
|
||||||
{% if task|lookup:'failed' %}
|
{% if task|lookup:'failed' %}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
from django import template
|
from django import template
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
from time import strftime
|
from time import strftime
|
||||||
import dateutil.parser
|
import dateutil.parser
|
||||||
|
import json
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
@@ -65,6 +67,11 @@ def deltatimeprint(d):
|
|||||||
return strfdeltah(d)
|
return strfdeltah(d)
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter(is_safe=True)
|
||||||
|
def jsdict(dict,key):
|
||||||
|
s = dict.get(key)
|
||||||
|
return mark_safe(json.dumps(s))
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def lookup(dict, key):
|
def lookup(dict, key):
|
||||||
s = dict.get(key)
|
s = dict.get(key)
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ urlpatterns = [
|
|||||||
url(r'^list-jobs/$',views.session_jobs_view),
|
url(r'^list-jobs/$',views.session_jobs_view),
|
||||||
url(r'^jobs-status/$',views.session_jobs_status),
|
url(r'^jobs-status/$',views.session_jobs_status),
|
||||||
url(r'^job-kill/(?P<id>.*)$',views.kill_async_job),
|
url(r'^job-kill/(?P<id>.*)$',views.kill_async_job),
|
||||||
|
url(r'^test-job/(?P<aantal>\d+)$',views.test_job_view),
|
||||||
url(r'^list-graphs/$',views.graphs_view),
|
url(r'^list-graphs/$',views.graphs_view),
|
||||||
url(r'^(?P<theuser>\d+)/ote-bests/(?P<startdatestring>\w+.*)/(?P<enddatestring>\w+.*)$',views.rankings_view),
|
url(r'^(?P<theuser>\d+)/ote-bests/(?P<startdatestring>\w+.*)/(?P<enddatestring>\w+.*)$',views.rankings_view),
|
||||||
url(r'^(?P<theuser>\d+)/ote-bests/(?P<deltadays>\d+)$',views.rankings_view),
|
url(r'^(?P<theuser>\d+)/ote-bests/(?P<deltadays>\d+)$',views.rankings_view),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import colorsys
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
lbstoN = 4.44822
|
lbstoN = 4.44822
|
||||||
|
|
||||||
landingpages = (
|
landingpages = (
|
||||||
@@ -226,3 +227,5 @@ def myqueue(queue,function,*args,**kwargs):
|
|||||||
job = queue.enqueue(function,*args,**kwargs)
|
job = queue.enqueue(function,*args,**kwargs)
|
||||||
|
|
||||||
return job
|
return job
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+101
-7
@@ -14,6 +14,7 @@ from django.views.generic.base import TemplateView
|
|||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django import template
|
from django import template
|
||||||
from django.db import IntegrityError, transaction
|
from django.db import IntegrityError, transaction
|
||||||
|
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.http import (
|
from django.http import (
|
||||||
HttpResponse, HttpResponseRedirect,
|
HttpResponse, HttpResponseRedirect,
|
||||||
@@ -99,7 +100,7 @@ from rowers.tasks import handle_makeplot,handle_otwsetpower,handle_sendemailtcx,
|
|||||||
from rowers.tasks import (
|
from rowers.tasks import (
|
||||||
handle_sendemail_unrecognized,handle_sendemailnewcomment,
|
handle_sendemail_unrecognized,handle_sendemailnewcomment,
|
||||||
handle_sendemailnewresponse, handle_updatedps,
|
handle_sendemailnewresponse, handle_updatedps,
|
||||||
handle_updatecp
|
handle_updatecp,long_test_task
|
||||||
)
|
)
|
||||||
|
|
||||||
from scipy.signal import savgol_filter
|
from scipy.signal import savgol_filter
|
||||||
@@ -131,13 +132,69 @@ queue = django_rq.get_queue('default')
|
|||||||
queuelow = django_rq.get_queue('low')
|
queuelow = django_rq.get_queue('low')
|
||||||
queuehigh = django_rq.get_queue('low')
|
queuehigh = django_rq.get_queue('low')
|
||||||
|
|
||||||
|
import redis
|
||||||
|
import threading
|
||||||
from redis import StrictRedis,Redis
|
from redis import StrictRedis,Redis
|
||||||
from rq.exceptions import NoSuchJobError
|
from rq.exceptions import NoSuchJobError
|
||||||
from rq.registry import StartedJobRegistry
|
from rq.registry import StartedJobRegistry
|
||||||
from rq import Queue,cancel_job
|
from rq import Queue,cancel_job
|
||||||
|
|
||||||
|
from django.core.cache import cache
|
||||||
|
|
||||||
|
def getvalue(data):
|
||||||
|
perc = 0
|
||||||
|
total = 1
|
||||||
|
done = 0
|
||||||
|
id = 0
|
||||||
|
session_key = 'noot'
|
||||||
|
for i in data.iteritems():
|
||||||
|
if i[0] == 'total':
|
||||||
|
total = float(i[1])
|
||||||
|
if i[0] == 'done':
|
||||||
|
done = float(i[1])
|
||||||
|
if i[0] == 'id':
|
||||||
|
id = i[1]
|
||||||
|
if i[0] == 'session_key':
|
||||||
|
session_key = i[1]
|
||||||
|
|
||||||
|
return total,done,id,session_key
|
||||||
|
|
||||||
|
class SessionTaskListener(threading.Thread):
|
||||||
|
def __init__(self, r, channels):
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.redis = r
|
||||||
|
self.pubsub = self.redis.pubsub()
|
||||||
|
self.pubsub.subscribe(channels)
|
||||||
|
|
||||||
|
def work(self, item):
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = json.loads(item['data'])
|
||||||
|
total,done,id,session_key = getvalue(data)
|
||||||
|
perc = int(100.*done/total)
|
||||||
|
cache.set(id,perc,3600)
|
||||||
|
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
for item in self.pubsub.listen():
|
||||||
|
if item['data'] == "KILL":
|
||||||
|
self.pubsub.unsubscribe()
|
||||||
|
print self, "unsubscribed and finished"
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.work(item)
|
||||||
|
|
||||||
|
|
||||||
queuefailed = Queue("failed",connection=Redis())
|
queuefailed = Queue("failed",connection=Redis())
|
||||||
redis_connection = StrictRedis()
|
redis_connection = StrictRedis()
|
||||||
|
r = Redis()
|
||||||
|
|
||||||
|
client = SessionTaskListener(r,['tasks'])
|
||||||
|
client.start()
|
||||||
|
|
||||||
|
|
||||||
rq_registry = StartedJobRegistry(queue.name,connection=redis_connection)
|
rq_registry = StartedJobRegistry(queue.name,connection=redis_connection)
|
||||||
rq_registryhigh = StartedJobRegistry(queuehigh.name,connection=redis_connection)
|
rq_registryhigh = StartedJobRegistry(queuehigh.name,connection=redis_connection)
|
||||||
rq_registrylow = StartedJobRegistry(queuelow.name,connection=redis_connection)
|
rq_registrylow = StartedJobRegistry(queuelow.name,connection=redis_connection)
|
||||||
@@ -181,14 +238,13 @@ def remove_asynctask(request,id):
|
|||||||
|
|
||||||
newtasks = []
|
newtasks = []
|
||||||
for task in oldtasks:
|
for task in oldtasks:
|
||||||
print task[0]
|
|
||||||
if id not in task[0]:
|
if id not in task[0]:
|
||||||
newtasks += [(task[0],task[1])]
|
newtasks += [(task[0],task[1])]
|
||||||
|
|
||||||
request.session['async_tasks'] = newtasks
|
request.session['async_tasks'] = newtasks
|
||||||
|
|
||||||
def get_job_result(jobid):
|
def get_job_result(jobid):
|
||||||
if settings.EBUG:
|
if settings.DEBUG:
|
||||||
result = celery_result.AsyncResult(jobid).result
|
result = celery_result.AsyncResult(jobid).result
|
||||||
else:
|
else:
|
||||||
running_job_ids = rq_registry.get_job_ids()
|
running_job_ids = rq_registry.get_job_ids()
|
||||||
@@ -210,12 +266,14 @@ verbose_job_status = {
|
|||||||
'updatecpwater': 'Critical Power Calculation for OTW Workouts',
|
'updatecpwater': 'Critical Power Calculation for OTW Workouts',
|
||||||
'otwsetpower': 'Rowing Physics OTW Power Calculation',
|
'otwsetpower': 'Rowing Physics OTW Power Calculation',
|
||||||
'make_plot': 'Create static chart',
|
'make_plot': 'Create static chart',
|
||||||
|
'long_test_task': 'Long Test Task',
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_job_status(jobid):
|
def get_job_status(jobid):
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
job = celery_result.AsyncResult(jobid)
|
job = celery_result.AsyncResult(jobid)
|
||||||
jobresult = job.result
|
jobresult = job.result
|
||||||
|
|
||||||
if 'fail' in job.status.lower():
|
if 'fail' in job.status.lower():
|
||||||
jobresult = '0'
|
jobresult = '0'
|
||||||
summary = {
|
summary = {
|
||||||
@@ -261,6 +319,25 @@ def kill_async_job(request,id='aap'):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
remove_asynctask(request,id)
|
remove_asynctask(request,id)
|
||||||
|
cache.delete(id)
|
||||||
|
url = reverse(session_jobs_status)
|
||||||
|
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
@login_required()
|
||||||
|
def test_job_view(request,aantal=100):
|
||||||
|
|
||||||
|
session_key = request.session._session_key
|
||||||
|
|
||||||
|
job = myqueue(queuehigh,long_test_task,int(aantal),
|
||||||
|
session_key=session_key)
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
request.session['async_tasks'] += [(job.id,'long_test_task')]
|
||||||
|
except KeyError:
|
||||||
|
request.session['async_tasks'] = [(job.id,'long_test_task')]
|
||||||
|
|
||||||
url = reverse(session_jobs_status)
|
url = reverse(session_jobs_status)
|
||||||
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
@@ -310,14 +387,31 @@ def get_stored_tasks_status(request):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
taskids = []
|
taskids = []
|
||||||
|
|
||||||
taskstatus = [{
|
taskstatus = []
|
||||||
|
for id,func_name in taskids:
|
||||||
|
progress = 0
|
||||||
|
cached_progress = cache.get(id)
|
||||||
|
finished = get_job_status(id)['finished']
|
||||||
|
if finished:
|
||||||
|
cache.set(id,100)
|
||||||
|
progress = 100
|
||||||
|
elif cached_progress>0:
|
||||||
|
progress = cached_progress
|
||||||
|
else:
|
||||||
|
progress = 0
|
||||||
|
|
||||||
|
this_task_status = {
|
||||||
'id':id,
|
'id':id,
|
||||||
'status':get_job_status(id)['status'],
|
'status':get_job_status(id)['status'],
|
||||||
'failed':get_job_status(id)['failed'],
|
'failed':get_job_status(id)['failed'],
|
||||||
'finished':get_job_status(id)['finished'],
|
'finished':get_job_status(id)['finished'],
|
||||||
'func_name':func_name,
|
'func_name':func_name,
|
||||||
'verbose': verbose_job_status[func_name]
|
'verbose': verbose_job_status[func_name],
|
||||||
} for id,func_name in taskids]
|
'progress': progress,
|
||||||
|
}
|
||||||
|
|
||||||
|
taskstatus.append(this_task_status)
|
||||||
|
|
||||||
|
|
||||||
return taskstatus
|
return taskstatus
|
||||||
|
|
||||||
@@ -6528,7 +6622,6 @@ def workout_flexchart3_view(request,*args,**kwargs):
|
|||||||
if request.user == row.user.user:
|
if request.user == row.user.user:
|
||||||
mayedit=1
|
mayedit=1
|
||||||
|
|
||||||
|
|
||||||
workouttype = 'ote'
|
workouttype = 'ote'
|
||||||
if row.workouttype in ('water','coastal'):
|
if row.workouttype in ('water','coastal'):
|
||||||
workouttype = 'otw'
|
workouttype = 'otw'
|
||||||
@@ -6578,6 +6671,7 @@ def workout_flexchart3_view(request,*args,**kwargs):
|
|||||||
else:
|
else:
|
||||||
yparam2 = 'hr'
|
yparam2 = 'hr'
|
||||||
|
|
||||||
|
if not request.user.is_anonymous():
|
||||||
if favoritenr>=0 and r.showfavoritechartnotes:
|
if favoritenr>=0 and r.showfavoritechartnotes:
|
||||||
favoritechartnotes = favorites[favoritenr].notes
|
favoritechartnotes = favorites[favoritenr].notes
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -287,6 +287,7 @@ RQ_QUEUES = {
|
|||||||
#SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
|
#SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
|
||||||
#SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"
|
#SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"
|
||||||
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
|
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
|
||||||
|
SESSION_SAVE_EVERY_REQUEST = True
|
||||||
|
|
||||||
# admin stuff for error reporting
|
# admin stuff for error reporting
|
||||||
SERVER_EMAIL='admin@rowsandall.com'
|
SERVER_EMAIL='admin@rowsandall.com'
|
||||||
|
|||||||
Reference in New Issue
Block a user