Skip to content

Instantly share code, notes, and snippets.

@ReubenBond
Created July 6, 2015 12:29
Show Gist options
  • Save ReubenBond/f7d7dd546e83a8a8856e to your computer and use it in GitHub Desktop.
Save ReubenBond/f7d7dd546e83a8a8856e to your computer and use it in GitHub Desktop.
Orleans with client/server/interfaces/implementations in a single file. https://github.com/dotnet/orleans/pull/528
namespace RosleansSilo
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using Orleans;
using Orleans.Providers;
using Orleans.Runtime.Configuration;
using Orleans.Runtime.Host;
using Orleans.Storage;
public interface IHappyGrain : IGrainWithGuidKey
{
Task<MyCustomClass> ReadMindUsingTelepathy(string wordsOfWisdom);
}
[StorageProvider(ProviderName = "default")]
public class HappyGrain : Grain<MyCustomClass>, IHappyGrain
{
public Task<MyCustomClass> ReadMindUsingTelepathy(string wordsOfWisdom)
{
if (this.State.Messages == null)
{
this.State.Messages = new List<string>();
}
// This is just random silliness :)
this.State.Messages.Reverse();
this.State.Messages.Add(wordsOfWisdom);
this.State.Messages.Reverse();
if (this.State.Messages.Count > 5)
{
this.State.Messages.RemoveRange(5, this.State.Messages.Count - 5);
}
this.State.Count = this.State.Messages.Count;
return Task.FromResult(this.State);
}
}
public class MyCustomClass : GrainState
{
public int Count { get; set; }
public List<string> Messages { get; set; }
public override string ToString()
{
var messages = this.Messages ?? Enumerable.Empty<string>();
return string.Format(
"Count: {0}, Messages:\n{1}",
this.Count,
string.Join("\n", messages.Select((_, i) => string.Format("[{0}] {1}", i, _))));
}
}
internal class Program
{
private const string DataConnectionString = "UseDevelopmentStorage=true";
private const string DeploymentId = "blah";
private static readonly Random Random = new Random();
private static void Main(string[] args)
{
if (args.Length == 0 || args[0] == "s")
{
var hostConfig = GetClusterConfiguration();
// Start the silo.
var instanceId = Guid.NewGuid().ToString("N").Substring(0, 5);
var silo = new SiloHost(instanceId, hostConfig);
silo.InitializeOrleansSilo();
if (!silo.StartOrleansSilo())
{
Console.WriteLine("Failed to start silo");
}
}
else
{
// Configure the client
GrainClient.Initialize(
new ClientConfiguration
{
DeploymentId = DeploymentId,
DataConnectionString = DataConnectionString,
GatewayProvider = ClientConfiguration.GatewayProviderType.AzureTable,
});
// Mess around with a grain.
var grain = GrainClient.GrainFactory.GetGrain<IHappyGrain>(Guid.Empty);
for (int i = 0; i < 5; i++)
{
var result = grain.ReadMindUsingTelepathy(Random.Next() + " trust in yourself").Result;
Console.WriteLine(result);
}
}
Console.ReadKey();
}
#region Helpers
private static ClusterConfiguration GetClusterConfiguration()
{
// Work out network details such as a suitable listen address and ports.
var hostAddress = GetNodeAddress().Result;
var internalPort = Random.Next(50000, ushort.MaxValue - 1);
var proxyPort = Random.Next(30000, 49999);
// Configure the host to use the local Azure Storage Emulator for service discovery.
var hostConfig = new ClusterConfiguration
{
Defaults =
{
HostNameOrIPAddress = hostAddress.ToString(),
Port = internalPort,
ProxyGatewayEndpoint = new IPEndPoint(hostAddress, proxyPort),
},
Globals =
{
DeploymentId = DeploymentId,
ServiceId = Guid.NewGuid(),
DataConnectionString = DataConnectionString,
LivenessType = GlobalConfiguration.LivenessProviderType.AzureTable,
ReminderServiceType = GlobalConfiguration.ReminderServiceProviderType.AzureTable,
}
};
hostConfig.Globals.RegisterStorageProvider<MemoryStorage>("default");
return hostConfig;
}
public static async Task<IPAddress> GetNodeAddress(string host = null)
{
var nodeAddresses = await Dns.GetHostAddressesAsync(host ?? Dns.GetHostName());
var nodeAddressV4 =
nodeAddresses.FirstOrDefault(_ => _.AddressFamily == AddressFamily.InterNetwork && !IsLocalAddress(_));
var nodeAddressV6 =
nodeAddresses.FirstOrDefault(_ => _.AddressFamily == AddressFamily.InterNetworkV6 && !IsLocalAddress(_));
var nodeAddress = nodeAddressV4 ?? nodeAddressV6;
if (nodeAddress == null)
{
throw new InvalidOperationException("Could not determine network address.");
}
return nodeAddress;
}
public static bool IsLocalAddress(IPAddress address)
{
if (address.AddressFamily == AddressFamily.InterNetworkV6)
{
return address.IsIPv6LinkLocal;
}
// 169.254.0.0/16
var addrBytes = address.GetAddressBytes();
return addrBytes[0] == 0xA9 && addrBytes[1] == 0xFE;
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment