Skip to content

Commit

Permalink
Merge pull request #1188 from codalab/develop
Browse files Browse the repository at this point in the history
Merge develop into master
  • Loading branch information
Didayolo authored Nov 2, 2023
2 parents a5e1976 + e379b6f commit 9ba29d8
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 39 deletions.
1 change: 1 addition & 0 deletions .env_circleci
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ RABBITMQ_DEFAULT_USER=rabbit-username
RABBITMQ_DEFAULT_PASS=rabbit-password-you-should-change
RABBITMQ_PORT=5672
RABBITMQ_HOST=rabbit
WORKER_CONNECTION_TIMEOUT=100000000 # milliseconds

FLOWER_BASIC_AUTH=root:password-you-should-change

Expand Down
1 change: 1 addition & 0 deletions .env_sample
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ RABBITMQ_DEFAULT_USER=rabbit-username
RABBITMQ_DEFAULT_PASS=rabbit-password-you-should-change
RABBITMQ_MANAGEMENT_PORT=15672
RABBITMQ_PORT=5672
WORKER_CONNECTION_TIMEOUT=100000000 # milliseconds

FLOWER_PUBLIC_PORT=5555

Expand Down
23 changes: 23 additions & 0 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# HOW YOU CAN CONTRIBUTE TO THE CODABENCH PROJECT

## First step: being a codabench user.

- create a user account on https://codalab.lisn.fr and on https://codabench.org.
- register on https://codabench.org to this existing competition (IRIS-tuto) https://www.codabench.org/competitions/1115/ and make a submission (from https://github.com/codalab/competition-examples/tree/master/codabench/iris): sample_result_submission and sample_code_submission. See https://github.com/codalab/codabench/wiki/User_Participating-in-a-Competition
- create your own private competition (from https://github.com/codalab/competition-examples/tree/master/codabench/ ). See https://github.com/codalab/codabench/wiki/Getting-started-with-Codabench

## Second step: setting a local instance of Codabench.

- Follow the tutorial in codabench wiki: https://github.com/codalab/codabench/wiki/Codabench-Installation. According to your hosting OS, you might have to tune your environment file a bit. Try without enabling the SSL protocol (doing so, you don't need a domain name for the server). Try using the embedded Minio storage solution instead of a private cloud storage.
- if needed, you can also look into https://github.com/codalab/codabench/wiki/How-to-deploy-Codabench-on-your-server

## Third step: using one's local instance

- create your own competition and play with it. You can look at the output logs of each different docker container.
- setting you as an admin of your platform (https://github.com/codalab/codabench/wiki/Administrator-procedures#give-superuser-privileges-to-an-user) and visit the Django Admin menu: https://github.com/codalab/codabench/wiki/Administrator-procedures#give-superuser-privileges-to-an-user

## Fourth step: setting an autonomous computer-worker on your PC

- configure and launch the docker container: https://github.com/codalab/codabench/wiki/Compute-Worker-Management---Setup
- create a private queue on your new own competition on the production server codabench.org: https://github.com/codalab/codabench/wiki/Queue-Management#create-queue
- assign your own compute-worker to this private queue instead of the default queue.
3 changes: 3 additions & 0 deletions Dockerfile.rabbitmq
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM rabbitmq:management
ARG WORKER_CONNECTION_TIMEOUT
RUN echo "consumer_timeout = $WORKER_CONNECTION_TIMEOUT" >> /etc/rabbitmq/conf.d/10-defaults.conf
46 changes: 27 additions & 19 deletions compute_worker/compute_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ def _update_submission(self, data):

logger.info(f"Updating submission @ {url} with data = {data}")

resp = self.requests_session.patch(url, data, timeout=15)
resp = self.requests_session.patch(url, data, timeout=150)
if resp.status_code == 200:
logger.info("Submission updated successfully!")
else:
Expand All @@ -360,23 +360,31 @@ def _update_status(self, status, extra_information=None):

def _get_container_image(self, image_name):
logger.info("Running pull for image: {}".format(image_name))
try:
cmd = [CONTAINER_ENGINE_EXECUTABLE, 'pull', image_name]
container_engine_pull = check_output(cmd)
logger.info("Pull complete for image: {0} with output of {1}".format(image_name, container_engine_pull))
except CalledProcessError:
error_message = f"Pull for image: {image_name} returned a non-zero exit code! Check if the docker image exists on docker hub."
logger.info(error_message)
# Prepare data to be sent to submissions api
docker_pull_fail_data = {
"type": "Docker_Image_Pull_Fail",
"error_message": error_message,
}
# Send data to be written to ingestion logs
self._update_submission(docker_pull_fail_data)
# Send error through web socket to the frontend
asyncio.run(self._send_data_through_socket(error_message))
raise DockerImagePullException(f"Pull for {image_name} failed!")
retries, max_retries = (0, 3)
while retries < max_retries:
try:
cmd = [CONTAINER_ENGINE_EXECUTABLE, 'pull', image_name]
container_engine_pull = check_output(cmd)
logger.info("Pull complete for image: {0} with output of {1}".format(image_name, container_engine_pull))
break # Break if the loop is successful
except CalledProcessError:
retries += 1
if retries >= max_retries:
error_message = f"Pull for image: {image_name} returned a non-zero exit code! Check if the docker image exists on docker hub."
logger.info(error_message)
# Prepare data to be sent to submissions api
docker_pull_fail_data = {
"type": "Docker_Image_Pull_Fail",
"error_message": error_message,
}
# Send data to be written to ingestion logs
self._update_submission(docker_pull_fail_data)
# Send error through web socket to the frontend
asyncio.run(self._send_data_through_socket(error_message))
raise DockerImagePullException(f"Pull for {image_name} failed!")
else:
logger.info("Failed. Retrying in 5 seconds...")
time.sleep(5) # Wait 5 seconds before retrying

async def _send_data_through_socket(self, error_message):
"""
Expand Down Expand Up @@ -682,7 +690,7 @@ def _put_dir(self, url, directory):
start_time = time.time()
zip_path = make_archive(os.path.join(self.root_dir, str(uuid.uuid4())), 'zip', directory)
duration = time.time() - start_time
logger.info("Time needed to zip archive: {duration} seconds.")
logger.info(f"Time needed to zip archive: {duration} seconds.")
if is_valid_zip(zip_path): # Check zip integrity
self._put_file(url, file=zip_path) # Send the file
break # Leave the loop in case of success
Expand Down
4 changes: 3 additions & 1 deletion compute_worker/compute_worker_requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
celery==4.4.0
requests==2.20.0
watchdog==0.8.3
watchdog==2.1.1
argh==0.26.2
websockets==8.1
aiofiles==0.4.0
pyyaml==5.3.1
6 changes: 5 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,11 @@ services:
# Rabbitmq & Flower monitoring tool
#-----------------------------------------------
rabbit:
image: rabbitmq:management
build:
context: .
dockerfile: Dockerfile.rabbitmq
args:
- WORKER_CONNECTION_TIMEOUT=${WORKER_CONNECTION_TIMEOUT}
# setting hostname here makes data persist properly between
# containers being destroyed..!
hostname: rabbit
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ urllib3<1.25,>=1.21.1
uvicorn[standard]==0.13.3
#daphne==2.2.2
pyyaml==5.3.1
watchdog==0.8.3
watchdog==2.1.1
argh==0.26.2
python-dateutil==2.7.3
bpython==0.17.1
websockets==8.1
Expand Down
7 changes: 6 additions & 1 deletion src/static/js/ours/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,12 @@ function getBase64(file) {
debug: $.tablesort.DEBUG,
asc: 'sorted ascending',
desc: 'sorted descending',
compare: function(a, b) {
compare: function(a, b, settings) {
// Convert the values to numbers for proper sorting
if (!isNaN(parseFloat(a)) && !isNaN(parseFloat(b))) {
var a = parseFloat(a);
var b = parseFloat(b);
}
if (a > b) {
return 1;
} else if (a < b) {
Expand Down
30 changes: 17 additions & 13 deletions src/static/riot/competitions/detail/_tabs.tag
Original file line number Diff line number Diff line change
Expand Up @@ -249,58 +249,62 @@
}
})
if(self.competition.participant_status === 'approved' && self.competition.make_programs_available){
self.competition.files.push(ingestion_program)
self.competition.files.push(scoring_program)
Object.keys(ingestion_program).length != 0 ? self.competition.files.push(ingestion_program) : null
Object.keys(scoring_program).length != 0 ? self.competition.files.push(scoring_program) : null
}if(self.competition.participant_status === 'approved' && self.competition.make_input_data_available){
self.competition.files.push(input_data)
Object.keys(input_data).length != 0 ? self.competition.files.push(input_data) : null
}
if(self.competition.admin && !self.competition.make_programs_available){
self.competition.files.push(ingestion_program)
self.competition.files.push(scoring_program)
Object.keys(ingestion_program).length != 0 ? self.competition.files.push(ingestion_program) : null
Object.keys(scoring_program).length != 0 ? self.competition.files.push(scoring_program) : null
}
if(self.competition.admin && !self.competition.make_input_data_available){
self.competition.files.push(input_data)
Object.keys(input_data).length != 0 ? self.competition.files.push(input_data) : null
}
if(self.competition.admin){
self.competition.files.push(reference_data)
Object.keys(reference_data).length != 0 ? self.competition.files.push(reference_data) : null
}

})
// Need code for public_data and starting_kit at phase level
if(self.competition.participant_status === 'approved'){
_.forEach(phase.tasks, task => {
_.forEach(task.solutions, solution => {
self.competition.files.push({
soln = {
key: solution.data,
name: solution.name,
file_size: solution.size,
phase: phase.name,
task: task.name,
type: 'Solution',
available: true
})
}
Object.keys(solution).length != 0 ? self.competition.files.push(soln) : null
})
})
if (phase.starting_kit != null){
self.competition.files.push({
s_kit = {
key: phase.starting_kit.key,
name: phase.starting_kit.name,
file_size: phase.starting_kit.file_size,
phase: phase.name,
task: '-',
type: 'Starting Kit',
available: true
})
}
Object.keys(phase.starting_kit).length != 0 ? self.competition.files.push(s_kit) : null
}
if (phase.public_data != null){
self.competition.files.push({
p_data = {
key: phase.public_data.key,
name: phase.public_data.name,
file_size: phase.public_data.file_size,
phase: phase.name,
task: '-',
type: 'Public Data',
available: true
})
}
Object.keys(phase.public_data).length != 0 ? self.competition.files.push(p_data) : null
}
}
})
Expand Down
6 changes: 3 additions & 3 deletions src/static/riot/competitions/editor/_phases.tag
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
<div class="fluid field required" ref="tasks_select_container" id="tasks_select_container">
<label for="tasks">
Tasks (Order will be saved) Note: Adding a new task will cause all submissions to be run against it.
<span data-tooltip="Use task manager to create new tasks" data-inverted=""
<span data-tooltip="Use Resources section to create new tasks" data-inverted=""
data-position="bottom center"><i class="help icon circle"></i></span>
</label>
<select name="tasks" id="tasks" class="ui search selection dropdown" ref="multiselect"
Expand All @@ -100,7 +100,7 @@
<div class="fluid field" ref="public_data_select_container" id="public_data_select_container">
<label for="public_data">
Public Data (Only 1 per phase)
<span data-tooltip="Use task manager to create new public data sets" data-inverted=""
<span data-tooltip="Use Resources section to create new public datasets" data-inverted=""
data-position="bottom center"><i class="help icon circle"></i></span>
</label>
<select name="public_data" id="public_data" class="ui search selection dropdown" ref="public_data_multiselect"
Expand All @@ -110,7 +110,7 @@
<div class="fluid field" ref="starting_kit_select_container" id="starting_kit_select_container">
<label for="starting_kit">
Starting Kit (Only 1 per phase)
<span data-tooltip="Use task manager to create new starting kits" data-inverted=""
<span data-tooltip="Use Resources section to create new starting kits" data-inverted=""
data-position="bottom center"><i class="help icon circle"></i></span>
</label>
<select name="starting_kit" id="starting_kit" class="ui search selection dropdown" ref="starting_kit_multiselect"
Expand Down

0 comments on commit 9ba29d8

Please sign in to comment.