I am new to Lagom and I want to deal with Event Sourcing at some later point. So I'm not using the persistentEntityRegistry, instead I'm using a simple repository for CRUD operations.
Anyway I would like to have the ability to notify other Services, when a create operation has happened.
In the hello-lagom project the topic is implemented like this:
override def greetingsTopic(): Topic[GreetingMessage] =
TopicProducer.singleStreamWithOffset {
fromOffset =>
persistentEntityRegistry.eventStream(HelloEventTag.INSTANCE, fromOffset)
.map(ev => (convertEvent(ev), ev.offset))
}
This will obviously not work, when I'm not working without the event sourcing, so I just wondered if there is another way to publish events to the topic.
I'm thinking about sth. like this:
override def createSth = ServiceCall { createCommandData =>
val id = UUID.randomUUID()
repository.addSth(Sth(id, createCommandData.someValue)) map {createdItem =>
myTopic.publish(SthWasCreated(id))
}
}
Related
Lets say we modified an event to have a new field added. I understand that we can handle the serialization for event mapping changes in this documentation https://www.lagomframework.com/documentation/1.5.x/scala/Serialization.html but how does lagom know which version the event is? When declaring and defining case classes events, we do not specify the event version. So how does lagom serialization know which event version mapping to use?
In the image below, there is a field called fromVersion. How does lagom know the current version of events pulled from event store datastore?
So, to implement migration you add following code:
private val itemAddedMigration = new JsonMigration(2) {
override def transform(fromVersion: Int, json: JsObject): JsObject = {
if (fromVersion < 2) {
json + ("discount" -> JsNumber(0.0d))
} else {
json
}
}
}
override def migrations = Map[String, JsonMigration](
classOf[ItemAdded].getName -> itemAddedMigration
)
}
That means that all new events of type ItemAdded now will have version 2. All previous events will be treated as version 1.
It is defined in the class PlayJsonSerializer
Please see the following code:
private def parseManifest(manifest: String) = {
val i = manifest.lastIndexOf('#')
val fromVersion = if (i == -1) 1 else manifest.substring(i + 1).toInt
val manifestClassName = if (i == -1) manifest else manifest.substring(0, i)
(fromVersion, manifestClassName)
}
Also, you can check it in the database. I use Cassandra, I if I will open my database, in eventsbytag1 collection I can find the field ser_manifest where described version. Where is simple class - it is version 1, where you have specified additional '#2', it means version 2 and so on.
If you need more information about how it works, you can check method fromBinary in class PlayJsonSerializer.
i'm trying to implement an observer pattern using scala and spark streaming. the idea is that whenever i receive a record from the stream (from kafka) i notify the observer by calling the method "notifyObservers" inside the closure. here's the code:
the stream is provided by the kafka utils.
the method notifyObserver is defined into an abstract class following the rules of the pattern.
the error I think is related on the fact that methods cant be serialize.
Am I thinking correctly? and if it was, what kind of solution should I follow?
thanks
def onMessageConsumed() = {
stream.foreachRDD(rdd => {
rdd.foreach(consumerRecord => {
val record = new Record[T](consumerRecord.topic(),
consumerRecord.value())
//notify observers with the record to compute
notifyObservers(record)
})
})
}
Yes, the classes that are used in the code that is sent to other executors (executed in foreach, etc.), should implement Serializable interface.
also, if you're notification code requires connection to some resource, you need to wrap foreach into foreachPartition, something like this:
stream.foreachRDD(rdd => {
rdd.foreachPartition(rddPartition =>
// setup connection to external component
rddPartition.foreach(consumerRecord => {
val record = new Record[T](consumerRecord.topic(),
consumerRecord.value())
notifyObservers(record)
})
// close connection to external component
})
})
I would like to keep track of how many times a certain key is subscribed to in #ngrx/store. I don't want to have repeated code in each component that subscribes but was hoping to hook into select() somehow. I don't think #effects apply here because I am not looking at dispatched actions.
Does anyone have any ideas on how I would implement this?
Assuming that subscribing to a key means selecting something from the store.
You can try extending the Store with your own service and using that then override the select method with something like:
#Injectable()
class CountingStore<S> extends Store<S> {
public keyCount: {[key:string]: number} = {};
public select = (key: string) => {
keyCount[key] = keyCount[key] ? keyCount[key] + 1 : 1;
return super.select(key);
}
}
We have a class Thing that implements IObservable<Thing>. In another class, there is a collection of Things , and that class needs to react to updates from all those observables in a unified manner. The obvious way to do that is Observable.Merge(), and that generally works; however, when the collection changes, we also need to subscribe to any new Things in our merged subscription (and in theory unsubscribe from all the removed ones, but that seems less problematic - they just won't produce any updates anymore).
We currently achieve that by recreating the subscription on every change of the collection, but that seems rather suboptimal in terms of processing overhead and also due to missing updates from any of the Things in the brief time between discarding the old subscription and creating the new one (which has proven to be an issue in practice, especially as we also need to Buffer() the subscription for a short amount of time, and the buffered items are lost when disposing the subscription).
What is the proper way of merging a changing collection of observables like this?
If you have an IObservable<IObservable<T>> observable, then calling Merge on that, will include children of new parents, if you catch my drift. The trick is converting the ObservableCollection<IObservable<Thing>> to an IObservable<IObservable<Thing>>.
If you have ReactiveUI running around, and are ok to use it, then you could convert the ObservableCollection<IObservable<Thing>> to a ReactiveCollection<IObservable<Thing>>. ReactiveCollection inherits from ObservableCollection, and also implements IObservable.
If ReactiveUI is out of the question (which I'm guessing it is because you're already using a Caliburn Micro collection), then you can convert using ObservableCollection's events:
ObservableCollection<IObservable<Thing>> observableCollection = new ObservableCollection<IObservable<Thing>>();
IObservable<IObservable<Thing>> oCollectionObservable = Observable.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
h => observableCollection.CollectionChanged += h,
h => observableCollection.CollectionChanged -= h
)
.SelectMany(ep => ep.EventArgs.NewItems.Cast<IObservable<Thing>>());
Here's some sample code demonstrating use:
oCollectionObservable
.Merge()
.Subscribe(t => Console.WriteLine($"Received Thing {{Id = {t.Id}}}"));
var firstObservable = Observable.Range(1, 5)
.Select(i => new Thing { Id = i })
.Concat(
Observable.Range(8, 5)
.Select(i => new Thing { Id = i })
.Delay(TimeSpan.FromSeconds(2))
);
observableCollection.Add(firstObservable);
var subject = new Subject<Thing>();
observableCollection.Add(subject);
subject.OnNext(new Thing { Id = 6 });
subject.OnNext(new Thing { Id = 7 });
Using the following class:
public class Thing
{
public int Id { get; set; }
}
I'm trying to learn how to use WebSockets and Akka using the Chat example in the Play for Scala book.
In the book, there is one "ChatRoom" being created, and that's instantiated in the Chat controller with something as simple as this:
val room = Akka.system.actorOf(Props[ChatRoom])
I want to expand this example and have multiple chat rooms available instead of just one. A user can provide a string, which can be a chatroom "name", and that would create a new chatroom. Anyone that tries to join this chatroom would share a broadcast with each other, but not with people in another chatroom. Very similar to IRC.
My questions are the following:
1: How do I create a ChatRoom with a unique name if one does not already exist?
2: How can I check if the existing ChatRoom exists and get a reference to it?
The chatroom name will come via either the URL or a query parameter, that part will be trivial. I'm just not entirely sure how to uniquely identify the Akka ChatRoom and later retrieve that Actor by name.
You can name actors in Akka, so instead of having:
Akka.system.actorOf(Props[ChatRoom])
You would have:
Akka.system.actorOf(Props[ChatRoom],"room1")
Then, depending on the Akka version you're using, use either Akka.system.actorFor("room1") or Akka.system.actorSelection("room1") to get a reference to the wanted chat room.
Use the Akka EventBus trait. You can use eventBus and LookupClassification to implement topic based publish-subscribe where the "topic" is the roomID and the subscribers are either the actors for each room or the web-socket actors for each client.
import akka.event.EventBus
import akka.event.LookupClassification
final case class MsgEnvelope(topic: String, payload: Any)
/**
* Publishes the payload of the MsgEnvelope when the topic of the
* MsgEnvelope equals the String specified when subscribing.
*/
class LookupBusImpl extends EventBus with LookupClassification {
type Event = MsgEnvelope
type Classifier = String
type Subscriber = ActorRef
// is used for extracting the classifier from the incoming events
override protected def classify(event: Event): Classifier = event.topic
// will be invoked for each event for all subscribers which registered themselves
// for the event’s classifier
override protected def publish(event: Event, subscriber: Subscriber): Unit = {
subscriber ! event.payload
}
// must define a full order over the subscribers, expressed as expected from
// `java.lang.Comparable.compare`
override protected def compareSubscribers(a: Subscriber, b: Subscriber): Int =
a.compareTo(b)
// determines the initial size of the index data structure
// used internally (i.e. the expected number of different classifiers)
override protected def mapSize: Int = 128
}
Then register your actors (in reality you would keep a count of how many users are in each room and subscribe when users enter the room and unsubscribe and kill the actor when no-one is in the room)
val lookupBus = new LookupBusImpl
lookupBus.subscribe(room1Actor, "room1")
lookupBus.subscribe(room2Actor, "room2")
The message will be switched based on the roomID
lookupBus.publish(MsgEnvelope("room1", "hello room1"))
lookupBus.publish(MsgEnvelope("room2", "hello room2"))
lookupBus.publish(MsgEnvelope("room3", "hello dead letter"))