EventStore projection “fromCategory” does not produce any state

Dup: https://stackoverflow.com/questions/48309809/eventstore-projection-fromcategory-does-not-produce-any-state

tldr; Created a stream with some events, partitioned that stream, state of fromCategory is not working.

I played a bit with EventStore, and created some events calle NoteAdded in there. These events’ data object is just like {id: 'one|two|three|...}. I can see them in the stream n2 in the web interface.

Then, I run a query like this:

fromStream('n2')
  .when({
      $init: function(s,e) {
          return {count:0}
      },
      $any: function (s,e) {
          s.count++;
          return s;
      }
  })

which produces a correct result: {"count": 4}.

Next, I created a projection ("repN2", Continuous, Emitting allowed) like so:

fromStream('n2')
.when({
    $any: function(state, ev) {
  linkTo('n2c-' + ev.data.id, ev)
}})

The result, is as expected: I see several streams like n2c-one etc. in the web interface.

Now, I want to use the fromCategory selector, so I created a new projection (stateCatN2, Continuous, emitting allowed) like that:

fromCategory('n2c').foreachStream()
  .when({
      $init: function(s,e) {
          return {count:0}
      },
      $any: function (s,e) {
          s.count++;
          return s;
      }
  })

In the projection view of the web interface I see no state, no result.

However, I expect that I could get something like http://localhost:2113/projection/stateCatN2/state?partition=one to give me a {count: 1}. However, when I GET this url, I get a response code of 200, but an empty body.

System built-in projections like $by_category are all running.

What am I missing here?

Could you check the state for ‘n2’ :

http://localhost:2113/projection/stateCatN2/state?partition=n2

``

The projection is probably resolving the link to’s for the events in the category event and is therefore partitioning it on the base stream.

Hi,

No idea, anyone??

Hi Sebastian,

It is possible that the events are being processed, but written to a different partition due to LinkTo’s or something along those lines.

I don’t believe there is a way to get a projection’s state for all partitions, however there is a bit of a workaround to find out what partitions are getting written.

If your projection has written a checkpoint, it would have written a checkpoint stream for every partition it has processed.

You can read through $all and find any stream named “$projections-{projection_name}-{stream_name}-checkpoint.”

{stream_name}” will be the name of the partition.

If your projection hasn’t processed enough events to write a checkpoint, you can simply stop and restart it. This forces a checkpoint to be written.

The partition is named after the category and the id, thus your link should look like:

http://localhost:2113/projection/stateCatN2/state?partition=n2c-one

``

regards,

alex

Just out of curiosity:

$any: function (s,e) {
          s.count++;
          return s;
      }

Is this ok? I thought 's' was supposed to be immutable. I'd expect the body to be something like:

return { count: s.count + 1 };

s = state

To be fair the functions are defined as f(state,event) -> state so you can also return s. It just tends to be more convenient to save the line of code.

Greg

I was aware that s is state.
This function is like a reducer function right? like in redux where it is reducing actions into state, here it is reducing events into state.

In redux the arguments of the reducer function are supposed to be immutable, so s.count++ is not allowed because it mutates the argument. You are supposed to return a changed copy of the state.

I assumed it would be the same in this projector function. Isn't that the case?

Normally the function is expressed as f(state,event)->state

Projections allows you to manipulate the state coming in and copies it for you! It saves a lot of boilerplate code … Consider as example you have a state with 5 items on it.

case “ShitHappened” : {

var mys = new MyState();

mys.Foo = s.Foo + 1;

mys.Bar = s.Bar;

mys.Baz = s.Baz;

mys.Foo = s.Foo;

mys.WhoCares = s.WhoCares;

return mys; var mycolor = new Color(“ffffff”);

}

vs

case “ShitHappened” : {
s.Foo++;

}

Haha fair enough :smiley:
It also saves creating an extra copy of the state.
I think the redux guys base themselves on the functional paradigm to not mutate arguments, so the reducer function can be pure.
Although to be fair, being pure is not that hard in JavaScript nowadays:

return { ...s, foo: s.foo + 1 };

What JavaScript engine is Eventstore using actually? V8?

Yes we embed v8 (the model however was created years ago! before such things existed)