1 module neton.client.registry.HeartBeat;
2 
3 import hunt.logging;
4 import grpc;
5 import neton.protocol.neton;
6 import neton.protocol.neton;
7 import neton.protocol.netonrpc;
8 
9 import hunt.concurrency.ScheduledThreadPoolExecutor;
10 import hunt.concurrency.ThreadPoolExecutor;
11 import hunt.concurrency.Executors;
12 import hunt.concurrency.ExecutorService;
13 import hunt.concurrency.Future;
14 import hunt.util.Common;
15 import core.time;
16 import std.stdio;
17 
18 class HeartBeat
19 {
20     private
21     {
22         LeaseClient _client;
23         long _leaseID;
24         ScheduledThreadPoolExecutor _executor;
25     }
26 
27     this(Channel channel)
28     {
29         _client = new LeaseClient(channel);
30         _executor = cast(ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(1);
31     }
32 
33     bool grant(long ttl, ref long ID)
34     {
35         assert(ttl > 1);
36 
37         LeaseGrantRequest request = new LeaseGrantRequest();
38         request.TTL = ttl;
39         request.ID = ID;
40 
41         LeaseGrantResponse response = _client.LeaseGrant(request);
42         if (response is null)
43         {
44             logError("LeaseGrant error : ",ID);
45             return false;
46         }
47         ID = response.ID;
48         _leaseID = ID;
49         return true;
50     }
51 
52     void start()
53     {
54         synchronized (this)
55         {
56             LeaseKeepAliveRequest request = new LeaseKeepAliveRequest();
57             request.ID = _leaseID;
58             auto stream = _client.LeaseKeepAlive();
59             stream.write(request);
60             LeaseKeepAliveResponse response;
61             stream.read(response);
62 
63             _executor.scheduleAtFixedRate(new HeartBeatTask(stream,request),
64                     seconds(response.TTL/2 + 1), seconds(response.TTL - 1));
65         }
66     }
67 
68     bool stop()
69     {
70         synchronized (this)
71         {
72             version(HUNT_DEBUG)logInfo("------ stop heartBeat : ",_leaseID);
73             _executor.shutdown();
74             LeaseRevokeRequest request = new LeaseRevokeRequest();
75             request.ID = _leaseID;
76             LeaseRevokeResponse response = _client.LeaseRevoke(request);
77             if (response is null)
78             {
79                 logError("LeaseRevoke error : ",_leaseID);
80                 return false;
81             }
82             return true;
83         }
84     }
85 }
86 
87 class HeartBeatTask : Runnable
88 {
89     private
90     {
91         LeaseKeepAliveRequest _request;
92         ClientReaderWriter!(LeaseKeepAliveResponse,LeaseKeepAliveRequest) _stream;
93     }
94 
95     this(ClientReaderWriter!(LeaseKeepAliveResponse,LeaseKeepAliveRequest) stream, LeaseKeepAliveRequest req)
96     {
97         _stream = stream;  
98         _request = req;
99     }
100 
101     void run()
102     {
103         version(HUNT_DEBUG)logInfo("send heart beat : ",_request.ID);
104         LeaseKeepAliveResponse response;
105         _stream.write(_request);
106         _stream.read(response);
107     }
108 
109 }