Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move ClusterConfiguration to legacy #3901

Merged
merged 15 commits into from Jan 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Orleans.sln
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2010
VisualStudioVersion = 15.0.27130.2024
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4CD3AA9E-D937-48CA-BB6C-158E12257D23}"
EndProject
Expand Down
@@ -1,4 +1,4 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Orleans.Hosting;
using Orleans.Runtime.Configuration;

Expand All @@ -7,9 +7,10 @@ namespace Orleans.Runtime.MembershipService
/// <inheritdoc />
public class LegacyDynamoDBMembershipConfigurator : ILegacyMembershipConfigurator
{
public void ConfigureServices(GlobalConfiguration configuration, IServiceCollection services)
public void ConfigureServices(object configuration, IServiceCollection services)
{
services.UseDynamoDBMembership(options => options.ConnectionString = configuration.DataConnectionString);
var reader = new GlobalConfigurationReader(configuration);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I though you went with the option of moving these legacy Configurator to Orleans.Core.Legacy package? and use reflection to configure membership and gateway list provider

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I touched on this in the PR comments. The pattern we'd planned on didn't work. The issue was that either way something needs to know about something it has no knowledge of, either the options or the clusterConfiguration. As you can see from how this pattern turned out, it's not a bad approach. Probably the least bad of the possible bad approaches.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry my bad, I went read it and deleted some noisy comments

services.UseDynamoDBMembership(options => options.ConnectionString = reader.GetPropertyValue<string>("DataConnectionString"));
}
}
}
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageId>Microsoft.Orleans.Clustering.DynamoDB</PackageId>
<Title>Microsoft Orleans clustering provider for AWS DynamoDB</Title>
Expand All @@ -22,6 +22,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Orleans.Core.Legacy\Orleans.Core.Legacy.csproj" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you need dependency on Orleans.Core.Legacy? you used reflection to get DataConnectionString from ClusterConfiguration. What else is using Orleans.Core.Legacy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've pulled all references of Cluster config out of the core packages, but not all of the extension libraries. So any library that still references cluster config needs depend on core legacy. This can (and IMHO should) be handled in smaller, more targeted change sets rather than adding to this one.

<ProjectReference Include="..\..\Orleans.Runtime.Abstractions\Orleans.Runtime.Abstractions.csproj" />
<ProjectReference Include="..\..\OrleansProviders\OrleansProviders.csproj" />
</ItemGroup>
Expand Down
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageId>Microsoft.Orleans.Reminders.DynamoDB</PackageId>
<Title>Microsoft Orleans Reminders DynamoDB</Title>
Expand Down Expand Up @@ -26,6 +26,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Orleans.Core.Legacy\Orleans.Core.Legacy.csproj" />
<ProjectReference Include="..\..\Orleans.Runtime.Abstractions\Orleans.Runtime.Abstractions.csproj" />
</ItemGroup>
</Project>
@@ -1,4 +1,4 @@
using Orleans;
using Orleans;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
Expand All @@ -9,6 +9,7 @@
using Microsoft.Extensions.Logging;
using Orleans.Reminders.DynamoDB;
using Microsoft.Extensions.Options;
using Orleans.Hosting;

namespace OrleansAWSUtils.Reminders
{
Expand All @@ -33,6 +34,7 @@ public class DynamoDBReminderTable : IReminderTable
private const string TABLE_NAME_DEFAULT_VALUE = "OrleansReminders";
private ILogger logger;
private readonly ILoggerFactory loggerFactory;
private readonly StorageOptions storageOptions;
private DynamoDBStorage storage;
private readonly Guid serviceId;

Expand All @@ -41,23 +43,24 @@ public class DynamoDBReminderTable : IReminderTable
/// </summary>
/// <param name="grainReferenceConverter">The grain factory.</param>
/// <param name="loggerFactory">logger factory to use</param>
public DynamoDBReminderTable(IGrainReferenceConverter grainReferenceConverter, ILoggerFactory loggerFactory, IOptions<SiloOptions> siloOptions)
public DynamoDBReminderTable(IGrainReferenceConverter grainReferenceConverter, ILoggerFactory loggerFactory, IOptions<SiloOptions> siloOptions, IOptions<StorageOptions> storageOptions)
{
this.grainReferenceConverter = grainReferenceConverter;
this.logger = loggerFactory.CreateLogger<DynamoDBReminderTable>();
this.loggerFactory = loggerFactory;
this.serviceId = siloOptions.Value.ServiceId;
this.storageOptions = storageOptions.Value;
}

/// <summary>
/// Initialize current instance with specific global configuration and logger
/// </summary>
/// <param name="config"> Global configuration to initialize with </param>
/// <returns></returns>
public Task Init(GlobalConfiguration config)
public Task Init()
{
storage = new DynamoDBStorage(config.DataConnectionStringForReminders, loggerFactory);
logger.Info(ErrorCode.ReminderServiceBase, "Initializing AWS DynamoDB Reminders Table");
this.storage = new DynamoDBStorage(this.storageOptions.DataConnectionStringForReminders, this.loggerFactory);
this.logger.Info(ErrorCode.ReminderServiceBase, "Initializing AWS DynamoDB Reminders Table");

var secondaryIndex = new GlobalSecondaryIndex
{
Expand All @@ -70,7 +73,7 @@ public Task Init(GlobalConfiguration config)
}
};

return storage.InitializeTable(TABLE_NAME_DEFAULT_VALUE,
return this.storage.InitializeTable(TABLE_NAME_DEFAULT_VALUE,
new List<KeySchemaElement>
{
new KeySchemaElement { AttributeName = REMINDER_ID_PROPERTY_NAME, KeyType = KeyType.HASH },
Expand All @@ -94,7 +97,7 @@ public Task Init(GlobalConfiguration config)
/// <returns> Return the RemiderTableData if the rows were read successfully </returns>
public async Task<ReminderEntry> ReadRow(GrainReference grainRef, string reminderName)
{
var reminderId = ConstructReminderId(serviceId, grainRef, reminderName);
var reminderId = ConstructReminderId(this.serviceId, grainRef, reminderName);

var keys = new Dictionary<string, AttributeValue>
{
Expand All @@ -104,11 +107,11 @@ public async Task<ReminderEntry> ReadRow(GrainReference grainRef, string reminde

try
{
return await storage.ReadSingleEntryAsync(TABLE_NAME_DEFAULT_VALUE, keys, Resolve).ConfigureAwait(false);
return await this.storage.ReadSingleEntryAsync(TABLE_NAME_DEFAULT_VALUE, keys, this.Resolve).ConfigureAwait(false);
}
catch (Exception exc)
{
logger.Warn(ErrorCode.ReminderServiceBase,
this.logger.Warn(ErrorCode.ReminderServiceBase,
$"Intermediate error reading reminder entry {Utils.DictionaryToString(keys)} from table {TABLE_NAME_DEFAULT_VALUE}.", exc);
throw;
}
Expand All @@ -123,20 +126,20 @@ public async Task<ReminderTableData> ReadRows(GrainReference grainRef)
{
var expressionValues = new Dictionary<string, AttributeValue>
{
{ $":{SERVICE_ID_PROPERTY_NAME}", new AttributeValue(serviceId.ToString()) },
{ $":{SERVICE_ID_PROPERTY_NAME}", new AttributeValue(this.serviceId.ToString()) },
{ $":{GRAIN_REFERENCE_PROPERTY_NAME}", new AttributeValue(grainRef.ToKeyString()) }
};

try
{
var expression = $"{SERVICE_ID_PROPERTY_NAME} = :{SERVICE_ID_PROPERTY_NAME} AND {GRAIN_REFERENCE_PROPERTY_NAME} = :{GRAIN_REFERENCE_PROPERTY_NAME}";
var records = await storage.ScanAsync(TABLE_NAME_DEFAULT_VALUE, expressionValues, expression, Resolve).ConfigureAwait(false);
var records = await this.storage.ScanAsync(TABLE_NAME_DEFAULT_VALUE, expressionValues, expression, this.Resolve).ConfigureAwait(false);

return new ReminderTableData(records);
}
catch (Exception exc)
{
logger.Warn(ErrorCode.ReminderServiceBase,
this.logger.Warn(ErrorCode.ReminderServiceBase,
$"Intermediate error reading reminder entry {Utils.DictionaryToString(expressionValues)} from table {TABLE_NAME_DEFAULT_VALUE}.", exc);
throw;
}
Expand All @@ -152,7 +155,7 @@ public async Task<ReminderTableData> ReadRows(uint beginHash, uint endHash)
{
var expressionValues = new Dictionary<string, AttributeValue>
{
{ $":{SERVICE_ID_PROPERTY_NAME}", new AttributeValue(serviceId.ToString()) },
{ $":{SERVICE_ID_PROPERTY_NAME}", new AttributeValue(this.serviceId.ToString()) },
{ $":Begin{GRAIN_HASH_PROPERTY_NAME}", new AttributeValue { N = beginHash.ToString() } },
{ $":End{GRAIN_HASH_PROPERTY_NAME}", new AttributeValue { N = endHash.ToString() } }
};
Expand All @@ -169,13 +172,13 @@ public async Task<ReminderTableData> ReadRows(uint beginHash, uint endHash)
expression = $"{SERVICE_ID_PROPERTY_NAME} = :{SERVICE_ID_PROPERTY_NAME} AND ({GRAIN_HASH_PROPERTY_NAME} > :Begin{GRAIN_HASH_PROPERTY_NAME} OR {GRAIN_HASH_PROPERTY_NAME} <= :End{GRAIN_HASH_PROPERTY_NAME})";
}

var records = await storage.ScanAsync(TABLE_NAME_DEFAULT_VALUE, expressionValues, expression, Resolve).ConfigureAwait(false);
var records = await this.storage.ScanAsync(TABLE_NAME_DEFAULT_VALUE, expressionValues, expression, this.Resolve).ConfigureAwait(false);

return new ReminderTableData(records);
}
catch (Exception exc)
{
logger.Warn(ErrorCode.ReminderServiceBase,
this.logger.Warn(ErrorCode.ReminderServiceBase,
$"Intermediate error reading reminder entry {Utils.DictionaryToString(expressionValues)} from table {TABLE_NAME_DEFAULT_VALUE}.", exc);
throw;
}
Expand All @@ -202,7 +205,7 @@ private ReminderEntry Resolve(Dictionary<string, AttributeValue> item)
/// <returns> Return true if the row was removed </returns>
public async Task<bool> RemoveRow(GrainReference grainRef, string reminderName, string eTag)
{
var reminderId = ConstructReminderId(serviceId, grainRef, reminderName);
var reminderId = ConstructReminderId(this.serviceId, grainRef, reminderName);

var keys = new Dictionary<string, AttributeValue>
{
Expand All @@ -215,7 +218,7 @@ public async Task<bool> RemoveRow(GrainReference grainRef, string reminderName,
var conditionalValues = new Dictionary<string, AttributeValue> { { CURRENT_ETAG_ALIAS, new AttributeValue { N = eTag } } };
var expression = $"{ETAG_PROPERTY_NAME} = {CURRENT_ETAG_ALIAS}";

await storage.DeleteEntryAsync(TABLE_NAME_DEFAULT_VALUE, keys, expression, conditionalValues).ConfigureAwait(false);
await this.storage.DeleteEntryAsync(TABLE_NAME_DEFAULT_VALUE, keys, expression, conditionalValues).ConfigureAwait(false);
return true;
}
catch (ConditionalCheckFailedException)
Expand All @@ -232,13 +235,13 @@ public async Task TestOnlyClearTable()
{
var expressionValues = new Dictionary<string, AttributeValue>
{
{ $":{SERVICE_ID_PROPERTY_NAME}", new AttributeValue(serviceId.ToString()) }
{ $":{SERVICE_ID_PROPERTY_NAME}", new AttributeValue(this.serviceId.ToString()) }
};

try
{
var expression = $"{SERVICE_ID_PROPERTY_NAME} = :{SERVICE_ID_PROPERTY_NAME}";
var records = await storage.ScanAsync(TABLE_NAME_DEFAULT_VALUE, expressionValues, expression,
var records = await this.storage.ScanAsync(TABLE_NAME_DEFAULT_VALUE, expressionValues, expression,
item => new Dictionary<string, AttributeValue>
{
{ REMINDER_ID_PROPERTY_NAME, item[REMINDER_ID_PROPERTY_NAME] },
Expand All @@ -247,21 +250,21 @@ public async Task TestOnlyClearTable()

if (records.Count <= 25)
{
await storage.DeleteEntriesAsync(TABLE_NAME_DEFAULT_VALUE, records);
await this.storage.DeleteEntriesAsync(TABLE_NAME_DEFAULT_VALUE, records);
}
else
{
List<Task> tasks = new List<Task>();
foreach (var batch in records.BatchIEnumerable(25))
{
tasks.Add(storage.DeleteEntriesAsync(TABLE_NAME_DEFAULT_VALUE, batch));
tasks.Add(this.storage.DeleteEntriesAsync(TABLE_NAME_DEFAULT_VALUE, batch));
}
await Task.WhenAll(tasks);
}
}
catch (Exception exc)
{
logger.Warn(ErrorCode.ReminderServiceBase,
this.logger.Warn(ErrorCode.ReminderServiceBase,
$"Intermediate error removing reminder entries {Utils.DictionaryToString(expressionValues)} from table {TABLE_NAME_DEFAULT_VALUE}.", exc);
throw;
}
Expand All @@ -274,32 +277,32 @@ public async Task TestOnlyClearTable()
/// <returns> Return the entry ETag if entry was upsert successfully </returns>
public async Task<string> UpsertRow(ReminderEntry entry)
{
var reminderId = ConstructReminderId(serviceId, entry.GrainRef, entry.ReminderName);
var reminderId = ConstructReminderId(this.serviceId, entry.GrainRef, entry.ReminderName);

var fields = new Dictionary<string, AttributeValue>
{
{ REMINDER_ID_PROPERTY_NAME, new AttributeValue(reminderId) },
{ GRAIN_HASH_PROPERTY_NAME, new AttributeValue { N = entry.GrainRef.GetUniformHashCode().ToString() } },
{ SERVICE_ID_PROPERTY_NAME, new AttributeValue(serviceId.ToString()) },
{ SERVICE_ID_PROPERTY_NAME, new AttributeValue(this.serviceId.ToString()) },
{ GRAIN_REFERENCE_PROPERTY_NAME, new AttributeValue( entry.GrainRef.ToKeyString()) },
{ PERIOD_PROPERTY_NAME, new AttributeValue(entry.Period.ToString()) },
{ START_TIME_PROPERTY_NAME, new AttributeValue(entry.StartAt.ToString()) },
{ REMINDER_NAME_PROPERTY_NAME, new AttributeValue(entry.ReminderName) },
{ ETAG_PROPERTY_NAME, new AttributeValue { N = random.Next(int.MaxValue).ToString() } }
{ ETAG_PROPERTY_NAME, new AttributeValue { N = this.random.Next(int.MaxValue).ToString() } }
};

try
{
if (logger.IsEnabled(LogLevel.Debug)) logger.Debug("UpsertRow entry = {0}, etag = {1}", entry.ToString(), entry.ETag);
if (this.logger.IsEnabled(LogLevel.Debug)) this.logger.Debug("UpsertRow entry = {0}, etag = {1}", entry.ToString(), entry.ETag);

await storage.PutEntryAsync(TABLE_NAME_DEFAULT_VALUE, fields);
await this.storage.PutEntryAsync(TABLE_NAME_DEFAULT_VALUE, fields);

entry.ETag = fields[ETAG_PROPERTY_NAME].N;
return entry.ETag;
}
catch (Exception exc)
{
logger.Warn(ErrorCode.ReminderServiceBase,
this.logger.Warn(ErrorCode.ReminderServiceBase,
$"Intermediate error updating entry {entry.ToString()} to the table {TABLE_NAME_DEFAULT_VALUE}.", exc);
throw;
}
Expand Down
@@ -1,4 +1,4 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Orleans.Runtime.Configuration;
using Orleans.Runtime.MembershipService;
using Orleans.Hosting;
Expand All @@ -8,13 +8,14 @@ namespace OrleansSQLUtils
/// <inheritdoc />
public class LegacySqlMembershipConfigurator : ILegacyMembershipConfigurator
{
public void ConfigureServices(GlobalConfiguration configuration, IServiceCollection services)
public void ConfigureServices(object configuration, IServiceCollection services)
{
services.UseSqlMembership(
options =>
{
options.AdoInvariant = configuration.AdoInvariant;
options.ConnectionString = configuration.DataConnectionString;
var reader = new GlobalConfigurationReader(configuration);
options.AdoInvariant = reader.GetPropertyValue<string>("AdoInvariant");
options.ConnectionString = reader.GetPropertyValue<string>("DataConnectionString");
});
}
}
Expand Down
Expand Up @@ -34,7 +34,9 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Orleans.Core.Legacy\Orleans.Core.Legacy.csproj" />
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same answer. :/

<ProjectReference Include="..\..\Orleans.Runtime.Abstractions\Orleans.Runtime.Abstractions.csproj" />
<ProjectReference Include="..\..\Orleans.Runtime.Legacy\Orleans.Runtime.Legacy.csproj" />
<ProjectReference Include="..\..\OrleansProviders\OrleansProviders.csproj" />
</ItemGroup>

Expand Down
Expand Up @@ -34,6 +34,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Orleans.Core.Legacy\Orleans.Core.Legacy.csproj" />
<ProjectReference Include="..\..\OrleansProviders\OrleansProviders.csproj" />
</ItemGroup>

Expand Down
Expand Up @@ -81,6 +81,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Orleans.Core.Legacy\Orleans.Core.Legacy.csproj" />
<ProjectReference Include="..\..\Orleans.Runtime.Abstractions\Orleans.Runtime.Abstractions.csproj" />
</ItemGroup>
</Project>