require 'spec_helper' require 'flydata/source_postgresql/query_based_sync/query_based_sync_postgresql_context' require 'flydata/source_postgresql/query_based_sync/resource_requester' module Flydata module SourcePostgresql module QueryBasedSync describe ResourceRequester do include_context 'query based sync postgresql context' let(:subject_object) { described_class.new(context) } describe '#create_resource_client' do subject { subject_object.create_resource_client(context) } it { is_expected.to be_kind_of(FlydataCore::Postgresql::PGClient) } end describe '#fetch_responses_once' do let(:table_name) { 'table_1' } let(:result) { double('result') } let(:response) { double('response') } let(:query_cond) { {} } let(:latest_src_pos) { FlydataCore::Postgresql::SourcePos.new(current_snapshot) } subject { subject_object.fetch_responses_once(table_name, latest_src_pos) } shared_examples 'returning expected responses' do it 'runs a query and return responses' do expect_any_instance_of(FlydataCore::Postgresql::PGClient). to receive(:query).and_return(result) expect(Response).to receive(:create_responses).with(context, table_name, result, query_cond).and_return([response]) expect(subject).to eq([response]) end end context 'when table_src_pos file exists but does not have pk_values' do let(:table_1_snapshot) { create_ss('1015:1015:') } let(:query_cond) { {from_sid: create_ss('1015:1015:'), to_sid: create_ss('1020:1020:'), pk_values: nil} } it_behaves_like 'returning expected responses' end context 'when table_src_pos file does not exist' do before do FileUtils.rm(table_1_src_pos_file.path) end let(:query_cond) { {from_sid: create_ss('1010:1010:'), to_sid: create_ss('1020:1020:'), pk_values: nil} } it_behaves_like 'returning expected responses' end context 'when table_src_pos has pk_values' do let(:table_1_snapshot) { create_ss('1012:1012:') } let(:table_1_to_snapshot) { create_ss('1020:1020:') } let(:table_1_pk_values) { [{"id"=>2}] } let(:query_cond) { {from_sid: create_ss('1012:1012:'), to_sid: create_ss('1020:1020:'), pk_values: [{"id"=>2}]} } it_behaves_like 'returning expected responses' end context 'when table_src_pos snapshot is up to date' do let(:table_1_snapshot) { current_snapshot } it { is_expected.to be_nil } end context 'when getting PG::TRSerializationFailure' do before do allow_any_instance_of(FlydataCore::Postgresql::PGClient).to receive(:query).and_raise( PG::TRSerializationFailure.new("ERROR: canceling statement due to conflict with recovery DETAIL: User query might have needed to see row versions that must be removed.") ) end it { expect{subject}.to raise_error(FlydataCore::RetryableError) } end end end end end end