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.Linq;
11 : using Cqrs.Domain;
12 :
13 : namespace Cqrs.Snapshots
14 : {
15 : /// <summary>
16 : /// An <see cref="ISnapshotStrategy{TAuthenticationToken}"/> that takes a snapshot every 15 versions.
17 : /// </summary>
18 : /// <typeparam name="TAuthenticationToken">The <see cref="Type"/> of the authentication token.</typeparam>
19 : public class DefaultSnapshotStrategy<TAuthenticationToken> : ISnapshotStrategy<TAuthenticationToken>
20 1 : {
21 : private const int SnapshotInterval = 15;
22 :
23 : /// <summary>
24 : /// Indicates if the <paramref name="aggregateType"/> is able to be snapshotted by checking if the <paramref name="aggregateType"/>
25 : /// directly inherits <see cref="SnapshotAggregateRoot{TAuthenticationToken,TSnapshot}"/>
26 : /// </summary>
27 : /// <param name="aggregateType">The <see cref="Type"/> of <see cref="IAggregateRoot{TAuthenticationToken}"/> to check.</param>
28 1 : public virtual bool IsSnapshotable(Type aggregateType)
29 : {
30 : if (aggregateType.BaseType == null)
31 : return false;
32 : if (aggregateType.BaseType.IsGenericType && aggregateType.BaseType.GetGenericTypeDefinition() == typeof(SnapshotAggregateRoot<,>))
33 : return true;
34 : return IsSnapshotable(aggregateType.BaseType);
35 : }
36 :
37 : /// <summary>
38 : /// Checks <see cref="IsSnapshotable"/> and if it is, also checks if the calculated version number would be exactly dividable by <see cref="GetSnapshotInterval"/>.
39 : /// </summary>
40 : /// <param name="aggregate">The <see cref="IAggregateRoot{TAuthenticationToken}"/> to check.</param>
41 1 : public virtual bool ShouldMakeSnapShot(IAggregateRoot<TAuthenticationToken> aggregate)
42 : {
43 : if (!IsSnapshotable(aggregate.GetType()))
44 : return false;
45 :
46 : // Why isn't this something as simple as `(aggregate.Version + aggregate.GetUncommittedChanges().Count()) % SnapshotInterval`???
47 : int i = aggregate.Version;
48 :
49 : int limit = aggregate.GetUncommittedChanges().Count();
50 : for (int j = 0; j < limit; j++)
51 : if (++i % GetSnapshotInterval() == 0 && i != 0)
52 : return true;
53 : return false;
54 : }
55 :
56 : /// <summary>
57 : /// Returns the value of <see cref="SnapshotInterval"/>.
58 : /// </summary>
59 1 : protected virtual int GetSnapshotInterval()
60 : {
61 : return SnapshotInterval;
62 : }
63 : }
64 : }
|