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!