Skip to content

Commit

Permalink
Updating to ASP.NET Core 2.0, adding partitioning support to web serv…
Browse files Browse the repository at this point in the history
…ice, and cleaning up.
  • Loading branch information
vturecek committed Nov 16, 2017
1 parent a71dd28 commit 1c21f24
Show file tree
Hide file tree
Showing 17 changed files with 406 additions and 252 deletions.
2 changes: 1 addition & 1 deletion Voting/ApplicationPackageRoot/ApplicationManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
The attribute ServiceTypeName below must match the name defined in the imported ServiceManifest.xml file. -->
<Service Name="VotingData">
<StatefulService ServiceTypeName="VotingDataType" TargetReplicaSetSize="[VotingData_TargetReplicaSetSize]" MinReplicaSetSize="[VotingData_MinReplicaSetSize]">
<UniformInt64Partition PartitionCount="[VotingData_PartitionCount]" LowKey="-9223372036854775808" HighKey="9223372036854775807" />
<UniformInt64Partition PartitionCount="[VotingData_PartitionCount]" LowKey="0" HighKey="25" />
</StatefulService>
</Service>
<Service Name="VotingWeb" ServicePackageActivationMode="ExclusiveProcess">
Expand Down
4 changes: 2 additions & 2 deletions Voting/Voting.sfproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<Import Project="$(ApplicationProjectTargetsPath)" Condition="Exists('$(ApplicationProjectTargetsPath)')" />
<Import Project="..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.6.0\build\Microsoft.VisualStudio.Azure.Fabric.Application.targets" Condition="Exists('..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.6.0\build\Microsoft.VisualStudio.Azure.Fabric.Application.targets')" />
<Target Name="ValidateMSBuildFiles">
<Error Condition="!Exists('..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.6.0\build\Microsoft.VisualStudio.Azure.Fabric.Application.props')" Text="Unable to find the '..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.6.0\build\Microsoft.VisualStudio.Azure.Fabric.Application.props' file. Please restore the 'Microsoft.VisualStudio.Azure.Fabric.MSBuild' Nuget package" />
<Error Condition="!Exists('..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.6.0\build\Microsoft.VisualStudio.Azure.Fabric.Application.targets')" Text="Unable to find the '..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.6.0\build\Microsoft.VisualStudio.Azure.Fabric.Application.targets' file. Please restore the 'Microsoft.VisualStudio.Azure.Fabric.MSBuild' Nuget package" />
<Error Condition="!Exists('..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.6.0\build\Microsoft.VisualStudio.Azure.Fabric.Application.props')" Text="Unable to find the '..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.6.0\build\Microsoft.VisualStudio.Azure.Fabric.Application.props' file. Please restore the 'Microsoft.VisualStudio.Azure.Fabric.MSBuild' Nuget package." />
<Error Condition="!Exists('..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.6.0\build\Microsoft.VisualStudio.Azure.Fabric.Application.targets')" Text="Unable to find the '..\packages\Microsoft.VisualStudio.Azure.Fabric.MSBuild.1.6.0\build\Microsoft.VisualStudio.Azure.Fabric.Application.targets' file. Please restore the 'Microsoft.VisualStudio.Azure.Fabric.MSBuild' Nuget package." />
</Target>
</Project>
37 changes: 20 additions & 17 deletions VotingData/Controllers/VoteDataController.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.ServiceFabric.Data;
using System.Threading;
using Microsoft.ServiceFabric.Data.Collections;
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
// ------------------------------------------------------------

namespace VotingData.Controllers
{
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.ServiceFabric.Data;
using Microsoft.ServiceFabric.Data.Collections;

[Route("api/[controller]")]
public class VoteDataController : Controller
{
Expand All @@ -23,32 +26,32 @@ public VoteDataController(IReliableStateManager stateManager)
[HttpGet]
public async Task<IActionResult> Get()
{
var ct = new CancellationToken();
CancellationToken ct = new CancellationToken();

var votesDictionary = await this.stateManager.GetOrAddAsync<IReliableDictionary<string, int>>("counts");
IReliableDictionary<string, int> votesDictionary = await this.stateManager.GetOrAddAsync<IReliableDictionary<string, int>>("counts");

using (ITransaction tx = this.stateManager.CreateTransaction())
{
var list = await votesDictionary.CreateEnumerableAsync(tx);
IAsyncEnumerable<KeyValuePair<string, int>> list = await votesDictionary.CreateEnumerableAsync(tx);

var enumerator = list.GetAsyncEnumerator();
IAsyncEnumerator<KeyValuePair<string, int>> enumerator = list.GetAsyncEnumerator();

var result = new List<KeyValuePair<string, int>>();
List<KeyValuePair<string, int>> result = new List<KeyValuePair<string, int>>();

while (await enumerator.MoveNextAsync(ct))
{
result.Add(enumerator.Current);
}

return Json(result);
return this.Json(result);
}
}

// PUT api/VoteData/name
[HttpPut("{name}")]
public async Task<IActionResult> Put(string name)
{
var votesDictionary = await this.stateManager.GetOrAddAsync<IReliableDictionary<string, int>>("counts");
IReliableDictionary<string, int> votesDictionary = await this.stateManager.GetOrAddAsync<IReliableDictionary<string, int>>("counts");

using (ITransaction tx = this.stateManager.CreateTransaction())
{
Expand All @@ -63,7 +66,7 @@ public async Task<IActionResult> Put(string name)
[HttpDelete("{name}")]
public async Task<IActionResult> Delete(string name)
{
var votesDictionary = await this.stateManager.GetOrAddAsync<IReliableDictionary<string, int>>("counts");
IReliableDictionary<string, int> votesDictionary = await this.stateManager.GetOrAddAsync<IReliableDictionary<string, int>>("counts");

using (ITransaction tx = this.stateManager.CreateTransaction())
{
Expand All @@ -80,4 +83,4 @@ public async Task<IActionResult> Delete(string name)
}
}
}
}
}
19 changes: 12 additions & 7 deletions VotingData/Program.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
using Microsoft.ServiceFabric.Services.Runtime;
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
// ------------------------------------------------------------

namespace VotingData
{
using System;
using System.Diagnostics;
using System.Threading;
using Microsoft.ServiceFabric.Services.Runtime;

internal static class Program
{
/// <summary>
Expand All @@ -20,7 +24,8 @@ private static void Main()
// When Service Fabric creates an instance of this service type,
// an instance of the class is created in this host process.

ServiceRuntime.RegisterServiceAsync("VotingDataType",
ServiceRuntime.RegisterServiceAsync(
"VotingDataType",
context => new VotingData(context)).GetAwaiter().GetResult();

ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(VotingData).Name);
Expand All @@ -35,4 +40,4 @@ private static void Main()
}
}
}
}
}
98 changes: 65 additions & 33 deletions VotingData/ServiceEventSource.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Fabric;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.ServiceFabric.Services.Runtime;
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
// ------------------------------------------------------------

namespace VotingData
{
using System;
using System.Diagnostics.Tracing;
using System.Fabric;
using System.Threading.Tasks;

[EventSource(Name = "MyCompany-Voting-VotingData")]
internal sealed class ServiceEventSource : EventSource
{
Expand All @@ -22,20 +23,25 @@ static ServiceEventSource()
}

// Instance constructor is private to enforce singleton semantics
private ServiceEventSource() : base() { }
private ServiceEventSource() : base()
{
}

#region Keywords

// Event keywords can be used to categorize events.
// Each keyword is a bit flag. A single event can be associated with multiple keywords (via EventAttribute.Keywords property).
// Keywords must be defined as a public class named 'Keywords' inside EventSource that uses them.
public static class Keywords
{
public const EventKeywords Requests = (EventKeywords)0x1L;
public const EventKeywords ServiceInitialization = (EventKeywords)0x2L;
public const EventKeywords Requests = (EventKeywords) 0x1L;
public const EventKeywords ServiceInitialization = (EventKeywords) 0x2L;
}

#endregion

#region Events

// Define an instance method for each event you want to record and apply an [Event] attribute to it.
// The method name is the name of the event.
// Pass any parameters you want to record with the event (only primitive integer types, DateTime, Guid & string are allowed).
Expand All @@ -50,17 +56,18 @@ public void Message(string message, params object[] args)
if (this.IsEnabled())
{
string finalMessage = string.Format(message, args);
Message(finalMessage);
this.Message(finalMessage);
}
}

private const int MessageEventId = 1;

[Event(MessageEventId, Level = EventLevel.Informational, Message = "{0}")]
public void Message(string message)
{
if (this.IsEnabled())
{
WriteEvent(MessageEventId, message);
this.WriteEvent(MessageEventId, message);
}
}

Expand All @@ -69,9 +76,8 @@ public void ServiceMessage(ServiceContext serviceContext, string message, params
{
if (this.IsEnabled())
{

string finalMessage = string.Format(message, args);
ServiceMessage(
this.ServiceMessage(
serviceContext.ServiceName.ToString(),
serviceContext.ServiceTypeName,
GetReplicaOrInstanceId(serviceContext),
Expand All @@ -87,26 +93,37 @@ public void ServiceMessage(ServiceContext serviceContext, string message, params
// This results in more efficient parameter handling, but requires explicit allocation of EventData structure and unsafe code.
// To enable this code path, define UNSAFE conditional compilation symbol and turn on unsafe code support in project properties.
private const int ServiceMessageEventId = 2;

[Event(ServiceMessageEventId, Level = EventLevel.Informational, Message = "{7}")]
private
#if UNSAFE
unsafe
#endif
void ServiceMessage(
string serviceName,
string serviceTypeName,
long replicaOrInstanceId,
Guid partitionId,
string applicationName,
string applicationTypeName,
string nodeName,
string message)
void ServiceMessage(
string serviceName,
string serviceTypeName,
long replicaOrInstanceId,
Guid partitionId,
string applicationName,
string applicationTypeName,
string nodeName,
string message)
{
#if !UNSAFE
WriteEvent(ServiceMessageEventId, serviceName, serviceTypeName, replicaOrInstanceId, partitionId, applicationName, applicationTypeName, nodeName, message);
this.WriteEvent(
ServiceMessageEventId,
serviceName,
serviceTypeName,
replicaOrInstanceId,
partitionId,
applicationName,
applicationTypeName,
nodeName,
message);
#else
const int numArgs = 8;
fixed (char* pServiceName = serviceName, pServiceTypeName = serviceTypeName, pApplicationName = applicationName, pApplicationTypeName = applicationTypeName, pNodeName = nodeName, pMessage = message)
fixed (char* pServiceName = serviceName, pServiceTypeName = serviceTypeName, pApplicationName = applicationName, pApplicationTypeName =
applicationTypeName, pNodeName = nodeName, pMessage = message)
{
EventData* eventData = stackalloc EventData[numArgs];
eventData[0] = new EventData { DataPointer = (IntPtr) pServiceName, Size = SizeInBytes(serviceName) };
Expand All @@ -124,38 +141,52 @@ void ServiceMessage(
}

private const int ServiceTypeRegisteredEventId = 3;
[Event(ServiceTypeRegisteredEventId, Level = EventLevel.Informational, Message = "Service host process {0} registered service type {1}", Keywords = Keywords.ServiceInitialization)]

[Event(
ServiceTypeRegisteredEventId,
Level = EventLevel.Informational,
Message = "Service host process {0} registered service type {1}",
Keywords = Keywords.ServiceInitialization)]
public void ServiceTypeRegistered(int hostProcessId, string serviceType)
{
WriteEvent(ServiceTypeRegisteredEventId, hostProcessId, serviceType);
this.WriteEvent(ServiceTypeRegisteredEventId, hostProcessId, serviceType);
}

private const int ServiceHostInitializationFailedEventId = 4;
[Event(ServiceHostInitializationFailedEventId, Level = EventLevel.Error, Message = "Service host initialization failed", Keywords = Keywords.ServiceInitialization)]

[Event(
ServiceHostInitializationFailedEventId,
Level = EventLevel.Error,
Message = "Service host initialization failed",
Keywords = Keywords.ServiceInitialization)]
public void ServiceHostInitializationFailed(string exception)
{
WriteEvent(ServiceHostInitializationFailedEventId, exception);
this.WriteEvent(ServiceHostInitializationFailedEventId, exception);
}

// A pair of events sharing the same name prefix with a "Start"/"Stop" suffix implicitly marks boundaries of an event tracing activity.
// These activities can be automatically picked up by debugging and profiling tools, which can compute their execution time, child activities,
// and other statistics.
private const int ServiceRequestStartEventId = 5;

[Event(ServiceRequestStartEventId, Level = EventLevel.Informational, Message = "Service request '{0}' started", Keywords = Keywords.Requests)]
public void ServiceRequestStart(string requestTypeName)
{
WriteEvent(ServiceRequestStartEventId, requestTypeName);
this.WriteEvent(ServiceRequestStartEventId, requestTypeName);
}

private const int ServiceRequestStopEventId = 6;

[Event(ServiceRequestStopEventId, Level = EventLevel.Informational, Message = "Service request '{0}' finished", Keywords = Keywords.Requests)]
public void ServiceRequestStop(string requestTypeName, string exception = "")
{
WriteEvent(ServiceRequestStopEventId, requestTypeName, exception);
this.WriteEvent(ServiceRequestStopEventId, requestTypeName, exception);
}

#endregion

#region Private methods

private static long GetReplicaOrInstanceId(ServiceContext context)
{
StatelessServiceContext stateless = context as StatelessServiceContext;
Expand Down Expand Up @@ -185,6 +216,7 @@ private int SizeInBytes(string s)
}
}
#endif

#endregion
}
}
}
27 changes: 14 additions & 13 deletions VotingData/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
// ------------------------------------------------------------

namespace VotingData
{
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
IConfigurationBuilder builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
this.Configuration = builder.Build();
}

public IConfigurationRoot Configuration { get; }
Expand All @@ -34,10 +35,10 @@ public void ConfigureServices(IServiceCollection services)
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddConsole(this.Configuration.GetSection("Logging"));
loggerFactory.AddDebug();

app.UseMvc();
}
}
}
}
Loading

0 comments on commit 1c21f24

Please sign in to comment.