Skip to content

Commit

Permalink
fix(control_system): should only remove modules only in system [PPT-1…
Browse files Browse the repository at this point in the history
…102] (#238)
  • Loading branch information
stakach authored Dec 6, 2023
1 parent c3e6ab7 commit 846ec7f
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 16 deletions.
29 changes: 29 additions & 0 deletions spec/control_system_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,35 @@ module PlaceOS::Model
driver.destroy
end

it "removes modules only when there is a single instance of it remaining" do
device_driver = Generator.driver(role: Driver::Role::Device)
device_mod2 = Generator.module(driver: device_driver).save!
device_mod = Generator.module(driver: device_driver).save!

control_system = Generator.control_system
control_system.modules = [device_mod.id.as(String), device_mod2.id.as(String)]
control_system.save!

driver = Generator.driver(role: Driver::Role::Logic)
mod = Generator.module(driver: driver, control_system: control_system).save!
control_system = mod.control_system!
control_system.modules.should contain(mod.id)
control_system.modules.size.should eq 3

control_system2 = Generator.control_system
control_system2.modules = [device_mod2.id.as(String)]
control_system2.save!

control_system = ControlSystem.find!(control_system.id.as(String))
control_system.destroy

Module.find?(mod.id.as(String)).should be_nil
Module.find?(device_mod.id.as(String)).should be_nil
Module.find!(device_mod2.id.as(String)).id.should eq device_mod2.id
device_driver.destroy
driver.destroy
end

describe "generation of json data" do
it "#module_data" do
cs = Generator.control_system.save!
Expand Down
31 changes: 15 additions & 16 deletions src/placeos-models/control_system.cr
Original file line number Diff line number Diff line change
Expand Up @@ -190,26 +190,25 @@ module PlaceOS::Model
def cleanup_modules
return if self.modules.empty?

# Locate modules that have no other associated ControlSystems
args = [] of String
query = ""

self.modules.each_with_index do |v, i|
args << v
query += ", " unless i == 0
query += "$#{i + 1}"
end

lonesome_modules = Module.find_all_by_sql(<<-SQL, args: args)
select m.* from "#{Module.table_name}" m, "#{ControlSystem.table_name}" s where m.id in (#{query}) and m.id = ANY(s.modules)
SQL

# Asynchronously remove the modules
lonesome_modules.map do |m|
modules_with_single_occurrence.map do |m|
future { m.destroy }
end.each(&.get)
end

def modules_with_single_occurrence : Array(Module)
Module.where(%[
id IN (
SELECT module
FROM (
SELECT UNNEST(modules) AS module
FROM sys
) AS module_list
WHERE module IN ('#{self.modules.join("', '")}')
GROUP BY module
HAVING COUNT(*) = 1)
]).to_a
end

# ensure all the modules are valid and exist
def check_modules
# TODO:: escape the modules list
Expand Down

0 comments on commit 846ec7f

Please sign in to comment.