These are normal programming needs which always trigger debates around use of threads, locking threads etc. Here we'll see how we address them in diesel.
Some basic looping can be achieved with expressions such as:
$val xx = [1,2,3]
$val yy = xx map x => a.b(x)
If you feel lazy to type a long list, use this builder:
$val xx = rangeList (from = 1, to = 55)
If you feel like making a huge list - make sure you have enough memory - this is not lazy!
This is one of the biggest problems in programming: how to wait without leaking resources.
You should never use sleep, in general. In diesel however, the sleep will not actually hold up threads, it will only delay your particular flow, it is implemented asynchronously - see more Concurrency, asynchronous and distributed.
Here's a simple way to wait with recursion:
$val poll = mylogic.poll (ip="1.2.3.4", count=5)
$mock mylogic.poll (ip, count > 0) {
(payload = "failed")
ctx.sleep (duration = 3600)
snakk.json (url="http://${ip}")
$if (payload contains "Running") {
(payload = "success")
}
$else {
mylogic.poll (ip, count = count - 1)
}
}
The logic here shows some features typical in rules programming:
if (count > 0) - it is handle in the rule trigger conditionThere are a couple of other ways to wait in diesel:
Before we look at waiting - what are you waiting for?
Naturally in diesel - whenever you call specific APIs, you'll trigger a flow - this is the typical way to wait for an external event, it's natural behavior: you don't need to wait or loop or something else like that just to wait for an event: Just let it happen and handle it.
If events need to be correlated with an internal state, like a state machine, then keep that state in the db - either memory or disk and implement custom logic to match it:
$when diesel.rest (path ~= "/myeventoccured")
=> ...
The most natural way to poll for something is to use a cron. Here we'll start a unique cron and then handle the two outcomes:
Here we're starting a cron to poll maximum 10 times at 5 minutes:
$when mylogic.startProcessAndPoll {
// start the process somehow
diesel.cron.set (
name="someuniquepollID",
env="sandbox",
schedule="5 minutes",
count = 10,
cronMsg = "$msg mylogic.pollOnce()",
doneMsg = "$msg mylogic.pollExpired()"
)
}
$when mylogic.pollOnce (name, env) {
snakk.json(url="http://this.is.keptalive.com/keepalive")
// some condition to poll for - this signifies we're done polling
$if (payload contains "Running") {
diesel.cron.cancel(name,env) // stop the poll
mylogic.continueWithRunning
}
}
$when mylogic.pollExpired (name, env) {
ctx.log (msg = "Oops - poll ended without success! We failed!")
}
Note that both mylogic.pollOnce and mylogic.pollExpired are ran not in the context of the original flow, but in their stand-alone flows. You can only correlate them with in-memory state. You can also send yourself some state in the cronMsg and doneMsg, i.e.: cronMsg = "$msg this.one.failed(ip=\"1.2.3.4\")"
However, because of this, while they are useful in general backend programming, they are less useful to return a state synchronously, for instance in the context of running a test. We can do that in two ways:
Streams are what we use for cooperating processes - this is what's required to check the status and poll on one "flow" while the original "flow" is waiting.
You need to log in to post a comment!