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(),