From bd376af884fe42c37fe3bbfdb63bb1434d191f48 Mon Sep 17 00:00:00 2001 From: Holger Just Date: Tue, 14 Feb 2017 22:47:55 +0100 Subject: [PATCH] Use thread-safe raw objects for field hashes and arrays --- lib/rackstash/fields/abstract_collection.rb | 8 ++++++-- lib/rackstash/fields/array.rb | 2 +- lib/rackstash/fields/hash.rb | 2 +- spec/rackstash/fields/array_spec.rb | 4 ++-- spec/rackstash/fields/hash_spec.rb | 14 +++++++------- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/lib/rackstash/fields/abstract_collection.rb b/lib/rackstash/fields/abstract_collection.rb index 02cb9d1..78afda0 100644 --- a/lib/rackstash/fields/abstract_collection.rb +++ b/lib/rackstash/fields/abstract_collection.rb @@ -7,6 +7,8 @@ require 'bigdecimal' require 'pathname' require 'uri' +require 'concurrent' + module Rackstash module Fields class AbstractCollection @@ -101,7 +103,7 @@ module Rackstash when Rackstash::Fields::AbstractCollection return wrap ? value : value.raw when ::Hash - hash = value.each_with_object({}) do |(k, v), memo| + hash = value.each_with_object(Concurrent::Hash.new) do |(k, v), memo| memo[utf8_encode(k)] = normalize(v, scope: scope) end hash = Rackstash::Fields::Hash.new.tap do |hash_field| @@ -109,7 +111,9 @@ module Rackstash end if wrap return hash when ::Array, ::Set, ::Enumerator - array = value.map { |e| normalize(e, scope: scope) } + array = value.each_with_object(Concurrent::Array.new) do |e, memo| + memo << normalize(e, scope: scope) + end array = Rackstash::Fields::Array.new.tap do |array_field| array_field.raw = array end if wrap diff --git a/lib/rackstash/fields/array.rb b/lib/rackstash/fields/array.rb index 630f87d..53af33d 100644 --- a/lib/rackstash/fields/array.rb +++ b/lib/rackstash/fields/array.rb @@ -9,7 +9,7 @@ module Rackstash module Fields class Array < AbstractCollection def initialize - @raw = [] + @raw = Concurrent::Array.new end # Retrieve a stored value from a given `index` diff --git a/lib/rackstash/fields/hash.rb b/lib/rackstash/fields/hash.rb index 424d13e..755853a 100644 --- a/lib/rackstash/fields/hash.rb +++ b/lib/rackstash/fields/hash.rb @@ -11,7 +11,7 @@ module Rackstash # @param forbidden_keys [Set,Array] a list of strings # which are not allowed to be used as keys in this hash def initialize(forbidden_keys: EMPTY_SET) - @raw = {} + @raw = Concurrent::Hash.new if forbidden_keys.is_a?(Set) forbidden_keys = forbidden_keys.dup.freeze unless forbidden_keys.frozen? diff --git a/spec/rackstash/fields/array_spec.rb b/spec/rackstash/fields/array_spec.rb index 3f46813..1337576 100644 --- a/spec/rackstash/fields/array_spec.rb +++ b/spec/rackstash/fields/array_spec.rb @@ -56,7 +56,7 @@ describe Rackstash::Fields::Array do end it 'returns a simple array' do - expect(array.as_json).to be_a ::Array + expect(array.as_json).to be_instance_of ::Array expect(array.as_json.length).to eql 3 end @@ -70,7 +70,7 @@ describe Rackstash::Fields::Array do it 'returns a nested array' do expect(array[2]).to be_a Rackstash::Fields::Array - expect(array.as_json[2]).to be_an ::Array + expect(array.as_json[2]).to be_instance_of ::Array expect(array.as_json[2]).to eql %w[v1 v2] end diff --git a/spec/rackstash/fields/hash_spec.rb b/spec/rackstash/fields/hash_spec.rb index 167d376..c13b1d9 100644 --- a/spec/rackstash/fields/hash_spec.rb +++ b/spec/rackstash/fields/hash_spec.rb @@ -100,21 +100,21 @@ describe Rackstash::Fields::Hash do end it 'returns a simple hash' do - expect(hash.as_json).to be_a ::Hash + expect(hash.as_json).to be_instance_of ::Hash expect(hash.as_json.keys).to eql %w[simple hash array] end it 'returns a nested hash' do - expect(hash['hash']).to be_a Rackstash::Fields::Hash + expect(hash['hash']).to be_instance_of Rackstash::Fields::Hash - expect(hash.as_json['hash']).to be_a Hash + expect(hash.as_json['hash']).to be_instance_of Hash expect(hash.as_json['hash']).to eql 'key' => 'nested value', 'number' => 42 end it 'returns a nested array' do - expect(hash['array']).to be_a Rackstash::Fields::Array + expect(hash['array']).to be_instance_of Rackstash::Fields::Array - expect(hash.as_json['array']).to be_an ::Array + expect(hash.as_json['array']).to be_instance_of ::Array expect(hash.as_json['array']).to eql %w[v1 v2] end @@ -291,7 +291,7 @@ describe Rackstash::Fields::Hash do it 'returns a new object' do new_hash = hash.merge(foo: :bar) - expect(new_hash).to be_a Rackstash::Fields::Hash + expect(new_hash).to be_instance_of Rackstash::Fields::Hash expect(new_hash).not_to equal hash # The origiginal hash is not changed @@ -370,7 +370,7 @@ describe Rackstash::Fields::Hash do raw = { :time => Time.now, 'string' => 'foo' } hash = Rackstash::Fields::Hash(raw) - expect(hash).to be_a Rackstash::Fields::Hash + expect(hash).to be_instance_of Rackstash::Fields::Hash expect(hash['time']).to be_a String expect(hash['string']).to eql 'foo' end