diff --git a/lib/karafka/core/configurable/node.rb b/lib/karafka/core/configurable/node.rb index f2d0540..c4c1ff2 100644 --- a/lib/karafka/core/configurable/node.rb +++ b/lib/karafka/core/configurable/node.rb @@ -117,6 +117,9 @@ def compile if lazy_leaf && !initialized build_dynamic_accessor(value) + elsif lazy_leaf && initialized + singleton_class.attr_accessor(value.name) + public_send("#{value.name}=", initialized) else public_send("#{value.name}=", initialized) end diff --git a/spec/lib/karafka/core/configurable_spec.rb b/spec/lib/karafka/core/configurable_spec.rb index e7cbc13..ffde073 100644 --- a/spec/lib/karafka/core/configurable_spec.rb +++ b/spec/lib/karafka/core/configurable_spec.rb @@ -147,6 +147,51 @@ expect(configurable_class.config.to_h[:superscope][:additional]).to eq(7) end end + + context 'when we define a lazy evaluated root setting' do + let(:configurable_class) do + default1 = default + constructor1 = constructor + + Class.new do + extend Karafka::Core::Configurable + + setting( + :lazy_setting, + default: default1, + constructor: constructor1, + lazy: true + ) + end + end + + let(:config) { configurable_class.config } + let(:constructor) { ->(default) { default || 1 } } + + context 'when default is not false nor nil' do + let(:default) { 100 } + + it { expect(config.lazy_setting).to eq(100) } + end + + context 'when default is false' do + let(:default) { false } + + it { expect(config.lazy_setting).to eq(1) } + end + + context 'when default is false and value is false for some time' do + let(:attempts) { [1, 10, false, false, false, false] } + let(:default) { false } + let(:constructor) { ->(default) { default || attempts.pop } } + + it 'expect to retry until non-false is present and then cache it' do + 3.times { expect(config.lazy_setting).to eq(false) } + expect(config.lazy_setting).to eq(10) + expect(config.lazy_setting).to eq(10) + end + end + end end context 'when we define settings on an instance level' do @@ -290,5 +335,50 @@ def testable end end end + + context 'when we define a lazy evaluated root setting' do + let(:configurable_class) do + default1 = default + constructor1 = constructor + + Class.new do + include Karafka::Core::Configurable + + setting( + :lazy_setting, + default: default1, + constructor: constructor1, + lazy: true + ) + end + end + + let(:config) { configurable_class.new.tap(&:configure).config } + let(:constructor) { ->(default) { default || 1 } } + + context 'when default is not false nor nil' do + let(:default) { 100 } + + it { expect(config.lazy_setting).to eq(100) } + end + + context 'when default is false' do + let(:default) { false } + + it { expect(config.lazy_setting).to eq(1) } + end + + context 'when default is false and value is false for some time' do + let(:attempts) { [1, 10, false, false, false, false, false] } + let(:default) { false } + let(:constructor) { ->(default) { default || attempts.pop } } + + it 'expect to retry until non-false is present and then cache it' do + 3.times { expect(config.lazy_setting).to eq(false) } + expect(config.lazy_setting).to eq(10) + expect(config.lazy_setting).to eq(10) + end + end + end end end