Skip to content

Commit f161eb0

Browse files
committed
Add CounterGrain
1 parent b1893be commit f161eb0

File tree

9 files changed

+166
-4
lines changed

9 files changed

+166
-4
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace OrleansTemplate.Abstractions.Grains
2+
{
3+
using System.Threading.Tasks;
4+
using Orleans;
5+
6+
/// <summary>
7+
/// Holds the total count.
8+
/// </summary>
9+
/// <remarks>Implemented using the 'Reduce' pattern (See https://github.com/OrleansContrib/DesignPatterns/blob/master/Reduce.md).</remarks>
10+
/// <seealso cref="IGrainWithGuidKey" />
11+
public interface ICounterGrain : IGrainWithGuidKey
12+
{
13+
Task<long> AddCount(long value);
14+
15+
Task<long> GetCount();
16+
}
17+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace OrleansTemplate.Abstractions.Grains
2+
{
3+
using System.Threading.Tasks;
4+
using Orleans;
5+
6+
/// <summary>
7+
/// Holds the total count on a given silo and then feeds this forward to the <see cref="ICounterGrain"/>.
8+
/// </summary>
9+
/// <remarks>Implemented using the 'Reduce' pattern (See https://github.com/OrleansContrib/DesignPatterns/blob/master/Reduce.md).</remarks>
10+
/// <seealso cref="IGrain" />
11+
public interface ICounterStatelessGrain : IGrainWithIntegerKey
12+
{
13+
Task Increment();
14+
}
15+
}

Source/Content/OrleansTemplate/Source/OrleansTemplate.Client/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ private static IClientBuilder CreateClientBuilder() =>
4343
})
4444
.ConfigureApplicationParts(
4545
parts => parts
46-
.AddApplicationPart(typeof(IHelloGrain).Assembly)
46+
.AddApplicationPart(typeof(ICounterGrain).Assembly)
4747
.WithReferences())
4848
.AddSimpleMessageStreamProvider(StreamProviderName.Default);
4949
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace OrleansTemplate.Grains
2+
{
3+
using System.Threading.Tasks;
4+
using Orleans;
5+
using OrleansTemplate.Abstractions.Grains;
6+
7+
public class CounterGrain : Grain<long>, ICounterGrain
8+
{
9+
public async Task<long> AddCount(long value)
10+
{
11+
this.State += value;
12+
await this.WriteStateAsync();
13+
return this.State;
14+
}
15+
16+
public Task<long> GetCount() => Task.FromResult(this.State);
17+
}
18+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
namespace OrleansTemplate.Grains
2+
{
3+
using System;
4+
using System.Threading.Tasks;
5+
using Orleans;
6+
using Orleans.Concurrency;
7+
using OrleansTemplate.Abstractions.Grains;
8+
9+
/// <summary>
10+
/// An implementation of the 'Reduce' pattern (See https://github.com/OrleansContrib/DesignPatterns/blob/master/Reduce.md).
11+
/// </summary>
12+
/// <seealso cref="Grain" />
13+
/// <seealso cref="ICounterStatelessGrain" />
14+
[StatelessWorker]
15+
public class CounterStatelessGrain : Grain, ICounterStatelessGrain
16+
{
17+
private long count = 0;
18+
19+
public Task Increment()
20+
{
21+
this.count += 1;
22+
return Task.CompletedTask;
23+
}
24+
25+
public override Task OnActivateAsync()
26+
{
27+
this.RegisterTimer(this.OnTimerTick, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
28+
return base.OnActivateAsync();
29+
}
30+
31+
private Task OnTimerTick(object arg)
32+
{
33+
var count = this.count;
34+
this.count = 0;
35+
var counter = this.GrainFactory.GetGrain<ICounterGrain>(Guid.Empty);
36+
return counter.AddCount(count);
37+
}
38+
}
39+
}

Source/Content/OrleansTemplate/Source/OrleansTemplate.Grains/HelloGrain.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ namespace OrleansTemplate.Grains
66

77
public class HelloGrain : Grain, IHelloGrain
88
{
9-
public Task<string> SayHello(string name) => Task.FromResult($"Hello {name}!");
9+
public async Task<string> SayHello(string name)
10+
{
11+
var counter = this.GrainFactory.GetGrain<ICounterStatelessGrain>(0L);
12+
await counter.Increment();
13+
14+
return $"Hello {name}!";
15+
}
1016
}
1117
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
namespace OrleansTemplate.Server.IntegrationTest
2+
{
3+
using System;
4+
using System.Threading.Tasks;
5+
using OrleansTemplate.Abstractions.Grains;
6+
using OrleansTemplate.Server.IntegrationTest.Fixtures;
7+
using Xunit;
8+
9+
public class CounterGrainTest
10+
{
11+
[Fact]
12+
public async Task AddCount_PassValue_ReturnsTotalCount()
13+
{
14+
using (var fixture = new ClusterFixture())
15+
{
16+
var grain = fixture.Cluster.GrainFactory.GetGrain<ICounterGrain>(Guid.Empty);
17+
18+
var count = await grain.AddCount(10L);
19+
20+
Assert.Equal(10L, count);
21+
}
22+
}
23+
24+
[Fact]
25+
public async Task GetCount_Default_ReturnsTotalCount()
26+
{
27+
using (var fixture = new ClusterFixture())
28+
{
29+
var grain = fixture.Cluster.GrainFactory.GetGrain<ICounterGrain>(Guid.Empty);
30+
31+
var count = await grain.GetCount();
32+
33+
Assert.Equal(0L, count);
34+
}
35+
}
36+
}
37+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
namespace OrleansTemplate.Server.IntegrationTest
2+
{
3+
using System;
4+
using System.Threading.Tasks;
5+
using OrleansTemplate.Abstractions.Grains;
6+
using OrleansTemplate.Server.IntegrationTest.Fixtures;
7+
using Xunit;
8+
9+
public class CounterStatelessGrainTest
10+
{
11+
[Fact]
12+
public async Task Increment_Default_EventuallyIncrementsTotalCount()
13+
{
14+
using (var fixture = new ClusterFixture())
15+
{
16+
var grain = fixture.Cluster.GrainFactory.GetGrain<ICounterStatelessGrain>(0L);
17+
var counterGrain = fixture.Cluster.GrainFactory.GetGrain<ICounterGrain>(Guid.Empty);
18+
19+
await grain.Increment();
20+
var countBefore = await counterGrain.GetCount();
21+
22+
Assert.Equal(0L, countBefore);
23+
24+
await Task.Delay(TimeSpan.FromSeconds(2));
25+
26+
var countAfter = await counterGrain.GetCount();
27+
}
28+
}
29+
}
30+
}

Source/Content/OrleansTemplate/Tests/OrleansTemplate.Server.IntegrationTest/HelloGrainTest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ public class HelloGrainTest : IClassFixture<ClusterFixture>
1616
[Fact]
1717
public async Task SayHello_PassName_ReturnsGreeting()
1818
{
19-
var helloGrain = this.cluster.GrainFactory.GetGrain<IHelloGrain>(Guid.NewGuid());
19+
var grain = this.cluster.GrainFactory.GetGrain<IHelloGrain>(Guid.NewGuid());
2020

21-
var greeting = await helloGrain.SayHello("Rehan");
21+
var greeting = await grain.SayHello("Rehan");
2222

2323
Assert.Equal("Hello Rehan!", greeting);
2424
}

0 commit comments

Comments
 (0)