Aaron Lahman - MSFT

How do I control scope with causalities For instance, can my causality be
scoped only to depth 1 and greater


Example:

void RootCauseDepth0_CausalityDepth1()
{
Port<bool> nextStep = new Port<bool>();
nextStep.Post(true);

Activate(
dispatcherQueue,
Arbiter.Receive(
false,
nextStep,
delegate(bool b)
{
Dispatcher.AddCausality(new Causality("test", _exceptionTarget));

... // do some stuff, routing exceptions to _exceptionTarget
}
)
);

// This exception should not be routed to _exceptionTarget, correct
throw new InvalidOperationException();
}

void SomeOtherFunction()
{
// This exception *definitely* won't be routed to
// _exceptionTarget, right
throw new InvalidOperationException();
}

void Example()
{
// wait for failure on our exception port
Activate(dispatcherQueue, Arbiter.Receive(false, _exceptionTarget,
ExceptionHandler));

Activate(dispatcherQueue,
Arbiter.FromHandler(
RootCauseDepth0_CausalityDepth1));
Activate(dispatcherQueue,
Arbiter.FromHandler(
SomeOtherFunction));
}


#aaron


Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Are causalities scoped to Arbiter/delegate depth?

George Chrysanthakopoulos

SomeOtherFunction() is not affected bythe causality in the routine RootCauseDepth0_CausalityDepth1(). Causalities travel only when you try to post from a piece of code, that had prior down Dispatcher.AddCausality().

Now, i cant tell you what happens in the throw statement at the end of RootCauseDepth0_CausalityDepth1(), since i dont see where you actually added the causality.

In general, just like with try/catch, unless you nest another causality within a causality (which is supported), you cant control further when exceptions can be routed to the causality port. They will be always routed as long as the piece of code you are executing, is logically connected with some handler that started a causality.





Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Are causalities scoped to Arbiter/delegate depth?

Aaron Lahman - MSFT

Reposting, in order to point out location of causality in original example. See line 12 of the original example, marked with '#' characters this time.

Original question:

Does the throw at the end of RootCauseDepth0_CausalityDepth1() get handled by the causality I would expect it not to, or maybe I need to call RemoveCausality at the end of the Arbiter.Receive delegate

New question:

What happens if Delegate.RemoveCausality() throws What about if Delegate.AddCausality() throws Unlike try-catch, both can throw OutOfMemoryException.

void RootCauseDepth0_CausalityDepth1()

{
Port<bool> nextStep = new Port<bool>();
nextStep.Post(true);

Activate(
dispatcherQueue,
Arbiter.Receive(
false,
nextStep,
delegate(bool b)
{
############# Dispatcher.AddCausality(new Causality("test", _exceptionTarget));

... // do some stuff, routing exceptions to _exceptionTarget
}
)
);

// This exception should not be routed to _exceptionTarget, correct
throw new InvalidOperationException();
}

void SomeOtherFunction()
{
// This exception *definitely* won't be routed to
// _exceptionTarget, right
throw new InvalidOperationException();
}

void Example()
{
// wait for failure on our exception port
Activate(dispatcherQueue, Arbiter.Receive(false, _exceptionTarget,
ExceptionHandler));

Activate(dispatcherQueue,
Arbiter.FromHandler(
RootCauseDepth0_CausalityDepth1));
Activate(dispatcherQueue,
Arbiter.FromHandler(
SomeOtherFunction));
}

#aaron




Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Are causalities scoped to Arbiter/delegate depth?

George Chrysanthakopoulos

Since the CCR is just a runtime library, as you point out, any API calls can fail due to outOfMemory exceptions (they dont have the luxury of the special treatment the try/catch code gets on thread local store, nor do they gain much from using TLS).

So indeed when using Dispatcher.AddCausality, Dispatcher.RemoveCausality, a traditional try.catch around these calls can further ensure the right action is taken.

I believe you meant Dispatcher.Add/RemoveCausality, not Delegate in your post above.





Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Are causalities scoped to Arbiter/delegate depth?

Aaron Lahman - MSFT

Thanks, that clarifies the second question about exception handling with causalities for exception handling, but this doesn't answer the first question.

George Chrysanthakopoulos wrote:

I believe you meant Dispatcher.Add/RemoveCausality, not Delegate in your post above.

I don't understand your comment "I believe you meant Dispatcher.AddCausality", since I did highlight Dispatcher.AddCausality in my second post (originally using ####, now using red highlighter):

Code Snippet

IEnumerator<ITask> RootCauseDepth0_CausalityDepth1()

{
Port<bool> nextStep = new Port<bool>();
nextStep.Post(true);

yeild return Arbiter.Receive(
false,
nextStep,
delegate(bool b)
{

// QUESTION 1: (original question) Is this causality scoped only to

// this delegate or will it linger outside of the Receive task
Dispatcher.AddCausality(trycatchCausality = new Causality("test", _exceptionTarget));

... // do some stuff, routing exceptions to _exceptionTarget
}
);


// This exception should not be routed to _exceptionTarget, correct
throw new InvalidOperationException();
}

void SomeOtherFunction()
{
// QUESTION 2: This exception *definitely* won't be routed to
// _exceptionTarget, right

throw new InvalidOperationException();
}

void Example()
{
// wait for failure on our exception port
Activate(dispatcherQueue, Arbiter.Receive(false, _exceptionTarget,
ExceptionHandler));

Activate(dispatcherQueue,
Arbiter.FromHandler(
RootCauseDepth0_CausalityDepth1));
Activate(dispatcherQueue,
Arbiter.FromHandler(
SomeOtherFunction));
}

Should the red highlighted causality be scoped only to the receive delegate

Thanks,

#aaron






Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Are causalities scoped to Arbiter/delegate depth?

George Chrysanthakopoulos

Hi i must have misunderstood this statement:

"New question:

What happens if Delegate.RemoveCausality() throws What about if Delegate.AddCausality() throws Unlike try-catch, both can throw OutOfMemoryException."

I any case, to answer your first question, the causality is scopped within the method that adds it, but if within this delegate or method you do a port.Post, then whichever handler wakes up due to that post, will also carry this causality (it flows when you post).

But if you dont do anymore posts, then the causality will evaporate when the delegate finishes, not ever "escaping" that delegate





Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Are causalities scoped to Arbiter/delegate depth?

Aaron Lahman - MSFT

Sorry for the confusion over the typo!

I didn't realize causalities followed messages posted durring their scope. Does the causality follow posts that go between services If so, which takes precidence when a handler throws an exception -- will a Fault be sent on the response port, will the causality post the exception to the exception port, or will both ports get a message posted to them

Example:

Code Snippet

class Service1

{

Service2Operations _service2Port = ...

PortSet<Response,Fault> _responsePort = ...

IEnumerator<ITask> MyHandler( ... )

{

Port<Exception> _exceptionPort = new Port<Result>();

Dispatcher.AddCausality("my causality", _exceptionPort);

_service2Port.Post(new WorkItem(..., _responsePort) );

yeild return Arbiter.Receive(false, _exceptionPort, delegate(Exception ex)

{

Console.WriteLine("Type: {0}", ex.GetType().Name);

});

}

}

class Service2

{

[ServiceHandler]

IEnumerator<ITask> WorkItemHandler(WorkItem item)

{

throw new XyzzyException();

}

}

Should this example output to console: "Type: XyzzyException" Will it do so if Service1 and Service2 are on separate nodes Will it do so if they are on separate computers Will _responsePort get a message posted of type Fault

Thanks,

#aaron





Re: Microsoft Robotics - Concurrency and Coordination Runtime (CCR) Are causalities scoped to Arbiter/delegate depth?

George Chrysanthakopoulos

Causalities actually indirectly propagate between nodes and computers. Remember that within node, between nodes, and between machines, DSS behaves the same, other than performance. But isolation, error handling, everything else is the same. Truly distributed runtime Smile

Back to causalities:

At the DSS level you actually have to be explicit on what causalities you want your message to carry. You must do this on the outbound operation:

Code Snippet

WorkItem workOperation = new WorkItem(..., _responsePort);

workOperation.Causalities = new Causality("my dssp work item causality",_exceptionPort);

_service2Port.Post(workOperation);

This is done so you dont accidentlay leak causalities across services you did not mean to.

Now, what the runtime does, is that instead of sending the causality information over to the receiving service, it actually doe snothing different thatn usual: It waits for a response. If the response to this operation is a fault, it will *then* throw an exception on your operations causalities. Basically it will translate a fault to an exception, post the fault on the response port, AND post the exception on the causality.

The exception text will be based on the Fault reasonText, so it should be something close to the original, remote node, exception.