Select on a go send and receive channel at the same time - select

Suppose I have a buffered send and unbuffered receive channel:
s := make(chan<- int, 5)
r := make(<-chan int)
Is it possible to select on them both, so that r will be selected if it has anything to read, and s will be selected if it is not full? Something equivalent to this, but not using 100% CPU:
for {
if len(s) < cap(s) {
// Send something
}
if len(r) > 0 {
// Receive something
}
}
Note that I want to decide what to send at the time that I send it, not earlier.
Edit
This question is basically equivalent to "Can I block until a channel is ready-to-send, without sending anything?"

You can do this with select but since the value to be sent is evaluated only once, if both channel are not ready, the value to be sent would become outdated by the time it can be sent.
So add a default case which will be executed if none of the channels are ready, in which you just "sleep" a little, then try again (with an updated new value calculated/acquired to be sent). By sleeping you will not consume CPU resources:
s := make(chan<- int, 5)
r := make(<-chan int)
for {
v := valueToSend() // Evaluated each time we try to send
select {
case s <- v:
fmt.Println("Sent value:", v)
case vr := <-r:
fmt.Println("Received:", vr)
default: // If none are ready currently, we end up here
time.Sleep(time.Millisecond * 1)
}
}
Note that checking the length or capacity of a channel and then sending/receiving is not considered a good solution because the channel might become not ready between the time you check its length/cap and you try to send/receive, as illustrated below:
if len(r) > 0 {
// r is ready to receive
// Optional other code here,
// meanwhile another goroutine might receive the value from r!
r <- // If other goroutine received from r, this will block!
}

It's a simple select:
select {
case s <- n:
// Successful send.
case n := <- r:
// Successful receive. Do something with n.
}

Instead of sending the value directly, you could send an object which can compute the value. Then you can detect when the object is sent, and then compute. You can use sync.Once to make sure the computation is done once, and gate access to the result. This avoids using Sleeps.
Something like this: https://play.golang.org/p/oL2HA2jl91

Can I block until a channel is ready-to-send, without sending anything?
Not with primitive go channels. You could probably manage to pull something together using the SharedBuffer type in my channels library, but even that is complicated and it uses a great deal of reflection under the covers.
https://godoc.org/github.com/eapache/channels#SharedBuffer

Related

Scala Akka Typed - send request inside behavior with ask

I'm kinda new to akka typed and I was trying to send a message which requires an answer within a given time.
I found the request-response pattern with ask which seemed interesting but is there a way to implement it inside of an already defined Behaviours.receive?
Here the idea is to call nextPlayerTurn each time a player answers or after a timeout
override def refereeTurn(): Behavior[Msg] = Behaviors.receive {
case (_, msg: GuessMsg) =>
if(currentPlayer.isDefined && currentPlayer.get == msg.getSender) {
controller ! msg
} else {
println("Player tried to guess after Timeout")
}
Behaviors.same
case (context, msg: ReceivedResponseMsg) =>
if(currentPlayer.isDefined && currentPlayer.get == msg.getSender)
nextPlayerTurn(context)
Behaviors.same
...
}
...
/**
* Tells to a player to start his turn and sets a timer that defines time in which a player has to make a guess.
* If such guess isn't made, sends that user an end turn message, fails the promise of his turn and allows next
* player to play his turn
*/
override def nextPlayerTurn(ctx: ActorContext[Msg]): Unit = {
implicit val timeout: Timeout = Timeout.timeout
currentPlayer = Option(turnManager.nextPlayer)
ctx.ask[Msg,Msg](currentPlayer.get, ref => YourTurnMsg(ref)) {
case Success(msg: GuessMsg) => println("\n SUCCESS"); msg
case Failure(_) => println(currentPlayer.get +" didn't guess in time"); TurnEnd(currentPlayer.get)
case _ => TurnEnd(currentPlayer.get)
}
}
In this case after the YourTurnMsg is sent the player is supposed to respond with a GuessMsg which stops the timer, this never happens due to the case matching inside refereeTurn Begaviour being executed instead of the Success (which instead always gives a Failure after the Timeout).
Did i get the wrong idea about the ask patter and should just make a new Behaviour with a timer?
If you want to use the ask pattern then the code that handles the result needs to send a message to the main actor rather than trying to do any processing directly. You can send a different message based on the result or just send the raw result and process it in the actor, but you must not do anything that depends on actor state in that code because it could be run on a different thread.
But ask is not cheap so in this case it seems better to just set a timer and see which message comes back first.

How to test `Var`s of `scala.rx` with scalatest?

I have a method which connects to a websocket and gets stream messages from some really outside system.
The simplified version is:
def watchOrders(): Var[Option[Order]] = {
val value = Var[Option[Order]](None)
// onMessage( order => value.update(Some(order))
value
}
When I test it (with scalatest), I want to make it connect to the real outside system, and only check the first 4 orders:
test("watchOrders") {
var result = List.empty[Order]
val stream = client.watchOrders()
stream.foreach {
case Some(order) =>
result = depth :: result
if (result.size == 4) { // 1.
assert(orders should ...) // 2.
stream.kill() // 3.
}
case _ =>
}
Thread.sleep(10000) // 4.
}
I have 4 questions:
Is it the right way to check the first 4 orders? there is no take(4) method found in scala.rx
If the assert fails, the test still passes, how to fix it?
Is it the right way to stop the stream?
If the thread doesn't sleep here, the test will pass the code in case Some(order) never runs. Is there a better way to wait?
One approach you might consider to get a List out of a Var is to use the .fold combinator.
The other issue you have is dealing with the asynchronous nature of the data - assuming you really want to talk to this outside real world system in your test code (ie, this is closer to the integration test side of things), you are going to want to look at scalatest's support for async tests and will probably do something like construct a future out of a promise that you can complete when you accumulate the 4 elements in your list.
See: http://www.scalatest.org/user_guide/async_testing

RxJS combineLatest: how to get emit after just one value changes?

I'm trying to learn the RxJS library. One of the cases I don't quite understand is described in this jsfiddle (code also below).
var A= new Rx.Subject();
var B= new Rx.Subject();
A.onNext(0);
// '.combineLatest' needs all the dependency Observables to get emitted, before its combined signal is emitted.
//
// How to have a combined signal emitted when any of the dependencies change (using earlier given values for the rest)?
//
A.combineLatest( B, function (a,b) { return a+b; } )
.subscribe( function (v) { console.log( "AB: "+ v ); } );
B.onNext("a");
A.onNext(1);
I'd like to get two emits to the "AB" logging. One from changing B to "a" (A already has the value 0). Another from changing A to 1.
However, only changes that occur after a subscribe seem to matter (even though A has a value and thus the combined result could be computed).
Should I use "hot observables" for this, or some other method than .combineLatest?
My problem in the actual code (bigger than this sample) is that I need to make separate initialisations after the subscribes, which cuts stuff in two separate places instead of having the initial values clearly up front.
Thanks
I think you have misunderstood how the Subjects work. Subjects are hot Observables. They do not hold on to values, so if they receive an onNext with no subscribers than that value will be lost to the world.
What you are looking for is a either the BehaviorSubject or the ReplaySubject both of which hold onto past values that re-emit them to new subscribers. In the former case you always construct it with an initial value
//All subscribers will receive 0
var subject = new Rx.BehaviorSubject(0);
//All subscribers will receive 1
//Including all future subscribers
subject.onNext(1);
in the latter you set the number of values to be replayed for each subscription
var subject = new Rx.ReplaySubject(1);
//All new subscribers will receive 0 until the subject receives its
//next onNext call
subject.onNext(0);
Rewriting your example it could be:
var A= new Rx.BehaviorSubject(0);
var B= new Rx.Subject();
// '.combineLatest' needs all the dependency Observables to get emitted, before its combined signal is emitted.
//
// How to have a combined signal emitted when any of the dependencies change (using earlier given values for the rest)?
//
A.combineLatest( B, function (a,b) { return a+b; } )
.subscribe( function (v) { console.log( "AB: "+ v ); } );
B.onNext("a");
A.onNext(1);
//AB: 0a
//AB: 1a
On another note, realizing of course that this is all new to you, in most cases you should not need to use a Subject directly as it generally means that you are trying to wrangle Rx into the safety of your known paradigms. You should ask yourself, where is your data coming from? How is it being created? If you ask those questions enough, following your chain of events back up to the source, 9 out of 10 times you will find that there is probably an Observable wrapper for it.

Some of the Actor messages are missing --AKKA FSM

Here is the sample code flow:
class FSMActor{
when(Idle) {
case Event(Start, Uninitialized) =>
case Event(InitMap(inMap), t # EvaluteRuleMap(v, c)) =>
logger.info(s"State = $stateName, Event = Event(_, InitMap(inMap))")
goto(EVALRule) using t.copy(ruleMap = inMap)
}
when(EVALRule) {
case Event(RowMap(m), t # EvaluteRuleMap(v, c)) =>
logger.debug("input row map m " + m)
**if ( <somecondition> ) { // If comment this if-else block, I could see rowMaps being received.
logger.debug(s"Moving to State Trigger x=$x")
goto(TriggerRule) using t.copy(ruleMap = x.get)
} else {
logger.debug(s"staying in EVALRule, x = $x")
stay
}**
}
when(TriggerRule) {
case Event(_, _) => ....
}
}
}
When the control in in "EVALRule" state, It will keep receiving streams maps(RowMap) and based on some computation, it moves to trigger rule.
Unfortunately for some weird reason, some of the incoming RowMaps are not being received at "case Event(RowMap(m), t # EvaluteRuleMap(v, c)) =>" and
If I comment the code bock (bolded in the above code) then I could see all incoming rowmaps being received.
Could anyone let me know why is so? I've been trying to find the cause but couldn't get it to.
Appreciate your help, thanks.
When if ( <somecondition> ) is true, you are moving to the TriggerRule state. In that state you are looking for messages of type EVENT instead of Event (all caps). So the message is not handled by the FSM.
In general, when missing messages in FSM, the best way to debug is to write a whenUnhandled block with a log/print statement to see what messages are not handled by the states you have defined.
There was some issue with message handling in the code itself, we debugged it and fixed the issue, now its working seamlessly.

Combining local result with possible (timeout/error) async web result

I have two methods that both return an IObservable
IObservable<Something[]> QueryLocal();
and
IObservable<Something[]> QueryWeb();
QueryLocal is always successful. QueryWeb is susceptible to both a timeout and possible web errors.
I wish to implement a QueryLocalAndWeb() that calls both and combines their results.
So far I have:
IObservable<Something[]> QueryLocalAndWeb()
{
var a = QueryLocal();
var b = QueryWeb();
var plan = a.And(b).Then((x, y) => x.Concat(y).ToArray());
return Observable.When(plan).Timeout(TimeSpan.FromSeconds(10), a);
}
However, I'm not sure that it handles the case where QueryWeb yields an error.
In the future I might have a QueryWeb2() that also needs to be taken into account.
So, how do I combine the results from a number of IObservables ignoring the ones that throw errors (or time out)?
I guess OnErrorResumeNext should be able to handle this scenario:
From MSDN:
Continues an observable sequence that is terminated normally or by an
exception with the next observable sequence.
IObservable<Something[]> QueryLocalAndWeb()
{
var a = QueryLocal();
var b = QueryWeb().Timeout(TimeSpan.FromSeconds(10));
return Observable.OnErrorResumeNext(b, a);
}
You can do concat of array by using Aggregation on the returned observable.
I am assuming that both local and web are cold observable i.e they start producing values only when someone subscribes to them.
How about:
var plan = a.And(b).Then((x, y) => x.Concat(y.Catch(Observable.Empty<Something[]>()).ToArray());