Line data Source code
1 : #region Copyright
2 : // // -----------------------------------------------------------------------
3 : // // <copyright company="Chinchilla Software Limited">
4 : // // Copyright Chinchilla Software Limited. All rights reserved.
5 : // // </copyright>
6 : // // -----------------------------------------------------------------------
7 : #endregion
8 :
9 : using System;
10 : using System.Collections.Generic;
11 : using System.Linq;
12 : using cdmdotnet.Logging;
13 : using Cqrs.Domain;
14 : using Cqrs.Messages;
15 :
16 : namespace Cqrs.Events
17 : {
18 : /// <summary>
19 : /// Stores instances of <see cref="IEvent{TAuthenticationToken}"/> for replay, <see cref="IAggregateRoot{TAuthenticationToken}"/> and <see cref="ISaga{TAuthenticationToken}"/> rehydration.
20 : /// </summary>
21 : /// <typeparam name="TAuthenticationToken">The <see cref="Type"/> of the authentication token.</typeparam>
22 : public abstract class EventStore<TAuthenticationToken>
23 : : IEventStore<TAuthenticationToken>
24 1 : {
25 : /// <summary>
26 : /// The pattern used to generate the stream name.
27 : /// </summary>
28 : protected const string CqrsEventStoreStreamNamePattern = "{0}/{1}";
29 :
30 : /// <summary>
31 : /// The <see cref="IEventBuilder{TAuthenticationToken}"/> used to build events.
32 : /// </summary>
33 : protected IEventBuilder<TAuthenticationToken> EventBuilder { get; set; }
34 :
35 : /// <summary>
36 : /// The <see cref="IEventDeserialiser{TAuthenticationToken}"/> used to deserialise events.
37 : /// </summary>
38 : protected IEventDeserialiser<TAuthenticationToken> EventDeserialiser { get; set; }
39 :
40 : /// <summary>
41 : /// The <see cref="ITelemetryHelper"/> to use.
42 : /// </summary>
43 : protected ITelemetryHelper TelemetryHelper { get; set; }
44 :
45 : /// <summary>
46 : /// The <see cref="ILogger"/> to use.
47 : /// </summary>
48 : protected ILogger Logger { get; private set; }
49 :
50 : /// <summary>
51 : /// Instantiates a new instance of <see cref="EventStore{TAuthenticationToken}"/>.
52 : /// </summary>
53 1 : protected EventStore(IEventBuilder<TAuthenticationToken> eventBuilder, IEventDeserialiser<TAuthenticationToken> eventDeserialiser, ILogger logger)
54 : {
55 : EventBuilder = eventBuilder;
56 : EventDeserialiser = eventDeserialiser;
57 : Logger = logger;
58 : TelemetryHelper = new NullTelemetryHelper();
59 : }
60 :
61 : /// <summary>
62 : /// Saves the provided <paramref name="event"/>.
63 : /// </summary>
64 : /// <typeparam name="T">The <see cref="Type"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/> the <see cref="IEvent{TAuthenticationToken}"/> was raised in.</typeparam>
65 : /// <param name="event">The <see cref="IEvent{TAuthenticationToken}"/> to be saved.</param>
66 1 : public virtual void Save<T>(IEvent<TAuthenticationToken> @event)
67 : {
68 : Save(typeof(T), @event);
69 : }
70 :
71 : /// <summary>
72 : /// Generate a unique stream name based on the provided <paramref name="aggregateRootType"/> and the <see cref="IEvent{TAuthenticationToken}.Id"/> from the provided <paramref name="event"/>.
73 : /// </summary>
74 : /// <param name="aggregateRootType">The <see cref="Type"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/>.</param>
75 : /// <param name="event">The <see cref="IEvent{TAuthenticationToken}"/> to extract information from.</param>
76 1 : protected virtual string GenerateStreamName(Type aggregateRootType, IEvent<TAuthenticationToken> @event)
77 : {
78 : return GenerateStreamName(aggregateRootType, @event.GetIdentity());
79 : }
80 :
81 : /// <summary>
82 : /// Generate a unique stream name based on the provided <paramref name="aggregateRootType"/> and the <paramref name="aggregateId"/>.
83 : /// </summary>
84 : /// <param name="aggregateRootType">The <see cref="Type"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/>.</param>
85 : /// <param name="aggregateId">The ID of the <see cref="IAggregateRoot{TAuthenticationToken}"/>.</param>
86 1 : protected virtual string GenerateStreamName(Type aggregateRootType, Guid aggregateId)
87 : {
88 : return string.Format(CqrsEventStoreStreamNamePattern, aggregateRootType.FullName, aggregateId);
89 : }
90 :
91 : /// <summary>
92 : /// Saves the provided <paramref name="event"/>.
93 : /// </summary>
94 : /// <param name="aggregateRootType"> <see cref="Type"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/> the <see cref="IEvent{TAuthenticationToken}"/> was raised in.</param>
95 : /// <param name="event">The <see cref="IEvent{TAuthenticationToken}"/> to be saved.</param>
96 1 : public virtual void Save(Type aggregateRootType, IEvent<TAuthenticationToken> @event)
97 : {
98 : Logger.LogDebug(string.Format("Saving aggregate root event type '{0}'", @event.GetType().FullName), string.Format("{0}\\Save", GetType().Name));
99 : EventData eventData = EventBuilder.CreateFrameworkEvent(@event);
100 : string streamName = GenerateStreamName(aggregateRootType, @event);
101 : eventData.AggregateId = streamName;
102 : eventData.AggregateRsn = @event.GetIdentity();
103 : eventData.Version = @event.Version;
104 : eventData.CorrelationId = @event.CorrelationId;
105 : PersistEvent(eventData);
106 : Logger.LogInfo(string.Format("Saving aggregate root event type '{0}'... done", @event.GetType().FullName), string.Format("{0}\\Save", GetType().Name));
107 : TelemetryHelper.TrackMetric(string.Format("Cqrs/EventStore/Save/{0}", streamName), 1);
108 : }
109 :
110 : /// <summary>
111 : /// Gets a collection of <see cref="IEvent{TAuthenticationToken}"/> for the <typeparamref name="T">aggregate root</typeparamref> with the ID matching the provided <paramref name="aggregateId"/>.
112 : /// </summary>
113 : /// <typeparam name="T">The <see cref="Type"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/> the <see cref="IEvent{TAuthenticationToken}"/> was raised in.</typeparam>
114 : /// <param name="aggregateId">The <see cref="IAggregateRoot{TAuthenticationToken}.Id"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/>.</param>
115 : /// <param name="useLastEventOnly">Loads only the last event<see cref="IEvent{TAuthenticationToken}"/>.</param>
116 : /// <param name="fromVersion">Load events starting from this version</param>
117 1 : public virtual IEnumerable<IEvent<TAuthenticationToken>> Get<T>(Guid aggregateId, bool useLastEventOnly = false, int fromVersion = -1)
118 : {
119 : IEnumerable<IEvent<TAuthenticationToken>> results = Get(typeof (T), aggregateId, useLastEventOnly, fromVersion).ToList();
120 : TelemetryHelper.TrackMetric(string.Format("Cqrs/EventStore/Get/{0}", GenerateStreamName(typeof(T), aggregateId)), results.Count());
121 :
122 : return results;
123 : }
124 :
125 : /// <summary>
126 : /// Gets a collection of <see cref="IEvent{TAuthenticationToken}"/> for the <see cref="IAggregateRoot{TAuthenticationToken}"/> of type <paramref name="aggregateRootType"/> with the ID matching the provided <paramref name="aggregateId"/>.
127 : /// </summary>
128 : /// <param name="aggregateRootType"> <see cref="Type"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/> the <see cref="IEvent{TAuthenticationToken}"/> was raised in.</param>
129 : /// <param name="aggregateId">The <see cref="IAggregateRoot{TAuthenticationToken}.Id"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/>.</param>
130 : /// <param name="useLastEventOnly">Loads only the last event<see cref="IEvent{TAuthenticationToken}"/>.</param>
131 : /// <param name="fromVersion">Load events starting from this version</param>
132 1 : public abstract IEnumerable<IEvent<TAuthenticationToken>> Get(Type aggregateRootType, Guid aggregateId, bool useLastEventOnly = false, int fromVersion = -1);
133 :
134 : /// <summary>
135 : /// Gets a collection of <see cref="IEvent{TAuthenticationToken}"/> for the <see cref="IAggregateRoot{TAuthenticationToken}"/> of type <paramref name="aggregateRootType"/> with the ID matching the provided <paramref name="aggregateId"/> up to and including the provided <paramref name="version"/>.
136 : /// </summary>
137 : /// <param name="aggregateRootType"> <see cref="Type"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/> the <see cref="IEvent{TAuthenticationToken}"/> was raised in.</param>
138 : /// <param name="aggregateId">The <see cref="IAggregateRoot{TAuthenticationToken}.Id"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/>.</param>
139 : /// <param name="version">Load events up-to and including from this version</param>
140 1 : public abstract IEnumerable<IEvent<TAuthenticationToken>> GetToVersion(Type aggregateRootType, Guid aggregateId, int version);
141 :
142 : /// <summary>
143 : /// Gets a collection of <see cref="IEvent{TAuthenticationToken}"/> for the <typeparamref name="T">aggregate root</typeparamref> with the ID matching the provided <paramref name="aggregateId"/> up to and including the provided <paramref name="version"/>.
144 : /// </summary>
145 : /// <typeparam name="T">The <see cref="Type"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/> the <see cref="IEvent{TAuthenticationToken}"/> was raised in.</typeparam>
146 : /// <param name="aggregateId">The <see cref="IAggregateRoot{TAuthenticationToken}.Id"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/>.</param>
147 : /// <param name="version">Load events up-to and including from this version</param>
148 1 : public virtual IEnumerable<IEvent<TAuthenticationToken>> GetToVersion<T>(Guid aggregateId, int version)
149 : {
150 : IEnumerable<IEvent<TAuthenticationToken>> results = GetToVersion(typeof(T), aggregateId, version).ToList();
151 : TelemetryHelper.TrackMetric(string.Format("Cqrs/EventStore/GetToVersion/{0}", GenerateStreamName(typeof(T), aggregateId)), results.Count());
152 :
153 : return results;
154 : }
155 :
156 : /// <summary>
157 : /// Gets a collection of <see cref="IEvent{TAuthenticationToken}"/> for the <see cref="IAggregateRoot{TAuthenticationToken}"/> of type <paramref name="aggregateRootType"/> with the ID matching the provided <paramref name="aggregateId"/> up to and including the provided <paramref name="versionedDate"/>.
158 : /// </summary>
159 : /// <param name="aggregateRootType"> <see cref="Type"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/> the <see cref="IEvent{TAuthenticationToken}"/> was raised in.</param>
160 : /// <param name="aggregateId">The <see cref="IAggregateRoot{TAuthenticationToken}.Id"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/>.</param>
161 : /// <param name="versionedDate">Load events up-to and including from this <see cref="DateTime"/></param>
162 1 : public abstract IEnumerable<IEvent<TAuthenticationToken>> GetToDate(Type aggregateRootType, Guid aggregateId, DateTime versionedDate);
163 :
164 : /// <summary>
165 : /// Gets a collection of <see cref="IEvent{TAuthenticationToken}"/> for the <typeparamref name="T">aggregate root</typeparamref> with the ID matching the provided <paramref name="aggregateId"/> up to and including the provided <paramref name="versionedDate"/>.
166 : /// </summary>
167 : /// <typeparam name="T">The <see cref="Type"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/> the <see cref="IEvent{TAuthenticationToken}"/> was raised in.</typeparam>
168 : /// <param name="aggregateId">The <see cref="IAggregateRoot{TAuthenticationToken}.Id"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/>.</param>
169 : /// <param name="versionedDate">Load events up-to and including from this <see cref="DateTime"/></param>
170 1 : public virtual IEnumerable<IEvent<TAuthenticationToken>> GetToDate<T>(Guid aggregateId, DateTime versionedDate)
171 : {
172 : IEnumerable<IEvent<TAuthenticationToken>> results = GetToDate(typeof(T), aggregateId, versionedDate).ToList();
173 : TelemetryHelper.TrackMetric(string.Format("Cqrs/EventStore/GetToDate/{0}", GenerateStreamName(typeof(T), aggregateId)), results.Count());
174 :
175 : return results;
176 : }
177 :
178 : /// <summary>
179 : /// Gets a collection of <see cref="IEvent{TAuthenticationToken}"/> for the <see cref="IAggregateRoot{TAuthenticationToken}"/> of type <paramref name="aggregateRootType"/> with the ID matching the provided <paramref name="aggregateId"/> from and including the provided <paramref name="fromVersionedDate"/> up to and including the provided <paramref name="toVersionedDate"/>.
180 : /// </summary>
181 : /// <param name="aggregateRootType"> <see cref="Type"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/> the <see cref="IEvent{TAuthenticationToken}"/> was raised in.</param>
182 : /// <param name="aggregateId">The <see cref="IAggregateRoot{TAuthenticationToken}.Id"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/>.</param>
183 : /// <param name="fromVersionedDate">Load events from and including from this <see cref="DateTime"/></param>
184 : /// <param name="toVersionedDate">Load events up-to and including from this <see cref="DateTime"/></param>
185 1 : public abstract IEnumerable<IEvent<TAuthenticationToken>> GetBetweenDates(Type aggregateRootType, Guid aggregateId, DateTime fromVersionedDate, DateTime toVersionedDate);
186 :
187 : /// <summary>
188 : /// Gets a collection of <see cref="IEvent{TAuthenticationToken}"/> for the <typeparamref name="T">aggregate root</typeparamref> with the ID matching the provided <paramref name="aggregateId"/> from and including the provided <paramref name="fromVersionedDate"/> up to and including the provided <paramref name="toVersionedDate"/>.
189 : /// </summary>
190 : /// <typeparam name="T">The <see cref="Type"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/> the <see cref="IEvent{TAuthenticationToken}"/> was raised in.</typeparam>
191 : /// <param name="aggregateId">The <see cref="IAggregateRoot{TAuthenticationToken}.Id"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/>.</param>
192 : /// <param name="fromVersionedDate">Load events from and including from this <see cref="DateTime"/></param>
193 : /// <param name="toVersionedDate">Load events up-to and including from this <see cref="DateTime"/></param>
194 1 : public virtual IEnumerable<IEvent<TAuthenticationToken>> GetBetweenDates<T>(Guid aggregateId, DateTime fromVersionedDate, DateTime toVersionedDate)
195 : {
196 : IEnumerable<IEvent<TAuthenticationToken>> results = GetBetweenDates(typeof(T), aggregateId, fromVersionedDate, toVersionedDate).ToList();
197 : TelemetryHelper.TrackMetric(string.Format("Cqrs/EventStore/GetBetweenDates/{0}", GenerateStreamName(typeof(T), aggregateId)), results.Count());
198 :
199 : return results;
200 : }
201 :
202 : /// <summary>
203 : /// Get all <see cref="IEvent{TAuthenticationToken}"/> instances for the given <paramref name="correlationId"/>.
204 : /// </summary>
205 : /// <param name="correlationId">The <see cref="IMessage.CorrelationId"/> of the <see cref="IEvent{TAuthenticationToken}"/> instances to retrieve.</param>
206 1 : public abstract IEnumerable<EventData> Get(Guid correlationId);
207 :
208 : /// <summary>
209 : /// Persist the provided <paramref name="eventData"/> into storage.
210 : /// </summary>
211 : /// <param name="eventData">The <see cref="EventData"/> to persist.</param>
212 1 : protected abstract void PersistEvent(EventData eventData);
213 : }
214 : }
|