Check if any jobs exist before querying jobs

At the moment the dashboard does two API calls to find out if a service
has:

1. Scheduled jobs
2. Normal jobs

API calls are slow because they are synchronous, go over the network and
touch the database. We can’t cache these API calls because:
- a scheduled job could become a normal job at any time
- the statistics on a normal job are constantly updating

However there are plenty of services which don’t have any jobs, and
probably never will. And finding out if a service has any jobs is
reliably cacheable (because as soon as a service creates its first job
it has some jobs).

So this commit:
- refactors the way we get scheduled/normal jobs into the job_api_client
  to make the view a bit slimmer
- makes an additional, Redis-wrapped call to find out if any jobs exist
  before trying to get the jobs

This should result in a speedup on the dashboard, and can be used in the
future if there’s anywhere else we want to show or hide something
depending on whether a service has created any jobs (I have some ideas).
This commit is contained in:
Chris Hill-Scott
2018-07-20 10:18:51 +01:00
parent c1b2f63671
commit 505de52d38
5 changed files with 122 additions and 27 deletions

View File

@@ -1,6 +1,6 @@
from collections import defaultdict
from app.notify_client import NotifyAdminAPIClient, _attach_current_user
from app.notify_client import NotifyAdminAPIClient, _attach_current_user, cache
class JobApiClient(NotifyAdminAPIClient):
@@ -16,6 +16,8 @@ class JobApiClient(NotifyAdminAPIClient):
'sent to dvla'
}
NORMAL_JOB_STATUSES = JOB_STATUSES - {'scheduled', 'cancelled'}
def __init__(self):
super().__init__("a" * 73, "b")
@@ -60,8 +62,38 @@ class JobApiClient(NotifyAdminAPIClient):
return jobs
def get_page_of_jobs(self, service_id, page):
return self.get_jobs(
service_id,
statuses=self.NORMAL_JOB_STATUSES,
page=page,
)
def get_immediate_jobs(self, service_id):
return self.get_jobs(
service_id,
limit_days=7,
statuses=self.NORMAL_JOB_STATUSES,
)['data']
def get_scheduled_jobs(self, service_id):
return sorted(
self.get_jobs(service_id, statuses=['scheduled'])['data'],
key=lambda job: job['scheduled_for']
)
@cache.set('has_jobs-{service_id}')
def has_jobs(self, service_id):
return bool(self.get_jobs(service_id)['data'])
def create_job(self, job_id, service_id, scheduled_for=None):
self.redis_client.set(
'has_jobs-{}'.format(service_id),
True,
ex=cache.TTL,
)
data = {"id": job_id}
if scheduled_for:
@@ -78,6 +110,7 @@ class JobApiClient(NotifyAdminAPIClient):
return job
@cache.delete('has_jobs-{service_id}')
def cancel_job(self, service_id, job_id):
job = self.post(