Skip to content

Commit

Permalink
Initial commit of different retry mechanisms.
Browse files Browse the repository at this point in the history
  • Loading branch information
fkdosilovic committed Nov 3, 2024
1 parent 428ac30 commit 160fcbb
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 19 deletions.
4 changes: 1 addition & 3 deletions examples/atd_submission.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import os
import time

import judge0

Expand All @@ -19,8 +18,7 @@ def run_example(client_class, language_id):
)

client.create_submission(submission)
time.sleep(1)
client.get_submission(submission)
client.wait(submission)

print(f"{submission.status=}")
print(f"{submission.stdout=}")
Expand Down
4 changes: 1 addition & 3 deletions examples/atd_submissions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import os
import time

import judge0

Expand All @@ -25,8 +24,7 @@ def run_example(client_class, lang_id_python, lang_id_c):

submissions = [submission1, submission2]
client.create_submissions(submissions)
time.sleep(1)
client.get_submissions(submissions)
client.wait(submissions)

for submission in submissions:
print(f"{submission.status=}")
Expand Down
4 changes: 1 addition & 3 deletions examples/rapid_submission.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import os
import time

import judge0

Expand All @@ -19,8 +18,7 @@ def run_example(client_class, language_id):
)

client.create_submission(submission)
time.sleep(1)
client.get_submission(submission)
client.wait(submission)

print(f"{submission.status=}")
print(f"{submission.stdout=}")
Expand Down
4 changes: 1 addition & 3 deletions examples/rapid_submissions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import os
import time

import judge0

Expand All @@ -25,8 +24,7 @@ def run_example(client_class, lang_id_python, lang_id_c):

submissions = [submission1, submission2]
client.create_submissions(submissions)
time.sleep(1)
client.get_submissions(submissions)
client.wait(submissions)

for submission in submissions:
print(f"{submission.status=}")
Expand Down
4 changes: 1 addition & 3 deletions examples/sulu_submission.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import os
import time

import judge0

Expand All @@ -19,8 +18,7 @@ def run_example(client_class, language_id):
)

client.create_submission(submission)
time.sleep(1)
client.get_submission(submission)
client.wait(submission)

print(f"{submission.status=}")
print(f"{submission.stdout=}")
Expand Down
4 changes: 1 addition & 3 deletions examples/sulu_submissions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import os
import time

import judge0

Expand All @@ -25,8 +24,7 @@ def run_example(client_class, lang_id_python, lang_id_c):

submissions = [submission1, submission2]
client.create_submissions(submissions)
time.sleep(1)
client.get_submissions(submissions)
client.wait(submissions)

for submission in submissions:
print(f"{submission.status=}")
Expand Down
4 changes: 4 additions & 0 deletions src/judge0/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
SuluJudge0CE,
SuluJudge0ExtraCE,
)
from .retry import MaxRetries, MaxWaitTime, RegularPeriodRetry

from .submission import Submission

Expand All @@ -19,4 +20,7 @@
SuluJudge0CE,
SuluJudge0ExtraCE,
Submission,
RegularPeriodRetry,
MaxRetries,
MaxWaitTime,
]
34 changes: 33 additions & 1 deletion src/judge0/clients.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from typing import Iterable, Union
from typing import Iterable, Optional, Union

import requests

from .retry import RegularPeriodRetry, RetryMechanism

from .submission import Submission


Expand Down Expand Up @@ -160,6 +162,36 @@ def get_submissions(
for submission, attrs in zip(submissions, resp.json()["submissions"]):
submission.set_attributes(attrs)

def wait(
self,
submissions: Union[Submission, list[Submission]],
*,
retry_mechanism: Optional[RetryMechanism] = None,
):
if retry_mechanism is None:
retry_mechanism = RegularPeriodRetry()

if not isinstance(submissions, (list, tuple)):
submissions = [submissions]

submissions_to_check = {
submission.token: submission for submission in submissions
}

while len(submissions_to_check) > 0 and not retry_mechanism.is_done():
self.get_submissions(submissions_to_check.values())
for token in list(submissions_to_check):
submission = submissions_to_check[token]
if submission.is_done():
submissions_to_check.pop(token)

# Don't wait if there is no submissions to check for anymore.
if len(submissions_to_check) == 0:
break

retry_mechanism.wait()
retry_mechanism.step()


class ATD(Client):
def __init__(self, endpoint, host_header_value, api_key):
Expand Down
68 changes: 68 additions & 0 deletions src/judge0/retry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import time
from abc import ABC, abstractmethod


class RetryMechanism(ABC):
@abstractmethod
def is_done(self) -> bool:
pass

@abstractmethod
def wait(self) -> None:
pass

@abstractmethod
def step(self) -> None:
pass


class MaxRetries(RetryMechanism):
"""Check for submissions status every 100 ms and retry a maximum of
`max_retries` times."""

def __init__(self, max_retries: int = 20):
self.n_retries = 0
self.max_retries = max_retries

def step(self):
self.n_retries += 1

def wait(self):
time.sleep(0.1)

def is_done(self) -> bool:
return self.n_retries >= self.max_retries


class MaxWaitTime(RetryMechanism):
"""Check for submissions status every 100 ms and wait for all submissions
a maximum of `max_wait_time` (seconds)."""

def __init__(self, max_wait_time_sec: float = 5 * 60):
self.max_wait_time_sec = max_wait_time_sec
self.total_wait_time = 0

def step(self):
self.total_wait_time += 0.1

def wait(self):
time.sleep(0.1)

def is_done(self):
return self.total_wait_time >= self.max_wait_time_sec


class RegularPeriodRetry(RetryMechanism):
"""Check for submissions status periodically for indefinite amount of time."""

def __init__(self, wait_time_sec: float = 0.1):
self.wait_time_sec = wait_time_sec

def step(self):
pass

def wait(self):
time.sleep(self.wait_time_sec)

def is_done(self) -> bool:
return False
8 changes: 8 additions & 0 deletions src/judge0/submission.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from base64 import b64decode, b64encode

from .common import Status


ENCODED_REQUEST_FIELDS = {
"source_code",
Expand Down Expand Up @@ -146,3 +148,9 @@ def to_dict(self) -> dict:
body[field] = value

return body

def is_done(self) -> bool:
if self.status is None:
return False
else:
return self.status not in [Status.IN_QUEUE, Status.ACCEPTED]

0 comments on commit 160fcbb

Please sign in to comment.