Stream: beginners

Topic: Any way to run detached Task|thread|process|command?


view this post on Zulip Pavel Mikuš (Oct 05 2024 at 09:37):

Hello, new enthusiastic rocer here :)
I have ported most of my task manager application into roc, its based on the webserver platform. I am fighting (hopefully :sweat_smile: ) one of the last issues, and that is having something to poke the local-host address every X minutes, to trigger notification logic.

I think currently there is not way to create a thread in Roc, right?
I hoped I can bypass this via Command, using something like "bash -c CMD &" or nohup, or some combination, but I have sunk several hours into it and nothing worked so far, usually I get error 127 and no such file or directory errs.

module [execute]

import pf.Command
import pf.Stdout
import KaskMonitor

execute =
    res = Command.output! (Command.new "nohup" |> Command.arg "$(bashScript)")
    Stdout.line! (Inspect.toStr res.status)
    Stdout.line! (Str.fromUtf8 res.stdout |> Result.withDefault "broken stdout")
    Stdout.line! (Str.fromUtf8 res.stderr |> Result.withDefault "broken stderr")
    Task.ok {}

bashScript =
    f = "/tmp/kodos"
    sleepDur = 1
    address = "localhost:8000/notify"
    "echo MonitorScript && sleep 3 && [[ -f $(f) ]] && exit; echo $$ > $(f); while true; do [ \"\$(curl -s -o /dev/null -w \"%{http_code}\" $(address))\" != \"200\" ] && rm -f $(f) && exit;sleep $(sleepDur);done"

Hmm, now I am thinking I can also just create a never returning get request and use DB to ensure I cannot spawn several of them.. I considered it initially, but I am afraid there could be some internal timeout in the web-server platform, or maybe introduced later?

view this post on Zulip Anton (Oct 05 2024 at 10:38):

I think currently there is not way to create a thread in Roc, right?

Not yet

"echo MonitorScript && sleep 3 && [[ -f $(f) ]] && exit; echo $$ > $(f); while true; do [ \"\$(curl -s -o /dev/null -w \"%{http_code}\" $(address))\" != \"200\" ] && rm -f $(f) && exit;sleep $(sleepDur);done"

We use rust's std::process::Command under the hood, and I don't think you can pass arguments to commands that use && or ; to rust's Command.
One solution that comes to mind is to clone basic-webserver locally and add another function like this one that uses rust's spawn. I would also put your series of commands in a single bash script.

A never ending request that calls Task.loop and Sleep.millis may also work.

I expect @Brendan Hansknecht will know the best solution.
Making things happen repeatedly or at a specific time, is quite common in webservers. So perhaps we should consider providing a nice way to do this in basic-webserver.

view this post on Zulip Pavel Mikuš (Oct 05 2024 at 11:52):

Ok, I see, thanks. I'll do it via the never ending request then, I am sure there will be future refactorings anyway :) I don't want to maintain local copy of the platform, and the bash script is ugly as duck :)


Last updated: Jul 06 2025 at 12:14 UTC