-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Provide docs for Log Consistency Providers and split test #2598
Comments
No doubt: the very next step is to add documentation and samples, both for the geo-distribution use case and for the simpler, non-geodistributed event sourcing. I will create a new PR shortly. The only things already there right now are
In a separate branch, I already have three geo-distributed samples, including information about how to configure and run them under Windows Azure. I will add them to the current Orleans samples. |
Thank you for promptly reply @sebastianburckhardt Yes, I think the first thing you can do, is just a very simple page that allow people that are already familiar with ES (including the old code) to configure Orleans to use your new provider mode. After that, with time, you can elaborate more samples and a more complete doc page. That will unlock right now people (like me) to use it and provide feedback. Also, I don't see in that code where we can replay events. For example, someone introduced a new grain type or an external system that behave as a projection. How can the events be replayed? That would be good to have in the "Hello world ES". Again, thanks for your great work! |
Maybe I can give you enough information right here, to unblock you now before I get to writing the documentation. To get the equivalent of the previous ES support in Orleans, for a class like in the JournaledPerson example at [StorageProvider(ProviderName = "WhateverStorageProviderYouWantToUse")]
[LogConsistencyProvider(ProviderName = "LogStorage")]
public class JournaledPersonGrain : JournaledGrain<PersonState,IPersonEvent>, IJournaledPersonGrain with corresponding provider configuration <LogConsistencyProviders>
<Provider Type="Orleans.EventSourcing.LogStorage.LogConsistencyProvider" Name="LogStorage" />
</LogConsistencyProviders> (the storage provider is optional, if you leave it out the default storage provider is used). The All events in the log are replayed automatically right after the grain is activated. From then on, events are applied incrementally. Finally, there is a little pitfall here. A grain can start executing even before the log of events is loaded and replayed (this is so a grain can be available even if the connection to storage is temporarily broken, or if it takes a long time to load the state). In most cases, you probably want to avoid this behavior; to make sure the grain is fully caught up during activation, you can call
|
Thanks for get back. I tried it but I'm getting the same error from #2597 :( Regarding the replay, I understand that all the event stream is applied to the state serially up to the HEAD version. My question was, once the events are applied, if there is a way to replay it again so a new projection can be generated from that. I guess the only way to do it today, is to loop into the event (btw, I don't see a |
@sebastianburckhardt I got it to "work" However this line here https://github.com/dotnet/orleans/blob/master/test/TestGrains/EventSourcing/JournaledPersonGrain.cs#L135 never is true. Is there anything wrong? |
Ok... I changed that delay to 200 and it worked... I'm not quite sure I followed why... The Confirm() should be atomic, right? Or is it writing to the storage somewhere else in parallel? Also, orleans/src/OrleansEventSourcing/LogStorage/LogConsistencyProvider.cs Lines 16 to 22 in 0f4ba04
The GrainState table is getting this:
|
Currently, the API does not include a direct way to enforce a replaying of the events, nor a way to get access to the whole event history. This is because the API is trying to be as generic as possible (make as few assumptions as possible about the underlying provider). Not all providers even persist the events, and are in that sense not strictly event sourcing. For example, However, if you are using If there is an important reason why the provider should grant access to the events, we can consider adding additional methods to the API, perhaps to retrieve whatever piece of the event sequence is still around. |
The event storage API is indeed somewhat "parallel" / "asynchronous". After the call to In this particular unit test, I am using an estimated time of 20ms for this provider to complete the storage operations, which is of course fragile - it definitely depends on the storage provider, here memory storage which was always fast on my machine. Regular application code should never make such such timing assumptions. Rather, to ensure that all pending event storage operations have completed, call By the way, all the included log consistency providers are reentrancy-safe: adding the [Reentrant] attribute on a JournaledGrain does not cause dangerous race conditions on storage. The provider ensures only one storage operation is pending at all times, and it batches multiple such operations together to improve performance. |
Yes I'm using that. Hence why I'm seeing the full events in the storage. Regarding the projections, imagine a scenario that you have a long series of events. Whenever one event happen you publish to a stream so you can generate a projection in another grain. Later on, you introduce a new grain type that will represent a new kind of projection. That will require you to replay all the events from begining and process them on this new grain type to generate the new projection. That is something really common and one of the benefits of ES. To be able to leverage the application event history even on new systems. So, I think you should expose the list of commited events so you can based on that generate projections anytime (e.g. when someone call a grain method publish each one of the events a new stream). It is important that we can get all, or a filtered list of events, for exemple, "starting on version x and stop on y". |
Ok, I think I see the point. One way to support this scenario elegantly is to let several grains share the same event log. This is not yet supported (right now, each grain uses its own log), but it may be a good feature to add. I believe @jkonecki also proposed this feature, we have a prototype that does this for a specialized class of providers based on event storage. Also, we can add support for log retrieval to the API, like you say. However, as mentioned earlier, log retrieval may not behave uniformly for all providers. It would be helpful to have a clearer idea on what kind of storage back-end people would like to use in conjunction with this feature. We need to formulate an event storage API that works across a variety of such storage options. |
That would be good, but I think will introduce a lot of complexity for now. I think projections are totally unrelated to the source of the events which in this case is the Regarding the backends, I think we should provide a common interface to just read and write events to a store. The way it is persisted, is totally out from the |
Hey @sebastianburckhardt do you think that will be too long before more complete docs are around or an ES API is in place? |
not too long. I will resume work on this later this week, and hope to make some progress by next week. The Event Sourcing is likely to keep developing over a period of time, also based on feedback. Note that the plan is to have two separate APIs; the programming API inside the grain, and the event-store API. What's there so far is the programming API for use inside grains. Based on our discussion, I will add a function for accessing events in the log. This is a minor addition that can go into a small PR. Adding the event store API is the big next step. We already have a prototype for this written by @jkonecki but I need to update it slightly to fit together with the rest of the story. This prototype works with GetEventStore, but the API is meant to be more general. I will create a PR for this with the work-in-progress flag. |
Ok thanks, that sounds good. Looking forward for it. Thanks |
As I am writing the docs I get the strong impression most of the time, users should work with the confirmed state, not the tentative state. Unless anyone has strong objections, I will change the default names so "State" refers to the confirmed state, not the tentative one, while "TentativeState" can still be used to access the tentative state. |
I agree @sebastianburckhardt I think that is the way the state is named on Reliable collections APIs on SF as well. Makes it clear. |
@sebastianburckhardt that sounds good to me. |
First of all, thank you @sebastianburckhardt for the great work!
After #1854 got merged I tried play with it but was unable to get it to work. I was unable to find among the tons of tests what are the files related to
OrleansEventSourcing
project. The configuration and requirements is what is hardest to find.I would suggest a simple page with the minimum required configuration to get it to work.
Also, would be good if that project has its own test project. I can do it myself if you point out what exactly is related to this project inside the test projects.
Thank you Sebastian! :)
The text was updated successfully, but these errors were encountered: