diff --git a/rq_dashboard/templates/rq_dashboard/jobs.html b/rq_dashboard/templates/rq_dashboard/jobs.html
index 982e576d..d874dc19 100644
--- a/rq_dashboard/templates/rq_dashboard/jobs.html
+++ b/rq_dashboard/templates/rq_dashboard/jobs.html
@@ -23,6 +23,9 @@
+ {% if scheduler_is_here %}
+
+ {% endif %}
@@ -47,7 +50,7 @@
Name |
- Age |
+ Created at{% if registry_name == 'scheduled' %} / Enqueued at{% endif %} |
Actions |
@@ -69,7 +72,12 @@
<%= $('').text(d.exc_info).html() %>
<% } %>
- <%= d.created_at %> |
+
+ <%= d.created_at %>
+ <% if (d.long_created_at !== d.long_enqueued_at) { %>
+ / <%= d.enqueued_at %>
+ <% } %>
+ |
<% if (d.exc_info) { %>
Requeue
diff --git a/rq_dashboard/templates/rq_dashboard/queues.html b/rq_dashboard/templates/rq_dashboard/queues.html
index fd502098..3db3d2e0 100644
--- a/rq_dashboard/templates/rq_dashboard/queues.html
+++ b/rq_dashboard/templates/rq_dashboard/queues.html
@@ -14,6 +14,9 @@ Queues
| Queue |
Queued jobs |
Deferred jobs |
+ {% if scheduler_is_here %}
+ Scheduled jobs |
+ {% endif %}
Started jobs |
Finished jobs |
Failed jobs |
@@ -21,7 +24,11 @@ Queues
- Loading... |
+ {% if scheduler_is_here %}
+ Loading... |
+ {% else %}
+ Loading... |
+ {% endif %}
@@ -32,6 +39,9 @@ Queues
<%= d.name %> |
<%= d.count %> |
<%= d.deferred_job_registry_count %> |
+ {% if scheduler_is_here %}
+ <%= d.scheduled_job_registry_count %> |
+ {% endif %}
<%= d.started_job_registry_count %> |
<%= d.finished_job_registry_count %> |
<%= d.failed_job_registry_count %> |
@@ -40,7 +50,11 @@ Queues
diff --git a/rq_dashboard/templates/rq_dashboard/scripts/dashboard.js b/rq_dashboard/templates/rq_dashboard/scripts/dashboard.js
index f8677d04..75d447cc 100644
--- a/rq_dashboard/templates/rq_dashboard/scripts/dashboard.js
+++ b/rq_dashboard/templates/rq_dashboard/scripts/dashboard.js
@@ -52,7 +52,7 @@ var toRelative = function(universal_date_string) {
var toShort = function(universal_date_string) {
var tzo = new Date().getTimezoneOffset();
var d = Date.create(universal_date_string).rewind({ minutes: tzo });
- return d.format()
+ return d.format('{d} {Month}, {yyyy}, {hh}:{mm}')
}
var api = {
diff --git a/rq_dashboard/templates/rq_dashboard/scripts/jobs.js b/rq_dashboard/templates/rq_dashboard/scripts/jobs.js
index 6ccd3e9e..c01f7d91 100644
--- a/rq_dashboard/templates/rq_dashboard/scripts/jobs.js
+++ b/rq_dashboard/templates/rq_dashboard/scripts/jobs.js
@@ -38,7 +38,12 @@
if (jobs.length > 0) {
$.each(jobs, function(i, job) {
+ job.long_created_at = toShort(Date.create(job.created_at));
job.created_at = toRelative(Date.create(job.created_at));
+ if (job.enqueued_at !== undefined) {
+ job.long_enqueued_at = toShort(Date.create(job.enqueued_at))
+ job.enqueued_at = toRelative(Date.create(job.enqueued_at));
+ }
if (job.ended_at !== undefined) {
job.ended_at = toRelative(Date.create(job.ended_at));
}
diff --git a/rq_dashboard/web.py b/rq_dashboard/web.py
index 97346755..d130d047 100644
--- a/rq_dashboard/web.py
+++ b/rq_dashboard/web.py
@@ -53,6 +53,13 @@
from .version import VERSION as rq_dashboard_version
+# Quick import solution for backward compat
+scheduler_is_here = True
+try:
+ from rq.registry import ScheduledJobRegistry
+except ImportError:
+ scheduler_is_here = False
+
blueprint = Blueprint(
"rq_dashboard", __name__, template_folder="templates", static_folder="static",
)
@@ -105,57 +112,120 @@ def _wrapped(*args, **kwargs):
def serialize_queues(instance_number, queues):
- return [
- dict(
- name=q.name,
- count=q.count,
- queued_url=url_for(
- ".jobs_overview",
- instance_number=instance_number,
- queue_name=q.name,
- registry_name="queued",
- per_page="8",
- page="1",
- ),
- failed_job_registry_count=FailedJobRegistry(q.name).count,
- failed_url=url_for(
- ".jobs_overview",
- instance_number=instance_number,
- queue_name=q.name,
- registry_name="failed",
- per_page="8",
- page="1",
- ),
- started_job_registry_count=StartedJobRegistry(q.name).count,
- started_url=url_for(
- ".jobs_overview",
- instance_number=instance_number,
- queue_name=q.name,
- registry_name="started",
- per_page="8",
- page="1",
- ),
- deferred_job_registry_count=DeferredJobRegistry(q.name).count,
- deferred_url=url_for(
- ".jobs_overview",
- instance_number=instance_number,
- queue_name=q.name,
- registry_name="deferred",
- per_page="8",
- page="1",
- ),
- finished_job_registry_count=FinishedJobRegistry(q.name).count,
- finished_url=url_for(
- ".jobs_overview",
- instance_number=instance_number,
- queue_name=q.name,
- registry_name="finished",
- per_page="8",
- page="1",
- ),
- )
- for q in queues
- ]
+ if scheduler_is_here:
+ result_list = [
+ dict(
+ name=q.name,
+ count=q.count,
+ queued_url=url_for(
+ ".jobs_overview",
+ instance_number=instance_number,
+ queue_name=q.name,
+ registry_name="queued",
+ per_page="8",
+ page="1",
+ ),
+ failed_job_registry_count=FailedJobRegistry(q.name).count,
+ failed_url=url_for(
+ ".jobs_overview",
+ instance_number=instance_number,
+ queue_name=q.name,
+ registry_name="failed",
+ per_page="8",
+ page="1",
+ ),
+ started_job_registry_count=StartedJobRegistry(q.name).count,
+ started_url=url_for(
+ ".jobs_overview",
+ instance_number=instance_number,
+ queue_name=q.name,
+ registry_name="started",
+ per_page="8",
+ page="1",
+ ),
+ deferred_job_registry_count=DeferredJobRegistry(q.name).count,
+ deferred_url=url_for(
+ ".jobs_overview",
+ instance_number=instance_number,
+ queue_name=q.name,
+ registry_name="deferred",
+ per_page="8",
+ page="1",
+ ),
+ finished_job_registry_count=FinishedJobRegistry(q.name).count,
+ finished_url=url_for(
+ ".jobs_overview",
+ instance_number=instance_number,
+ queue_name=q.name,
+ registry_name="finished",
+ per_page="8",
+ page="1",
+ ),
+ scheduled_job_registry_count=ScheduledJobRegistry(q.name).count,
+ scheduled_url=url_for(
+ ".jobs_overview",
+ instance_number=instance_number,
+ queue_name=q.name,
+ registry_name="scheduled",
+ per_page="8",
+ page="1",
+ ),
+ )
+ for q in queues
+ ]
+ else:
+ result_list = [
+ dict(
+ name=q.name,
+ count=q.count,
+ queued_url=url_for(
+ ".jobs_overview",
+ instance_number=instance_number,
+ queue_name=q.name,
+ registry_name="queued",
+ per_page="8",
+ page="1",
+ ),
+ failed_job_registry_count=FailedJobRegistry(q.name).count,
+ failed_url=url_for(
+ ".jobs_overview",
+ instance_number=instance_number,
+ queue_name=q.name,
+ registry_name="failed",
+ per_page="8",
+ page="1",
+ ),
+ started_job_registry_count=StartedJobRegistry(q.name).count,
+ started_url=url_for(
+ ".jobs_overview",
+ instance_number=instance_number,
+ queue_name=q.name,
+ registry_name="started",
+ per_page="8",
+ page="1",
+ ),
+ deferred_job_registry_count=DeferredJobRegistry(q.name).count,
+ deferred_url=url_for(
+ ".jobs_overview",
+ instance_number=instance_number,
+ queue_name=q.name,
+ registry_name="deferred",
+ per_page="8",
+ page="1",
+ ),
+ finished_job_registry_count=FinishedJobRegistry(q.name).count,
+ finished_url=url_for(
+ ".jobs_overview",
+ instance_number=instance_number,
+ queue_name=q.name,
+ registry_name="finished",
+ per_page="8",
+ page="1",
+ ),
+ )
+ for q in queues
+ ]
+ return result_list
def serialize_date(dt):
@@ -165,9 +235,15 @@ def serialize_date(dt):
def serialize_job(job):
+ enqueued_at = (
+ job.enqueued_at
+ if job.enqueued_at
+ else ScheduledJobRegistry(job.origin).get_scheduled_time(job)
+ )
return dict(
id=job.id,
created_at=serialize_date(job.created_at),
+ enqueued_at=serialize_date(enqueued_at),
ended_at=serialize_date(job.ended_at),
exc_info=str(job.exc_info) if job.exc_info else None,
description=job.description,
@@ -225,6 +301,8 @@ def get_queue_registry_jobs_count(queue_name, registry_name, offset, per_page):
current_queue = StartedJobRegistry(queue_name)
elif registry_name == "finished":
current_queue = FinishedJobRegistry(queue_name)
+ elif registry_name == "scheduled":
+ current_queue = ScheduledJobRegistry(queue_name)
else:
current_queue = queue
total_items = current_queue.count
@@ -259,6 +337,7 @@ def queues_overview(instance_number):
rq_dashboard_version=rq_dashboard_version,
rq_version=rq_version,
active_tab="queues",
+ scheduler_is_here=scheduler_is_here,
deprecation_options_usage=current_app.config.get(
"DEPRECATED_OPTIONS", False
),
@@ -320,6 +399,7 @@ def jobs_overview(instance_number, queue_name, registry_name, per_page, page):
rq_dashboard_version=rq_dashboard_version,
rq_version=rq_version,
active_tab="jobs",
+ scheduler_is_here=scheduler_is_here,
deprecation_options_usage=current_app.config.get(
"DEPRECATED_OPTIONS", False
),
@@ -398,6 +478,10 @@ def empty_queue(queue_name, registry_name):
ids = FinishedJobRegistry(queue_name).get_job_ids()
for id in ids:
delete_job_view(id)
+ elif registry_name == "scheduled":
+ ids = ScheduledJobRegistry(queue_name).get_job_ids()
+ for id in ids:
+ delete_job_view(id)
return dict(status="OK")
@@ -513,10 +597,15 @@ def list_jobs(instance_number, queue_name, registry_name, per_page, page):
@jsonify
def job_info(instance_number, job_id):
job = Job.fetch(job_id)
+ enqueued_at = (
+ job.enqueued_at
+ if job.enqueued_at
+ else ScheduledJobRegistry(job.origin).get_scheduled_time(job)
+ )
return dict(
id=job.id,
created_at=serialize_date(job.created_at),
- enqueued_at=serialize_date(job.enqueued_at),
+ enqueued_at=serialize_date(enqueued_at),
ended_at=serialize_date(job.ended_at),
origin=job.origin,
status=job.get_status(),