1 module neton.client.Watcher;
2 
3 import neton.protocol.neton;
4 import neton.protocol.neton;
5 import neton.protocol.netonrpc;
6 import neton.client.Listener;
7 import neton.client.Event;
8 import neton.util.future;
9 import grpc;
10 import hunt.logging;
11 import core.thread;
12 import std.algorithm.mutation;
13 import std.stdio;
14 
15 class Watcher
16 {
17     private
18     {
19         string _prefix;
20 
21         ClientReaderWriter!(WatchResponse, WatchRequest) _stream;
22         Future!(int, WatchResponse) _createWatch;
23         Future!(int, WatchResponse) _cancelWatch;
24         Listener[][long] _listenMap;
25         long[string] _keyWatchIdMap;
26 
27     }
28 
29     long watch(string key, Listener lit)
30     {
31         writefln("watch key: %s , listener :%s ", key, lit);
32         string configKey = _prefix ~ "/" ~ key;
33         if (key in _keyWatchIdMap)
34         {
35             auto id = _keyWatchIdMap[key];
36             if (id in _listenMap)
37             {
38                 _listenMap[id] ~= lit;
39                 return id;
40             }
41             else
42             {
43                 _keyWatchIdMap.remove(key);
44             }
45         }
46 
47         WatchRequest request = new WatchRequest();
48         request._requestUnionCase = WatchRequest.RequestUnionCase.createRequest;
49         request._createRequest = new WatchCreateRequest();
50         request._createRequest.key = cast(ubyte[]) configKey;
51         ubyte[] end = cast(ubyte[]) configKey.dup;
52         request._createRequest.rangeEnd = end;
53         end[$ - 1] += 1;
54         _stream.write(request);
55 
56         auto f = new Future!(int, WatchResponse)(0);
57         _createWatch = f;
58         WatchResponse response = f.get();
59         auto id = response.watchId;
60         _listenMap[id] ~= lit;
61         _keyWatchIdMap[key] = id;
62         return id;
63     }
64 
65     bool cancel(string key, Listener listener)
66     {
67         writefln("cancel watch key: %s , listener :%s ", key, listener);
68 
69         long id;
70         if (key in _keyWatchIdMap)
71         {
72             id = _keyWatchIdMap[key];
73             // logError("before cancel size : ", _listenMap[id].length);
74             _listenMap[id] = remove!(a => a is listener)(_listenMap[id]);
75             // logError("after cancel size : ", _listenMap[id].length);
76             if (_listenMap[id].length > 0)
77                 return true;
78         }
79         else
80             return false;
81         WatchRequest request = new WatchRequest();
82         request._requestUnionCase = WatchRequest.RequestUnionCase.cancelRequest;
83         request._cancelRequest = new WatchCancelRequest();
84         request._cancelRequest.watchId = id;
85         _stream.write(request);
86         auto f = new Future!(int, WatchResponse)(0);
87         _cancelWatch = f;
88         f.get();
89         return true;
90     }
91 
92     this(ClientReaderWriter!(WatchResponse, WatchRequest) stream, string prefix)
93     {
94         this._stream = stream;
95         this._prefix = prefix;
96 
97         new Thread(() {
98             WatchResponse response;
99             try
100             {
101                 while (_stream.read(response))
102                 {
103                     // logError("begin ",);
104                     if (response.created)
105                     {
106                         // logError("created ", response.watchId);
107                         _createWatch.done(response);
108                     }
109                     else if (response.canceled)
110                     {
111                         // logError("canceled ", response.watchId);
112                         _cancelWatch.done(response);
113                     }
114                     else
115                     {
116                         // logError("other ");
117                         foreach (neton.protocol.neton.Event e; response.events)
118                         {
119                             neton.client.Event.Event event;
120                             event.key = cast(string) e.kv.key;
121                             event.value = cast(string) e.kv.value;
122                             auto type = cast(int)(e.type);
123                             event.type = cast(neton.client.Event.Event.EventType) type;
124                             auto id = response.watchId;
125                             // logError("errr start ", response.watchId);
126                             if (id in _listenMap)
127                             {
128                                 foreach (listener; _listenMap[id])
129                                     listener.onEvent(event);
130                             }
131                             // logError("errr end ", response.watchId);
132                         }
133                     }
134                     // logError("end");
135                 }
136             }
137             catch (Throwable e)
138             {
139                 logError(e.msg);
140             }
141             // logError("in false");
142         }).start();
143     }
144 
145     bool close()
146     {
147         _stream.writesDone();
148         return _stream.finish().ok();
149     }
150 
151 }