-
Notifications
You must be signed in to change notification settings - Fork 0
[wip] add: code submission endpoint #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
5d14f73
bcd7cef
6034998
5a07925
b7cdb3e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| (ns codes.clj.contest.submission-runner.adapters.submission | ||
| (:require [codes.clj.contest.submission-runner.wire.db.submission :as wire.db.submission] | ||
| [codes.clj.contest.submission-runner.wire.in.submission :as wire.in.submission])) | ||
|
|
||
| (defn wire->internal | ||
| {:malli/schema [:=> [:cat wire.in.submission/Submission] wire.db.submission/Submission]} | ||
| [{:keys [id code code-hash language test-cases]}] | ||
| {:submission/id id | ||
| :submission/code code | ||
| :submission/code_hash code-hash | ||
| :submission/language language | ||
| :submission/test_cases test-cases}) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| (ns codes.clj.contest.submission-runner.controllers.submission) | ||
|
|
||
| (defn submit-code-execution! | ||
| [_submission] | ||
| (random-uuid)) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| (ns codes.clj.contest.submission-runner.ports.http-in.submission | ||
| (:require [codes.clj.contest.submission-runner.adapters.submission :as adapters.submission] | ||
| [codes.clj.contest.submission-runner.controllers.submission :as controllers.submission])) | ||
|
|
||
| (defn submit-code-execution! | ||
| [{{submission :body} :parameters | ||
| _components :components}] | ||
| (let [id (-> submission | ||
| (adapters.submission/wire->internal) | ||
| (controllers.submission/submit-code-execution!))] | ||
| {:status 201 :body {:id id}})) | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,16 @@ | ||
| (ns codes.clj.contest.submission-runner.routes | ||
| (:require [codes.clj.contest.submission-runner.ports.http-in :as ports.http-in] | ||
| [codes.clj.contest.submission-runner.ports.http-in.submission :as ports.http-in.submission] | ||
| [codes.clj.contest.submission-runner.schemas.wire-in :as schemas.wire-in] | ||
| [codes.clj.contest.submission-runner.wire.in.submission :as wire.in.submission] | ||
| [codes.clj.contest.submission-runner.wire.out.submission :as wire.out.submission] | ||
| [reitit.swagger :as swagger])) | ||
|
|
||
| (def routes | ||
| [["/swagger.json" | ||
| {:get {:no-doc true | ||
| :swagger {:info {:title "btc-wallet" | ||
| :description "small sample using the microservice-boilerplate"}} | ||
| :swagger {:info {:title "Submission Runner" | ||
| :description "Submission Runner API"}} | ||
| :handler (swagger/create-swagger-handler)}}] | ||
|
|
||
| ["/wallet" | ||
|
|
@@ -32,4 +35,17 @@ | |
| :responses {201 {:body schemas.wire-in/WalletEntry} | ||
| 400 {:body :string} | ||
| 500 {:body :string}} | ||
| :handler ports.http-in/do-withdrawal!}}]]]) | ||
| :handler ports.http-in/do-withdrawal!}}]] | ||
|
|
||
| ;; submitions routes | ||
| ["/code" | ||
| {:swagger {:tags ["Code Runner"]}} | ||
| ["/submission" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think even we going to receive this by another backend we need to ensure a bearer token is passed, since this will be accessed by only one service, this could be stored in the configuration files |
||
| {:post {:summary "Submit to execution your code" | ||
| :parameters {:body wire.in.submission/Submission} | ||
| :responses {201 {:body wire.out.submission/SubmissionResult} | ||
| 400 {:body :string} | ||
| 500 {:body :string}} | ||
| :handler ports.http-in.submission/submit-code-execution!}}]]]) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| (ns codes.clj.contest.submission-runner.wire.db.submission) | ||
|
|
||
| (def Submission | ||
| [:map | ||
| [:submission/id string?] | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. UUID? |
||
| [:submission/code string?] | ||
| [:submission/code_hash string?] | ||
| [:submission/language [:enum :clojure]] | ||
| [:submission/test_cases | ||
| [:map-of :keyword | ||
| [:map | ||
| [:input :any] | ||
| [:output :any]]]]]) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| (ns codes.clj.contest.submission-runner.wire.in.submission) | ||
|
|
||
| (def Submission | ||
| [:map | ||
| [:id string?] | ||
| [:code string?] | ||
| [:code-hash string?] | ||
| [:language [:enum :clojure]] | ||
| [:test-cases [:map-of :keyword | ||
| [:map | ||
| [:input :any] | ||
| [:output :any]]]]]) | ||
|
|
||
| (comment | ||
| (require '[malli.generator :as m]) | ||
| (require '[malli.core :as m.core]) | ||
| (m/generate Submission) | ||
| (m.core/validate | ||
| Submission | ||
| {:code "(ns runner | ||
| (:require [clojure.test :refer [use-fixtures]]) | ||
| (defn my-sum [a b] (+ a b)))" | ||
| :language :clojure | ||
| :test-cases {:case-1 {:input "(my-sum 1 2)" | ||
| :output 3} | ||
| :case-2 {:input "(my-sum 2 3)" | ||
| :output 5}}}) | ||
|
Comment on lines
+20
to
+27
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @rafaeldelboni what do you think of this input?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this way I will have to merge it, so I think is better to receive it already merged,
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Who is going to send this payload the frontend?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The idea is use this code + test cases to build the code that will run in the pod right?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Hm, 🤔 idk why I was thinking of having two backends.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yep, the idea was to merge it in some way and send to the pod
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. :language could be an enum WDYT?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice 👍🏽 |
||
|
|
||
| ; | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| (ns codes.clj.contest.submission-runner.wire.out.submission) | ||
|
|
||
| (def SubmissionResult | ||
| [:map | ||
| [:id uuid?]]) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| (ns integration.codes.clj.contest.submission-runner.submission-runner-test | ||
| (:require [clj-commons.digest :as digest] | ||
| [clojure.test :refer [use-fixtures]] | ||
| [integration.codes.clj.contest.submission-runner.util :as util] | ||
| [matcher-combinators.matchers :as matchers] | ||
| [parenthesin.helpers.malli :as helpers.malli] | ||
| [parenthesin.helpers.state-flow.server.pedestal :as state-flow.server] | ||
| [state-flow.api :refer [defflow]] | ||
| [state-flow.assertions.matcher-combinators :refer [match?]] | ||
| [state-flow.core :as state-flow :refer [flow]])) | ||
|
|
||
| (use-fixtures :once helpers.malli/with-intrumentation) | ||
|
|
||
| (defflow | ||
| flow-integration-wallet-test | ||
| {:init util/start-system! | ||
| :cleanup util/stop-system! | ||
| :fail-fast? true} | ||
|
|
||
| (flow "should receive an submission" | ||
| [:let [id (random-uuid) | ||
| code "(ns runner | ||
| (:require [clojure.string :as str])) | ||
| (defn my-sum [a b] (+ a b))" | ||
| submission-input {:id id | ||
| :code code | ||
| :code-hash (digest/md5 code) | ||
| :language :clojure | ||
| :test-cases {:case-1 {:input "(my-sum 1 2)" | ||
| :output 3} | ||
| :case-2 {:input "(my-sum 2 3)" | ||
| :output 5}}}] | ||
| return (state-flow.server/request! {:method :post | ||
| :uri "/code/submission" | ||
| :body submission-input})] | ||
|
|
||
| (match? (matchers/embeds {:status 201 | ||
| :body {:id string?}}) | ||
| return))) | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,18 +1,38 @@ | ||
| (ns integration.codes.clj.contest.submission-runner.util | ||
| (:require [com.stuartsierra.component :as component] | ||
| (:require [codes.clj.contest.submission-runner.routes :as routes] | ||
| [com.stuartsierra.component :as component] | ||
| [parenthesin.components.config.aero :as components.config] | ||
| [parenthesin.components.db.jdbc-hikari :as components.database] | ||
| [parenthesin.components.http.clj-http :as components.http] | ||
| [parenthesin.components.router.reitit-malli :as components.router] | ||
| [parenthesin.components.server.reitit-pedestal-jetty :as components.webserver] | ||
| [parenthesin.helpers.logs :as logs] | ||
| [parenthesin.helpers.migrations :as migrations] | ||
| [pg-embedded-clj.core :as pg-emb])) | ||
|
|
||
| (defn- create-and-start-components! [] | ||
| (component/start-system | ||
| (component/system-map | ||
| :config (components.config/new-config) | ||
| :http (components.http/new-http-mock {}) | ||
| :router (components.router/new-router routes/routes) | ||
| :database (component/using (components.database/new-database) | ||
| [:config]) | ||
| :webserver (component/using (components.webserver/new-webserver) | ||
| [:config :http :router :database])))) | ||
|
|
||
| (defn start-system! | ||
| [system-start-fn] | ||
| (fn [] | ||
| (logs/setup :info :auto) | ||
| (pg-emb/init-pg) | ||
| (migrations/migrate (migrations/configuration-with-db)) | ||
| (system-start-fn))) | ||
| ([] | ||
| ((start-system! create-and-start-components!))) | ||
| ([system-start-fn] | ||
| (fn [] | ||
| (logs/setup :info :auto) | ||
| (pg-emb/init-pg) | ||
| (migrations/migrate (migrations/configuration-with-db)) | ||
| (system-start-fn)))) | ||
|
|
||
| (defn stop-system! | ||
| [system] | ||
| (component/stop-system system) | ||
| (pg-emb/halt-pg!)) | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| (ns unit.codes.clj.contest.submission-runner.adapters.submission-test | ||
| (:require [clj-commons.digest :as digest] | ||
| [clojure.test :refer [deftest is testing use-fixtures]] | ||
| [clojure.test.check.clojure-test :refer [defspec]] | ||
| [clojure.test.check.properties :as properties] | ||
| [codes.clj.contest.submission-runner.adapters.submission :as adapters.submission] | ||
| [codes.clj.contest.submission-runner.wire.db.submission :as wire.db.submission] | ||
| [codes.clj.contest.submission-runner.wire.in.submission :as wire.in.submission] | ||
| [malli.core :as m] | ||
| [malli.generator :as mg] | ||
| [matcher-combinators.test :refer [match?]] | ||
| [parenthesin.helpers.malli :as helpers.malli])) | ||
|
|
||
| (use-fixtures :once helpers.malli/with-intrumentation) | ||
|
|
||
| (defspec wirer->internal-spec 50 | ||
| (properties/for-all [code (mg/generator wire.in.submission/Submission)] | ||
| (m/validate wire.db.submission/Submission (adapters.submission/wire->internal code)))) | ||
|
|
||
| (def id (random-uuid)) | ||
| (def code "(ns runner | ||
| (:require [clojure.string :as str])) | ||
| (defn my-sum [a b] (+ a b))") | ||
|
|
||
| (def code-submission {:id (str id) | ||
| :code code | ||
| :code-hash (digest/md5 code) | ||
| :language :clojure | ||
| :test-cases {:case-1 {:input "(my-sum 1 2)" | ||
| :output 3} | ||
| :case-2 {:input "(my-sum 2 3)" | ||
| :output 5}}}) | ||
|
|
||
| (deftest wire->internal | ||
| (testing "adpater to db submission" | ||
| (is (match? {:submission/id (str id) | ||
| :submission/code code | ||
| :submission/code_hash (digest/md5 code) | ||
| :submission/language :clojure | ||
| :submission/test_cases {:case-1 {:input "(my-sum 1 2)" | ||
| :output 3} | ||
| :case-2 {:input "(my-sum 2 3)" | ||
| :output 5}}} | ||
| (adapters.submission/wire->internal code-submission))))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you are generating this just to insert into the database, you can delegate the UUID generation to postgres.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still not 100% clear what we are going to save on postgres
id, code, code-hash, language and test-cases as string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good question, I think I would store information to be possible to trace back the author, contest and the submission.
I would have an table to the contests (where the base challenge, and test inputs (and demo test inputs) would be stored, another for the authors, another for the submission where you would have the challenge id, author id, and the submission itself, to not store to much data in the database I would keep only the latest submission for each challenge and author, so if I submit and answer for a challenge we update the submission table by author-id and challenge-id with the new code, code-hash and updated date
After I would have a table with the execution results where you could store submission-id, code-hash and the result.
We can whiteboard this later if you want so.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would love to whiteboard this