Created
September 8, 2014 00:50
-
-
Save ReubenBond/738dceb8f409afa39fe6 to your computer and use it in GitHub Desktop.
AzureJsonStore.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -------------------------------------------------------------------------------------------------------------------- | |
// <summary> | |
// The Azure JSON table storage provider. | |
// </summary> | |
// -------------------------------------------------------------------------------------------------------------------- | |
namespace Grains.Utilities | |
{ | |
using System.Configuration; | |
using System.Threading.Tasks; | |
using FreeBay.Models.Utility; | |
using Microsoft.WindowsAzure; | |
using Microsoft.WindowsAzure.Storage; | |
using Microsoft.WindowsAzure.Storage.Table; | |
using Newtonsoft.Json; | |
using Orleans; | |
using Orleans.Runtime; | |
using Orleans.Storage; | |
/// <summary> | |
/// The Azure JSON table storage provider. | |
/// </summary> | |
public class AzureJsonStore : IStorageProvider | |
{ | |
/// <summary> | |
/// The connection string setting. | |
/// </summary> | |
public const string ConnectionStringSetting = "ConnectionStringSetting"; | |
/// <summary> | |
/// The table name setting. | |
/// </summary> | |
public const string TableNameSetting = "TableName"; | |
/// <summary> | |
/// Gets or sets the log. | |
/// </summary> | |
public OrleansLogger Log { get; set; } | |
/// <summary> | |
/// Gets or sets the name. | |
/// </summary> | |
public string Name { get; set; } | |
/// <summary> | |
/// Gets or sets the table. | |
/// </summary> | |
public CloudTable Table { get; set; } | |
/// <summary> | |
/// Gets or sets the account. | |
/// </summary> | |
public CloudStorageAccount Account { get; set; } | |
/// <summary> | |
/// Gets or sets the client. | |
/// </summary> | |
public CloudTableClient Client { get; set; } | |
/// <summary> | |
/// Initialization function called by Orleans Provider Manager when a new provider class instance is created | |
/// </summary> | |
/// <param name="name">Name assigned for this provider</param> | |
/// <param name="providerRuntime">Callback for accessing system functions in the Provider Runtime</param> | |
/// <param name="config">Configuration metadata to be used for this provider instance</param> | |
/// <returns> | |
/// Completion promise Task for the initialization work for this provider | |
/// </returns> | |
public async Task Init(string name, Orleans.Providers.IProviderRuntime providerRuntime, Orleans.Providers.IProviderConfiguration config) | |
{ | |
var connectionStringSetting = config.Properties[ConnectionStringSetting]; | |
if (string.IsNullOrWhiteSpace(connectionStringSetting)) | |
{ | |
throw new ConfigurationErrorsException(ConnectionStringSetting + " must be provided."); | |
} | |
var tableName = config.Properties[TableNameSetting]; | |
if (string.IsNullOrWhiteSpace(tableName)) | |
{ | |
throw new ConfigurationErrorsException(TableNameSetting + " must be provided."); | |
} | |
var connectionString = CloudConfigurationManager.GetSetting(connectionStringSetting); | |
this.Account = CloudStorageAccount.Parse(connectionString); | |
this.Client = new CloudTableClient(this.Account.TableStorageUri, this.Account.Credentials); | |
this.Table = this.Client.GetTableReference(tableName); | |
await this.Table.CreateIfNotExistsAsync(); | |
} | |
/// <summary> | |
/// Close function for this storage provider instance. | |
/// </summary> | |
/// <returns> | |
/// Completion promise for the Close operation on this provider. | |
/// </returns> | |
public Task Close() | |
{ | |
return Task.FromResult(0); | |
} | |
/// <summary> | |
/// Read data function for this storage provider instance. | |
/// </summary> | |
/// <param name="grainType">Type of this grain [fully qualified class name]</param> | |
/// <param name="grainRef">Grain reference object for this grain.</param> | |
/// <param name="grainState">State data object to be populated for this grain.</param> | |
/// <returns> | |
/// Completion promise for the Read operation on the specified grain. | |
/// </returns> | |
public async Task ReadStateAsync(string grainType, GrainReference grainRef, IGrainState grainState) | |
{ | |
var rowkey = grainState.GetType().Name; | |
var partitionKey = grainRef.ToKeyString(); | |
var query = new TableQuery<GrainStateTableEntity>().Where( | |
TableQuery.CombineFilters( | |
TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey), | |
TableOperators.And, | |
TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, rowkey))); | |
var result = await this.Table.ExecuteQuerySegmentedAsync(query, null); | |
if (result.Results != null && result.Results.Count > 0) | |
{ | |
var entity = result.Results[0]; | |
var properties = (IGrainState)JsonConvert.DeserializeObject(entity.State, grainState.GetType(), Globals.JsonConfig); | |
grainState.SetAll(properties.AsDictionary()); | |
} | |
} | |
/// <summary> | |
/// Write data function for this storage provider instance. | |
/// </summary> | |
/// <param name="grainType">Type of this grain [fully qualified class name]</param> | |
/// <param name="grainRef">Grain reference object for this grain.</param> | |
/// <param name="grainState">State data object to be written for this grain.</param> | |
/// <returns> | |
/// Completion promise for the Write operation on the specified grain. | |
/// </returns> | |
public async Task WriteStateAsync(string grainType, GrainReference grainRef, IGrainState grainState) | |
{ | |
var rowkey = grainState.GetType().Name; | |
var partitionKey = grainRef.ToKeyString(); | |
var entity = new GrainStateTableEntity { PartitionKey = partitionKey, RowKey = rowkey, State = JsonConvert.SerializeObject(grainState, Globals.JsonConfig) }; | |
await this.Table.ExecuteAsync(TableOperation.InsertOrReplace(entity)); | |
} | |
/// <summary> | |
/// Delete / Clear data function for this storage provider instance. | |
/// </summary> | |
/// <param name="grainType">Type of this grain [fully qualified class name]</param> | |
/// <param name="grainRef">Grain reference object for this grain.</param> | |
/// <param name="grainState">Copy of last-known state data object for this grain.</param> | |
/// <returns> | |
/// Completion promise for the Delete operation on the specified grain. | |
/// </returns> | |
public async Task ClearStateAsync(string grainType, GrainReference grainRef, IGrainState grainState) | |
{ | |
var rowkey = grainState.GetType().Name; | |
var partitionKey = grainRef.ToKeyString(); | |
var entity = new GrainStateTableEntity { PartitionKey = partitionKey, RowKey = rowkey }; | |
await this.Table.ExecuteAsync(TableOperation.Delete(entity)); | |
} | |
/// <summary> | |
/// The grain state table entity. | |
/// </summary> | |
public class GrainStateTableEntity : TableEntity | |
{ | |
/// <summary> | |
/// Gets or sets the state. | |
/// </summary> | |
public string State { get; set; } | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment