class ZuoraConnect::AppInstanceBase
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 } 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.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? 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 begin sql = <<-eos SELECT zuora_users.zuora_identity_response FROM "#{self.id}".zuora_users ORDER BY zuora_users.updated_at DESC LIMIT 1; eos user = ActiveRecord::Base.connection.execute(sql).to_a.first if user.present? zuora_identity_response = JSON.parse(user.fetch('zuora_identity_response', '{}')) self.user_timezone = zuora_identity_response.values.first&.dig('timeZone') end rescue => ex Rails.logger.error('Failed to get users while setting app instance timezone', ex) end if self.user_timezone.present? # connect instance which has a custom timezone if !self.auto_deployed? && ( ActiveSupport::TimeZone[self.task_data.dig('user_settings', 'timezone') || '']&.utc_offset != ActiveSupport::TimeZone[self.user_timezone]&.utc_offset ) if self.environment == 'Production' ZuoraConnect.logger.error( "Instance and user timezones are different. User has '#{self.user_timezone}' and " \ "instance has '#{self.task_data.dig('user_settings', 'timezone')}'", app_instance_id: self.id ) end self.user_timezone = nil Time.zone = self.timezone else begin Time.zone = self.user_timezone rescue ArgumentError Time.zone = self.timezone end end else Time.zone = self.timezone end 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 params = { name: self.task_data.dig('name'), zuora_entity_ids: (self.task_data.dig(LOGIN_TENANT_DESTINATION,'entities') || []).map{|e| e['id']}.uniq, 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 params = params.reject{|k,v| !self.attributes.keys.member?(k.to_s) || self[k] == v} self.update_columns(params) if params.present? end end