Skip to content

Commit

Permalink
Fi 2311 store session ids (#427)
Browse files Browse the repository at this point in the history
* id saved from response + rename spec file

* spec test fix

* linting

* Update lib/inferno/dsl/fhir_resource_validation.rb

Co-authored-by: Dylan Hall <dehall@mitre.org>

* db + repo insert conflict, sorted options, idx fix

* validator job fix + more tests
8fb8107

* unit test clean up

---------

Co-authored-by: Dylan Hall <dehall@mitre.org>
  • Loading branch information
rpassas and dehall authored Feb 27, 2024
1 parent 123ab58 commit cfabde4
Show file tree
Hide file tree
Showing 10 changed files with 302 additions and 14 deletions.
14 changes: 14 additions & 0 deletions lib/inferno/db/migrations/010_add_validator_sessions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Sequel.migration do
change do
create_table :validator_sessions do
column :id, String, primary_key: true, null: false, size: 36
column :validator_session_id, String, null: false, size: 255
column :test_suite_id, String, null: false, size: 255
column :validator_name, String, null: false, size: 255
column :suite_options, String, text: true
column :last_accessed, DateTime, null: false
index [:validator_session_id], unique: true
index [:test_suite_id, :validator_name, :suite_options], unique: true
end
end
end
14 changes: 14 additions & 0 deletions lib/inferno/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@
primary_key [:id]
end

create_table(:validator_sessions, :ignore_index_errors=>true) do
String :id, :size=>36, :null=>false
String :validator_session_id, :size=>255, :null=>false
String :test_suite_id, :size=>255, :null=>false
String :validator_name, :size=>255, :null=>false
String :suite_options, :text=>true
DateTime :last_accessed, :null=>false

primary_key [:id]

index [:test_suite_id, :validator_name, :suite_options], :unique=>true
index [:validator_session_id], :unique=>true
end

create_table(:session_data, :ignore_index_errors=>true) do
String :id, :size=>255, :null=>false
foreign_key :test_session_id, :test_sessions, :type=>String, :size=>36, :null=>false, :key=>[:id]
Expand Down
25 changes: 19 additions & 6 deletions lib/inferno/dsl/fhir_resource_validation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ def self.included(klass)

class Validator
attr_reader :requirements
attr_accessor :session_id
attr_accessor :session_id, :name, :test_suite_id

# @private
def initialize(requirements = nil, &)
def initialize(name = nil, test_suite_id = nil, requirements = nil, &)
@name = name
@test_suite_id = test_suite_id
instance_eval(&)
@requirements = requirements
end
Expand All @@ -40,6 +42,10 @@ def default_validator_url
ENV.fetch('FHIR_RESOURCE_VALIDATOR_URL')
end

def validator_session_repo
@validator_session_repo ||= Inferno::Repositories::ValidatorSessions.new
end

# Set the url of the validator service
#
# @param validator_url [String]
Expand Down Expand Up @@ -231,6 +237,10 @@ def issue_message(issue, resource)

# @private
def wrap_resource_for_hl7_wrapper(resource, profile_url)
validator_session_id =
validator_session_repo.find_validator_session_id(test_suite_id,
name.to_s, requirements)
@session_id = validator_session_id if validator_session_id
wrapped_resource = {
cliContext: {
**cli_context.definition,
Expand Down Expand Up @@ -269,8 +279,11 @@ def call_validator(resource, profile_url)
# @private
def operation_outcome_from_hl7_wrapped_response(response)
res = JSON.parse(response)

@session_id = res['sessionId']
if res['sessionId'] != @session_id
validator_session_repo.save(test_suite_id:, validator_session_id: res['sessionId'],
validator_name: name.to_s, suite_options: requirements)
@session_id = res['sessionId']
end

# assume for now that one resource -> one request
issues = res['outcomes'][0]['issues']&.map do |i|
Expand All @@ -287,7 +300,7 @@ def operation_outcome_from_validator_response(response, runnable)
else
runnable.add_message('error', "Validator Response: HTTP #{response.status}\n#{response.body}")
raise Inferno::Exceptions::ErrorInValidatorException,
'Validator response was an unexpected format. '\
'Validator response was an unexpected format. ' \
'Review Messages tab or validator service logs for more information.'
end
end
Expand Down Expand Up @@ -353,7 +366,7 @@ def fhir_validators
def fhir_resource_validator(name = :default, required_suite_options: nil, &block)
current_validators = fhir_validators[name] || []

new_validator = Inferno::DSL::FHIRResourceValidation::Validator.new(required_suite_options, &block)
new_validator = Inferno::DSL::FHIRResourceValidation::Validator.new(name, id, required_suite_options, &block)

current_validators.reject! { |validator| validator.requirements == required_suite_options }
current_validators << new_validator
Expand Down
1 change: 1 addition & 0 deletions lib/inferno/entities.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
require_relative 'entities/test_run'
require_relative 'entities/test_session'
require_relative 'entities/test_suite'
require_relative 'entities/validator_session'

module Inferno
# Entities are domain objects whose identity is based on an `id`. Entities
Expand Down
22 changes: 22 additions & 0 deletions lib/inferno/entities/validator_session.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module Inferno
module Entities
class ValidatorSession < Entity
ATTRIBUTES = [
:id,
:created_at,
:updated_at,
:validator_session_id,
:test_suite_id,
:validator_name,
:suite_options,
:validator_index
].freeze

include Inferno::Entities::Attributes

def initialize(params)
super(params, ATTRIBUTES)
end
end
end
end
6 changes: 3 additions & 3 deletions lib/inferno/jobs/invoke_validator_session.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ class InvokeValidatorSession
def perform(suite_id, validator_name, validator_index)
suite = Inferno::Repositories::TestSuites.new.find suite_id
validator = suite.fhir_validators[validator_name.to_sym][validator_index]

response_body = validator.validate(FHIR::Patient.new, 'http://hl7.org/fhir/StructureDefinition/Patient')

if response_body.start_with? '{'
res = JSON.parse(response_body)
session_id = res['sessionId']
# TODO: (FI-2311) store this session ID so it can be referenced as needed
session_repo = Inferno::Repositories::ValidatorSessions.new
session_repo.save(test_suite_id: suite_id, validator_session_id: session_id,
validator_name:, suite_options: validator.requirements)
validator.session_id = session_id
else
Inferno::Application['logger'].error("InvokeValidatorSession - error from validator: #{response_body}")
Expand Down
1 change: 1 addition & 0 deletions lib/inferno/repositories.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
require_relative 'repositories/session_data'
require_relative 'repositories/test_runs'
require_relative 'repositories/test_sessions'
require_relative 'repositories/validator_sessions'
end

module Inferno
Expand Down
58 changes: 58 additions & 0 deletions lib/inferno/repositories/validator_sessions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
require 'base62-rb'
require_relative 'repository'

module Inferno
module Repositories
class ValidatorSessions < Repository
def save(params)
validator_session_id = params[:validator_session_id]
validator_name = params[:validator_name]
test_suite_id = params[:test_suite_id]
raw_suite_options = params[:suite_options]
time = Time.now

suite_options =
if raw_suite_options.blank?
'[]'
else
raw_suite_options.sort.to_s
end

db.insert_conflict(
target: [:test_suite_id,
:suite_options,
:validator_name],
update: { validator_session_id:,
test_suite_id:,
suite_options:,
validator_name: }
).insert(
id: "#{validator_session_id}_#{validator_name}",
validator_session_id:,
test_suite_id:,
validator_name:,
suite_options:,
last_accessed: time
)
end

def find_validator_session_id(test_suite_id, validator_name, suite_options)
suite_options = suite_options.nil? ? '[]' : suite_options.sort.to_s
session = self.class::Model
.find(test_suite_id:, validator_name:, suite_options:)
return nil if session.nil?

time = Time.now
session.update(last_accessed: time)
session[:validator_session_id]
end

class Model < Sequel::Model(db)
def before_save
time = Time.now
self.last_accessed ||= time
end
end
end
end
end
10 changes: 5 additions & 5 deletions spec/inferno/dsl/fhir_resource_validation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
let(:validation_url) { 'http://example.com' }
let(:profile_url) { 'PROFILE' }
let(:validator) do
Inferno::DSL::FHIRResourceValidation::Validator.new do
Inferno::DSL::FHIRResourceValidation::Validator.new('test_validator', 'test_suite') do
url 'http://example.com'
end
end
Expand Down Expand Up @@ -195,13 +195,13 @@
})
end

expect(v1.cli_context.definition.fetch(:txServer, :missing)).to eq(nil)
expect(v1.cli_context.definition.fetch(:txServer, :missing)).to be_nil
expect(v1.cli_context.definition.fetch(:displayWarnings, :missing)).to eq(:missing)
expect(v1.cli_context.txServer).to eq(nil)
expect(v1.cli_context.txServer).to be_nil

expect(v2.cli_context.definition.fetch(:txServer, :missing)).to eq(:missing)
expect(v2.cli_context.definition[:displayWarnings]).to eq(true)
expect(v2.cli_context.displayWarnings).to eq(true)
expect(v2.cli_context.definition[:displayWarnings]).to be(true)
expect(v2.cli_context.displayWarnings).to be(true)

expect(v3.cli_context.igs).to eq(['hl7.fhir.us.core#1.0.1'])
expect(v3.cli_context.extensions).to eq([])
Expand Down
Loading

0 comments on commit cfabde4

Please sign in to comment.