components_testing_TaskRelaunchProbeHost.bs

import "pkg:/source/utils/misc.bs"
import "pkg:/source/utils/tasks.bs"

sub init()
  m.top.task = CreateObject("roSGNode", "TaskRelaunchProbeTask")
end sub

sub launch()
  launchTask(m.top.task)
end sub

sub stopTask()
  m.top.task.control = "STOP"
end sub

' The app's sequence: STOP, then launchTask, with nothing in between.
sub stopAndRelaunch()
  task = m.top.task
  task.control = "STOP"
  ' bsc-disable-next-line no-same-node-relaunch this probe relaunches the same node on purpose, to measure the race
  launchTask(task)
end sub

' Stops the running task and launches a NEW node in its place, in one callback. `m.top.task`
' then holds the new node; the stopped one is returned so the spec can still read it.
function stopAndLaunchFresh() as object
  previous = m.top.task
  previous.control = "STOP"
  m.top.task = CreateObject("roSGNode", "TaskRelaunchProbeTask")
  launchTask(m.top.task)
  return previous
end function

' Configures the probe task before it is launched: how it blocks, for how long, and the
' input value its function reads.
sub configure(args as object)
  m.top.task.setFields({ blockMode: args.blockMode, blockMs: args.blockMs, seq: args.seq })
end sub

' The app's full sequence, which is not just STOP-then-launch: every site writes its INPUT
' field between the two (`m.searchTask.query = query`, `m.loadDetailsTask.itemId = itemId`).
' That write is why an ignored relaunch can still look right — the old run, if it survives,
' reads the new value.
sub stopWriteRelaunch(newSeq as integer)
  task = m.top.task
  task.control = "STOP"
  task.seq = newSeq
  ' bsc-disable-next-line no-same-node-relaunch this probe relaunches the same node on purpose, to measure the race
  launchTask(task)
end sub

' Lets every invocation of the function return.
sub release()
  m.top.task.release = true
end sub