70 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			70 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using dotnet_etcd;
 | |
| using Etcdserverpb;
 | |
| using Grpc.Core;
 | |
| 
 | |
| namespace DysonNetwork.Shared.Etcd;
 | |
| 
 | |
| public class EtcdService(string connectionString) : IEtcdService
 | |
| {
 | |
|     private readonly EtcdClient _etcdClient = new(connectionString);
 | |
|     private long _leaseId;
 | |
|     private string? _serviceKey;
 | |
|     private readonly CancellationTokenSource _cts = new();
 | |
| 
 | |
|     public async Task RegisterServiceAsync(string serviceName, string serviceAddress, int ttl = 15)
 | |
|     {
 | |
|         _serviceKey = $"/services/{serviceName}/{Guid.NewGuid()}";
 | |
|         var leaseGrantResponse = await _etcdClient.LeaseGrantAsync(new LeaseGrantRequest { TTL = ttl });
 | |
|         _leaseId = leaseGrantResponse.ID;
 | |
| 
 | |
|         await _etcdClient.PutAsync(new PutRequest
 | |
|         {
 | |
|             Key = Google.Protobuf.ByteString.CopyFromUtf8(_serviceKey),
 | |
|             Value = Google.Protobuf.ByteString.CopyFromUtf8(serviceAddress),
 | |
|             Lease = _leaseId
 | |
|         });
 | |
| 
 | |
|         _ = Task.Run(async () =>
 | |
|         {
 | |
|             while (!_cts.Token.IsCancellationRequested)
 | |
|             {
 | |
|                 try
 | |
|                 {
 | |
|                     await _etcdClient.LeaseKeepAlive(new LeaseKeepAliveRequest { ID = _leaseId },
 | |
|                         _ => { }, _cts.Token);
 | |
|                     await Task.Delay(TimeSpan.FromSeconds(ttl / 3), _cts.Token);
 | |
|                 }
 | |
|                 catch (RpcException)
 | |
|                 {
 | |
|                     // Ignored
 | |
|                 }
 | |
|             }
 | |
|         }, _cts.Token);
 | |
|     }
 | |
| 
 | |
|     public async Task UnregisterServiceAsync()
 | |
|     {
 | |
|         if (!string.IsNullOrEmpty(_serviceKey))
 | |
|         {
 | |
|             await _etcdClient.DeleteRangeAsync(_serviceKey);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public async Task<List<string>> DiscoverServicesAsync(string serviceName)
 | |
|     {
 | |
|         var prefix = $"/services/{serviceName}/";
 | |
|         var rangeResponse = await _etcdClient.GetRangeAsync(prefix);
 | |
|         return rangeResponse.Kvs.Select(kv => kv.Value.ToStringUtf8()).ToList();
 | |
|     }
 | |
| 
 | |
|     public void Dispose()
 | |
|     {
 | |
|         _cts.Cancel();
 | |
|         if (_leaseId != 0)
 | |
|         {
 | |
|             _etcdClient.LeaseRevoke(new LeaseRevokeRequest { ID = _leaseId });
 | |
|         }
 | |
| 
 | |
|         _etcdClient.Dispose();
 | |
|     }
 | |
| } |