diff --git a/lib/batch_loader.rb b/lib/batch_loader.rb index bfc7819..99d3b5c 100644 --- a/lib/batch_loader.rb +++ b/lib/batch_loader.rb @@ -77,23 +77,29 @@ def __ensure_batched return if __executor_proxy.value_loaded?(item: @item) items = __executor_proxy.list_items - loader = -> (item, value = (no_value = true; nil), &block) do + loader = __loader + @batch_block.call(items, loader) + items.each do |item| + next if __executor_proxy.value_loaded?(item: item) + loader.call(item, @default_value) + end + __executor_proxy.delete(items: items) + end + + def __loader + mutex = Mutex.new + -> (item, value = (no_value = true; nil), &block) do if no_value && !block raise ArgumentError, "Please pass a value or a block" elsif block && !no_value raise ArgumentError, "Please pass a value or a block, not both" end - next_value = block ? block.call(__executor_proxy.loaded_value(item: item)) : value - __executor_proxy.load(item: item, value: next_value) - end - - @batch_block.call(items, loader) - items.each do |item| - next if __executor_proxy.value_loaded?(item: item) - loader.call(item, @default_value) + mutex.synchronize do + next_value = block ? block.call(__executor_proxy.loaded_value(item: item)) : value + __executor_proxy.load(item: item, value: next_value) + end end - __executor_proxy.delete(items: items) end def __singleton_class diff --git a/spec/batch_loader_spec.rb b/spec/batch_loader_spec.rb index 9705a52..778ba57 100644 --- a/spec/batch_loader_spec.rb +++ b/spec/batch_loader_spec.rb @@ -110,7 +110,7 @@ slow_executor_proxy = SlowExecutorProxy.new([], &batch_block) lazy = BatchLoader.new(item: 1, executor_proxy: slow_executor_proxy).batch(default_value: [], &batch_block) - expect(lazy).to eq([1, 2]) + expect(lazy).to match_array([1, 2]) end it 'supports alternative default values' do