Skip to content

Commit

Permalink
Making gem thread safe (#549)
Browse files Browse the repository at this point in the history
* Thread-safe gem

* Fixing small bugs to make tests pass

* Added test which confirms threaded behavior

Co-authored-by: Michael Bianco <iloveitaly@gmail.com>
  • Loading branch information
andrewdicken-stripe and iloveitaly authored Jul 7, 2022
1 parent 64b6199 commit 376b2a2
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 16 deletions.
6 changes: 3 additions & 3 deletions lib/netsuite/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def reset!
end

def attributes
@attributes ||= {}
Thread.current[:netsuite_gem_attributes] ||= {}
end

def connection(params={}, credentials={})
Expand Down Expand Up @@ -51,11 +51,11 @@ def filters=(list)
end

def wsdl_cache
@wsdl_cache ||= {}
Thread.current[:netsuite_gem_wsdl_cache] ||= {}
end

def clear_wsdl_cache
@wsdl_cache = {}
Thread.current[:netsuite_gem_wsdl_cache] = {}
end

def cached_wsdl
Expand Down
32 changes: 19 additions & 13 deletions lib/netsuite/utilities.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,20 @@ module Utilities
# TODO need structured logger for various statements

def clear_cache!
@netsuite_get_record_cache = {}
@netsuite_find_record_cache = {}
Thread.current[:netsuite_gem_netsuite_get_record_cache] = {}
Thread.current[:netsuite_gem_netsuite_find_record_cache] = {}

DataCenter.clear_cache!
end

def netsuite_get_record_cache
Thread.current[:netsuite_gem_netsuite_get_record_cache] ||= {}
end

def netsuite_find_record_cache
Thread.current[:netsuite_gem_netsuite_find_record_cache] ||= {}
end

def append_memo(ns_record, added_memo, opts = {})
opts[:skip_if_exists] ||= false

Expand Down Expand Up @@ -194,11 +203,10 @@ def get_record(record_klass, id, opts = {})
opts[:external_id] ||= false

if opts[:cache]
@netsuite_get_record_cache ||= {}
@netsuite_get_record_cache[record_klass.to_s] ||= {}
netsuite_get_record_cache[record_klass.to_s] ||= {}

if @netsuite_get_record_cache[record_klass.to_s].has_key?(id.to_i)
return @netsuite_get_record_cache[record_klass.to_s][id.to_i]
if netsuite_get_record_cache[record_klass.to_s].has_key?(id.to_i)
return netsuite_get_record_cache[record_klass.to_s][id.to_i]
end
end

Expand All @@ -212,14 +220,14 @@ def get_record(record_klass, id, opts = {})
end

if opts[:cache]
@netsuite_get_record_cache[record_klass.to_s][id.to_i] = ns_record
netsuite_get_record_cache[record_klass.to_s][id.to_i] = ns_record
end

return ns_record
rescue ::NetSuite::RecordNotFound
# log.warn("record not found", ns_record_type: record_klass.name, ns_record_id: id)
if opts[:cache]
@netsuite_get_record_cache[record_klass.to_s][id.to_i] = nil
netsuite_get_record_cache[record_klass.to_s][id.to_i] = nil
end

return nil
Expand All @@ -234,10 +242,8 @@ def find_record(record, names, opts = {})
# FIXME: Records that have the same name but different types will break
# the cache
names.each do |name|
@netsuite_find_record_cache ||= {}

if @netsuite_find_record_cache.has_key?(name)
return @netsuite_find_record_cache[name]
if netsuite_find_record_cache.has_key?(name)
return netsuite_find_record_cache[name]
end

# sniff for an email-like input; useful for employee/customer searches
Expand All @@ -263,7 +269,7 @@ def find_record(record, names, opts = {})
}) }

if search.results.first
return @netsuite_find_record_cache[name] = search.results.first
return netsuite_find_record_cache[name] = search.results.first
end
end

Expand Down
14 changes: 14 additions & 0 deletions spec/netsuite/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@
config.reset!
expect(config.attributes).to be_empty
end

it 'ensures that attributes are not shared between threads' do
config.attributes[:blah] = 'something'
expect(config.attributes[:blah]).to eq('something')

thread = Thread.new {
config.attributes[:blah] = 'something_else'
expect(config.attributes[:blah]).to eq('something_else')
}

thread.join

expect(config.attributes[:blah]).to eq('something')
end
end

describe '#filters' do
Expand Down

0 comments on commit 376b2a2

Please sign in to comment.