rbuckland/akka-escqrs

Implement an Abstract View Implementation

Opened this issue · 4 comments

Views for akka-persistence are tied directly to the processor they "view" via the processorId.

In the same way that processor's have special logic for recovery, the view will also. Asses an, if required, implement an Abstract View that matches the logic of the framework.

I actually started on this the other day. I think we will need this longterm.

Need to ensure that the "processorId" is either passed in as a parameter or injected into both so that it is consistent between the two (Processor and View). We don't want to go with the default one, it should be "stable" and have some form of business / domain meaning. This id is used to identify the journal that is replayed. Need to ensure that is is very stable. This is one of the "best practices" per the documents:

"Overriding processorId is the recommended way to generate stable identifier"

Will commit something later today or early Monday.

Use of a common / shared processorId I think is all ready to go.

In the framework library is a “trait” called ActorSupport, for Companion Objects.
I wrote these because you should not pass ActorRef’s around. So .. ActorSelection should be by name.

For example:

  override val personProcessor = context.actorSelection(PersonProcessor.actorPath)

A stable identifier is the className.. / qualified name of the Processor .. on the trait .. ActorSupport.ACTOR_NAME
So .. maybe enhancing the ActorSupport trait is the best approach - this should have some parameters to help decide what type of “common” name to generate/

Current;y it takes “off” the first 3 package names .. (uk.co.soqqo.service.SomeProcessor —> service.SomeProcessor) .. a little brittle.

for example:

class SomeProcessor()
                           (implicit val bindingModule: BindingModule)
  extends SZValidationUuidAbstractProcessor[SomeObject, SomeEvent, SomeCommand]
  with AutoInjectable

   // all the event sourced stuff (extending the SZUuidAbtsractProcessor
}

// companion object that holds the name common for the SomeProcessor
object SomeProcessor extends ActorSupport {
  def props: Props =  Props(classOf[SomeProcessor])
}

package io.straight.fw.akka

/**

  • @author rbuckland
    */
    trait ActorSupport {

    def ACTOR_NAME: String = {
    //tail tail tail is to strip off the first 3 package names ( this could explode!)
    val name = this.getClass.getPackage.getName.split('.').tail.tail.tail.mkString(".") +
    "." + this.getClass.getSimpleName.split('$')(0)
    return name

    }

    def actorPath = "/user/" + ACTOR_NAME

}

so ,, the name is Always ACTOR_NAME

A view can just use the processorId it wants to use like :

def processorId = SomeProcessor.ACTOR_NAME

Ramon Buckland
ramon@thebuckland.com
“You are never too old to set another goal or to dream a new dream” - C.S. Lewis

Ramon Buckland
ramon@thebuckland.com
“You are never too old to set another goal or to dream a new dream” - C.S. Lewis

On 6 Apr 2014, at 14:24, Todd notifications@github.com wrote:

I actually started on this the other day. I think we will need this longterm.

Need to ensure that the "processorId" is either passed in as a parameter or injected into both so that it is consistent between the two (Processor and View). We don't want to go with the default one, it should be "stable" and have some form of business / domain meaning. This id is used to identify the journal that is replayed. Need to ensure that is is very stable. This is one of the "best practices" per the documents:

"Overriding processorId is the recommended way to generate stable identifier"

Will commit something later today or early Monday.


Reply to this email directly or view it on GitHub.

Yes so I have looked at the ActorSupport trait, and agree that enhancing it is probably the correct approach. My only concern is that the actor name has a hierarchical path in it, if we simply go with the ACTOR_NAME, then we are binding to where we are today in the path, this could change in the future and would have an impact on the journal replay as I understand it.

So I tend to think this value to be either strictly the class name, i.e. "PersonProcessor", or some identifier injected; still thinking this one over.

I agree on classname ..
It is kind of why I went with “(subgroup).ClassName” .. that way I got some sort of categorisation I too felt that the full package name was too much.
So .. perhaps .. by convention for no other reason you could do

// not checked .. (take the lowest package.. *services/ web/ something/ .. and append the “getSimpleName”
// to make —> services.MyProcessor
val fullProcessorName = this.getClass.getPackage.getName.split('.’).reverse.head + “.” + this.getClass.getSimpleName.split('$')(0)

Ramon Buckland
ramon@thebuckland.com
“You are never too old to set another goal or to dream a new dream” - C.S. Lewis

On 6 Apr 2014, at 15:22, Todd notifications@github.com wrote:

Yes so I have looked at the ActorSupport trait, and agree that enhancing it is probably the correct approach. My only concern is that the actor name has a hierarchical path in it, if we simply go with the ACTOR_NAME, then we are binding to where we are today in the path, this could change in the future and would have an impact on the journal replay as I understand it.

So I tend to think this value to be either strictly the class name, i.e. "PersonProcessor", or some identifier injected; still thinking this one over.


Reply to this email directly or view it on GitHub.