his_emr_api_lab 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 778184a052cac6932ec700f03b99615024440af3944c371d0cfa997f357c525c
4
- data.tar.gz: 045fb73daab53abc457c08152c5148251a6dccb239f0c76e09f3172007e44b6e
3
+ metadata.gz: f53ca7acc69718ba31cf2ae278b6fdbdc4996d3ad6a28db0a08d3945d1463998
4
+ data.tar.gz: 77b2cfdc430706b9864e9ec71b2f4b64c2ec11a5695b45b81984c86a8fefefd4
5
5
  SHA512:
6
- metadata.gz: 95f56b7a5d1b36565074904d49e5ff69b34fb57bed690a7bec5d269749c6813e094b4e02b397517523edd90e0714710376f489338788838fad775f3c724659db
7
- data.tar.gz: 380096a9132eb857a4a321260593640eec0d6a5b08f661e97a1ba2396619eb5984c1aca488e364930dff737ff397b07865597b9ed321c7a93101c151a8d2566f
6
+ metadata.gz: 19f53f3c471dd4552f64bf1200a6bbd8051e7bc7bc7e0670b2079bea4af61621575a9c0e7f5cdc06c43ac7b80c2534e6ca704fd06e43b0deed3475ea66690017
7
+ data.tar.gz: cbe4e02964f635b60e7e7b0c6b53ac3b406ab9bff55da582371a3de38a8d65901bcca1771a7b3cf0d8be83e31ac8bf0a15e9c752f7131bb631f1011df95fa713
@@ -29,16 +29,11 @@ module Lab
29
29
  # given block until the queue is empty or connection is terminated
30
30
  # by calling method +choke+.
31
31
  def consume_orders(from: 0, limit: 30)
32
- last_seq = { value: 0 }
33
-
34
32
  bum.binge_changes(since: from, limit: limit, include_docs: true) do |change|
35
33
  next unless change['doc']['type']&.casecmp?('Order')
36
34
 
37
35
  yield OrderDTO.new(change['doc']), self
38
- last_seq[:value] = self.last_seq
39
36
  end
40
-
41
- last_seq[:value]
42
37
  end
43
38
 
44
39
  def create_order(order)
@@ -29,6 +29,7 @@ require 'lab/lab_test'
29
29
  require 'lab/lims_order_mapping'
30
30
  require 'lab/lims_failed_import'
31
31
 
32
+ require_relative './worker'
32
33
  require_relative '../orders_service'
33
34
  require_relative '../results_service'
34
35
  require_relative '../tests_service'
@@ -47,14 +48,16 @@ module Lab
47
48
 
48
49
  attr_reader :rejections
49
50
 
50
- def consume_orders(from: nil, limit: 50_000)
51
+ def consume_orders(from: nil, **_kwargs)
52
+ limit = 50_000
53
+
51
54
  Parallel.each(read_orders(from, limit),
52
55
  in_processes: MAX_THREADS,
53
56
  finish: order_pmap_post_processor(from)) do |row|
54
57
  next unless row['doc']['type']&.casecmp?('Order')
55
58
 
56
- User.current = Migrator.lab_user
57
- yield OrderDTO.new(row['doc']), OpenStruct.new(last_seq: from)
59
+ User.current = Utils.lab_user
60
+ yield OrderDTO.new(row['doc']), OpenStruct.new(last_seq: (from || 0) + limit, current_seq: from)
58
61
  end
59
62
  end
60
63
 
@@ -70,7 +73,7 @@ module Lab
70
73
  private
71
74
 
72
75
  def last_seq_path
73
- Rails.root.join('log/lims/migration-last-id.dat')
76
+ LIMS_LOG_PATH.join('migration-last-id.dat')
74
77
  end
75
78
 
76
79
  def order_pmap_post_processor(last_seq)
@@ -129,18 +132,6 @@ module Lab
129
132
  def update_last_seq(_last_seq); end
130
133
  end
131
134
 
132
- def self.lab_user
133
- user = User.find_by_username('lab_daemon')
134
- return user if user
135
-
136
- god_user = User.first
137
-
138
- person = Person.create!(creator: god_user.user_id)
139
- PersonName.create!(person: person, given_name: 'Lab', family_name: 'Daemon', creator: god_user.user_id)
140
-
141
- User.create!(username: 'lab_daemon', person: person, creator: god_user.user_id)
142
- end
143
-
144
135
  def self.save_csv(filename, rows:, headers: nil)
145
136
  CSV.open(filename, File::WRONLY | File::CREAT) do |csv|
146
137
  csv << headers if headers
@@ -148,7 +139,7 @@ module Lab
148
139
  end
149
140
  end
150
141
 
151
- MIGRATION_REJECTIONS_CSV_PATH = Rails.root.join('log/lims/migration-rejections.csv')
142
+ MIGRATION_REJECTIONS_CSV_PATH = LIMS_LOG_PATH.join('migration-rejections.csv')
152
143
 
153
144
  def self.export_rejections(rejections)
154
145
  headers = ['Accession number', 'NHID', 'First name', 'Last name', 'Reason']
@@ -165,7 +156,7 @@ module Lab
165
156
  save_csv(MIGRATION_REJECTIONS_CSV_PATH, headers: headers, rows: rows)
166
157
  end
167
158
 
168
- MIGRATION_FAILURES_CSV_PATH = Rails.root.join('log/lims/migration-failures.csv')
159
+ MIGRATION_FAILURES_CSV_PATH = LIMS_LOG_PATH.join('migration-failures.csv')
169
160
 
170
161
  def self.export_failures
171
162
  headers = ['Accession number', 'NHID', 'Reason', 'Difference']
@@ -181,7 +172,7 @@ module Lab
181
172
  save_csv(MIGRATION_FAILURES_CSV_PATH, headers: headers, rows: rows)
182
173
  end
183
174
 
184
- MIGRATION_LOG_PATH = Rails.root.join('log/lims/migration.log')
175
+ MIGRATION_LOG_PATH = LIMS_LOG_PATH.join('migration.log')
185
176
 
186
177
  def self.start_migration
187
178
  log_dir = Rails.root.join('log/lims')
@@ -97,7 +97,9 @@ module Lab
97
97
  end
98
98
 
99
99
  def format_test_results(order)
100
- order.tests.each_with_object({}) do |test, results|
100
+ order.tests&.each_with_object({}) do |test, results|
101
+ next unless test.result
102
+
101
103
  results[test.name] = {
102
104
  results: test.result.each_with_object({}) do |measure, measures|
103
105
  measures[measure.indicator.name] = { result_value: "#{measure.value_modifier}#{measure.value}" }
@@ -39,6 +39,18 @@ module Lab
39
39
  end
40
40
  end
41
41
 
42
+ def self.lab_user
43
+ user = User.find_by_username('lab_daemon')
44
+ return user if user
45
+
46
+ god_user = User.first
47
+
48
+ person = Person.create!(creator: god_user.user_id)
49
+ PersonName.create!(person: person, given_name: 'Lab', family_name: 'Daemon', creator: god_user.user_id)
50
+
51
+ User.create!(username: 'lab_daemon', person: person, creator: god_user.user_id)
52
+ end
53
+
42
54
  def self.parse_date(str_date, fallback_date = nil)
43
55
  if str_date.blank? && fallback_date.blank?
44
56
  raise "Can't parse blank date"
@@ -2,12 +2,16 @@
2
2
 
3
3
  require 'cgi/util'
4
4
 
5
+ require_relative './api'
5
6
  require_relative './exceptions'
6
7
  require_relative './order_serializer'
7
8
  require_relative './utils'
8
9
 
9
10
  module Lab
10
11
  module Lims
12
+ LIMS_LOG_PATH = Rails.root.join('log/lims')
13
+ Dir.mkdir(LIMS_LOG_PATH) unless File.exist?(LIMS_LOG_PATH)
14
+
11
15
  ##
12
16
  # Pull/Push orders from/to the LIMS queue (Oops meant CouchDB).
13
17
  class Worker
@@ -15,6 +19,19 @@ module Lab
15
19
 
16
20
  attr_reader :lims_api
17
21
 
22
+ def self.start
23
+ File.open(LIMS_LOG_PATH.join('worker.lock'), File::WRONLY | File::CREAT, 0o644) do |fout|
24
+ fout.flock(File::LOCK_EX)
25
+
26
+ User.current = Utils.lab_user
27
+
28
+ fout.write("Worker ##{Process.pid} started at #{Time.now}")
29
+ worker = new(Api.new)
30
+ worker.pull_orders
31
+ worker.push_orders
32
+ end
33
+ end
34
+
18
35
  def initialize(lims_api)
19
36
  @lims_api = lims_api
20
37
  end
@@ -52,8 +69,8 @@ module Lab
52
69
  lims_api.update_order(mapping.lims_id, order_dto)
53
70
  mapping.update(pushed_at: Time.now)
54
71
  else
55
- order_dto = lims_api.create_order(order_dto)
56
- LimsOrderMapping.create!(order: order, lims_id: order_dto['_id'], pushed_at: Time.now)
72
+ update = lims_api.create_order(order_dto)
73
+ LimsOrderMapping.create!(order: order, lims_id: update['id'], revision: update['rev'], pushed_at: Time.now)
57
74
  end
58
75
  end
59
76
 
@@ -64,7 +81,8 @@ module Lab
64
81
  # Pulls orders from the LIMS queue and writes them to the local database
65
82
  def pull_orders
66
83
  logger.info("Retrieving LIMS orders starting from #{last_seq}")
67
- lims_api.consume_orders(from: last_seq) do |order_dto, context|
84
+
85
+ lims_api.consume_orders(from: last_seq, limit: 100) do |order_dto, context|
68
86
  logger.debug("Retrieved order ##{order_dto[:tracking_number]}: #{order_dto}")
69
87
 
70
88
  patient = find_patient_by_nhid(order_dto[:patient][:id])
@@ -80,6 +98,8 @@ module Lab
80
98
  save_failed_import(order_dto, 'Demographics not matching', diff)
81
99
  end
82
100
 
101
+ update_last_seq(context.current_seq)
102
+
83
103
  [:accepted, "Patient NPID, '#{order_dto[:patient][:id]}', matched"]
84
104
  rescue DuplicateNHID
85
105
  logger.warn("Failed to import order due to duplicate patient NHID: #{order_dto[:patient][:id]}")
@@ -90,8 +110,6 @@ module Lab
90
110
  rescue LimsException => e
91
111
  logger.warn("Failed to import order due to #{e.class} - #{e.message}")
92
112
  save_failed_import(order_dto, e.message)
93
- ensure
94
- update_last_seq(context.last_seq)
95
113
  end
96
114
  end
97
115
 
@@ -303,7 +321,7 @@ module Lab
303
321
  end
304
322
 
305
323
  def last_seq_path
306
- Rails.root.join('log/lims/last-seq.dat')
324
+ LIMS_LOG_PATH.join('last_seq.dat')
307
325
  end
308
326
  end
309
327
  end
@@ -24,18 +24,21 @@ class CouchBum
24
24
  # within the passed block.
25
25
  def binge_changes(since: 0, limit: nil, include_docs: nil, &block)
26
26
  catch(:choke) do
27
- extra_params = stringify_params(limit: limit, include_docs: include_docs)
27
+ logger.debug("Binging #{limit} changes from '#{since}'")
28
+ params = stringify_params(limit: limit, include_docs: include_docs)
29
+ params = "since=#{since}&#{params}" unless since.blank?
28
30
 
29
- changes = couch_rest(:get, "_changes?since=#{since}&#{extra_params}")
31
+ changes = couch_rest(:get, "_changes?#{params}")
30
32
  context = BingeContext.new(changes)
31
- changes['results'].each { |change| context.instance_exec(change, &block) }
33
+ changes['results'].each do |change|
34
+ context.current_seq = change['seq']
35
+ context.instance_exec(change, &block)
36
+ end
32
37
  end
33
38
  end
34
39
 
35
40
  def couch_rest(method, route, *args, **kwargs)
36
41
  url = expand_route(route)
37
-
38
- logger.debug("CouchBum: Executing #{method} #{url}")
39
42
  CouchRest.send(method, url, *args, **kwargs)
40
43
  rescue CouchRest::Exception => e
41
44
  logger.error("Failed to communicate with CouchDB: Status: #{e.http_code} - #{e.http_body}")
@@ -46,6 +49,8 @@ class CouchBum
46
49
 
47
50
  # Context under which the callback passed to binge_changes is executed.
48
51
  class BingeContext
52
+ attr_accessor :current_seq
53
+
49
54
  def initialize(changes)
50
55
  @changes = changes
51
56
  end
data/lib/lab/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lab
4
- VERSION = '0.0.3'
4
+ VERSION = '0.0.4'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: his_emr_api_lab
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elizabeth Glaser Pediatric Foundation Malawi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-18 00:00:00.000000000 Z
11
+ date: 2021-04-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: couchrest