react on a supply from a sequence - sequence

I can't understand why this program works:
my $supply = Supply.interval: 1;
react {
whenever $supply { put "Got $^a" }
whenever Promise.in(5) { put 'Timeout!'; done }
}
END put 'Ending…'
printing this:
Got 0
Got 1
Got 2
Got 3
Got 4
Timeout!
Ending…
and exits correctly, while this one:
my $supply = (1, 1, * + * … ∞).Supply;
react {
whenever $supply { put "Got $^a"; sleep 1 }
whenever Promise.in(5) { put 'Timeout!'; done }
}
END put 'Ending…'
prints
Got 1
Got 1
Got 2
Got 3
Got 5
Timeout!
but then it hangs and doesn't output the "Ending…"; isn't the "done" enough in this case?
If I replace "done" with "exit" the program works fine and exits.

Related

WorkManger doesn't trigger after manually stopped- Kotlin

I want to use workMager to do some work every 15min,at the same time I want to stop workManger when I clicked on the button "StopThread" below is my Code:
val workManager = WorkManager.getInstance(applicationContext)
val workRequest = PeriodicWorkRequest.Builder(
RandomNumberGeneratorWorker::class.java,
15,
TimeUnit.MINUTES
).addTag("API_Worker")
.build()
binding.buttonThreadStarter.setOnClickListener {
workManager.enqueue(workRequest)
}
binding.buttonStopthread.setOnClickListener {
workManager.cancelAllWorkByTag("API_Worker")
}
And this is the RandomNumberGeneratorWorker
class RandomNumberGeneratorWorker(
context: Context,
params: WorkerParameters
) :
Worker(context, params) {
private val MIN = 0
private val MAX = 100
private var mRandomNumber = 0
override fun doWork(): Result {
Log.d("worker_info","Job Started")
startRandomNumberGenerator();
return Result.success();
}
override fun onStopped() {
super.onStopped()
Log.i("worker_info", "Worker has been cancelled")
}
private fun startRandomNumberGenerator() {
Log.d("worker_info","startRandomNumberGenerator triggered")
var i = 0
while (i < 100 && !isStopped) {
try {
Thread.sleep(1000)
mRandomNumber = (Math.random() * (MAX - MIN + 1)).toInt() + MIN
Log.i(
"worker_info",
"Thread id: " + Thread.currentThread().id + ", Random Number: " + mRandomNumber
)
i++
} catch (e: InterruptedException) {
Log.i("worker_info", "Thread Interrupted")
}
}
}
}
The issue that I'm facing is when I stopped the workManger it didn't work again when I clicked on buttonThreadStarter
I did a little research and I found that I can start-stop-start..etc workManger with the code below :
val workRequest = OneTimeWorkRequest.from(RandomNumberGeneratorWorker::class.java)
binding.buttonThreadStarter.setOnClickListener {
workManager.beginUniqueWork("WorkerName",ExistingWorkPolicy.REPLACE,workRequest)
}
binding.buttonStopthread.setOnClickListener {
workManager.cancelAllWork()
}
but as you can see it's working when I used OneTimeWorkRequest and with that, I can't repeat the work every 15 mins , Any suggestion in how to resolve this issue
WorkManager is not designed for periodic works with exact timing. In reality, the works "are not even periodic".
As you can see here from the logs:
https://developer.android.com/topic/libraries/architecture/workmanager/how-to/debugging#use-alb-shell0dumpsys-jobscheduler
WorkManager delegates to the JobScheduler. JS jobs work in a way that you have a number of explicit(you set them) and implicit(set by the system) constraints and after all of them are satisfied - the job starts.
When you have a period there is an extra constraint - TIMING_DELAY. So if your 15min pass - this doesn't mean in no way that the job will be executed. There might be, and be sure that there will be other constraints. That is the case because WM is designed for resource optimization and it will ensure that the work will finish at some point, even on device restart. But it is not designed to be exact. It is quite the opposite.
And after all the constraints are satisfied - it might take a day, the job is no longer needed and a new job is created with again your 15min constraint - TIMING_DELAY. And the process starts again.
Also - when you say "doesn't trigger" - please, check why. Try to check the debug output from the JS and see if there is work at all. If there is - check what constraints are not satisfied.
But long story short - "every 15min" is not something for WorkManager. Normally you should use AlaramManager for exact timing, but with such a short interval you should try to consider using a Service.
Also, it is dangerous to call: cancelAllWork(). You might break the code of some library in your app. You should better use tags and cancel by tag.

Cypress | Cant change variable inside each loop

OK, So, I have this code:
Cypress.Commands.add ('MethodName', (argument) => {
var Fails = 0
cy.get('anything').each(Id => {
if (blablabla) {
Fails += 1
cy.log("Inside the each: " + Fails) //prints 1
}
})
cy.log("Outside the each: " + Fails) //prints 0
});
I want to test each item and if a condition is wrong, I want to add 1 to the variable "Fails".
Then, in the end, if Fails is 0, then there are no errors, and I want it to log the message "NO FAILS". The problem is , even if the variable changes to 1 inside the EACH, when its outside, it comes back to 0.
This is so frustrating to me, because Im used to write C# code and in C#, that would work, since the declaration of the variable is outside the each.
What do you guys suggest?
JavaScript runs asynchronously which means that your codes doesn't run in sequence. So what's happening in your case is Outside the each: is executing first and after that Inside the each: is being executed. To make sure that Outside each runs after inside each, you have to use then().
Cypress.Commands.add('MethodName', (argument) => {
var Fails = 0
cy.get('anything').each(Id => {
if (blablabla) {
Fails += 1
cy.log("Inside the each: " + Fails)
}
}).then(() => {
cy.log("Outside the each: " + Fails)
})
})

Error - Unexpected } at the end of While Loop

I'm using while true loop to constantly check run this script. After adding the if expression with whitelist ahk gives an error about unexpected } at the end of code. As far as I know there should be }.
Using Loop command gives the same error.
Removing the problematic } at the end causes the code running in background but not doing anything.
;Setup
Sleep, 1000
whiteList = "none"
;Main Loop
While True
{
siteName = YouTube
WinGetActiveTitle, tabName
Sleep, 10000
if tabName = %whiteList%{
Continue
}
;If current website is Youtube, ask if am I supposted to be here
if InStr(tabName, siteName){
Sleep, 10000
MsgBox, 292, Reality Check, Should you do this?
IfMsgBox, Yes
{
whiteList = tabName
}
;Close tab in mozilla
else
{
WinActivate, %tabName%
Sleep, 10
Send ^w
}
}
}
Code is unfinished, It should run in background and when the user is using YouTube fore some time it should ask him whether is he supposted to watch Youtube.
If he clicks yes, the program should ignore that specific page.
Else it should close it.
The % around the whiteList-var shouldn't be there. When I wrote it like below it seems to work:
if tabName = whiteList
Continue
Also the whiteList = tabName will just assign the string "tabName" to whiteList. Use whiteList := tabName for assigning, and if var1 = var2 for comparison.

How to implement "fallback condition" in while loop in Expect?

I have a machine I telnet into, and pass "ctrl+C" until I see the prompt. The ctrl+C may not always work, so I must try after every 5 seconds until I see my expected output ($prompt).
In case I don't get a $prompt, how do I ensure I can retry the while loop effectively? Is this code below the best practice? My concern is, that I don't know what I may get when the "ctrl+C" fails, it could be anything and it must be ignored unless it's $prompt.
while { $disableFlag == 0 } {
send "^C\r"
expect {
"*$prompt*" {
puts "Found the prompt"
sleep 5
}
"*" {
set disableFlag 1
puts "Retrying"
sleep 5
}
}
}
You probably want something like this (untested)
set timeout 5
send \03
expect {
"*$prompt*" {
puts "found the prompt"
}
timeout {
puts "did not see prompt within $timeout seconds. Retrying"
send \03
exp_continue
}
}
# do something after seeing the prompt
\03 is the octal value for ctrl-C: see http://wiki.tcl.tk/3038
If you want to bail out eventually:
set timeout 5
set count 0
send \03
expect {
"*$prompt*" {
puts "found the prompt"
}
timeout {
if {[incr count] == 10} { # die
error "did not see prompt after [expr {$timeout * $count}] seconds. Aborting"
}
puts "did not see prompt within $timeout seconds. Retrying"
send \03
exp_continue
}
}

Running multiple exec commands and waiting to finish before continuing

I know I ask a lot of questions and I know there is a lot on here about this exactly what I am trying to do but I have not been able to get it to work in my script nor figure out why it does not let me do this. I am trying to run several commands using exec in the background and the tests can range anywhere between 5 and 45 minutes (longer if they have to cue for a license). It takes forever to run them back to back so I was wondering what I need to do to make my script wait for them to finish before moving on the the next section of script.
while {$cnt <= $len} {
# Begin count for running tests
set testvar [lindex $f $cnt]
if {[file exists $path0/$testvar] == 1} {
cd $testvar
} else {
exec mkdir $testvar
cd $testvar
exec create_symobic_link_here
}
# Set up test environment
exec -ignorestderr make clean
exec -ignorestderr make depends
puts "Running $testvar"
set runtest [eval exec -ignorestderr bsub -I -q lin_i make $testvar SEED=1 VPDDUMP=on |tail -n 1 >> $path0/runtestfile &]
cd ../
incr cnt
}
I know there is nothing here to make the script wait for the process to finish but I have tried many different things any this is the only way I can get it to run everything. It just doesn't wait.
One way is to modify your tests to create a "finished" file. This file should be created whether the test completes correctly or fails.
Modify the startup loop to remove this file before starting the test:
catch { file delete $path0/$testvar/finished }
Then create a second loop:
while { true } {
after 60000
set cnt 1 ; # ?
set result 0
while { $cnt <= $len } {
set testvar [lindex $f $cnt]
if { [file exists $path0/$testvar/finished] } {
incr result
}
incr cnt
}
if { $result == $len } {
break
}
}
This loop as written will never exit if any one test doesn't create the 'finished' file. So I would add in an additional stop condition (no more than one hour) to exit the loop.
Another way would be to save the process ids of the background processes in a list and then the second loop would check each process id to see if it is still running. This method would not require any modifications to the test, but is a little harder to implement (not too hard on unix/mac, harder on windows).
Edit: loop using process id check:
To use process ids, the main loop needs to be modified to save the process ids of the background jobs:
Before the main loop starts, clear the process id list:
set pidlist {}
In the main loop, save the process ids from the exec command (In tcl, [exec ... &] returns the background process id):
lappend pidlist $runtest ; # goes after the exec bsub...
A procedure to check for the existence of a process (for unix/mac). Tcl/Tk does not have any process control commands, so the unix 'kill' command is used. 'kill -0' on unix only checks for process existence, and does not affect the execution of the process.
# return 0 if the process does not exist, 1 if it does
proc checkpid { ppid } {
set pexists [catch {exec kill -0 $ppid}]
return [expr {1-$pexists}]
}
And the second loop to check to see if the tests are done becomes:
set tottime 0
while { true } {
after 60000
incr tottime 1 ; # in minutes
set result 0
foreach {pid} $pidlist {
if { ! [checkpid $pid] } {
incr result
}
}
if { $result == $len } {
break
}
if { $tottime > 120 } {
puts "Total test time exceeded."
break ; # or exit
}
}
If a test process gets hung and never exits, this loop will never exit, so a second stop condition on total time is used.