First of all the promise is not resolved when i try to execute runCode
documentation is not done correctly you have no information about how to use it and if information is provided how to use it they it is half only not the full info. how to use it..
code-executor currently supports most of the languages in src/langs. More languages need to be added so that code-executor can fulfill all requirements for popular use-cases such as Competitive Coding websites.
Structure
To add languages, you can add a Dockerfile and a start.sh script like in Python.
Note: Make sure to test the Dockerfile and the start.sh script with some sample code before making a PR to the dev branch.
So technically, we do not need the internal map logic in code-executor which maintains maps from job IDs to promises, as bulljs already does this internally.
The current published version of code-executor doesn't throw error when trying to connect to an invalid Redis URL. Instead it connects to localhost:6379. Need to fix this.
It should be more tolerant to outputs where there can be an extra space, a carriage return etc.
Alternatively, best way to do this is by serializing the return value and then compare these serialized objects instead of strings. This has a lot of benefits:
Data structures can be returned as a result of procedure calls, instead of providing a specific output format for each problem.
Sometimes people interpret non printable characters in a wrong way (different from intended). This solves that problem so that users never get a penalty just because they counted one space less or more.
The scripts used to spawn workers consist of a lot of repetitive code, it would be really useful to have a CLI instead.
The CLI could have options like:
This spawns 10 workers on the server with the redis instance for managing the queue located at redis://127.0.0.1:6379.
This is just an example of the bare minimum requirement. Feel free to suggest features that could be included in the CLI ๐ฏ
Proposed structure
I'd propose you have a file bin/code-executor.js which just imports the CLI from dist/src/cli.js and runs it. dist/src/cli.js is the build output from src/cli.ts, which has the CLI in typescript.
Currently, code-executor supports all languages mentioned in src/langs. There are no script yet to test if these languages work properly. You can add tests in test for each language.
Proposed structure
Each language has a folder inside test, the name of the folder is the name of the language
There are two scripts in each folder, one for master and one for the worker.
You might consider using a testing library such as mocha or chai. However, for this, timeouts need to be configured properly since these tests will be running on Github Actions in the future. Nonetheless, adding a unit testing library for each language is not a priority right now, verifying that the Dockerfiles for all the languages work can be done with or without mocha or chai.
Since the input is stored as a file inside the docker image, there is a possibility that someone could leak the test cases. For example, they could do the following in Python:
This can be fixed by modifying the permissions inside the Docker containers. An alternative could be to take input through stdin. This is a critical bug and needs to be fixed.
However, a user might still be able to spawn a reverse shell inside the container or run a fork bomb. A feasible way to prevent this would be to block all outgoing network traffic and using something like nsjail inside the containers. This too is a security risk of critical severity.
Currently, the runner is very straightforward, it executes every test case sequentially, there are different strategies it can support:
Maybe the runner can execute multiple test cases in parallel, and you can possibly configure how many in parallel at a time. This is linked to the issue about leaking test cases from other tests you are not executing against, I mentioned a possible approach to handle this there (#15 (comment))
The runner has the option of executing a certain group of test cases first, and only executing the others if the first group passes. This is a very common use case, as judging platforms want to often not run against private test cases if the sample test cases didn't pass in the first place. There are many solutions for this, maybe each test case can have a "depend_on" attribute which tells it depends on other test case to succeed, and only runs if that test case passed successfully.
code-executor needs atleast one instance of worker class running to run the jobs. If a user tries to run a job without starting any worker instance, the promise returned by the code-executor will never resolve or reject. Need to find a way to check if any worker instances are running, if not, throw an error.