Skip to content

Instantly share code, notes, and snippets.

@fespinoza
Created June 2, 2016 13:40
Show Gist options
  • Save fespinoza/3f44d9d77b9c13ad816c865799249947 to your computer and use it in GitHub Desktop.
Save fespinoza/3f44d9d77b9c13ad816c865799249947 to your computer and use it in GitHub Desktop.
Bug Reproduction: ActiveRecord::StatementInvalid: PG::DuplicatePstatement: ERROR: prepared statement "XXX" already exists

Bug Reproduction: ActiveRecord::StatementInvalid: PG::DuplicatePstatement: ERROR: prepared statement "XXX" already exists

so basically here in postgres_adapter.rb I am manually raising a raise Rack::Timeout::RequestTimeoutError and if that exception is captured, the code continues to execute, then the next time the code wants to access the DB the PG::DuplicatePstatement: ERROR will occurr.

the way to solve this is to add a begin/ensure block to the affected area to make sure prepared statements are generated correctly

NOTE: i raise the error when the counter gets to 130 since this method is excecuted many times

require 'rails_helper'
resource 'Client Activity Tracking', document: false do
# TODO: remove this after a while, since it's just inteded to be a fix for
# the sign in count values, as we introduced this
get '/api/profile' do
example 'fixing the sign in count' do
user = create(:user)
expect do
do_auth_request user: user
end.to change { user.reload.client_sign_in_count }.from(0).to(1)
end
end
end
# lib/active_record/connection_adapters/postgresql_adapter.rb
def prepare_statement(sql)
sql_key = sql_key(sql)
unless @statements.key? sql_key
nextkey = @statements.next_key
begin
@connection.prepare nextkey, sql
rescue => e
raise translate_exception_class(e, sql)
end
@counter ||= 0
puts "original hello world #{@counter}"
@counter += 1
raise Rack::Timeout::RequestTimeoutError.new({}) if @counter == 130
# Clear the queue
@connection.get_last_result
@statements[sql_key] = nextkey
end
@statements[sql_key]
end
module UsefulLogInfo
extend ActiveSupport::Concern
included do
before_action :log_client_information
before_action :raven_set_user_context
end
def log_client_information
user_info = "user_agent='#{user_agent}' "\
"device='#{device}' "\
"app_install_id='#{app_install_id}' "\
"app_name='#{app_name}' "\
"requested_api_version='#{api_version}' "\
"requested_language='#{accept_language}' "\
"used_language='#{I18n.locale}' "\
"if_none_match='#{if_none_match}'"
Rails.logger.info ">>> #{user_info}"
rescue => e
puts e.inspect
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment