Skip to content

Commit

Permalink
Reload monitor on problem update
Browse files Browse the repository at this point in the history
  • Loading branch information
magnified103 committed Oct 13, 2024
1 parent aa56e9d commit 8327221
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 33 deletions.
1 change: 1 addition & 0 deletions dmoj/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,7 @@
BRIDGED_JUDGE_PROXIES = None
BRIDGED_DJANGO_ADDRESS = [('localhost', 9998)]
BRIDGED_DJANGO_CONNECT = None
BRIDGED_MONITOR_UPDATE_URL = 'http://localhost:9990/update/problems'

# Event Server configuration
EVENT_DAEMON_USE = False
Expand Down
6 changes: 4 additions & 2 deletions judge/bridge/monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,15 @@ class SendProblemsHandler(FileSystemEventHandler):
EVENT_TYPE_CREATED,
)

def __init__(self, signal):
def __init__(self, signal, propagation_signal):
self.signal = signal
self.propagation_signal = propagation_signal

def on_any_event(self, event):
if event.event_type not in self.ALLOWED_EVENT_TYPES:
return
self.signal.set()
self.propagation_signal.set()


class Monitor:
Expand Down Expand Up @@ -110,7 +112,7 @@ class Handler(JudgeControlRequestHandler):
api_server = HTTPServer(api_listen, Handler)
self.api_server_thread = threading.Thread(target=api_server.serve_forever)

self._handler = SendProblemsHandler(self.updater_signal)
self._handler = SendProblemsHandler(self.updater_signal, self.propagation_signal)
self._observer = Observer()

for _, dir_glob in self.problem_globs:
Expand Down
87 changes: 56 additions & 31 deletions judge/views/problem_transfer.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import base64
import hmac
import logging
import struct
from contextlib import closing
from urllib.request import urlopen

import requests
from celery import shared_task
from django.conf import settings
from django.contrib.auth.models import AnonymousUser
from django.contrib.auth.models import AnonymousUser, User
from django.core.exceptions import PermissionDenied, ValidationError
from django.core.validators import RegexValidator
from django.db.models import Q
from django.forms import CharField, Form
from django.http import Http404, HttpResponseRedirect, JsonResponse
from django.http import Http404, JsonResponse
from django.urls import reverse
from django.utils import timezone
from django.utils.decorators import method_decorator
Expand All @@ -23,10 +27,14 @@
from reversion import revisions

from judge.models import Language, Problem, ProblemExportKey, ProblemGroup, ProblemType
from judge.utils.celery import redirect_to_task_status
from judge.utils.views import TitleMixin
from judge.widgets import HeavySelect2Widget


logger = logging.getLogger('judge.problem.transfer')


class ProblemExportMixin:
def setup(self, request, *args, **kwargs):
if not settings.VNOJ_PROBLEM_ENABLE_EXPORT:
Expand Down Expand Up @@ -139,41 +147,58 @@ def clean(self):
self.add_error('secret', _('No remaining uses'))


@shared_task(bind=True)
def import_problem(self, user_id, problem, new_code):
old_code = problem
problem_info = requests.post(get_problem_export_url(),
data={'code': old_code},
timeout=settings.VNOJ_PROBLEM_IMPORT_TIMEOUT).json()

if not problem_info:
raise Http404()
problem = Problem()
problem.code = new_code
# Use the exported code
problem.judge_code = settings.VNOJ_PROBLEM_IMPORT_JUDGE_PREFIX + problem_info['code']
problem.name = problem_info['name']
problem.description = problem_info['description']
problem.time_limit = problem_info['time_limit']
problem.memory_limit = problem_info['memory_limit']
problem.points = problem_info['points']
problem.partial = problem_info['partial']
problem.short_circuit = problem_info['short_circuit']
problem.group = ProblemGroup.objects.order_by('id').first() # Uncategorized
problem.date = timezone.now()
problem.is_manually_managed = True
with revisions.create_revision(atomic=True):
problem.save()
problem.allowed_languages.set(Language.objects.filter(include_in_problem=True))
problem.types.set([ProblemType.objects.order_by('id').first()]) # Uncategorized
user = User.objects.get(id=user_id)
problem.curators.add(user.profile)
revisions.set_user(user)
revisions.set_comment(_('Imported from %s%s') % (
settings.VNOJ_PROBLEM_IMPORT_HOST, reverse('problem_detail', args=(old_code,))))
url = settings.BRIDGED_MONITOR_UPDATE_URL
logger.info('Pinging for problem update: %s', url)
try:
with closing(urlopen(url, data=b'')) as f:
f.read()
except Exception:
logger.exception('Failed to ping for problem update: %s', url)


class ProblemImportView(TitleMixin, FormView):
title = _('Import Problem')
template_name = 'problem/import.html'
form_class = ProblemImportForm

def form_valid(self, form):
problem_info = requests.post(get_problem_export_url(),
data={'code': form.cleaned_data['problem']},
timeout=settings.VNOJ_PROBLEM_IMPORT_TIMEOUT).json()

if not problem_info:
raise Http404('Request timed out')
problem = Problem()
problem.code = form.cleaned_data['new_code']
# Use the exported code
problem.judge_code = settings.VNOJ_PROBLEM_IMPORT_JUDGE_PREFIX + problem_info['code']
problem.name = problem_info['name']
problem.description = problem_info['description']
problem.time_limit = problem_info['time_limit']
problem.memory_limit = problem_info['memory_limit']
problem.points = problem_info['points']
problem.partial = problem_info['partial']
problem.short_circuit = problem_info['short_circuit']
problem.group = ProblemGroup.objects.order_by('id').first() # Uncategorized
problem.date = timezone.now()
problem.is_manually_managed = True
with revisions.create_revision(atomic=True):
problem.save()
problem.allowed_languages.set(Language.objects.filter(include_in_problem=True))
problem.types.set([ProblemType.objects.order_by('id').first()]) # Uncategorized
problem.curators.add(self.request.profile)
revisions.set_user(self.request.user)
revisions.set_comment(_('Imported from %s%s') % (
settings.VNOJ_PROBLEM_IMPORT_HOST, reverse('problem_detail', args=(form.cleaned_data['problem'],))))
return HttpResponseRedirect(reverse('problem_edit', args=(problem.code,)))
status = import_problem.delay(user_id=self.request.user.id, **form.cleaned_data)
return redirect_to_task_status(
status, message=_('Importing %s...') % (form.cleaned_data['new_code'],),
redirect=reverse('problem_edit', args=(form.cleaned_data['new_code'],)),
)

def dispatch(self, request, *args, **kwargs):
if not settings.VNOJ_PROBLEM_ENABLE_IMPORT:
Expand Down

0 comments on commit 8327221

Please sign in to comment.