Skip to content

Commit b67f041

Browse files
authored
Update README.md
1 parent 9758d14 commit b67f041

File tree

1 file changed

+109
-1
lines changed

1 file changed

+109
-1
lines changed

README.md

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,109 @@
1-
# Topshelf.Leader
1+
# Topshelf.Leader
2+
3+
An extension method to the Topshelf `ServiceConfigurator<T>` class that adds Leader checking to the service startup.
4+
5+
## Getting started
6+
```
7+
Install-Package Topshelf.Leader
8+
```
9+
10+
Once the package is installed, create a Console application and wireup the Topshelf service as you normally would except for the `WhenStarted()` method - this should no longer be used.
11+
12+
You should use the `WhenStartedAsLeader()` method that Topshelf.Leader provides instead which constains its own version of the `WhenStarted()` method, one with cancellation token support.
13+
14+
### Example
15+
```c#
16+
using Topshelf.Leader;
17+
18+
public class Program
19+
{
20+
static void Main(string[] args)
21+
{
22+
var rc = HostFactory.Run(x =>
23+
{
24+
x.Service<TheService>(s =>
25+
{
26+
s.WhenStartedAsLeader(builder =>
27+
{
28+
builder.WhenStarted(async (service, token) =>
29+
{
30+
await service.Start(token);
31+
});
32+
});
33+
s.ConstructUsing(name => new TheService());
34+
s.WhenStopped(service => service.Stop());
35+
});
36+
}
37+
}
38+
}
39+
```
40+
41+
## How does it work?
42+
43+
The `WhenStarted()` method will be executed when the service discovers that it is the current leader. If that situation changes the cancellation token will be set to cancelled. You decide how to handle this situation, throw an exception, exit gracefully or even carry on whatever you were doing - that's entirely up to you.
44+
45+
### Example of a service which supports leadership change
46+
```c#
47+
public class TestService
48+
{
49+
public async Task Start(CancellationToken stopToken)
50+
{
51+
while (!stopToken.IsCancellationRequested)
52+
{
53+
// do your work here, if it's async pass the stopToken to it
54+
}
55+
}
56+
}
57+
```
58+
59+
## Leadership Manager
60+
61+
The responsibility for deciding who is the leader, and maintaining that status is delegated to any class which implements the `ILeaderManager` interface. You configure which manager to use during the configuration stage. If one isn't supplied then an in memory manager is used - this is not muti-process aware so is **not suitable for production use - only for testing**.
62+
63+
### Configuring the leadership manager
64+
```c#
65+
var rc = HostFactory.Run(x =>
66+
{
67+
x.Service<TheService>(s =>
68+
{
69+
s.WhenStartedAsLeader(builder =>
70+
{
71+
builder.WhenStarted(async (service, token) =>
72+
{
73+
await service.Start(token);
74+
});
75+
builder.WithLeadershipManager(new YourManagerHere());
76+
});
77+
s.ConstructUsing(name => new TheService());
78+
s.WhenStopped(service => service.Stop());
79+
});
80+
}
81+
```
82+
83+
### Example of a simple leadership manager
84+
```c#
85+
public class InMemoryLeadershipManager : ILeadershipManager
86+
{
87+
private string owningNodeId;
88+
89+
public InMemoryLeadershipManager(string owningNodeId)
90+
{
91+
this.owningNodeId = owningNodeId;
92+
}
93+
94+
public void AssignLeader(string newLeaderId)
95+
{
96+
this.owningNodeId = newLeaderId;
97+
}
98+
99+
public Task<bool> AcquireLock(string nodeId, CancellationToken token)
100+
{
101+
return Task.FromResult(nodeId == owningNodeId);
102+
}
103+
104+
public Task<bool> RenewLock(string nodeId, CancellationToken token)
105+
{
106+
return Task.FromResult(nodeId == owningNodeId);
107+
}
108+
}
109+
```

0 commit comments

Comments
 (0)