-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdispatcher_client.ml
155 lines (140 loc) · 5.45 KB
/
dispatcher_client.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
module M_p = Message_processor
module M_p_c = Message_processor_client
module type Processor_client_inst = sig
module Processor: M_p_c.Processor
val update: Processor.Client.t -> unit
val update_bus: Processor.Client.t Bus.t
val client: Processor.Client.t ref
val order: int
val react_class: Reactjs.Low_level_bindings.react_class Js.t
end;;
module Client = struct
type t = (string, (module Processor_client_inst)) Hashtbl.t
let client_payload_to_string payload =
Yojson.Safe.to_string
(M_p.Client_payload.to_yojson payload)
let send_client_payload ws payload =
ws##send (Js.string (client_payload_to_string payload))
let create l =
let table: t = Hashtbl.create 10 in
List.iter begin
fun (module M: Processor_client_inst) ->
Hashtbl.add table (M.Processor.Client.get_name !(M.client)) (module M: Processor_client_inst)
end l;
table
let initial_request t ws =
Hashtbl.iter begin
fun name _ ->
send_client_payload ws (M_p.Client_payload.Full name);
end t
let process_server_payload t ws server_payload =
match server_payload with
| M_p.Server_payload.Full (name, version, data) -> begin
try
let (module M: Processor_client_inst) = Hashtbl.find t name in
match M.Processor.set_client_state !M.client data version with
| Ok client -> Ok (M.update client)
| Error _ as err -> err
with
Not_found -> Error ("Can't find processor " ^ name)
end
| M_p.Server_payload.Update (name, version, data) -> begin
try
let (module M: Processor_client_inst) = Hashtbl.find t name in
match M.Processor.update_client_state !M.client data version with
| Ok client -> Ok (M.update client)
| Error "Version mismatch" ->
send_client_payload ws (M_p.Client_payload.Full name);
Ok ()
| Error _ as err -> err
with
Not_found -> Error ("Can't find processor " ^ name)
end
| M_p.Server_payload.Empty -> Ok ()
let render_processor name (module M: Processor_client_inst) =
let open Reactjs in
let open Reactjs.Infix in
let open Util_react in
let title = M.Processor.Client.get_title !M.client in
Elem (DOM.make
~tag: `div
~class_name: "processor"
~elem_spec: (object%js
val key = !* name
end)
((match title with
| Some str -> [
el `div "title" [ Text str ]
]
| None -> []) @
[
el `div "content" [
Elem (create_element_from_class M.react_class)
]
])
)
let render t container_id child_components =
let open Reactjs in
let open Util_react in
let processors = List.sort
(fun (_, (module M1: Processor_client_inst)) (_, (module M2: Processor_client_inst)) -> M2.order - M1.order)
(Hashtbl.fold (fun name inst res -> (name, inst) :: res) t []) in
let react_elem =
begin
fun ~this ->
node `div "main"
((List.map (fun comp -> Elem (create_element_from_class comp)) child_components)
@
[
el `div "processors" [
el `div "processors-inner"
(List.fold_left (fun res (name, inst) -> (render_processor name inst) :: res) [] processors)
]
])
end
|> make_class_spec
|> create_class
|> create_element_from_class in
render ~react_elem (get_elem ~id: container_id)
end
let create_processor_client_inst
(type a)
?name
?title
(module P: M_p_c.Processor with type config = a)
order
config =
(module struct
module Processor = P
let client = ref (Processor.Client.create ?name ?title config order)
let order = order
let update_bus = Bus.create !client
let update t =
client := t;
Bus.emit update_bus t;
(*Processor.Client.print_state t*)
()
let react_class = Processor.get_react_class !client update_bus
end: Processor_client_inst)
let client = Client.create [
create_processor_client_inst (module Total_count_processor_client)
3
{ interval_s = 60 * 60 }
~name: "total_hour"
~title: "1 hour";
create_processor_client_inst (module Total_count_processor_client)
2
{ interval_s = 60 }
~name: "total_minute"
~title: "1 minute before the last one";
(*create_processor_client_inst (module Frequency_processor_client)
1
{ interval_s = 60 * 10; decay_s = 60 * 60 * 24 }
~title: "10min intervals";*)
create_processor_client_inst (module Conversations_processor_client)
0
{ interval_s = 60 * 10; decay_s = 60 * 60 * 24; history_limit = -1 };
create_processor_client_inst (module Last_seen_processor_client)
(-1)
()
]