Skip to content

Instantly share code, notes, and snippets.

@ni-ko-o-kin
Last active December 23, 2019 22:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ni-ko-o-kin/1a991ae262c6fb8bf295f0561afd5e34 to your computer and use it in GitHub Desktop.
Save ni-ko-o-kin/1a991ae262c6fb8bf295f0561afd5e34 to your computer and use it in GitHub Desktop.
elm-node
port module Main exposing (main)
import Json.Decode as D exposing (Decoder, Value)
import Json.Encode as E
import Platform exposing (worker)
type Msg
= Run Value
main : Program () () Msg
main =
worker
{ init = always ( (), Cmd.none )
, update = update
, subscriptions = always (Sub.batch [ run Run ])
}
type alias RunId =
String
type Input
= F1Input RunId (List Int)
| F2Input RunId String
type Output
= F1Output RunId Int
| F2Output RunId String
f1Decoder : Decoder Input
f1Decoder =
D.map2 F1Input
(D.field "runId" D.string)
(D.field "input" (D.list D.int))
f2Decoder : Decoder Input
f2Decoder =
D.map2 F2Input
(D.field "runId" D.string)
(D.field "input" D.string)
functionSelector : String -> Decoder Input
functionSelector function =
case function of
"f1" ->
f1Decoder
"f2" ->
f2Decoder
_ ->
D.fail "function not supported"
decoder =
D.field "functionId" D.string
|> D.andThen functionSelector
f1Encoder : Int -> ( String, E.Value )
f1Encoder result =
( "result", E.int result )
f2Encoder : String -> ( String, E.Value )
f2Encoder result =
( "result", E.string result )
outputEncoder : Output -> E.Value
outputEncoder out =
let
go runId result encoder =
E.object
[ ( "status", E.string "ok" )
, ( "runId", E.string runId )
, encoder result
]
in
case out of
F1Output runId result ->
go runId result f1Encoder
F2Output runId result ->
go runId result f2Encoder
f1 : List Int -> Int
f1 =
List.length
f2 : String -> String
f2 =
String.reverse
inputToOutput : Input -> Output
inputToOutput input =
case input of
F1Input runId items ->
items
|> f1
|> F1Output runId
F2Input runId text ->
text
|> f2
|> F2Output runId
update : Msg -> () -> ( (), Cmd Msg )
update (Run value) _ =
case D.decodeValue decoder value of
Err _ ->
( (), output Nothing )
Ok input ->
( ()
, input
|> inputToOutput
|> outputEncoder
|> Just
|> output
)
port run : (Value -> msg) -> Sub msg
port output : Maybe E.Value -> Cmd msg
const { randomBytes } = require("crypto");
const { Elm } = require("./elm-main");
const App = Elm.Main.init({});
const exec = async (functionId, outputCallback, runCallback, input) => {
const runId = randomBytes(16).toString("hex");
const p = new Promise((resolve, reject) => {
let timeout;
const go = v => {
if (v && v.runId === runId) {
clearTimeout(timeout);
outputCallback.unsubscribe(go);
if (v.status === "ok") {
console.log(
[
`resolved runId: ${runId}`,
` with input: ${input}`,
` to output: ${v.result}`,
""
].join("\n")
);
resolve(v.result);
} else if (v.status === "error") {
console.log(
[
`rejected runId: ${runId}`,
` with input: ${input}`,
` to msg: ${v.msg}`,
""
].join("\n")
);
reject(v.msg);
} else {
reject("error: invalid response status");
}
}
};
outputCallback.subscribe(go);
timeout = setTimeout(() => {
outputCallback.unsubscribe(go);
reject("error: invalid input or time limit exceeded");
}, 30 * 1000);
});
setTimeout(() => {
runCallback.send({ runId, functionId, input });
}, Math.random() * 1000);
return p;
};
(async () => {
const f1s = new Array(10).fill(null).map((_, idx) => {
return exec("f1", App.ports.output, App.ports.run, new Array(idx).fill(1));
});
const f2s = new Array(14).fill(null).map((_, idx, ary) => {
return exec(
"f2",
App.ports.output,
App.ports.run,
"emosewa si mle".slice(idx)
);
});
try {
console.log(await Promise.all([...f1s, ...f2s]));
} catch (e) {
console.error(e);
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment