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
EventStore repository to allow connection factory to be passed #107
Conversation
…y instead of connection objectct to allow more flexibility with regards to how connection object is resolved. (e.g. to allow connection polling, reconnection and more monitoring)
|
||
if (connection == null) | ||
{ | ||
throw new RepositoryUnavailableException("Couldn't connect to the EvenStore repository. See InnerException for details", new ArgumentNullException(nameof(connection))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ArgumentNullException
is not appropriate here - connection
is a result, not an argument.
InvalidOperationException
maybe, or do not passing anything as InnerException if there is no exception
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Valid point
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed InnerException at all
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is a problem with connection lifecycle.
Connection is created by calling the factory in the EventstoreRepository
, but the connection is never disposed of explicitly.
I propose to pass factory into EventStoreSession
, create new instance of the connection in the EventStoreSession
constructor, and dispose the connection in the session's Dispose
:
public class EventStoreSession<TState> : BaseEventSourcedSession<TState, int>
{
...
public EventStoreSession(IHoldAllConfiguration configuration,
Func<IEventStoreConnection> eventStoreConnectionFactory,
string streamName)
: base(configuration)
{
this.eventStoreConnection = eventStoreConnectionFactory(); // check for null factory before that, move error handling from repository here
this.streamName = streamName ?? throw new ArgumentNullException(nameof(streamName));
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
ConsiderSessionDisposed();
eventStoreConnection.Dispose();
}
base.Dispose(disposing);
}
}
@iblazhko , thanks for the spot Ivan, I have addressed your comment |
throw new StreamNotFoundException(id.ToString()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw
at L40 will leave the connection open.
|
||
return session; | ||
} | ||
|
||
public async Task<bool> Contains(TId selector) | ||
private void CleanupConnection(IEventStoreConnection connection) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This cleanup function could potentially be shared between EventStoreRepository and EventStoreSession
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iblazhko & @ninjaboy I am a bit worried about this API as it is now. The reason is that DI frameworks like Autofac will emit a Func for you even if you register a connection as single instance (see https://autofaccn.readthedocs.io/en/latest/advanced/delegate-factories.html). In this case if an instance is disposed, then any subsequent calls to the factory method will return a disposed version of the connection.
What I think would be best is to implement a factory of our own that explicitly manages instantiation of the connection and its lifetime.
@skleanthous , Shall explore the following approach then:
|
@ninjaboy Something like |
@skleanthous , However, looking at the interface that repository currently implements I won't be able to pass arbitrary parameters to the session. Because I have to stick to:
|
I must say that I am really confused so far with how the issue needs to be resolved. Any suggestion on how we shall handle the problem with connection object going into the Disposed state are welcome. |
https://groups.google.com/forum/#!topic/event-store/nkgzXpy56NQ |
BTW, I tried |
Will be done in a future release |
This change introduces connection factory method as a dependency to the EventStore repository instead of connection object to allow more flexibility with regards to how connection object is resolved. (e.g. to allow connection polling, re-connection and monitoring)
Work done
Changed
EventStoreRepository
constructor frompublic EventStoreRepository(IHoldAllConfiguration configs, IEventStoreConnection connection)
to
public EventStoreRepository(IHoldAllConfiguration configs, Func<IEventStoreConnection> connectionFactory)
EventStoreRepository
as the method to create new session was changedIntegrity