spec/connectors/crawler/crawler_scheduler_spec.rb (185 lines of code) (raw):
require 'core/connector_settings'
require 'connectors/crawler/scheduler'
require 'timecop'
describe Connectors::Crawler::Scheduler do
subject { described_class.new(poll_interval, heartbeat_interval) }
let(:poll_interval) { 999 }
let(:heartbeat_interval) { 999 }
shared_examples_for 'triggers' do |key|
it 'yields :sync task with an optional scheduling_key value' do
expect { |b| subject.when_triggered(&b) }.to yield_with_args(connector_settings, :sync, key)
end
end
shared_examples_for 'does not trigger' do |task|
it "does not yield #{task} task" do
expect { |b| subject.when_triggered(&b) }.to_not yield_control
end
end
describe '#connector_settings' do
context 'when elasticsearch query runs successfully' do
let(:connector_settings) { [{ :id => '123' }] }
before(:each) do
allow(Core::ConnectorSettings).to receive(:fetch_crawler_connectors).and_return(connector_settings)
end
it 'fetches crawler connectors' do
expect(subject.connector_settings).to eq(connector_settings)
end
end
context 'when elasticsearch query fails' do
before(:each) do
allow(Core::ConnectorSettings).to receive(:fetch_crawler_connectors).and_raise(StandardError)
end
it 'fetches crawler connectors' do
expect(subject.connector_settings).to be_empty
end
end
end
describe '#when_triggered' do
let(:connector_settings) { double }
before(:each) do
allow(subject).to receive(:connector_settings).and_return([connector_settings])
allow(connector_settings).to receive(:service_type).and_return('elastic-crawler')
subject.instance_variable_set(:@is_shutting_down, true)
end
context 'when custom scheduling is present' do
let(:connector_settings) { double }
let(:sync_now) { false }
let(:sync_enabled) { false }
let(:sync_interval) { '0 0 * * * ?' }
let(:full_sync_scheduling) do
{
:enabled => sync_enabled,
:interval => sync_interval
}
end
let(:weekly_enabled) { false }
let(:weekly_interval) { '0 0 * * 1 ?' }
let(:monthly_enabled) { false }
let(:monthly_interval) { '0 0 1 * * ?' }
let(:custom_scheduling_settings) do
{
:weekly_key => {
:name => 'weekly',
:enabled => weekly_enabled,
:interval => weekly_interval
},
:monthly_key => {
:name => 'monthly',
:enabled => monthly_enabled,
:interval => monthly_interval
}
}
end
let(:custom_sync_triggered) { false }
let(:next_trigger_time) { 1.day.from_now }
let(:weekly_next_trigger_time) { 1.day.from_now }
let(:monthly_next_trigger_time) { 1.day.from_now }
let(:time_at_poll_start) { Timecop.freeze(Time.now) }
let(:cron_parser) { instance_double(Fugit::Cron) }
before(:each) do
allow(Core::ConnectorSettings).to receive(:fetch_crawler_connectors).and_return(connector_settings)
allow(subject).to receive(:sync_triggered?).with(connector_settings, time_at_poll_start).and_call_original
allow(subject).to receive(:custom_sync_triggered?).with(connector_settings, time_at_poll_start).and_call_original
allow(connector_settings).to receive(:connector_status_allows_sync?).and_return(true)
allow(connector_settings).to receive(:sync_now?).and_return(sync_now)
allow(connector_settings).to receive(:full_sync_scheduling).and_return(full_sync_scheduling)
allow(connector_settings).to receive(:custom_scheduling_settings).and_return(custom_scheduling_settings)
allow(connector_settings).to receive(:valid_index_name?).and_return(true)
allow(connector_settings).to receive(:formatted).and_return('Formatted')
allow(Utility::Cron).to receive(:quartz_to_crontab).with(sync_interval)
allow(Utility::Cron).to receive(:quartz_to_crontab).with(weekly_interval)
allow(Utility::Cron).to receive(:quartz_to_crontab).with(monthly_interval)
allow(Fugit::Cron).to receive(:parse).and_return(cron_parser)
end
after(:each) do
Timecop.return
end
context 'when none are enabled' do
it_behaves_like 'does not trigger', :sync
end
context 'when one custom scheduling is enabled and ready to sync' do
let(:monthly_enabled) { true }
let(:monthly_next_trigger_time) { time_at_poll_start + poll_interval - 10 }
before(:each) do
allow(Utility::Cron).to receive(:quartz_to_crontab).with(monthly_interval)
allow(cron_parser).to receive(:next_time).and_return(monthly_next_trigger_time)
end
it_behaves_like 'triggers', :monthly_key
end
context 'when all custom scheduling is enabled and ready to sync' do
let(:weekly_enabled) { true }
let(:monthly_enabled) { true }
let(:weekly_next_trigger_time) { time_at_poll_start + poll_interval - 10 }
let(:monthly_next_trigger_time) { time_at_poll_start + poll_interval - 10 }
before(:each) do
allow(cron_parser).to receive(:next_time).and_return(weekly_next_trigger_time, monthly_next_trigger_time)
end
# it will return the first custom scheduling it encounters
it_behaves_like 'triggers', :weekly_key
end
context 'when base scheduling and all custom scheduling are enabled and require a sync' do
let(:sync_enabled) { true }
let(:weekly_enabled) { true }
let(:monthly_enabled) { true }
let(:next_trigger_time) { time_at_poll_start + poll_interval - 10 }
let(:weekly_next_trigger_time) { time_at_poll_start + poll_interval - 10 }
let(:monthly_next_trigger_time) { time_at_poll_start + poll_interval - 10 }
before(:each) do
allow(cron_parser).to receive(:next_time).and_return(next_trigger_time, weekly_next_trigger_time, monthly_next_trigger_time)
end
# it will return the base scheduling
it_behaves_like 'triggers', nil
end
context 'when base and custom scheduling are enabled and are scheduled after the poll interval' do
let(:sync_enabled) { true }
let(:weekly_enabled) { true }
let(:monthly_enabled) { true }
let(:next_trigger_time) { time_at_poll_start + poll_interval + 10 }
let(:weekly_next_trigger_time) { time_at_poll_start + poll_interval + 10 }
let(:monthly_next_trigger_time) { time_at_poll_start + poll_interval + 10 }
before(:each) do
allow(cron_parser).to receive(:next_time).with(time_at_poll_start).and_return(next_trigger_time, weekly_next_trigger_time, monthly_next_trigger_time)
end
# functionally the same as shared test 'does not trigger' but with an extra expect() to check for debug messages
it 'does not yield task' do
# expect three debug messages because three schedules are not being triggered
expect(Utility::Logger).to receive(:debug).exactly(3).times.with(match(/^Sync for (\w+.*)|( - \w+) not triggered as .*/))
expect { |b| subject.when_triggered(&b) }.to_not yield_control
end
end
context 'when base and custom scheduling are enabled, but one is scheduled after the poll interval' do
let(:sync_enabled) { true }
let(:weekly_enabled) { true }
let(:next_trigger_time) { time_at_poll_start + poll_interval + 10 }
let(:weekly_next_trigger_time) { time_at_poll_start + poll_interval - 10 }
before(:each) do
allow(cron_parser).to receive(:next_time).with(time_at_poll_start).and_return(next_trigger_time, weekly_next_trigger_time)
end
# functionally the same as shared test 'triggers', but with an extra expect() to check for a debug message
it 'yields :sync task with an optional scheduling_key value' do
expect(Utility::Logger).to receive(:debug).exactly(1).times.with(match(/^Sync for (\w+.*)|( - \w+) not triggered as .*/))
expect { |b| subject.when_triggered(&b) }.to yield_with_args(connector_settings, :sync, :weekly_key)
end
end
context 'when base and custom scheduling are enabled and require sync and are scheduled at the start of the poll interval' do
let(:sync_enabled) { true }
let(:weekly_enabled) { true }
let(:monthly_enabled) { true }
let(:next_trigger_time) { time_at_poll_start }
let(:weekly_next_trigger_time) { time_at_poll_start }
let(:monthly_next_trigger_time) { time_at_poll_start }
before(:each) do
allow(cron_parser).to receive(:next_time).with(time_at_poll_start).and_return(next_trigger_time, weekly_next_trigger_time, monthly_next_trigger_time)
end
it_behaves_like 'triggers', nil
end
context 'when base and custom scheduling are enabled and require sync and are scheduled at end of the poll interval' do
let(:sync_enabled) { true }
let(:weekly_enabled) { true }
let(:monthly_enabled) { true }
let(:next_trigger_time) { time_at_poll_start + poll_interval }
let(:weekly_next_trigger_time) { time_at_poll_start + poll_interval }
let(:monthly_next_trigger_time) { time_at_poll_start + poll_interval }
before(:each) do
allow(cron_parser).to receive(:next_time).with(time_at_poll_start).and_return(next_trigger_time, weekly_next_trigger_time, monthly_next_trigger_time)
end
it_behaves_like 'triggers', nil
end
end
end
end