Documentation Coverage Report
Current view: top level - Azure/Cqrs.Azure.BlobStorage - StorageStore.cs Hit Total Coverage
Version: 2.2 Artefacts: 18 18 100.0 %
Date: 2017-09-22

          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;
      11             : using System.Collections.Generic;
      12             : using System.IO;
      13             : using System.Linq;
      14             : using System.Linq.Expressions;
      15             : using System.Text;
      16             : using cdmdotnet.Logging;
      17             : using Cqrs.Entities;
      18             : using Cqrs.Events;
      19             : using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
      20             : using Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling;
      21             : using Microsoft.Practices.TransientFaultHandling;
      22             : using Microsoft.WindowsAzure.Storage;
      23             : using Newtonsoft.Json;
      24             : 
      25             : namespace Cqrs.Azure.BlobStorage
      26             : {
      27             :         /// <summary>
      28             :         /// A <see cref="IEnumerable{TData}"/> that uses Azure Storage for storage.
      29             :         /// </summary>
      30             :         public abstract class StorageStore<TData, TSource>
      31             :                 : IEnumerable<TData>
      32           1 :         {
      33             :                 /// <summary>
      34             :                 /// Gets the collection of writeable <see cref="CloudStorageAccount"/>.
      35             :                 /// </summary>
      36             :                 protected IList<Tuple<CloudStorageAccount, TSource>> WritableCollection { get; private set; }
      37             : 
      38             :                 /// <summary>
      39             :                 /// Gets the readable <see cref="CloudStorageAccount"/>.
      40             :                 /// </summary>
      41             :                 protected CloudStorageAccount ReadableStorageAccount { get; private set; }
      42             : 
      43             :                 /// <summary>
      44             :                 /// Gets the readable <typeparamref name="TSource"/>.
      45             :                 /// </summary>
      46             :                 internal TSource ReadableSource { get; private set; }
      47             : 
      48             :                 /// <summary>
      49             :                 /// Gets the <see cref="ILogger"/>.
      50             :                 /// </summary>
      51             :                 protected ILogger Logger { get; private set; }
      52             : 
      53             :                 /// <summary>
      54             :                 /// Gets or sets the <see cref="Func{Tstring}"/> that returns the name of the container.
      55             :                 /// </summary>
      56             :                 protected Func<string> GetContainerName { get; set; }
      57             : 
      58             :                 /// <summary>
      59             :                 /// Gets or sets the <see cref="Func{Tstring}"/> that returns if the container is public or not.
      60             :                 /// </summary>
      61             :                 protected Func<bool> IsContainerPublic { get; set; }
      62             : 
      63             :                 /// <summary>
      64             :                 /// Initializes a new instance of the <see cref="StorageStore{TData,TSource}"/> class using the specified container.
      65             :                 /// </summary>
      66           1 :                 protected StorageStore(ILogger logger)
      67             :                 {
      68             :                         Logger = logger;
      69             :                 }
      70             : 
      71             :                 /// <summary>
      72             :                 /// The default <see cref="JsonSerializerSettings"/> to use.
      73             :                 /// </summary>
      74             :                 public static JsonSerializerSettings DefaultSettings { get; private set; }
      75             : 
      76             :                 static StorageStore()
      77             :                 {
      78             :                         DefaultSettings = DefaultJsonSerializerSettings.DefaultSettings;
      79             :                 }
      80             : 
      81             :                 /// <summary>
      82             :                 /// Initialises the <see cref="StorageStore{TData,TSource}"/>.
      83             :                 /// </summary>
      84           1 :                 protected virtual void Initialise(IStorageStoreConnectionStringFactory storageDataStoreConnectionStringFactory)
      85             :                 {
      86             :                         WritableCollection = new List<Tuple<CloudStorageAccount, TSource>>();
      87             :                         ReadableStorageAccount = CloudStorageAccount.Parse(storageDataStoreConnectionStringFactory.GetReadableConnectionString());
      88             :                         ReadableSource = CreateSource(ReadableStorageAccount, GetContainerName(), IsContainerPublic());
      89             : 
      90             :                         foreach (string writableConnectionString in storageDataStoreConnectionStringFactory.GetWritableConnectionStrings())
      91             :                         {
      92             :                                 CloudStorageAccount storageAccount = CloudStorageAccount.Parse(writableConnectionString);
      93             :                                 TSource container = CreateSource(storageAccount, GetContainerName(), IsContainerPublic());
      94             : 
      95             :                                 WritableCollection.Add(new Tuple<CloudStorageAccount, TSource>(storageAccount, container));
      96             :                         }
      97             :                 }
      98             : 
      99             :                 #region Implementation of IEnumerable
     100             : 
     101             :                 /// <summary>
     102             :                 /// Returns an enumerator that iterates through the collection.
     103             :                 /// </summary>
     104             :                 /// <returns>
     105             :                 /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
     106             :                 /// </returns>
     107           1 :                 public abstract IEnumerator<TData> GetEnumerator();
     108             : 
     109             :                 /// <summary>
     110             :                 /// Returns an enumerator that iterates through a collection.
     111             :                 /// </summary>
     112             :                 /// <returns>
     113             :                 /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
     114             :                 /// </returns>
     115             :                 IEnumerator IEnumerable.GetEnumerator()
     116             :                 {
     117             :                         return GetEnumerator();
     118             :                 }
     119             : 
     120             :                 #endregion
     121             : 
     122             :                 #region Implementation of IQueryable
     123             : 
     124             :                 /// <summary>
     125             :                 /// Gets the expression tree that is associated with the instance of <see cref="T:System.Linq.IQueryable"/>.
     126             :                 /// </summary>
     127             :                 /// <returns>
     128             :                 /// The <see cref="T:System.Linq.Expressions.Expression"/> that is associated with this instance of <see cref="T:System.Linq.IQueryable"/>.
     129             :                 /// </returns>
     130             :                 public abstract Expression Expression { get; }
     131             : 
     132             :                 /// <summary>
     133             :                 /// Gets the type of the element(s) that are returned when the expression tree associated with this instance of <see cref="T:System.Linq.IQueryable"/> is executed.
     134             :                 /// </summary>
     135             :                 /// <returns>
     136             :                 /// A <see cref="T:System.Type"/> that represents the type of the element(s) that are returned when the expression tree associated with this object is executed.
     137             :                 /// </returns>
     138             :                 public abstract Type ElementType { get; }
     139             : 
     140             :                 /// <summary>
     141             :                 /// Gets the query provider that is associated with this data source.
     142             :                 /// </summary>
     143             :                 /// <returns>
     144             :                 /// The <see cref="T:System.Linq.IQueryProvider"/> that is associated with this data source.
     145             :                 /// </returns>
     146             :                 public abstract IQueryProvider Provider { get; }
     147             : 
     148             :                 #endregion
     149             : 
     150             :                 #region Implementation of IDisposable
     151             : 
     152             :                 /// <summary>
     153             :                 /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
     154             :                 /// </summary>
     155           1 :                 public void Dispose()
     156             :                 {
     157             :                         ReadableSource = default(TSource);
     158             :                         ReadableStorageAccount = null;
     159             : 
     160             :                         WritableCollection = null;
     161             :                 }
     162             : 
     163             :                 #endregion
     164             : 
     165             :                 #region Implementation of IDataStore<TData>
     166             : 
     167             :                 /// <summary>
     168             :                 /// Add the provided <paramref name="data"/> to the data store and persist the change.
     169             :                 /// </summary>
     170           1 :                 public abstract void Add(TData data);
     171             : 
     172             :                 /// <summary>
     173             :                 /// Add the provided <paramref name="data"/> to the data store and persist the change.
     174             :                 /// </summary>
     175           1 :                 public virtual void Add(IEnumerable<TData> data)
     176             :                 {
     177             :                         foreach (TData dataItem in data)
     178             :                                 Add(dataItem);
     179             :                 }
     180             : 
     181             :                 /// <summary>
     182             :                 /// Remove the provided <paramref name="data"/> (normally by <see cref="IEntity.Rsn"/>) from the data store and persist the change.
     183             :                 /// </summary>
     184           1 :                 public abstract void Destroy(TData data);
     185             : 
     186             :                 /// <summary>
     187             :                 /// Remove all contents (normally by use of a truncate operation) from the data store and persist the change.
     188             :                 /// </summary>
     189           1 :                 public abstract void RemoveAll();
     190             : 
     191             :                 /// <summary>
     192             :                 /// Update the provided <paramref name="data"/> in the data store and persist the change.
     193             :                 /// </summary>
     194           1 :                 public abstract void Update(TData data);
     195             : 
     196             :                 #endregion
     197             : 
     198             :                 /// <summary>
     199             :                 /// Creates a <typeparamref name="TSource" /> with the specified name <paramref name="sourceName"/> if it doesn't already exist.
     200             :                 /// </summary>
     201             :                 /// <param name="storageAccount">The storage account to create the container is</param>
     202             :                 /// <param name="sourceName">The name of the source.</param>
     203             :                 /// <param name="isPublic">Whether or not this source is publicly accessible.</param>
     204           1 :                 protected abstract TSource CreateSource(CloudStorageAccount storageAccount, string sourceName, bool isPublic = true);
     205             : 
     206             :                 /// <summary>
     207             :                 /// Gets the provided <paramref name="sourceName"/> in a safe to use in lower case format.
     208             :                 /// </summary>
     209             :                 /// <param name="sourceName">The name to make safe.</param>
     210           1 :                 protected virtual string GetSafeSourceName(string sourceName)
     211             :                 {
     212             :                         return GetSafeSourceName(sourceName, true);
     213             :                 }
     214             : 
     215             :                 /// <summary>
     216             :                 /// Gets the provided <paramref name="sourceName"/> in a safe to use in format.
     217             :                 /// </summary>
     218             :                 /// <param name="sourceName">The name to make safe.</param>
     219             :                 /// <param name="lowerCaseName">Indicates if the generated name is forced into a lower case format.</param>
     220           1 :                 protected virtual string GetSafeSourceName(string sourceName, bool lowerCaseName)
     221             :                 {
     222             :                         if (sourceName.Contains(":"))
     223             :                                 return sourceName;
     224             : 
     225             :                         string safeContainerName = sourceName.Replace(@"\", @"/").Replace(@"/", @"-");
     226             :                         if (lowerCaseName)
     227             :                                 safeContainerName = safeContainerName.ToLowerInvariant();
     228             :                         if (safeContainerName.StartsWith("-"))
     229             :                                 safeContainerName = safeContainerName.Substring(1);
     230             :                         if (safeContainerName.EndsWith("-"))
     231             :                                 safeContainerName = safeContainerName.Substring(0, safeContainerName.Length - 1);
     232             :                         safeContainerName = safeContainerName.Replace(" ", "-");
     233             : 
     234             :                         return safeContainerName;
     235             :                 }
     236             : 
     237             :                 /// <summary>
     238             :                 /// Characters Disallowed in Key Fields
     239             :                 /// 
     240             :                 /// The following characters are not allowed in values for the PartitionKey and RowKey properties:
     241             :                 /// 
     242             :                 /// The forward slash (/) character
     243             :                 /// The backslash (\) character
     244             :                 /// The number sign (#) character
     245             :                 /// The question mark (?) character
     246             :                 /// Control characters from U+0000 to U+001F, including:
     247             :                 /// The horizontal tab (\t) character
     248             :                 /// The linefeed (\n) character
     249             :                 /// The carriage return (\r) character
     250             :                 /// Control characters from U+007F to U+009F
     251             :                 /// </summary>
     252             :                 /// <param name="sourceName"></param>
     253             :                 /// <returns></returns>
     254             :                 internal static string GetSafeStorageKey(string sourceName)
     255             :                 {
     256             :                         var sb = new StringBuilder();
     257             :                         foreach (var c in sourceName
     258             :                                 .Where(c => c != '/'
     259             :                                                         && c != '\\'
     260             :                                                         && c != '#'
     261             :                                                         && c != '/'
     262             :                                                         && c != '?'
     263             :                                                         && !char.IsControl(c)))
     264             :                                 sb.Append(c);
     265             :                         return sb.ToString();
     266             :                 }
     267             : 
     268             :                 /// <summary>
     269             :                 /// Gets the default retry policy dedicated to handling transient conditions with Windows Azure Storage.
     270             :                 /// </summary>
     271             :                 protected virtual RetryPolicy AzureStorageRetryPolicy
     272             :                 {
     273             :                         get
     274             :                         {
     275             :                                 RetryManager retryManager = EnterpriseLibraryContainer.Current.GetInstance<RetryManager>();
     276             :                                 RetryPolicy retryPolicy = retryManager.GetDefaultAzureStorageRetryPolicy();
     277             :                                 retryPolicy.Retrying += (sender, args) =>
     278             :                                 {
     279             :                                         var msg = string.Format("Retrying action - Count: {0}, Delay: {1}", args.CurrentRetryCount, args.Delay);
     280             :                                         Logger.LogWarning(msg, exception: args.LastException);
     281             :                                 };
     282             :                                 return retryPolicy;
     283             :                         }
     284             :                 }
     285             : 
     286             :                 /// <summary>
     287             :                 /// Deserialise the provided <paramref name="dataStream"/> from its <see cref="Stream"/> representation.
     288             :                 /// </summary>
     289             :                 /// <param name="dataStream">A <see cref="Stream"/> representation of an <typeparamref name="TData"/> to deserialise.</param>
     290           1 :                 protected virtual TData Deserialise(Stream dataStream)
     291             :                 {
     292             :                         using (dataStream)
     293             :                         {
     294             :                                 using (var reader = new StreamReader(dataStream))
     295             :                                 {
     296             :                                         string jsonContents = reader.ReadToEnd();
     297             :                                         TData obj = Deserialise(jsonContents);
     298             :                                         return obj;
     299             :                                 }
     300             :                         }
     301             :                 }
     302             : 
     303             :                 /// <summary>
     304             :                 /// Deserialise the provided <paramref name="json"/> from its <see cref="string"/> representation.
     305             :                 /// </summary>
     306             :                 /// <param name="json">A <see cref="string"/> representation of an <typeparamref name="TData"/> to deserialise.</param>
     307           1 :                 protected virtual TData Deserialise(string json)
     308             :                 {
     309             :                         using (var stringReader = new StringReader(json))
     310             :                                 using (var jsonTextReader = new JsonTextReader(stringReader))
     311             :                                         return GetSerialiser().Deserialize<TData>(jsonTextReader);
     312             :                 }
     313             : 
     314             :                 /// <summary>
     315             :                 /// Serialise the provided <paramref name="data"/>.
     316             :                 /// </summary>
     317             :                 /// <param name="data">The <typeparamref name="TData"/> being serialised.</param>
     318             :                 /// <returns>A <see cref="Stream"/> representation of the provided <paramref name="data"/>.</returns>
     319           1 :                 protected virtual Stream Serialise(TData data)
     320             :                 {
     321             :                         string dataContent = JsonConvert.SerializeObject(data, GetSerialisationSettings());
     322             : 
     323             :                         byte[] byteArray = Encoding.UTF8.GetBytes(dataContent);
     324             :                         var stream = new MemoryStream(byteArray);
     325             : 
     326             :                         return stream;
     327             :                 }
     328             : 
     329             :                 /// <summary>
     330             :                 /// Returns <see cref="DefaultSettings"/>
     331             :                 /// </summary>
     332             :                 /// <returns><see cref="DefaultSettings"/></returns>
     333           1 :                 protected virtual JsonSerializerSettings GetSerialisationSettings()
     334             :                 {
     335             :                         return DefaultSettings;
     336             :                 }
     337             : 
     338             :                 /// <summary>
     339             :                 /// Creates a new <see cref="JsonSerializer"/> using the settings from <see cref="GetSerialisationSettings"/>.
     340             :                 /// </summary>
     341             :                 /// <returns>A new instance of <see cref="JsonSerializer"/>.</returns>
     342           1 :                 protected virtual JsonSerializer GetSerialiser()
     343             :                 {
     344             :                         JsonSerializerSettings settings = GetSerialisationSettings();
     345             :                         return JsonSerializer.Create(settings);
     346             :                 }
     347             :         }
     348             : }

Generated by: LCOV version 1.10