hq-engine 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,431 @@
1
+ module HQ
2
+ module Engine
3
+ module LibXmlRubyMixin
4
+
5
+ def load_data_file filename
6
+
7
+ ret = []
8
+
9
+ doc =
10
+ XML::Document.file \
11
+ filename,
12
+ :options =>XML::Parser::Options::NOBLANKS
13
+
14
+ return doc.find("//data/*").to_a
15
+
16
+ end
17
+
18
+ def load_data_string string
19
+
20
+ ret = []
21
+
22
+ doc =
23
+ XML::Document.string \
24
+ string,
25
+ :options =>XML::Parser::Options::NOBLANKS
26
+
27
+ return doc.find("//data/*").to_a
28
+
29
+ end
30
+
31
+ def write_data_file filename, data
32
+
33
+ doc = XML::Document.new
34
+ doc.root = XML::Node.new "data"
35
+
36
+ data.each do
37
+ |item|
38
+ doc.root << doc.import(item)
39
+ end
40
+
41
+ File.open filename, "w" do |f|
42
+ f.print doc.to_s
43
+ end
44
+
45
+ end
46
+
47
+
48
+ def load_schema_file filename
49
+
50
+ schema_doc =
51
+ XML::Document.file filename
52
+
53
+ schema =
54
+ Hash[
55
+ schema_doc.find("*").map do
56
+ |schema_elem|
57
+ [
58
+ "%s/%s" % [
59
+ schema_elem.name,
60
+ schema_elem["name"],
61
+ ],
62
+ schema_elem,
63
+ ]
64
+ end
65
+ ]
66
+
67
+ return schema
68
+
69
+ end
70
+
71
+ def field_to_json schemas, schema_elem, fields_elem, elem, value
72
+
73
+ fields_elem.find(
74
+ "* [name() != 'option']
75
+ ").each do
76
+ |field_elem|
77
+
78
+ field_name =
79
+ field_elem["name"]
80
+
81
+ case field_elem.name
82
+
83
+ when "text"
84
+
85
+ value[field_name] =
86
+ elem[field_name]
87
+
88
+ when "int", "ts-update"
89
+
90
+ temp = elem.attributes[field_name]
91
+
92
+ value[field_name] = temp.empty? ? nil : temp.to_i
93
+
94
+ when "list"
95
+
96
+ value[field_name] = []
97
+
98
+ elem.find("* [ name () = #{xp field_name} ]") \
99
+ .each do |child_elem|
100
+
101
+ prop = {}
102
+
103
+ field_to_json \
104
+ schemas,
105
+ schema_elem,
106
+ field_elem,
107
+ child_elem,
108
+ prop
109
+
110
+ value[field_name] << prop
111
+ end
112
+
113
+ when "struct"
114
+
115
+ prop = {}
116
+
117
+ child_elem =
118
+ elem.find_first \
119
+ "* [ name () = #{xp field_name} ]"
120
+
121
+ if child_elem
122
+ field_to_json \
123
+ schemas,
124
+ schema_elem,
125
+ field_elem,
126
+ child_elem,
127
+ prop
128
+ end
129
+
130
+ value[field_name] = prop unless prop.empty?
131
+
132
+ when "xml"
133
+
134
+ value[field_name] = ""
135
+
136
+ elem.find("* [ name () = #{xp field_name} ] / *") \
137
+ .each do |prop|
138
+
139
+ value[field_name] += prop.to_s
140
+ end
141
+
142
+ when "bool"
143
+
144
+ value[field_name] = \
145
+ elem.attributes[field_name] == "yes"
146
+
147
+ when "bigtext"
148
+
149
+ value[field_name] =
150
+ elem.find_first("* [ name () = #{xp field_name} ]") \
151
+ .content
152
+
153
+ else
154
+
155
+ raise "unexpected element #{field_elem.name} found in " \
156
+ "field list for schema " \
157
+ "#{schema_elem.attributes["name"]}"
158
+
159
+ end
160
+ end
161
+
162
+ content = []
163
+
164
+ elem.find("*").each do |child_elem|
165
+
166
+ option_elem =
167
+ fields_elem.find_first \
168
+ "option [ @name = #{xp child_elem.name} ]"
169
+
170
+ next unless option_elem
171
+
172
+ option_ref =
173
+ option_elem.attributes["ref"]
174
+
175
+ schema_option_elem =
176
+ schemas["schema-opion/#{option_ref}"]
177
+
178
+ raise "Error" \
179
+ unless schema_option_elem
180
+
181
+ schema_option_props_elem =
182
+ schema_option_elem.find_first "props"
183
+
184
+ prop = {}
185
+
186
+ field_to_json \
187
+ schemas,
188
+ schema_elem,
189
+ schema_option_props_elem,
190
+ child_elem,
191
+ prop
192
+
193
+ content << {
194
+ "type" => child_elem.name,
195
+ "value" => prop,
196
+ }
197
+
198
+ end
199
+
200
+ value["content"] = content \
201
+ unless content.empty?
202
+
203
+ end
204
+
205
+ def js_to_xml schemas, type, value
206
+
207
+ schema_elem =
208
+ schemas["schema/#{type}"]
209
+
210
+ elem =
211
+ XML::Node.new type
212
+
213
+ field_to_xml \
214
+ schemas,
215
+ schema_elem.find_first("id"),
216
+ value,
217
+ elem
218
+
219
+ field_to_xml \
220
+ schemas,
221
+ schema_elem.find_first("fields"),
222
+ value,
223
+ elem
224
+
225
+ return elem
226
+
227
+ end
228
+
229
+ def xml_to_json schemas, schema_elem, elem
230
+
231
+ value = {}
232
+
233
+ field_to_json \
234
+ schemas,
235
+ schema_elem,
236
+ schema_elem.find_first("id"),
237
+ elem,
238
+ value
239
+
240
+ field_to_json \
241
+ schemas,
242
+ schema_elem,
243
+ schema_elem.find_first("fields"),
244
+ elem,
245
+ value
246
+
247
+ return value
248
+ end
249
+
250
+ def field_to_xml schemas, fields_elem, value, elem
251
+
252
+ unless value.is_a? Hash
253
+ value = {}
254
+ end
255
+
256
+ fields_elem.find("
257
+ * [name() != 'option']
258
+ ").each do
259
+ |field_elem|
260
+
261
+ field_name =
262
+ field_elem["name"]
263
+
264
+ case field_elem.name
265
+
266
+ when "text", "int", "ts-update", "enum"
267
+ elem[field_name] = value[field_name].to_s
268
+
269
+ when "bigtext"
270
+ prop = XML::Node.new field_name
271
+ prop << value[field_name]
272
+ elem << prop
273
+
274
+ when "bool"
275
+ elem[field_name] = "yes" if value[field_name]
276
+
277
+ when "list"
278
+
279
+ items = value[field_name]
280
+
281
+ if items.is_a? Array
282
+
283
+ items.each do
284
+ |item|
285
+
286
+ prop =
287
+ XML::Node.new field_name
288
+
289
+ field_to_xml \
290
+ schemas,
291
+ field_elem,
292
+ item,
293
+ prop
294
+
295
+ elem << prop
296
+
297
+ end
298
+
299
+ end
300
+
301
+ when "struct"
302
+
303
+ prop =
304
+ XML::Node.new field_name
305
+
306
+ field_to_xml \
307
+ schemas,
308
+ field_elem,
309
+ value[field_name],
310
+ prop
311
+
312
+ if prop.attributes.length + prop.children.size > 0
313
+ elem << prop
314
+ end
315
+
316
+ when "xml"
317
+
318
+ prop =
319
+ XML::Node.new field_name
320
+
321
+ temp_doc =
322
+ XML::Document.string \
323
+ "<xml>#{value[field_name]}</xml>",
324
+ :options =>XML::Parser::Options::NOBLANKS
325
+
326
+ temp_doc.root.each do
327
+ |temp_elem|
328
+ prop << temp_elem.copy(true)
329
+ end
330
+
331
+ elem << prop
332
+
333
+ else
334
+
335
+ raise "unexpected element #{field_elem.name} found in field "
336
+ "list for schema #{schema_elem["name"]}"
337
+
338
+ end
339
+
340
+ end
341
+
342
+ if value["content"].is_a? Array
343
+
344
+ value["content"].each do
345
+ |item|
346
+
347
+ item_type = item["type"]
348
+ item_value = item["value"]
349
+
350
+ option_elem =
351
+ fields_elem.find_first "
352
+ option [@name = '#{item_type}']
353
+ "
354
+
355
+ next unless option_elem
356
+
357
+ option_ref =
358
+ option_elem["ref"]
359
+
360
+ schema_option_elem =
361
+ schemas["schema-option/#{option_ref}"]
362
+
363
+ next unless schema_option_elem
364
+
365
+ schema_option_props_elem =
366
+ schema_option_elem.find_first "props"
367
+
368
+ prop =
369
+ XML::Node.new item_type
370
+
371
+ field_to_xml \
372
+ schemas,
373
+ schema_option_props_elem,
374
+ item_value,
375
+ prop
376
+
377
+ elem << prop
378
+
379
+ end
380
+
381
+ end
382
+
383
+ end
384
+
385
+ def get_record_id_short schemas, record_elem
386
+
387
+ schema_elem =
388
+ schemas["schema/#{record_elem.name}"]
389
+
390
+ unless schema_elem
391
+ raise "No schema for #{record_elem.name}"
392
+ end
393
+
394
+ id_parts =
395
+ schema_elem.find("id/*").to_a.map do
396
+ |id_elem|
397
+
398
+ part =
399
+ record_elem[id_elem["name"]]
400
+
401
+ unless part
402
+ raise "No #{id_elem["name"]} for #{record_elem.name}"
403
+ end
404
+
405
+ part
406
+
407
+ end
408
+
409
+ id =
410
+ id_parts.join "/"
411
+
412
+ return id
413
+
414
+ end
415
+
416
+ def get_record_id_long schemas, record_elem
417
+
418
+ return "%s/%s" % [
419
+ record_elem.name,
420
+ get_record_id_short(schemas, record_elem),
421
+ ]
422
+
423
+ end
424
+
425
+ def to_xml_string elem
426
+ return elem.to_s
427
+ end
428
+
429
+ end
430
+ end
431
+ end
@@ -0,0 +1,95 @@
1
+ module HQ
2
+ module Engine
3
+ class MVCC
4
+
5
+ attr_accessor :transactions
6
+
7
+ def initialize
8
+ @transactions = {}
9
+ end
10
+
11
+ def generate_transaction_id
12
+ chars = (?a..?z).to_a
13
+ return (0...20).map { chars.sample }.join
14
+ end
15
+ -
16
+ def transaction_begin
17
+
18
+ tx_id =
19
+ generate_transaction_id
20
+
21
+ @transactions[tx_id] =
22
+ {
23
+ state: :begun,
24
+ changes: {},
25
+ }
26
+
27
+ return tx_id
28
+
29
+ end
30
+
31
+ def transaction_commit transaction_id
32
+
33
+ transaction =
34
+ @transactions[transaction_id]
35
+
36
+ transaction[:state] =
37
+ :committed
38
+
39
+ end
40
+
41
+ def transaction_rollback transaction_id
42
+
43
+ transaction =
44
+ @transactions[transaction_id]
45
+
46
+ transaction[:state] =
47
+ :rolled_back
48
+
49
+ end
50
+
51
+ def get_transaction_info transaction_id
52
+
53
+ transaction =
54
+ @transactions[transaction_id]
55
+
56
+ unless transaction
57
+ return nil
58
+ end
59
+
60
+ transaction_info = {
61
+ state: transaction[:state],
62
+ }
63
+
64
+ return transaction_info
65
+
66
+ end
67
+
68
+ def data_store \
69
+ transaction_id,
70
+ record_id,
71
+ record_value
72
+
73
+ transaction =
74
+ @transactions[transaction_id]
75
+
76
+ transaction[:changes][record_id] =
77
+ record_value
78
+
79
+ end
80
+
81
+ def data_retrieve \
82
+ transaction_id,
83
+ record_id
84
+
85
+ transaction =
86
+ @transactions[transaction_id]
87
+
88
+ return \
89
+ transaction[:changes][record_id]
90
+
91
+ end
92
+
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,20 @@
1
+ module HQ
2
+ module Engine
3
+
4
+ def self.register_commands hq
5
+
6
+ hq.register_command \
7
+ "unlock",
8
+ nil,
9
+ "Unlock crashed deployment" \
10
+ do
11
+ require "hq/engine/unlock-command"
12
+ command = HQ::Engine::UnlockCommand.new
13
+ command.hq = hq
14
+ command
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ module HQ
2
+ module Engine
3
+
4
+ class RuleError < RuntimeError
5
+
6
+ attr_accessor :file
7
+ attr_accessor :line
8
+ attr_accessor :column
9
+ attr_accessor :message
10
+
11
+ def to_s
12
+ return "bananas"
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,70 @@
1
+ require "multi_json"
2
+
3
+ module HQ
4
+ module Engine
5
+ class SubProcessRuleProvider
6
+
7
+ def initialize req_wr, resp_rd
8
+
9
+ @state = :error
10
+
11
+ @req_wr = req_wr
12
+ @resp_rd = resp_rd
13
+
14
+ @state = :open
15
+
16
+ end
17
+
18
+ def close
19
+
20
+ @state == :open \
21
+ or raise "Invalid state #{@state}"
22
+
23
+ @state = :error
24
+
25
+ @req_wr.close
26
+ @resp_rd.close
27
+
28
+ @state = :closed
29
+
30
+ end
31
+
32
+ def session
33
+
34
+ @state == :open \
35
+ or raise "Invalid state #{@state}"
36
+
37
+ require "hq/engine/subprocess-rule-provider/session"
38
+
39
+ chars = "abcdefghijklmnopqrstuvwxyz"
40
+ session_id = (0...16).map { chars[rand chars.length] }.join("")
41
+
42
+ return Session.new self, session_id
43
+
44
+ end
45
+
46
+ def perform request
47
+
48
+ @state == :open \
49
+ or raise "Invalid state #{@state}"
50
+
51
+ # send request
52
+
53
+ request_string =
54
+ MultiJson.dump request
55
+
56
+ @req_wr.puts request_string.length + 1
57
+ @req_wr.puts request_string
58
+
59
+ # receive reply
60
+
61
+ reply_len = @resp_rd.gets.to_i
62
+ reply_string = @resp_rd.read reply_len
63
+
64
+ return MultiJson.load reply_string
65
+
66
+ end
67
+
68
+ end
69
+ end
70
+ end