This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Applying two messages to two actors atomically

6 replies
Chris Marshall
Joined: 2009-06-17,
User offline. Last seen 44 weeks 3 days ago.
Can anyone think of a way of ensuring that (the state changes associated with) 2 messages to 2 actors are "applied" atomically. That is, if I have two actors, each representing something like an account and I want to enact a transfer such that it is not possible to view the state of the system such that one actor has applied its side of the transfer but the other has not. Please do not answer "use Akka" - as I can't; I realise that the solution may be somewhat messy. The solution cannot involve the actors themselves blocking, o/w I could simply do this:
case class Transfer(amt: Int, latch: CountDownLatch)
class Account extends Actor {  var amount = 0  def act() {    loop {      react {        case Transfer(amt, l) => l.countDown(); l.await(); amount += amt      }    }  }}
Chris 
dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Applying two messages to two actors atomically

That's pretty much how Akka does it, I think. This kind of problem is
not a good fit for actors -- transactional memory has the edge here.

On Mon, Nov 7, 2011 at 11:49, Chris Marshall wrote:
> Can anyone think of a way of ensuring that (the state changes associated
> with) 2 messages to 2 actors are "applied" atomically. That is, if I have
> two actors, each representing something like an account and I want to enact
> a transfer such that it is not possible to view the state of the system such
> that one actor has applied its side of the transfer but the other has not.
> Please do not answer "use Akka" - as I can't; I realise that the solution
> may be somewhat messy. The solution cannot involve the actors themselves
> blocking, o/w I could simply do this:
> case class Transfer(amt: Int, latch: CountDownLatch)
> class Account extends Actor {
>   var amount = 0
>   def act() {
>     loop {
>       react {
>         case Transfer(amt, l) => l.countDown(); l.await(); amount += amt
>       }
>     }
>   }
> }
> Chris

ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: Applying two messages to two actors atomically
Are you sure what you're asking for is logically coherent?  You want two asynchronous entities to both apply an operation at the same time without blocking?

There are lots of possible ways to structure things so that this will effectively happen, but none quite match what you're saying.

(1) You can make the actor and its data separable.  Then both actors can loan their data to a transactor that applies the operation, and they can watch an AtomicBoolean or something to know when they can assume ownership of the data again.

(2) You can have verification required:
  a ! (do-it,b)
  b ! (do-it,a)
  // a sends b ! held and stops processing messages that may rely on changing state
  // b sends a ! held, and does likewise
  // once a receives held, it changes state, sends b ! done, and starts processing again
  // likewise with b
Here, if we think about what messages we can receive:
  Initially, we get the old state
  If a is held and b is not, we get the old state from b but do not get state from a
  If both are held we do not get state
  If a is done and b is not, we get new state from a but not from b
  Finally, we get new state from both
Now, there's still the question of what it means for one actor to have applied its side of the transfer and the other not when messages are asynchronous--after all, the actual transfer could occur simultaneously, but you could receive a messages out of order from different times.  So you'd need some sort of timestamp that was also passed around if you wanted to keep things straight.

  --Rex

On Mon, Nov 7, 2011 at 8:49 AM, Chris Marshall <oxbow_lakes@hotmail.com> wrote:
Can anyone think of a way of ensuring that (the state changes associated with) 2 messages to 2 actors are "applied" atomically. That is, if I have two actors, each representing something like an account and I want to enact a transfer such that it is not possible to view the state of the system such that one actor has applied its side of the transfer but the other has not. Please do not answer "use Akka" - as I can't; I realise that the solution may be somewhat messy. The solution cannot involve the actors themselves blocking, o/w I could simply do this:
case class Transfer(amt: Int, latch: CountDownLatch)
class Account extends Actor {  var amount = 0  def act() {    loop {      react {         case Transfer(amt, l) => l.countDown(); l.await(); amount += amt      }    }  }}
Chris 

Chris Marshall
Joined: 2009-06-17,
User offline. Last seen 44 weeks 3 days ago.
RE: Applying two messages to two actors atomically
I want the asynchronous entities to *not be observable in a mutually inconsistent state*; they do not need to apply the state change at the same time, nor care about whether the other entity has applied its change (possibly what I'm asking is not logically coherent: it represents a system being asked to do something for which it was not designed). My solution looks like this:
- the event source creates a SyncPoint with a unique ID and a set of participants. It sends this to all *observers* before sending to the actors themselves- once the actors have applied their side of the change, they publish out a Synced message with their new state and the id of the sync point- an observer will put aside any state updates from actors which are participating in active sync points. Only when the transitive closure of an actor's sync points are completed, will the observer release the new state for these actors
It works but has the disadvantage that the source of events needs to know about all potential observers of state
Chris


Date: Mon, 7 Nov 2011 14:25:26 -0500
Subject: Re: [scala-user] Applying two messages to two actors atomically
From: ichoran@gmail.com
To: oxbow_lakes@hotmail.com
CC: scala-user@googlegroups.com

Are you sure what you're asking for is logically coherent?  You want two asynchronous entities to both apply an operation at the same time without blocking?

There are lots of possible ways to structure things so that this will effectively happen, but none quite match what you're saying.

(1) You can make the actor and its data separable.  Then both actors can loan their data to a transactor that applies the operation, and they can watch an AtomicBoolean or something to know when they can assume ownership of the data again.

(2) You can have verification required:
  a ! (do-it,b)
  b ! (do-it,a)
  // a sends b ! held and stops processing messages that may rely on changing state
  // b sends a ! held, and does likewise
  // once a receives held, it changes state, sends b ! done, and starts processing again
  // likewise with b
Here, if we think about what messages we can receive:
  Initially, we get the old state
  If a is held and b is not, we get the old state from b but do not get state from a
  If both are held we do not get state
  If a is done and b is not, we get new state from a but not from b
  Finally, we get new state from both
Now, there's still the question of what it means for one actor to have applied its side of the transfer and the other not when messages are asynchronous--after all, the actual transfer could occur simultaneously, but you could receive a messages out of order from different times.  So you'd need some sort of timestamp that was also passed around if you wanted to keep things straight.

  --Rex

On Mon, Nov 7, 2011 at 8:49 AM, Chris Marshall <oxbow_lakes@hotmail.com> wrote:
Can anyone think of a way of ensuring that (the state changes associated with) 2 messages to 2 actors are "applied" atomically. That is, if I have two actors, each representing something like an account and I want to enact a transfer such that it is not possible to view the state of the system such that one actor has applied its side of the transfer but the other has not. Please do not answer "use Akka" - as I can't; I realise that the solution may be somewhat messy. The solution cannot involve the actors themselves blocking, o/w I could simply do this:
case class Transfer(amt: Int, latch: CountDownLatch)
class Account extends Actor {  var amount = 0  def act() {    loop {      react {         case Transfer(amt, l) => l.countDown(); l.await(); amount += amt      }    }  }}
Chris 

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Applying two messages to two actors atomically


On Thu, Nov 10, 2011 at 3:52 PM, Chris Marshall <oxbow_lakes@hotmail.com> wrote:
I want the asynchronous entities to *not be observable in a mutually inconsistent state*; they do not need to apply the state change at the same time, nor care about whether the other entity has applied its change (possibly what I'm asking is not logically coherent: it represents a system being asked to do something for which it was not designed). My solution looks like this:
- the event source creates a SyncPoint with a unique ID and a set of participants. It sends this to all *observers* before sending to the actors themselves- once the actors have applied their side of the change, they publish out a Synced message with their new state and the id of the sync point - an observer will put aside any state updates from actors which are participating in active sync points. Only when the transitive closure of an actor's sync points are completed, will the observer release the new state for these actors
It works but has the disadvantage that the source of events needs to know about all potential observers of state

Akka offers transactors for this. (And uses STM for it, which means that it only works for in JVM coordinated consensus).
Ultimately this is a distributed consensus problem, which leads you into N-phased commits.

Cheers,

 

Chris


Date: Mon, 7 Nov 2011 14:25:26 -0500
Subject: Re: [scala-user] Applying two messages to two actors atomically
From: ichoran@gmail.com
To: oxbow_lakes@hotmail.com
CC: scala-user@googlegroups.com

Are you sure what you're asking for is logically coherent?  You want two asynchronous entities to both apply an operation at the same time without blocking?

There are lots of possible ways to structure things so that this will effectively happen, but none quite match what you're saying.

(1) You can make the actor and its data separable.  Then both actors can loan their data to a transactor that applies the operation, and they can watch an AtomicBoolean or something to know when they can assume ownership of the data again.

(2) You can have verification required:
  a ! (do-it,b)
  b ! (do-it,a)
  // a sends b ! held and stops processing messages that may rely on changing state
  // b sends a ! held, and does likewise
  // once a receives held, it changes state, sends b ! done, and starts processing again
  // likewise with b
Here, if we think about what messages we can receive:
  Initially, we get the old state
  If a is held and b is not, we get the old state from b but do not get state from a
  If both are held we do not get state
  If a is done and b is not, we get new state from a but not from b
  Finally, we get new state from both
Now, there's still the question of what it means for one actor to have applied its side of the transfer and the other not when messages are asynchronous--after all, the actual transfer could occur simultaneously, but you could receive a messages out of order from different times.  So you'd need some sort of timestamp that was also passed around if you wanted to keep things straight.

  --Rex

On Mon, Nov 7, 2011 at 8:49 AM, Chris Marshall <oxbow_lakes@hotmail.com> wrote:
Can anyone think of a way of ensuring that (the state changes associated with) 2 messages to 2 actors are "applied" atomically. That is, if I have two actors, each representing something like an account and I want to enact a transfer such that it is not possible to view the state of the system such that one actor has applied its side of the transfer but the other has not. Please do not answer "use Akka" - as I can't; I realise that the solution may be somewhat messy. The solution cannot involve the actors themselves blocking, o/w I could simply do this:
case class Transfer(amt: Int, latch: CountDownLatch)
class Account extends Actor {  var amount = 0  def act() {    loop {      react {         case Transfer(amt, l) => l.countDown(); l.await(); amount += amt      }    }  }}
Chris 




--
Viktor Klang

Akka Tech LeadTypesafe - Enterprise-Grade Scala from the Experts

Twitter: @viktorklang
Chris Marshall
Joined: 2009-06-17,
User offline. Last seen 44 weeks 3 days ago.
RE: Applying two messages to two actors atomically
Unfortunately, I can't justify the complete re-writing of the app to migrate to Akka; as I knew that there's be something in there to address this problem.
Chris

Date: Thu, 10 Nov 2011 16:30:40 +0100
Subject: Re: [scala-user] Applying two messages to two actors atomically
From: viktor.klang@gmail.com
To: oxbow_lakes@hotmail.com
CC: ichoran@gmail.com; scala-user@googlegroups.com



On Thu, Nov 10, 2011 at 3:52 PM, Chris Marshall <oxbow_lakes@hotmail.com> wrote:
I want the asynchronous entities to *not be observable in a mutually inconsistent state*; they do not need to apply the state change at the same time, nor care about whether the other entity has applied its change (possibly what I'm asking is not logically coherent: it represents a system being asked to do something for which it was not designed). My solution looks like this:
- the event source creates a SyncPoint with a unique ID and a set of participants. It sends this to all *observers* before sending to the actors themselves- once the actors have applied their side of the change, they publish out a Synced message with their new state and the id of the sync point - an observer will put aside any state updates from actors which are participating in active sync points. Only when the transitive closure of an actor's sync points are completed, will the observer release the new state for these actors
It works but has the disadvantage that the source of events needs to know about all potential observers of state

Akka offers transactors for this. (And uses STM for it, which means that it only works for in JVM coordinated consensus).
Ultimately this is a distributed consensus problem, which leads you into N-phased commits.

Cheers,

 

Chris


Date: Mon, 7 Nov 2011 14:25:26 -0500
Subject: Re: [scala-user] Applying two messages to two actors atomically
From: ichoran@gmail.com
To: oxbow_lakes@hotmail.com
CC: scala-user@googlegroups.com

Are you sure what you're asking for is logically coherent?  You want two asynchronous entities to both apply an operation at the same time without blocking?

There are lots of possible ways to structure things so that this will effectively happen, but none quite match what you're saying.

(1) You can make the actor and its data separable.  Then both actors can loan their data to a transactor that applies the operation, and they can watch an AtomicBoolean or something to know when they can assume ownership of the data again.

(2) You can have verification required:
  a ! (do-it,b)
  b ! (do-it,a)
  // a sends b ! held and stops processing messages that may rely on changing state
  // b sends a ! held, and does likewise
  // once a receives held, it changes state, sends b ! done, and starts processing again
  // likewise with b
Here, if we think about what messages we can receive:
  Initially, we get the old state
  If a is held and b is not, we get the old state from b but do not get state from a
  If both are held we do not get state
  If a is done and b is not, we get new state from a but not from b
  Finally, we get new state from both
Now, there's still the question of what it means for one actor to have applied its side of the transfer and the other not when messages are asynchronous--after all, the actual transfer could occur simultaneously, but you could receive a messages out of order from different times.  So you'd need some sort of timestamp that was also passed around if you wanted to keep things straight.

  --Rex

On Mon, Nov 7, 2011 at 8:49 AM, Chris Marshall <oxbow_lakes@hotmail.com> wrote:
Can anyone think of a way of ensuring that (the state changes associated with) 2 messages to 2 actors are "applied" atomically. That is, if I have two actors, each representing something like an account and I want to enact a transfer such that it is not possible to view the state of the system such that one actor has applied its side of the transfer but the other has not. Please do not answer "use Akka" - as I can't; I realise that the solution may be somewhat messy. The solution cannot involve the actors themselves blocking, o/w I could simply do this:
case class Transfer(amt: Int, latch: CountDownLatch)
class Account extends Actor {  var amount = 0  def act() {    loop {      react {         case Transfer(amt, l) => l.countDown(); l.await(); amount += amt      }    }  }}
Chris 




--
Viktor Klang

Akka Tech LeadTypesafe - Enterprise-Grade Scala from the Experts

Twitter: @viktorklang
Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Applying two messages to two actors atomically


2011/11/10 Chris Marshall <oxbow_lakes@hotmail.com>
Unfortunately, I can't justify the complete re-writing of the app to migrate to Akka; as I knew that there's be something in there to address this problem.

You can implement the same approach that Akka uses, with Scala Actors.

Cheers,

 

Chris

Date: Thu, 10 Nov 2011 16:30:40 +0100
Subject: Re: [scala-user] Applying two messages to two actors atomically
From: viktor.klang@gmail.com
To: oxbow_lakes@hotmail.com
CC: ichoran@gmail.com; scala-user@googlegroups.com



On Thu, Nov 10, 2011 at 3:52 PM, Chris Marshall <oxbow_lakes@hotmail.com> wrote:
I want the asynchronous entities to *not be observable in a mutually inconsistent state*; they do not need to apply the state change at the same time, nor care about whether the other entity has applied its change (possibly what I'm asking is not logically coherent: it represents a system being asked to do something for which it was not designed). My solution looks like this:
- the event source creates a SyncPoint with a unique ID and a set of participants. It sends this to all *observers* before sending to the actors themselves- once the actors have applied their side of the change, they publish out a Synced message with their new state and the id of the sync point - an observer will put aside any state updates from actors which are participating in active sync points. Only when the transitive closure of an actor's sync points are completed, will the observer release the new state for these actors
It works but has the disadvantage that the source of events needs to know about all potential observers of state

Akka offers transactors for this. (And uses STM for it, which means that it only works for in JVM coordinated consensus).
Ultimately this is a distributed consensus problem, which leads you into N-phased commits.

Cheers,

 

Chris


Date: Mon, 7 Nov 2011 14:25:26 -0500
Subject: Re: [scala-user] Applying two messages to two actors atomically
From: ichoran@gmail.com
To: oxbow_lakes@hotmail.com
CC: scala-user@googlegroups.com

Are you sure what you're asking for is logically coherent?  You want two asynchronous entities to both apply an operation at the same time without blocking?

There are lots of possible ways to structure things so that this will effectively happen, but none quite match what you're saying.

(1) You can make the actor and its data separable.  Then both actors can loan their data to a transactor that applies the operation, and they can watch an AtomicBoolean or something to know when they can assume ownership of the data again.

(2) You can have verification required:
  a ! (do-it,b)
  b ! (do-it,a)
  // a sends b ! held and stops processing messages that may rely on changing state
  // b sends a ! held, and does likewise
  // once a receives held, it changes state, sends b ! done, and starts processing again
  // likewise with b
Here, if we think about what messages we can receive:
  Initially, we get the old state
  If a is held and b is not, we get the old state from b but do not get state from a
  If both are held we do not get state
  If a is done and b is not, we get new state from a but not from b
  Finally, we get new state from both
Now, there's still the question of what it means for one actor to have applied its side of the transfer and the other not when messages are asynchronous--after all, the actual transfer could occur simultaneously, but you could receive a messages out of order from different times.  So you'd need some sort of timestamp that was also passed around if you wanted to keep things straight.

  --Rex

On Mon, Nov 7, 2011 at 8:49 AM, Chris Marshall <oxbow_lakes@hotmail.com> wrote:
Can anyone think of a way of ensuring that (the state changes associated with) 2 messages to 2 actors are "applied" atomically. That is, if I have two actors, each representing something like an account and I want to enact a transfer such that it is not possible to view the state of the system such that one actor has applied its side of the transfer but the other has not. Please do not answer "use Akka" - as I can't; I realise that the solution may be somewhat messy. The solution cannot involve the actors themselves blocking, o/w I could simply do this:
case class Transfer(amt: Int, latch: CountDownLatch)
class Account extends Actor {  var amount = 0  def act() {    loop {      react {         case Transfer(amt, l) => l.countDown(); l.await(); amount += amt      }    }  }}
Chris 




--
Viktor Klang

Akka Tech LeadTypesafe - Enterprise-Grade Scala from the Experts

Twitter: @viktorklang



--
Viktor Klang

Akka Tech LeadTypesafe - Enterprise-Grade Scala from the Experts

Twitter: @viktorklang

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland