How to stop ActorSystem schedular which is scheduled with interval - akka

Public boolean checkStatus(){
if(case){
return true;
}
return false;
}
final ActorSystem system = ActorSystem.apply();
Cancellable result = system.scheduler.schedule(Duration.create(delay,TimeUnit.MILLISECONDS),Duration.create(interval, TimeUnit.MILLISECONDS)(checkStatus());
How i can stop scheduler when checkStatus case is true.

Instead of cancelling scheduled task you can use scheduleOnce method instead and then schedule it again if check is false or not if it's true. You will get the semantics you want that way.
Something along those lines:
public boolean checkStatus(){
if(case){
return true;
}
return false;
}
public rescheduleIfFalse(ActorSystem system) {
if(!checkStatus) {
system.scheduleOnce(Duration.create(interval, TimeUnit.MILLISECONDS))(rescheduleIfFalse);
}
}
final ActorSystem system = ActorSystem.apply();
rescheduleIfFalse(system)

Related

Verify that suspend function has not returned a value after simulating some time

I am trying to validate that a suspend function does not return anything at all in a certain test.
Consider the following situation:
val completionSignal = Channel<Unit>(capacity = 1, onBufferOverflow = BufferOverflow.DROP_LATEST)
suspend fun waitForCompletionSignal(): String {
completionSignal.receive()
return "Completion signal received"
}
I want to test this code with 2 unit tests, one that validates it returns the string when I provide the CompletionSignal with a value (thats the easy one).
And one that validates that it does not return anything when i don't give it anything. This is the hard one, since how long should I wait? And can i be sure the test fails if my code changes and suddenly the string is returned?
I got the following approach but I am missing some pieces:
#Test
fun `waitForCompletionSignal when completionSignal is provided assert result`() = runTest {
// Start waiting for result
val result = async { waitForCompletionSignal() }
// Provide completion signal
completionSignal.trySend(Unit)
// Await result and verify its correct
assertThat(result.await() == "Completion signal received")
}
#Test
fun `waitForCompletionSignal when completionSignal is not provided assert no result`() = runTest {
// Start waiting for result
val result = async { waitForCompletionSignal() }
// TODO?? some validation that succeeds if the test is just like this, but fails when i do the following:
completionSignal.trySend(Unit)
// A regular await would wait indefinately, and checking if the deferred result is completed does not work very well as well.
}
I hope the question is clear, thanks in advance.
I made an extension function on the deferred type to be able to wait for a max amount of time and after that it will return null. In my particular situation a delay time of 0 (so no delay whatsoever) is enough, but I can imagine that in some situations its useful to delay for a minimum amount of time.
#ExperimentalCoroutinesApi
suspend inline fun <reified T> Deferred<T>.awaitOrNull(
time: Long = 0,
crossinline actBlock: () -> Unit = { }
): T? = coroutineScope {
actBlock()
val timeoutJob = async<T?> {
delay(time)
null
}
return#coroutineScope select<T?> {
this#awaitOrNull.onAwait {
timeoutJob.cancel()
it
}
timeoutJob.onAwait {
this#awaitOrNull.cancel()
it
}
}
}
Using this method i can write the following tests that fail / succeed as expected:
// Succeeds
#Test
fun `waitForCompletionSignal when completionSignal is provided assert result`() = runTest {
val result = async {
waitForCompletionSignal()
}.awaitOrNull {
completionSignal.trySend(Unit)
}
assertThat(result == "Completion signal received")
}
// Succeeds
#Test
fun `waitForCompletionSignal when completionSignal is not provided assert no result`() = runTest {
val result = async {
waitForCompletionSignal()
}.awaitOrNull()
assertThat(result == null)
}
// Fails (to prove that it works)
#Test
fun `waitForCompletionSignal when completionSignal is not provided assert no result`() = runTest {
val result = async {
waitForCompletionSignal()
}.awaitOrNull {
completionSignal.trySend(Unit) // This (obviously) causes the test to fail, as I wanted.
}
assertThat(result == null)
}

Task continuation with IAsyncOperation in UWP

I have a c++ class object which performs some processing in the background of a uwp application.
Its process operation is called by Unity's "Update" method ~60fps through an UWP IAsyncOperation.
The class has a isBusy property which is set to true after calling the operation, in order to block it being called from unity again before it finishes.
Using task continuation, I would like to set this to false after the processing is complete and returned through the IAsyncOperation.
IAsyncOperation<ResultsWrapper^>^ SomeClass::SomeClassUpdateMethod() {
return concurrency::create_async([this]() -> ResultsWrapper^
{
// Block processing
SomeClass::isBusy = true;
// Process image and return to await
LongRunningTask().then([this]() {
return SomeClass::TaskResults;
}).then([this]() {
isBusy = false;
});
});
}
concurrency::task<void> SomeClass::LongRunningTask(){
auto results = ref new TaskResults();
'''Work happens here'''
SomeClass::TaskResults = results;
}
What I expect to happen is for the ResultWrapper object to be returned to the main thread of the calling application (Unity), then the isBusy flag of the object set to false by the task continuation.
What happens is:
Error C2338 incorrect parameter type for the callable object in 'then'; consider _ExpectedParameterType or task<_ExpectedParameterType> (see below) \....\include\ppltasks.h
The reason this exception occurred is that you didn't return the ResultsWrapper^ type in the task chains.The second return you wrote means pass the value to the next chain to use instead of returning the value of the task.So you should write like the following code to return value correctly.
IAsyncOperation<ResultsWrapper^>^ SomeClass::SomeClassUpdateMethod()
{
return concurrency::create_async([this]() -> concurrency::task<ResultsWrapper^>
{
SomeClass::isBusy = true;
return LongRunningTask().then([this]() -> ResultsWrapper^
{
isBusy = false;
return SomeClass::TaskResults;
});
});
}
The code "return LongRunningTask().then(this ->ResultsWrapper^)" means convert the ResultsWrapper^ object to a task and return the task.
The return value of "LongRunningTask" method is task<void>,so you still need to return a task<void> value.
concurrency::task<void> SomeClass::LongRunningTask()
{
return concurrency::create_task(
[this]()
{
auto results = ref new TaskResults();
'''Work happens here'''
SomeClass::TaskResults = results;
});
}

OpenRAVE ControllerBase is blocking at the IsDone() method and never returns

I am working on a custom OpenRAVE ControllerBase C++ class that implements a robot controller.
I will try to keep the code as minimal as possible:
typedef actionlib::SimpleActionClient<control_msgs::FollowJointTrajectoryAction> TrajClient;
class ArmController : public ControllerBase {
.
.
.
virtual bool SetPath(TrajectoryBaseConstPtr ptraj) {
if (ptraj != NULL) {
TrajectoryBasePtr traj = SimplifyTrajectory(ptraj);
PlannerStatus status = planningutils::RetimeTrajectory(traj, false, 1.0, 1.0, "LinearTrajectoryRetimer");
if (status != PS_HasSolution) {
ROS_ERROR("Not executing trajectory because retimer failed.");
return false;
}
trajectory_msgs::JointTrajectory trajectory = FromOpenRaveToRosTrajectory(traj);
control_msgs::FollowJointTrajectoryGoal goal;
goal.trajectory = trajectory;
_ac->sendGoal(goal);
}
return true;
}
virtual bool IsDone() {
_ac->waitForResult(ros::Duration(5.0));
if (_ac->getState() == actionlib::SimpleClientGoalState::SUCCEEDED) {
return true;
}
}
}
This is a single controller for the robot arm, and I have implemented another one for the end-effector which is not currently in use (the end-effector is disconnected) in this case but it does some basic operations (like open, close gripper and listen to its joint state).
Then I have a Python script that tries to execute a trajectory on the robot:
robot.multicontroller = RaveCreateMultiController(env, "")
robot.SetController(robot.multicontroller)
robot_controller = RaveCreateController(env, 'arm_controller')
robot.multicontroller.AttachController(robot_controller, [2, 1, 0, 4, 5, 6], 0)
hand_controller = RaveCreateController(env, 'gripper_controller')
robot.multicontroller.AttachController(hand_controller, [3], 0)
trajectory_object = some_trajectory_object
robot.GetController().SetPath(trajectory_object)
robot.WaitForController(0)
The trajectory is being executed on the real robot with success but the code blocks at robot.WaitForController(0) and is actually in an endless loop in IsDone() method of the controller.
Any ideas?
I assume that your end-effector controller also implements a similar IsDone() method with a similar logic (i.e is waiting for the end-effector to reach its goal to return true, otherwise is returning false).
Since you are using a MultiController the WaitForController(0) in your Python script is not looking only to the arm controller but to all of the controllers attached to the MultiController.
From bool OpenRAVE::MultiController::IsDone() virtual
returns true only if all controllers return true.
Since you said that one of the controllers (the end-effector controller) is not in use, the IsDone of this controller returns false and hence the WaitForController(0) of the MultiController is blocked not on the arm controller you are suspecting, but instead is waiting for this not-in-use end-effector controller IsDone to evaluate to true, which will never do because you have it disconnected from the system; hence the blocking.
You have I think three options:
You either make sure that the end-effector is also connected to the system and hence the end-effector controller is working as expected (i.e the IsDone is returning True).
You are not attaching the end-effector controller to the multi-controller in your Python script (comment it out).
You change the logic of the IsDone method of the end-effector controller such that if is not connected, will return true.
Here is a quick solution:
def _is_rostopic_name_exists(self, topic_name):
if topic_name[0] != "/":
topic_name = "/" + topic_name
topics = rospy.get_published_topics()
for topic in topics:
if topic[0] == topic_name:
return True
return False
if _is_rostopic_name_exists("CModelRobotInput") and _is_rostopic_name_exists("CModelRobotOutput"):
hand_controller = RaveCreateController(env, 'robotiqcontroller')
robot.multicontroller.AttachController(hand_controller, [3], 0)
else:
RaveLogWarn("End-effector controller not attached, topics ('CModelRobotInput' or/and 'CModelRobotOutput') are not available.")
This way we are attaching the second controller to the multi-controller iff certain, required, ROS topics exist that are needed for the normal execution of that controller.

Increment counter inside RecordReader in Hadoop

I have created a custom RecordReader for a mapreduce job
class PatternRecordReader extends RecordReader<LongWritable, Text> {
#Override
public boolean nextKeyValue() {
try {
final String value = someParsingLogic();
final boolean hasValue = value != null;
if (hasValue) {
someLogic();
}else{
// I would like to increment a counter here
// something like context.getCounter(Counters.INVALID_INPUT).increment(1);
}
return hasValue;
}
I would like to increment a counter if no value is returned and be able to set it in the Task context, so that it would be accessible by the job.
Is there anyway to achieve this ?

Issue with a WS verifier method when migrating from Play 2.4 to Play 2.5

I have a method I need to refactor, as F.Promise has been deprecated in Play 2.5. It's pretty readable actually. It sends a request and authenticates via a custom security token and returns true if the response is 200.
public boolean verify(final String xSassToken){
WSRequest request = WS.url(mdVerifyXSassTokenURL)
.setHeader("X-SASS", xSassToken)
.setMethod("GET");
final F.Promise<WSResponse> responsePromise = request.execute();
try {
final WSResponse response = responsePromise.get(10000);
int status = response.getStatus();
if(status == 200 ) { //ok
return true;
}
} catch (Exception e) {
return false;
}
return false;
}
First thing I had to do was change this line:
final F.Promise<WSResponse> responsePromise = request.execute();
To this:
final CompletionStage<WSResponse> responsePromise = request.execute();
However, CompletionStage(T) doesn't have an equivalent get() method so I'm not sure the quickest and easiest way to get a WSResponse that I can verify the status of.
Yes, it does not. At least not directly.
What you are doing is "wrong" in the context of PlayFramework. get is a blocking call and you should avoid blocking as much as possible. That is why WS offers a non blocking API and a way to handle asynchronous results. So, first, you should probably rewrite your verify code to be async:
public CompletionStage<Boolean> verify(final String xSassToken) {
return WS.url(mdVerifyXSassTokenURL)
.setHeader("X-SASS", xSassToken)
.setMethod("GET")
.execute()
.thenApply(response -> response.getStatus() == Http.Status.OK);
}
Notice how I'm using thenApply to return a new a java.util.concurrent.CompletionStage instead of a plain boolean. That means that the code calling verify can also do the same. Per instance, an action at your controller can do something like this:
public class MyController extends Controller {
public CompletionStage<Result> action() {
return verify("whatever").thenApply(success -> {
if (success) return ok("successful request");
else return badRequest("xSassToken was not valid");
});
}
public CompletionStage<Boolean> verify(final String xSassToken) { ... }
}
This way your application will be able to handle a bigger workload without hanging.
Edit:
Since you have to maintain compatibility, this is what I would do to both evolve the design and also to keep code compatible while migrating:
/**
* #param xSassToken the token to be validated
* #return if the token is valid or not
*
* #deprecated Will be removed. Use {#link #verifyToken(String)} instead since it is non blocking.
*/
#Deprecated
public boolean verify(final String xSassToken) {
try {
return verifyToken(xSassToken).toCompletableFuture().get(10, TimeUnit.SECONDS);
} catch (Exception e) {
return false;
}
}
public CompletionStage<Boolean> verifyToken(final String xSassToken) {
return WS.url(mdVerifyXSassTokenURL)
.setHeader("X-SASS", xSassToken)
.setMethod("GET")
.execute()
.thenApply(response -> response.getStatus() == Http.Status.OK);
}
Basically, deprecate the old verify method and suggest users to migrate to new one.