Skip to content

Commit

Permalink
lazy init setting call
Browse files Browse the repository at this point in the history
  • Loading branch information
mensfeld committed Oct 25, 2023
1 parent 0c7023e commit f807318
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 9 deletions.
21 changes: 14 additions & 7 deletions lib/karafka/core/configurable/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def compile
@children.each do |value|
# Do not redefine something that was already set during compilation
# This will allow us to reconfigure things and skip override with defaults
skippable = respond_to?(value.name)
skippable = respond_to?(value.name) || (value.is_a?(Leaf) && value.compiled?)
lazy_leaf = value.is_a?(Leaf) && value.lazy?

# Do not create accessor for leafs that are lazy as they will get a custom method
Expand All @@ -106,10 +106,15 @@ def compile
next if skippable

initialized = if value.is_a?(Leaf)
next if value.compiled?

value.compiled = true
value.constructor ? value.constructor.call(value.default) : value.default

if value.constructor && value.lazy?
false
elsif value.constructor
value.constructor.call(value.default)
else
value.default
end
else
value.compile
value
Expand All @@ -130,21 +135,23 @@ def compile

private

# Defines a lazy evaluated accessor that will re-evaluate in case value constructor
# Defines a lazy evaluated read and writer that will re-evaluate in case value constructor
# evaluates to `nil` or `false`. This allows us to define dynamic constructors that
# can react to external conditions to become expected value once this value is
# available
#
# @param value [Leaf]
def build_dynamic_accessor(value)
singleton_class.attr_writer(value.name)

define_singleton_method(value.name) do
existing = instance_variable_get("@#{name}")
existing = instance_variable_get("@#{value.name}")

return existing if existing

built = value.constructor.call(value.default)

instance_variable_set("@#{name}", built)
instance_variable_set("@#{value.name}", built)
end
end
end
Expand Down
17 changes: 15 additions & 2 deletions spec/lib/karafka/core/configurable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@
end

context 'when default is false and value is false for some time' do
let(:attempts) { [1, 10, false, false, false, false] }
let(:attempts) { [1, 10, false, false, false] }
let(:default) { false }
let(:constructor) { ->(default) { default || attempts.pop } }

Expand All @@ -191,6 +191,19 @@
expect(config.lazy_setting).to eq(10)
end
end

context 'when we want to overwrite constructed state with a different one during config' do
let(:default) { false }
let(:constructor) { ->(_) { false } }

before do
configurable_class.configure do |config|
config.lazy_setting = 20
end
end

it { expect(config.lazy_setting).to eq(20) }
end
end
end

Expand Down Expand Up @@ -369,7 +382,7 @@ def testable
end

context 'when default is false and value is false for some time' do
let(:attempts) { [1, 10, false, false, false, false, false] }
let(:attempts) { [1, 10, false, false, false] }
let(:default) { false }
let(:constructor) { ->(default) { default || attempts.pop } }

Expand Down

0 comments on commit f807318

Please sign in to comment.