public Fetcher(IDocumentStore store, DaemonSettings settings, AsyncOptions options, IDaemonLogger logger, IDaemonErrorHandler errorHandler, IEnumerable <Type> eventTypes) { _settings = settings; _options = options; _logger = logger; _errorHandler = errorHandler; State = FetcherState.Waiting; // TODO -- this will have to change _tenant = store.Tenancy.Default; _streamIdentity = store.Events.StreamIdentity; _selector = _tenant.EventStorage(); EventTypeNames = eventTypes.Select(x => store.Events.EventMappingFor(x).Alias).ToArray(); var fields = _selector.SelectFields().Join(", "); _sql = $@" select seq_id from {_selector.Events.DatabaseSchemaName}.mt_events where seq_id > :last and seq_id <= :limit and extract(epoch from age(transaction_timestamp(), {_selector.Events.DatabaseSchemaName}.mt_events.timestamp)) >= :buffer order by seq_id; select {fields} from {_selector.Events.DatabaseSchemaName}.mt_events where seq_id > :last and seq_id <= :limit and type = ANY(:types) and extract(epoch from age(transaction_timestamp(), {_selector.Events.DatabaseSchemaName}.mt_events.timestamp)) >= :buffer order by seq_id; select min(seq_id) from {_selector.Events.DatabaseSchemaName}.mt_events where seq_id > :limit and type = ANY(:types) and extract(epoch from age(transaction_timestamp(), {_selector.Events.DatabaseSchemaName}.mt_events.timestamp)) >= :buffer; select max(seq_id) from {_selector.Events.DatabaseSchemaName}.mt_events where seq_id >= :limit and extract(epoch from age(transaction_timestamp(), {_selector.Events.DatabaseSchemaName}.mt_events.timestamp)) >= :buffer ".Replace(" as d", ""); }
public async Task smoke_test_able_to_fetch_a_page_of_events() { var list = new List<MembersJoined>(); for (int i = 0; i < 500; i++) { list.Add(new MembersJoined {Day = i, Location = Guid.NewGuid().ToString(), Members = new string[] {Guid.NewGuid().ToString()}}); } using (var session = theStore.LightweightSession()) { session.Events.Append(Guid.NewGuid(), list.ToArray()); await session.SaveChangesAsync().ConfigureAwait(false); } var options = new AsyncOptions(); var settings = new DaemonSettings { LeadingEdgeBuffer = 0.Seconds() }; using (var data = new Fetcher(theStore, settings, options, Substitute.For<IDaemonLogger>(), new StubErrorHandler(), new Type[] {typeof(MembersJoined)})) { var page = await data.FetchNextPage(0).ConfigureAwait(false); page.From.ShouldBe(0); page.To.ShouldBe(options.PageSize); page.Streams.SelectMany(x => x.Events).Count().ShouldBe(100); } }
public Fetcher(IDocumentStore store, DaemonSettings settings, AsyncOptions options, IDaemonLogger logger, IDaemonErrorHandler errorHandler, IEnumerable <Type> eventTypes) { _settings = settings; _options = options; _logger = logger; _errorHandler = errorHandler; State = FetcherState.Waiting; // TODO -- this will have to change _tenant = store.Tenancy.Default; _streamIdentity = store.Events.StreamIdentity; _selector = store.Events.StreamIdentity == StreamIdentity.AsGuid ? (IEventSelector) new EventSelector(store.Events, store.Advanced.Serializer) : new StringIdentifiedEventSelector(store.Events, store.Advanced.Serializer); _map = new NulloIdentityMap(store.Advanced.Serializer); EventTypeNames = eventTypes.Select(x => store.Events.EventMappingFor(x).Alias).ToArray(); _sql = $@" select seq_id from {_selector.Events.DatabaseSchemaName}.mt_events where seq_id > :last and seq_id <= :limit and age(transaction_timestamp(), {_selector.Events.DatabaseSchemaName}.mt_events.timestamp) >= :buffer order by seq_id; {_selector.ToSelectClause(null)} where seq_id > :last and seq_id <= :limit and type = ANY(:types) and age(transaction_timestamp(), {_selector.Events.DatabaseSchemaName}.mt_events.timestamp) >= :buffer order by seq_id; select min(seq_id) from {_selector.Events.DatabaseSchemaName}.mt_events where seq_id > :limit and type = ANY(:types) and age(transaction_timestamp(), {_selector.Events.DatabaseSchemaName}.mt_events.timestamp) >= :buffer; select max(seq_id) from {_selector.Events.DatabaseSchemaName}.mt_events where seq_id >= :limit and age(transaction_timestamp(), {_selector.Events.DatabaseSchemaName}.mt_events.timestamp) >= :buffer ".Replace(" as d", ""); }
public Fetcher(IDocumentStore store, DaemonSettings settings, AsyncOptions options, IDaemonLogger logger, IDaemonErrorHandler errorHandler, IEnumerable <Type> eventTypes) { _settings = settings; _options = options; _logger = logger; _errorHandler = errorHandler; State = FetcherState.Waiting; _connectionFactory = store.Advanced.Options.ConnectionFactory(); _selector = new EventSelector(store.Schema.Events, store.Advanced.Serializer); _map = new NulloIdentityMap(store.Advanced.Serializer); EventTypeNames = eventTypes.Select(x => store.Schema.Events.EventMappingFor(x).Alias).ToArray(); }
public Fetcher(IDocumentStore store, DaemonSettings settings, AsyncOptions options, IDaemonLogger logger, IDaemonErrorHandler errorHandler, IEnumerable<Type> eventTypes) { _settings = settings; _options = options; _logger = logger; _errorHandler = errorHandler; State = FetcherState.Waiting; _connectionFactory = store.Advanced.Options.ConnectionFactory(); _selector = new EventSelector(store.Schema.Events, store.Advanced.Serializer); _map = new NulloIdentityMap(store.Advanced.Serializer); EventTypeNames = eventTypes.Select(x => store.Schema.Events.EventMappingFor(x).Alias).ToArray(); }
public Daemon(DocumentStore store, ITenant tenant, DaemonSettings settings, IDaemonLogger logger, IEnumerable <IProjection> projections) { _store = store; _tenant = tenant; Logger = logger; _errorHandler = new DaemonErrorHandler(this, logger, settings.ExceptionHandling); foreach (var projection in projections) { if (projection == null) { throw new ArgumentOutOfRangeException(nameof(projection), $"No projection is configured"); } var fetcher = new Fetcher(store, settings, projection, logger, _errorHandler); var track = new ProjectionTrack(fetcher, store, projection, logger, _errorHandler, tenant); _tracks.Add(projection.ProjectedType(), track); } }
public Daemon(IDocumentStore store, DaemonSettings settings, IDaemonLogger logger, IEnumerable <IProjection> projections) { _store = store; Logger = logger; _errorHandler = new DaemonErrorHandler(this, logger, settings.ExceptionHandling); foreach (var projection in projections) { if (projection == null) { throw new ArgumentOutOfRangeException(nameof(projection), $"No projection is configured for view type {projection.Produces.FullName}"); } var fetcher = new Fetcher(store, settings, projection, logger, _errorHandler); var track = new ProjectionTrack(fetcher, store, projection, logger, _errorHandler); _tracks.Add(projection.Produces, track); } }
public async Task filters_by_event_type_name() { using (var session = theStore.OpenSession()) { for (int i = 0; i < 20; i++) { var joined = new MembersJoined { Day = i, Location = Guid.NewGuid().ToString(), Members = new string[] { Guid.NewGuid().ToString() } }; var departed = new MembersDeparted { Day = i, Location = Guid.NewGuid().ToString(), Members = new[] { Guid.NewGuid().ToString() } }; var reached = new ArrivedAtLocation { Day = i, Location = Guid.NewGuid().ToString() }; session.Events.Append(Guid.NewGuid(), joined, departed, reached); } await session.SaveChangesAsync().ConfigureAwait(false); } var settings = new DaemonSettings { LeadingEdgeBuffer = 0.Seconds() }; using (var data = new Fetcher(theStore, settings, new AsyncOptions(), Substitute.For<IDaemonLogger>(), new StubErrorHandler(), new Type[] {typeof(MembersDeparted), typeof(ArrivedAtLocation)})) { var page = await data.FetchNextPage(0).ConfigureAwait(false); var all = page.Streams.SelectMany(x => x.Events).ToArray(); all.OfType<Event<MembersJoined>>().Any().ShouldBeFalse(); all.OfType<Event<MembersDeparted>>().Any().ShouldBeTrue(); all.OfType<Event<ArrivedAtLocation>>().Any().ShouldBeTrue(); } }
public Fetcher(IDocumentStore store, DaemonSettings settings, IProjection projection, IDaemonLogger logger, IDaemonErrorHandler errorHandler) : this(store, settings, projection.AsyncOptions, logger, errorHandler, projection.Consumes) { }
public async Task correctly_correlates_by_stream() { var streams = new List<EventStream>(); var logger = new RecordingLogger(); using (var session = theStore.LightweightSession()) { session.Logger = logger; for (int i = 0; i < 20; i++) { var joined = new MembersJoined { Day = i, Location = Guid.NewGuid().ToString(), Members = new string[] { Guid.NewGuid().ToString() } }; var departed = new MembersDeparted { Day = i, Location = Guid.NewGuid().ToString(), Members = new[] { Guid.NewGuid().ToString() } }; var reached = new ArrivedAtLocation { Day = i, Location = Guid.NewGuid().ToString() }; session.Events.Append(Guid.NewGuid(), joined, departed, reached); } await session.SaveChangesAsync().ConfigureAwait(false); streams.AddRange(logger.LastCommit.GetStreams()); } var types = new Type[] { typeof(MembersJoined), typeof(MembersDeparted), typeof(ArrivedAtLocation) }; var settings = new DaemonSettings { LeadingEdgeBuffer = 0.Seconds() }; using (var data = new Fetcher(theStore, settings, new AsyncOptions(), Substitute.For<IDaemonLogger>(), new StubErrorHandler(), types)) { var page = await data.FetchNextPage(0).ConfigureAwait(false); foreach (var stream in page.Streams) { var existing = streams.Single(x => x.Id == stream.Id); existing.Events.Select(x => x.Id) .ShouldHaveTheSameElementsAs(stream.Events.Select(x => x.Id)); } } }
public async Task able_to_page_events() { var list = new List<MembersJoined>(); for (int i = 0; i < 500; i++) { list.Add(new MembersJoined { Day = i, Location = Guid.NewGuid().ToString(), Members = new string[] { Guid.NewGuid().ToString() } }); } using (var session = theStore.LightweightSession()) { session.Events.Append(Guid.NewGuid(), list.ToArray()); await session.SaveChangesAsync().ConfigureAwait(false); } var types = new Type[] {typeof(MembersJoined)}; var settings = new DaemonSettings { LeadingEdgeBuffer = 0.Seconds() }; using (var data = new Fetcher(theStore, settings, new AsyncOptions(), Substitute.For<IDaemonLogger>(), new StubErrorHandler(), types)) { var events1 = (await data.FetchNextPage(0).ConfigureAwait(false)).Streams.SelectMany(x => x.Events).ToArray(); var events2 = (await data.FetchNextPage(100).ConfigureAwait(false)).Streams.SelectMany(x => x.Events).ToArray(); var events3 = (await data.FetchNextPage(200).ConfigureAwait(false)).Streams.SelectMany(x => x.Events).ToArray(); events1.Intersect(events2).Any().ShouldBeFalse(); events1.Intersect(events3).Any().ShouldBeFalse(); events3.Intersect(events2).Any().ShouldBeFalse(); events1.Length.ShouldBe(100); events2.Length.ShouldBe(100); events3.Length.ShouldBe(100); } }
public Fetcher(IDocumentStore store, DaemonSettings settings, IProjection projection, IDaemonLogger logger, IDaemonErrorHandler errorHandler) : this(store, settings, projection.AsyncOptions, logger, errorHandler, projection.Consumes) { }