Current section
Files
Jump to
Current section
Files
src/cmd.gleam
import gleam/iterator
import gleam/result
import parse.{Day}
import snag.{Result, Snag}
import gleam/otp/task.{Task}
import gleam/erlang
import gleam/erlang/atom
import gleam/dynamic
import gleam/list
import gleam/result
import gleam/int
import gleam/function
import gleam
pub const input_dir = "input/"
pub const days_dir = "src/days/"
pub type Timing {
Endless
Ending(Timeout)
}
pub type Timeout =
Int
pub fn exec(
days: List(Day),
timing: Timing,
do: fn(Day) -> Result(a),
collect: fn(#(Result(a), Day)) -> String,
) -> List(String) {
days
|> task_map(do)
|> try_await_many(timing)
|> iterator.from_list()
|> iterator.map(result.flatten)
|> iterator.zip(iterator.from_list(days))
|> iterator.map(collect)
|> iterator.to_list()
}
fn now_ms() {
erlang.system_time(erlang.Millisecond)
}
fn task_map(over l: List(a), with f: fn(a) -> b) -> List(Task(b)) {
list.map(l, fn(x) { task.async(fn() { f(x) }) })
}
fn try_await_many(tasks: List(Task(a)), timing: Timing) -> List(Result(a)) {
let await = case timing {
// currently no await_forever so we'll use 10 mins
Endless -> fn(t) {
t
|> task.try_await(600_000)
|> result.map_error(snag_task_error)
}
Ending(timeout) -> {
let end = now_ms() + timeout
fn(t) {
end - now_ms()
|> int.clamp(min: 0, max: timeout)
|> task.try_await(t, _)
|> result.map_error(snag_task_error)
}
}
}
list.map(tasks, await)
}
fn snag_task_error(err: task.AwaitError) -> Snag {
case err {
task.Timeout -> "task timed out"
task.Exit(_) -> "task exited for some reason"
}
|> snag.new()
}