summaryrefslogtreecommitdiff
path: root/postgresqleu/scheduler/views.py
blob: 42bdd95d28527eb9c1713d145cbb68bd7eb158ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
from django.core.exceptions import PermissionDenied
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect, Http404
from django.contrib import messages
from django.db import connection
from django.db.models import F
from django.apps import apps
from django.utils import timezone

from datetime import datetime, timedelta

from postgresqleu.util.pagination import simple_pagination
from postgresqleu.util.request import get_int_or_error

from .models import ScheduledJob, JobHistory, get_config
from .forms import ScheduledJobForm
from .util import reschedule_job, notify_job_change


def index(request):
    if not request.user.is_superuser:
        raise PermissionDenied("Access denied")

    config = get_config()

    if request.method == 'POST':
        if request.POST.get('submit') == 'Hold all jobs':
            config.hold_all_jobs = True
            config.save()
            notify_job_change()
            return HttpResponseRedirect('.')
        elif request.POST.get('submit') == 'Re-enable job execution':
            what = get_int_or_error(request.POST, 'pending')
            if what == 0:
                messages.error(request, "Must decide what to do with pending jobs")
                return HttpResponseRedirect(".")
            elif what not in (1, 2):
                messages.error(request, "Invalid choice for pending jobs")
                return HttpResponseRedirect(".")

            if what == 2:
                # Re-schedule all pending jobs
                for job in ScheduledJob.objects.filter(enabled=True, nextrun__lte=timezone.now()):
                    reschedule_job(job, save=True)
            config.hold_all_jobs = False
            config.save()
            notify_job_change()
            messages.info(request, "Job execution re-enabled")
            return HttpResponseRedirect(".")

        raise Http404("Unknown button")

    jobs = ScheduledJob.objects.all().order_by(F('nextrun').asc(nulls_last=True))
    try:
        lastjob = ScheduledJob.objects.only('lastrun').filter(lastrun__isnull=False).order_by('-lastrun')[0]
        lastjobtime = lastjob.lastrun
        lastjob_recent = (timezone.now() - lastjobtime) < timedelta(hours=6)
    except IndexError:
        # No job has run yet, can happen on brand new installation
        lastjobtime = None
        lastjob_recent = False

    history = JobHistory.objects.only('time', 'job__description', 'success', 'runtime').select_related('job').order_by('-time')[:20]

    with connection.cursor() as curs:
        curs.execute("SELECT count(1) FROM pg_stat_activity WHERE application_name='pgeu scheduled job runner' AND datname=current_database()")
        n, = curs.fetchone()
        runner_active = (n > 0)

    return render(request, 'scheduler/index.html', {
        'jobs': jobs,
        'lastjob': lastjobtime,
        'lastjob_recent': lastjob_recent,
        'runner_active': runner_active,
        'holdall': config.hold_all_jobs,
        'history': history,
        'apps': {a.name: a.verbose_name for a in apps.get_app_configs()},
        'helplink': 'jobs',
    })


def job(request, jobid):
    if not request.user.is_superuser:
        raise PermissionDenied("Access denied")

    job = get_object_or_404(ScheduledJob, id=jobid)

    if request.method == 'POST':
        if request.POST.get('schedule-now', '') == '1':
            job.nextrun = timezone.now()
            job.save()
            notify_job_change()
            messages.info(request, "Scheduled immediate run of '{0}'".format(job.description))
            return HttpResponseRedirect('../')
        elif request.POST.get('reset-failure', '') == '1':
            job.lastrun = None
            job.lastrunsuccess = False
            job.save()
            messages.info(request, "Reset last run failure state of '{0}'".format(job.description))
            return HttpResponseRedirect('../')

        form = ScheduledJobForm(request, conference=None, instance=job, data=request.POST)
        if form.is_valid():
            form.save()
            reschedule_job(job, notify=True)
            return HttpResponseRedirect("../")
    else:
        form = ScheduledJobForm(request, conference=None, instance=job)

    history_objects = JobHistory.objects.filter(job=job).order_by('-time')
    (history, paginator, page_range) = simple_pagination(request, history_objects, 15)

    return render(request, 'scheduler/job.html', {
        'job': job,
        'history': history,
        'form': form,
        'page_range': page_range,
        'breadcrumbs': [('/admin/jobs/', 'Scheduled jobs'), ],
        'helplink': 'jobs',
    })


def history(request):
    if not request.user.is_superuser:
        raise PermissionDenied("Access denied")

    history_objects = JobHistory.objects.only('time', 'job__description', 'success', 'runtime').select_related('job').order_by('-time')
    (history, paginator, page_range) = simple_pagination(request, history_objects, 50)

    return render(request, 'scheduler/history.html', {
        'history': history,
        'page_range': page_range,
        'breadcrumbs': [('/admin/jobs/', 'Scheduled jobs'), ],
        'helplink': 'jobs',
    })