Looping, polling and waiting Pub Share

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.

Looping

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!

Waiting

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:

  • no check for if (count > 0) - it is handle in the rule trigger condition
  • assign failure upfront - it's only set to "success" if met.
  • when count is too low, the last message won't trigger any rules, so the payload stays "failed"

There are a couple of other ways to wait in diesel:

  • REST API
  • cron
  • streams

Before we look at waiting - what are you waiting for?

  • an external event
  • a "poll" that you started - i.e. you're checking for the status of something
  • an async flow that you started

Waiting with a REST API

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")
=> ...

Polling with a cron

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:

  • how to check for the poll
  • what to do for a successful poll
  • what to do if it never was ok

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:

  • correlated sub-flows
  • streams

Polling with streams

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.


Was this useful?    

By: Razie | 2024-10-27 | Tags: academy , reference , engine


Viewed 47 times ( | History | Print ) this page.

You need to log in to post a comment!

© Copyright DieselApps, 2012-2024, all rights reserved.