Can I "hook" a subscription in ngrx store - ngrx-effects

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);
}
}

Related

What data should I keep in aggregates

I am learning CQRS and event sourcing architecture (with nestjs), and I am a bit confused by aggregates.
I am following the kind of architecture explained here : https://danielwhittaker.me/2020/02/20/cqrs-step-step-guide-flow-typical-application/
If I understand well, the aggregate root is my "Write Model". It update itself using events which will be committed to the event bus, and I get its current state using event history (or cache).
As I never really read the data in the aggregate root (only the data needed to accept or not the next commands), and I don't persist it (the events are), should I really need to keep all my data in aggregates?
I am not sure if I am clear, so let's see a simplified example :
I've got a CreateProduct command for my shopping website, and a ProductCreated event. I use the content of the event to create views for some query like GetProductByCategory, SearchProduct, ...
Here the command :
class CreateProduct {
public name: string;
public description?: string;
// ...
}
I skip the commandHandler. If I understand well, my aggregate root should be like :
class ProductAggregateRoot extends AggregateRoot {
public id: string;
private name: string;
private description?: string;
create(data: { name: string, description?: string }) {
if (! data.name) {
throw Error('Name is required');
}
this.apply(new ProductCreated(uuid(), data));
}
onProductCreated(event: ProductCreated) {
this.id = event.id;
this.name = event.name;
this.description = event.description;
}
}
Can I just do :
class ProductAggregateRoot extends AggregateRoot {
public id: string
create(data: { name: string, description?: string }) {
if (! data.name) {
throw Error('Name is required');
}
this.apply(new ProductCreated(uuid(), data));
}
onProductCreated(event: ProductCreated) {
this.id = event.id;
}
}
as I never use name and description on the command side? It is just usefull for me to create the views on the query side.
It confuses me because it seems to be far from the domain (a Product is more than just an id). But I don't get the point to keep these data here. If I change my mind, I can add it later and rebuild my aggregate roots from the history.
I do not know about nestjs in particular, but in a general implementation of an Event Sourcing application is absolutely OK to only us the fields you need in order to satisfy your business rules. So in this case, since there are no rules involving name or description they don't need to be materialized into the aggregate root class when you handle additional commands (maybe DeleteProduct or similar).
When you apply your next command your application should materialize the aggregate root again from the history of events, so yes you can add fields later if needed.
You can see an example from the Serialized Java client here (https://serialized.io/java/working-with-aggregates/) where OrderPlaced event contains an amount that is not read into the transient state of the Order aggregate when handling commands.

Merging a changing collection of observables

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; }
}

Understanding RxJava: Differences between Runnable callback

I'm trying to understand RxJava and I'm sure this question is a nonsense... I have this code using RxJava:
public Observable<T> getData(int id) {
if (dataAlreadyLoaded()) {
return Observable.create(new Observable.OnSubscribe<T>(){
T data = getDataFromMemory(id);
subscriber.onNext(data);
});
}
return Observable.create(new Observable.OnSubscribe<T>(){
#Override
public void call(Subscriber<? super String> subscriber) {
T data = getDataFromRemoteService(id);
subscriber.onNext(data);
}
});
}
And, for instance, I could use it this way:
Action1<String> action = new Action<String>() {
#Override
public void call(String s) {
//Do something with s
}
};
getData(3).subscribe(action);
and this another with callback that implements Runnable:
public void getData(int id, MyClassRunnable callback) {
if (dataAlreadyLoaded()) {
T data = getDataFromMemory(id);
callback.setData(data);
callback.run();
} else {
T data = getDataFromRemoteService(id);
callback.setData(data);
callback.run();
}
}
And I would use it this way:
getData(3, new MyClassRunnable()); //Do something in run method
Which are the differences? Why is the first one better?
The question is not about the framework itself but the paradigm. I'm trying to understand the use cases of reactive.
I appreciate any help. Thanks.
First of all, your RxJava version is much more complex than it needs to be. Here's a much simpler version:
public Observable<T> getData(int id) {
return Observable.fromCallable(() ->
dataAlreadyLoaded() ? getDataFromMemory(id) : getDataFromRemoteService(id)
);
}
Regardless, the problem you present is so trivial that there is no discernible difference between the two solutions. It's like asking which one is better for assigning integer values - var = var + 1 or var++. In this particular case they are identical, but when using assignment there are many more possibilities (adding values other than one, subtracting, multiplying, dividing, taking into account other variables, etc).
So what is it you can do with reactive? I like the summary on reactivex's website:
Easily create event streams or data streams. For a single piece of data this isn't so important, but when you have a stream of data the paradigm makes a lot more sense.
Compose and transform streams with query-like operators. In your above example there are no operators and a single stream. Operators let you transform data in handy ways, and combining multiple callbacks is much harder than combining multiple Observables.
Subscribe to any observable stream to perform side effects. You're only listening to a single event. Reactive is well-suited for listening to multiple events. It's also great for things like error handling - you can create a long sequence of events, but any errors are forwarded to the eventual subscriber.
Let's look at a more concrete with an example that has more intrigue: validating an email and password. You've got two text fields and a button. You want the button to become enabled once there is a email (let's say .*#.*) and password (of at least 8 characters) entered.
I've got two Observables that represent whatever the user has currently entered into the text fields:
Observable<String> email = /* you figure this out */;
Observable<String> password = /* and this, too */;
For validating each input, I can map the input String to true or false.
Observable<Boolean> validEmail = email.map(str -> str.matches(".*#.*"));
Observable<Boolean> validPw = password.map(str -> str.length() >= 8);
Then I can combine them to determine if I should enable the button or not:
Observable.combineLatest(validEmail, validPw, (b1, b2) -> b1 && b2)
.subscribe(enableButton -> /* enable button based on bool */);
Now, every time the user types something new into either text field, the button's state gets updated. I've setup the logic so that the button just reacts to the state of the text fields.
This simple example doesn't show it all, but it shows how things get a lot more interesting after you get past a simple subscription. Obviously, you can do this without the reactive paradigm, but it's simpler with reactive operators.

How do I merge several observables using WhenAny(...) in ReactiveUI?

I have a question which is an extension of the following question raised on this site.
Is there a more elegant way to merge observables when return type is unimportant?
I have an IObservable<Unit> (lets say X), a reactive collection (Y) and a property (Z). Return type is not important. I just want to subscribe when any of these change.
I know how to observe all 3 and Subscribe using Observable.Merge as below.
Observable.Merge(X, Y.Changed, ObservableForProperty(Z).Select(_ => Unit.Default)).Subscribe(..)
And it works.
However, when I try to use WhenAny(...,....,....).Subscribe(), the subscribe does not get triggered when my X changes. What is the syntax for doing the above using WhenAny(...) rather than Observable.Merge(..)??
I prefer to use WhenAny(....) because I am using ReactiveUI in other places.
Example:
Say I've got a class derived from ReactiveObject with following properties.
public class AnotherVM : ReactiveObject
{
public bool IsTrue
{
get { return this.isTrue; }
set { this.RaiseAndSetIfChanged(x => x.isTrue, ref this.isTrue, value); }
}
public IObservable<Unit> Data
{
get { return this.data; }
}
public ReactiveCollection MyCol
{
get { return Mycol; }
}
}
public class MyVM : ReactiveObject
{
MyVM
{
// do WhenAny or Observable.Merge here....
}
}
I want to observe the above properties in AnotherVM class using Observable.Merge(..) or WhenAny(...) in MyVM class. I found that I do not always get a notification when I subscribe to the above in MyVM using WhenAny(...) or Merge(...) when either of the 3 properties change.
WhenAny is not for monitoring across sets of arbitrary observables, it's for monitoring the properties of an object supported by ReactiveUI (like a ReactiveObject or reactive collection).
For the general case of combining changes in observable streams, Observable.Merge is the right way to go.
EDIT
I note that you have declared the Data and MyCol properties read only. If you use a Merge like this:
Observerable.Merge(this.WhenAnyValue(o=>o.IsTrue, v=>Unit.Default),
this.Data,
this.MyCol.CollectionChanged.Select(v=>Unit.Default))
...then you must be careful not to change the backing fields. If you do, then you will get missing events - maybe this is what is happening?
In that case you would need to wire up those properties to RaiseAndSetIfChanged and use a Switch to keep track - e.g. if this.data could change then you would need (I'm using ReactiveUI 5 + .NET 4.5 here in case the RaiseAndSetIfChanged syntax looks odd):
public IObservable<Unit> Data
{
get { return this.data; }
private set { this.RaiseAndSetIfChanged(ref data, value); }
}
and your merge would be something like:
Observerable.Merge(this.WhenAnyValue(o=>o.IsTrue, v=>Unit.Default),
this.WhenAnyObservable(x => x.Data),
this.MyCol.CollectionChanged.Select(v=>Unit.Default))
WhenAnyObservable is conceptually equivalent to this:
WhenAny(x => x.Data, vm => vm.Value).Switch()
using Switch to flip over to the latest value of Data when it changes. Don't forget to use the setter to change values of data!
This should do it.
IObservable<Unit> merged =
Observerable.Merge
( this.WhenAnyValue(o=>o.IsTrue, v=>Unit.Default)
, this.Data
, this.MyCol.CollectionChanged.Select(v=>Unit.Default)
)
Theoretically you could write a special version of merge that would disregard the type of the observable and return IObservable<Unit>. Then you could write
IObservable<Unit> merged =
Observerable.MergeToUnit
( this.WhenAnyValue(o=>o.IsTrue)
, this.Data
, this.MyCol.CollectionChanged
)
but then you would need many overloads of MergeToUnit for up to the N parameters you would like to support.
The most general pattern to use with WhenAny with multiple objects is
Observable.CombineLatest
( source0.WhenAnyValue(s=>s.FieldA)
, source1.WhenAnyValue(s=>s.FieldB)
, source2.WhenAnyValue(s=>s.FieldC)
, source3.WhenAnyValue(s=>s.FieldD)
, (a,b,c,d) => Process(a,b,c,d)
)
It's sometimes just better to get used to using the standard combinators.

Wicket - Wrapped collection Model "transformation"

I have a domain object which has a collection of primitive values, which represent the primary keys of another domain object ("Person").
I have a Wicket component that takes IModel<List<Person>>, and allows you to view, remove, and add Persons to the list.
I would like to write a wrapper which implements IModel<List<Person>>, but which is backed by a PropertyModel<List<Long>> from the original domain object.
View-only is easy (Scala syntax for brevity):
class PersonModel(wrappedModel: IModel[List[Long]]) extends LoadableDetachableModel[List[Person]] {
#SpringBean dao: PersonDao =_
def load: List[Person] = {
// Returns a collection of Persons for each id
wrappedModel.getObject().map { id: Long =>
dao.getPerson(id)
}
}
}
But how might I write this to allow for adding and removing from the original List of Longs?
Or is a Model not the best place to do this translation?
Thanks!
You can do something like this:
class PersonModel extends Model<List<Person>> {
private transient List<Person> cache;
private IModel<List<String>> idModel;
public PersonModel( IModel<List<String>> idModel ) {
this.idModel = idModel;
}
public List<Person> getObject() {
if ( cache == null ) {
cache = convertIdsToPersons( idModel.getObject() );
return cache;
}
public void setObject( List<Person> ob ) {
cache = null;
idModel.setObject( convertPersonsToIds( ob ) );
}
}
This isn't very good code but it shows the general idea. One thing you need to consider is how this whole thing will be serialised between requests, you might be better off extending LoadableDetachableModel instead.
Another thing is the cache: it's there to avoid having to convert the list every time getObject() is called within a request. You may or may not need it in practice (depends on a lot of factors, including the speed of the conversion), but if you use it, it means that if something else is modifying the underlying collection, the changes may not be picked up by this model.
I'm not quite sure I understand your question and I don't understand the syntax of Scala.
But, to remove an entity from a list, you can provide a link that simply removes it using your dao. You must be using a repeater to populate your Person list so each repeater entry will have its own Model which can be passed to the deletion link.
Take a look at this Wicket example that uses a link with a repeater to select a contact. You just need to adapt it to delete your Person instead of selecting it.
As for modifying the original list of Longs, you can use the ListView.removeLink() method to get a link component that removes an entry from the backing list.