Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved inline projections and event capture #1584

Closed
jeremydmiller opened this issue Oct 19, 2020 · 5 comments
Closed

Improved inline projections and event capture #1584

jeremydmiller opened this issue Oct 19, 2020 · 5 comments
Assignees
Milestone

Comments

@jeremydmiller
Copy link
Member

This is an existing issue that's tripped up folks in the past. I think the way this has to be done is to reserve the event version numbers per stream before the events themselves are appended and the document updates are captured

@jeremydmiller jeremydmiller added this to the 4.0 milestone Oct 19, 2020
@jeremydmiller jeremydmiller changed the title Event version number should be available to inline projections Improved inline projections and event capture Nov 17, 2020
@jeremydmiller
Copy link
Member Author

Merged #996 into this issue.

There's a couple things here today (<v4):

  1. The inline projections cannot use any of the IEvent metadata like event or stream versions because it doesn't exist until the events are appended when the session is committed (SaveChanges())
  2. The event sequence numbers are reserved as part of appending the events, but if the transaction fails, that leaves gaps in the sequence that requires the async daemon to be slower in determining the leading edge of the event store and causes some inefficiency in the async projections.

Proposal

For the sake of the async daemon or its replacement, let's use Tombstone event records in the event table to mark events that failed.

If there are any active inline projections

The SaveChanges()/SaveChangesAsync() workflow changes just a little bit. Before building up the unit of work and committing that let's

  1. Execute a new function that first reaches into the database and "reserves" event version and event sequence id values by writing placeholder rows in the mt_events table. Do something that makes it clear that these rows are "pending". Maybe through the event type name?
  2. Writes the new version numbers and seq id to the IEvent objects that are being captured
  3. Execute the inline projections against the in memory IEvent objects like we do today, but this time it will have the stream version and seq id numbers available.

The existing append event function will change to do an update to capture the event body instead of an insert.

If SaveChanges/SaveChangesAsync() fails, try to issue an UPDATE statement that flips the reserved rows that didn't get made real to a "tombstone" that the async daemon knows it can skip over rather than having to wait to see if these events are still pending.

If there are no inline projections

This is a little tricker. I think we use a new append function that's smarter. Let's say that all events can be appended in one function call that's smart enough to deal with multiple streams as necessary. This new function will first write out matching tombstone records for all the events being captured, then commits in the function. Then it proceeds to update those new records with the real event bodies, but that update will only succeed if the rest of the session's unit of work succeeds. This will require us to move the event appending to the very first operation in the unit of work.

@oskardudycz
Copy link
Collaborator

@jeremydmiller I think that we should allow a bit more flexible logic for snapshoting to give user option to eg. snapshot on:

@jeremydmiller
Copy link
Member Author

@oskardudycz You've brought that up before, and it sound fine to me. I don't think that's part of this issue though. You might wanna start a new one to track that. I think you'd do that w/ some kind of background process.

@oskardudycz
Copy link
Collaborator

I'm not sure if that should be a background process. I think that this can be implemented in the regular one. Maybe I'm not making my thoughts clear enough...

@jeremydmiller
Copy link
Member Author

If only we had a zoom meeting tomorrow to talk in person....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants