marten icon indicating copy to clipboard operation
marten copied to clipboard

LiveAggregation invalid code generation when using static apply handlers + manual registration (v7 master)

Open Hawxy opened this issue 2 years ago • 3 comments

Given a projection of shape:

public record Point(Guid Id, string Name)
{
    public static Point Create(PointCreated e) => new(e.Id, e.Point.Name,);

    public static Point Apply(Point state, PointEdited e) => state with { Name = e.Point.Name };
}

And a definition of:

public class PointProjection : SingleStreamProjection<Point>
{
    public PointProjection()
    {
        CreateEvent<PointCreated>(Point.Create);

        ProjectEvent<IEvent<PointEdited>>(Point.Apply);
    }
}

Will generate an invalid live aggregation codegen of:

        public Example.Point Apply(Marten.Events.IEvent @event, Example.Point aggregate, Marten.IQuerySession session)
        {
            switch (@event)
            {
                case Marten.Events.IEvent<Example.PointEdited> event_PointEdited3:
                   // double mutation of aggregate
                    aggregate = Example.Point.Apply(aggregate, event_PointEdited3.Data);
                    aggregate = ProjectEvent1.Invoke(aggregate, event_PointEdited3);
                    break;
            }

            return aggregate;
        }

InlineAggregation appears to not be impacted by this scenario.

Hawxy avatar Mar 01 '24 12:03 Hawxy

Ugh, @Hawxy. I really don't want to change anything for this one to be honest. We made a change to honor static methods called Apply because it was tripping up multiple people. I'd rather hit this one with documentation. Or don't bother with the ProjectEvent() call that's a duplicate.

jeremydmiller avatar Mar 01 '24 13:03 jeremydmiller

In 7.1, I definitely want to have an easy to use, almost 100% explicit code model for at least live aggregations and start slowly weaning us off the codegen'd projections.

jeremydmiller avatar Mar 01 '24 13:03 jeremydmiller

Our scenario is a little more complex. We use the lambda as a central point to copy metadata from event headers to the projection before the event is applied.

ie

 ProjectEvent<IEvent<PointEdited>>((state, ev) => ev.WithMetadata(Point.Apply, state));

I'll patch my local copy of marten for the time being.

Hawxy avatar Mar 01 '24 15:03 Hawxy

Looking at this, I think this can just be beaten by using the [MartenIgnore] attribute. Just verify that, and doc it

jeremydmiller avatar Sep 11 '24 20:09 jeremydmiller

Sorry, it is just "use [MartenIgnore]", and I verified that's in the docs

jeremydmiller avatar Sep 15 '24 10:09 jeremydmiller