Skip to content

Commit 160fcbb

Browse files
committed
Initial commit of different retry mechanisms.
1 parent 428ac30 commit 160fcbb

10 files changed

+119
-19
lines changed

examples/atd_submission.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import os
2-
import time
32

43
import judge0
54

@@ -19,8 +18,7 @@ def run_example(client_class, language_id):
1918
)
2019

2120
client.create_submission(submission)
22-
time.sleep(1)
23-
client.get_submission(submission)
21+
client.wait(submission)
2422

2523
print(f"{submission.status=}")
2624
print(f"{submission.stdout=}")

examples/atd_submissions.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import os
2-
import time
32

43
import judge0
54

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

2625
submissions = [submission1, submission2]
2726
client.create_submissions(submissions)
28-
time.sleep(1)
29-
client.get_submissions(submissions)
27+
client.wait(submissions)
3028

3129
for submission in submissions:
3230
print(f"{submission.status=}")

examples/rapid_submission.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import os
2-
import time
32

43
import judge0
54

@@ -19,8 +18,7 @@ def run_example(client_class, language_id):
1918
)
2019

2120
client.create_submission(submission)
22-
time.sleep(1)
23-
client.get_submission(submission)
21+
client.wait(submission)
2422

2523
print(f"{submission.status=}")
2624
print(f"{submission.stdout=}")

examples/rapid_submissions.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import os
2-
import time
32

43
import judge0
54

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

2625
submissions = [submission1, submission2]
2726
client.create_submissions(submissions)
28-
time.sleep(1)
29-
client.get_submissions(submissions)
27+
client.wait(submissions)
3028

3129
for submission in submissions:
3230
print(f"{submission.status=}")

examples/sulu_submission.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import os
2-
import time
32

43
import judge0
54

@@ -19,8 +18,7 @@ def run_example(client_class, language_id):
1918
)
2019

2120
client.create_submission(submission)
22-
time.sleep(1)
23-
client.get_submission(submission)
21+
client.wait(submission)
2422

2523
print(f"{submission.status=}")
2624
print(f"{submission.stdout=}")

examples/sulu_submissions.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import os
2-
import time
32

43
import judge0
54

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

2625
submissions = [submission1, submission2]
2726
client.create_submissions(submissions)
28-
time.sleep(1)
29-
client.get_submissions(submissions)
27+
client.wait(submissions)
3028

3129
for submission in submissions:
3230
print(f"{submission.status=}")

src/judge0/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
SuluJudge0CE,
88
SuluJudge0ExtraCE,
99
)
10+
from .retry import MaxRetries, MaxWaitTime, RegularPeriodRetry
1011

1112
from .submission import Submission
1213

@@ -19,4 +20,7 @@
1920
SuluJudge0CE,
2021
SuluJudge0ExtraCE,
2122
Submission,
23+
RegularPeriodRetry,
24+
MaxRetries,
25+
MaxWaitTime,
2226
]

src/judge0/clients.py

+33-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
from typing import Iterable, Union
1+
from typing import Iterable, Optional, Union
22

33
import requests
44

5+
from .retry import RegularPeriodRetry, RetryMechanism
6+
57
from .submission import Submission
68

79

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

165+
def wait(
166+
self,
167+
submissions: Union[Submission, list[Submission]],
168+
*,
169+
retry_mechanism: Optional[RetryMechanism] = None,
170+
):
171+
if retry_mechanism is None:
172+
retry_mechanism = RegularPeriodRetry()
173+
174+
if not isinstance(submissions, (list, tuple)):
175+
submissions = [submissions]
176+
177+
submissions_to_check = {
178+
submission.token: submission for submission in submissions
179+
}
180+
181+
while len(submissions_to_check) > 0 and not retry_mechanism.is_done():
182+
self.get_submissions(submissions_to_check.values())
183+
for token in list(submissions_to_check):
184+
submission = submissions_to_check[token]
185+
if submission.is_done():
186+
submissions_to_check.pop(token)
187+
188+
# Don't wait if there is no submissions to check for anymore.
189+
if len(submissions_to_check) == 0:
190+
break
191+
192+
retry_mechanism.wait()
193+
retry_mechanism.step()
194+
163195

164196
class ATD(Client):
165197
def __init__(self, endpoint, host_header_value, api_key):

src/judge0/retry.py

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import time
2+
from abc import ABC, abstractmethod
3+
4+
5+
class RetryMechanism(ABC):
6+
@abstractmethod
7+
def is_done(self) -> bool:
8+
pass
9+
10+
@abstractmethod
11+
def wait(self) -> None:
12+
pass
13+
14+
@abstractmethod
15+
def step(self) -> None:
16+
pass
17+
18+
19+
class MaxRetries(RetryMechanism):
20+
"""Check for submissions status every 100 ms and retry a maximum of
21+
`max_retries` times."""
22+
23+
def __init__(self, max_retries: int = 20):
24+
self.n_retries = 0
25+
self.max_retries = max_retries
26+
27+
def step(self):
28+
self.n_retries += 1
29+
30+
def wait(self):
31+
time.sleep(0.1)
32+
33+
def is_done(self) -> bool:
34+
return self.n_retries >= self.max_retries
35+
36+
37+
class MaxWaitTime(RetryMechanism):
38+
"""Check for submissions status every 100 ms and wait for all submissions
39+
a maximum of `max_wait_time` (seconds)."""
40+
41+
def __init__(self, max_wait_time_sec: float = 5 * 60):
42+
self.max_wait_time_sec = max_wait_time_sec
43+
self.total_wait_time = 0
44+
45+
def step(self):
46+
self.total_wait_time += 0.1
47+
48+
def wait(self):
49+
time.sleep(0.1)
50+
51+
def is_done(self):
52+
return self.total_wait_time >= self.max_wait_time_sec
53+
54+
55+
class RegularPeriodRetry(RetryMechanism):
56+
"""Check for submissions status periodically for indefinite amount of time."""
57+
58+
def __init__(self, wait_time_sec: float = 0.1):
59+
self.wait_time_sec = wait_time_sec
60+
61+
def step(self):
62+
pass
63+
64+
def wait(self):
65+
time.sleep(self.wait_time_sec)
66+
67+
def is_done(self) -> bool:
68+
return False

src/judge0/submission.py

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from base64 import b64decode, b64encode
22

3+
from .common import Status
4+
35

46
ENCODED_REQUEST_FIELDS = {
57
"source_code",
@@ -146,3 +148,9 @@ def to_dict(self) -> dict:
146148
body[field] = value
147149

148150
return body
151+
152+
def is_done(self) -> bool:
153+
if self.status is None:
154+
return False
155+
else:
156+
return self.status not in [Status.IN_QUEUE, Status.ACCEPTED]

0 commit comments

Comments
 (0)