def new_session(session: self.data_lookup, username: self.access_token, password: self.refresh_token, holding_pattern: false, **args)
def new_session(session: self.data_lookup, username: self.access_token, password: self.refresh_token, holding_pattern: false, **args)
self.api_version = "v2"
self.username = username
self.password = password
self.last_refresh = session["#{self.id}::last_refresh"]
self.connect_user = session["#{self.id}::user::email"] if session["#{self.id}::user::email"].present?
PaperTrail.whodunnit = self.connect_user if defined?(PaperTrail)
ElasticAPM.set_user(self.connect_user) if defined?(ElasticAPM) && ElasticAPM.running?
recoverable_session = false
## DEV MODE TASK DATA MOCKUP
if ZuoraConnect.configuration.mode != "Production"
mock_task_data = {
"id" => ZuoraConnect.configuration.dev_mode_appinstance,
"mode" => ZuoraConnect.configuration.dev_mode_mode,
"name" => "Developer Instance"
}
case ZuoraConnect.configuration.dev_mode_options.class
when Hash
self.options = ZuoraConnect.configuration.dev_mode_options
when Array
mock_task_data["options"] = ZuoraConnect.configuration.dev_mode_options
end
ZuoraConnect.configuration.dev_mode_logins.each do |k,v|
v = v.merge({"entities": [] }) if !v.keys.include?("entities")
mock_task_data[k] = v
end
self.build_task(task_data: mock_task_data, session: session)
self.set_backup_creds if !self['zuora_logins'].present?
self.last_refresh = Time.now.to_i
else
time_expire = (session["#{self.id}::last_refresh"] || Time.now).to_i - INSTANCE_REFRESH_WINDOW.ago.to_i
if session.empty?
self.new_session_message = "REFRESHING - Session Empty"
ZuoraConnect.logger.debug(self.new_session_message)
raise ZuoraConnect::Exceptions::HoldingPattern if holding_pattern && !self.mark_for_refresh
self.refresh(session: session)
elsif (self.id != session["appInstance"].to_i)
self.new_session_message = "REFRESHING - AppInstance ID(#{self.id}) does not match session id(#{session["appInstance"].to_i})"
ZuoraConnect.logger.debug(self.new_session_message)
raise ZuoraConnect::Exceptions::HoldingPattern if holding_pattern && !self.mark_for_refresh
self.refresh(session: session)
elsif session["#{self.id}::task_data"].blank? && !ZuoraConnect.configuration.local_task_data
self.new_session_message = "REFRESHING - Task Data Blank"
ZuoraConnect.logger.debug(self.new_session_message)
raise ZuoraConnect::Exceptions::HoldingPattern if holding_pattern && !self.mark_for_refresh
self.refresh(session: session)
elsif session["#{self.id}::last_refresh"].blank?
self.new_session_message = "REFRESHING - No Time on Cookie"
recoverable_session = true
ZuoraConnect.logger.debug(self.new_session_message)
raise ZuoraConnect::Exceptions::HoldingPattern if holding_pattern && !self.mark_for_refresh
self.refresh(session: session)
# If the cache is expired and we can aquire a refresh lock
elsif (session["#{self.id}::last_refresh"].to_i < INSTANCE_REFRESH_WINDOW.ago.to_i) && self.mark_for_refresh
self.new_session_message = "REFRESHING - Session Old by #{time_expire.abs} second"
recoverable_session = true
ZuoraConnect.logger.debug(self.new_session_message)
self.refresh(session: session)
else
if time_expire < 0
self.new_session_message = ["REBUILDING - Expired by #{time_expire} seconds", self.marked_for_refresh? ? " cache updating as of #{self.reset_mark_refreshed_at} seconds ago" : nil].compact.join(',')
else
self.new_session_message = "REBUILDING - Expires in #{time_expire} seconds"
end
ZuoraConnect.logger.debug(self.new_session_message, self.default_ougai_items)
self.build_task(task_data: session["#{self.id}::task_data"], session: session)
end
end
return self
rescue ZuoraConnect::Exceptions::HoldingPattern => ex
while self.marked_for_refresh?
ZuoraConnect.logger.info("Holding - Expires in #{self.reset_mark_expires_at}. '#{self.new_session_message}'", self.default_ougai_items)
sleep(HOLDING_PATTERN_SLEEP)
end
self.reload_attributes([:refresh_token, :oauth_expires_at, :access_token])
session = self.data_lookup(session: session)
retry
rescue ZuoraConnect::Exceptions::MissMatch => ex
self.delete_app_instance
session = {}
ZuoraConnect.logger.error(ex, self.default_ougai_items.merge({app_instance_id_new: self.task_data['id']}))
retry
rescue ZuoraConnect::Exceptions::InvalidCredentialSet => ex
raise
rescue => ex
if recoverable_session
ZuoraConnect.logger.warn("REBUILDING - Using backup expired cache", ex, self.default_ougai_items)
self.build_task(task_data: session["#{self.id}::task_data"], session: session)
return self
else
ZuoraConnect.logger.error("Failed new session", ex, self.default_ougai_items)
raise
end
ensure
begin
I18n.locale = self.locale
rescue I18n::InvalidLocale => ex
ZuoraConnect.logger.error(ex) if !IGNORED_LOCALS.include?(ex.locale.to_s.downcase)
end
self.set_timezone
if self.task_data.present?
tenants = self.task_data.fetch('tenant_ids', [])
organizations = self.task_data.fetch('organizations', [])
if defined?(ElasticAPM) && ElasticAPM.running?
if ElasticAPM.respond_to?(:set_label)
ElasticAPM.set_label(:tenant_id, tenants.first)
ElasticAPM.set_label(:organization, organizations.first)
else
ElasticAPM.set_label(:tenant_id, tenants.first)
ElasticAPM.set_label(:organization, organizations.first)
end
end
tenants = (self.task_data.dig(LOGIN_TENANT_DESTINATION,'entities') || []).select {|entity| !entity['skip'].to_bool}.map{|e| e['entityId']}.uniq if tenants.blank?
params = {
name: self.task_data.dig('name'),
zuora_entity_ids: (self.task_data.dig(LOGIN_TENANT_DESTINATION,'entities') || []).select {|entity| !entity['skip'].to_bool}.map{|e| e['id']}.uniq,
zuora_global_tenant_id: task_data.dig(LOGIN_TENANT_DESTINATION, 'entities', 0, 'globalEntityId').to_i, # tenant id of the global/parent entity, 0 if nil
zuora_tenant_ids: tenants.map(&:to_s).uniq,
organizations: organizations
}
if self.methods.include?(LOGIN_TENANT_DESTINATION.to_sym)
client = self.send(LOGIN_TENANT_DESTINATION).client
if defined?(client.rest_domain)
ZuoraConnect::RequestIdMiddleware.zuora_rest_domain = client.rest_domain
params.merge!({zuora_domain: client.rest_domain, environment: client.environment })
end
end
# makes it safe to add elements to params which don't correspond to existing columns in an app's schema
# rejects those elements which do not correspond to model attributes for your app
params = params.reject{|k,v| !self.attributes.keys.member?(k.to_s) || self[k] == v}
self.update_columns(params) if params.present?
end
end