Skip to content

Commit

Permalink
fix race condition when using semantic methods (#356)
Browse files Browse the repository at this point in the history
Enumerable and predicate methods will now behave better when they refer
to stale proxies - filtering methods will just remove them. I run into
this occasionally when I have multiple rules firing, and some of them
are adding or removing items - and calling items.locations would raise a
NoMethodError for #location? due to a race condition. This should no
longer happen - it will just ignore the now-stale items.

Signed-off-by: Cody Cutrer <[email protected]>
  • Loading branch information
ccutrer authored Nov 25, 2024
1 parent daca142 commit 38af9a0
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 0 deletions.
29 changes: 29 additions & 0 deletions lib/openhab/core/items/proxy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,35 @@ def members
__getobj__.members
end

# Several methods can just return nil when it's a dummy item
# This helps when you're doing something like `items.locations.select {}`
# when items are getting created and removed in a concurrent thread to
# not have errors because an item disappeared
%i[
equipment
equipment?
equipment_type
location
location?
location_type
member_of?
point?
point_type
property_type
semantic?
semantic_type
tagged?
].each do |m|
class_eval <<~RUBY, __FILE__, __LINE__ + 1
def #{m}(*args) # def equipment(*args)
target = __getobj__ # target = __getobj__
return nil if target.nil? # return nil if target.nil?
#
target.#{m}(*args) # target.equipment(*args)
end # end
RUBY
end

# @return [String]
def to_s
return name if __getobj__.nil?
Expand Down
4 changes: 4 additions & 0 deletions spec/openhab/core/items/proxy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@
expect(item).not_to respond_to(:command)
expect { item.command }.to raise_error(NoMethodError)
end

it "disappears when calling semantic predicates on an array" do
expect([item].locations).to eql []
end
end

it "does not respond to GroupItem#members if it's backed by a non-GroupItem" do
Expand Down

0 comments on commit 38af9a0

Please sign in to comment.