diff --git a/spec/driver_cleanup_spec.cr b/spec/driver_cleanup_spec.cr new file mode 100644 index 00000000..1064b823 --- /dev/null +++ b/spec/driver_cleanup_spec.cr @@ -0,0 +1,31 @@ +require "./helper" + +module PlaceOS::Core + describe DriverCleanup do + it "get running drivers information in expected format" do + _, driver, mod = setup + module_manager = module_manager_mock + + builder = DriverResource.new(startup: true, module_manager: module_manager) + resource_manager = ResourceManager.new(driver_builder: builder) + resource_manager.start { } + + mod_id = mod.id.as(String) + + driver_path = module_manager.store.driver_binary_path(driver.file_name, driver.commit).to_s + + mod.reload! + mod.driver = mod.driver.not_nil!.reload! + + module_manager.load_module(mod) + + module_manager.local_processes.run_count.should eq(ProcessManager::Count.new(1, 1)) + + expected = ["drivers_place_private_helper_cce023_#{DriverCleanup.arch}"] + running = DriverCleanup.running_drivers + running.should eq(expected) + local = Dir.new(DriverStore::BINARY_PATH).children + running.should eq(expected) + end + end +end diff --git a/src/core-app.cr b/src/core-app.cr index a235dd32..429c0fb7 100644 --- a/src/core-app.cr +++ b/src/core-app.cr @@ -102,6 +102,9 @@ Signal::TERM.trap &terminate # Wait for redis and postgres to be ready PlaceOS::Core.wait_for_resources +# Start cleaning un-used driver task +PlaceOS::Core::DriverCleanup.start_cleanup + spawn do begin PlaceOS::Core.start_managers diff --git a/src/placeos-core/driver_cleanup.cr b/src/placeos-core/driver_cleanup.cr new file mode 100644 index 00000000..44f83684 --- /dev/null +++ b/src/placeos-core/driver_cleanup.cr @@ -0,0 +1,43 @@ +require "file_utils" +require "pg-orm" + +module PlaceOS::Core::DriverCleanup + def self.start_cleanup + spawn do + loop do + sleep(23.hours + rand(60).minutes) + cleanup_unused_drivers rescue nil + end + end + end + + def self.cleanup_unused_drivers + local = Dir.new(DriverStore::BINARY_PATH).children + running = running_drivers + stale = local - running + FileUtils.rm_rf(stale.map { |file| Path[DriverStore::BINARY_PATH, file] }) unless stale.empty? + end + + def self.arch + {% if flag?(:x86_64) %} "amd64" {% elsif flag?(:aarch64) %} "arm64" {% end %} || raise("Uknown architecture") + end + + def self.running_drivers + sql = <<-SQL + SELECT DISTINCT ON (driver.commit) + regexp_replace(regexp_replace(driver.file_name, '.cr$', '', 'g'), '[/.]', '_', 'g') || '_' || LEFT(driver.commit, 6) || '_' AS driver_file + FROM + mod, + driver + WHERE + mod.running = true + AND driver.id = mod.driver_id + ORDER BY driver.commit; + SQL + running = + ::DB.connect(Healthcheck.pg_healthcheck_url) do |db| + db.query_all sql, &.read(String) + end + running.map(&.+(arch)) + end +end diff --git a/src/placeos-core/healthcheck.cr b/src/placeos-core/healthcheck.cr index d2f832fc..883d3f50 100644 --- a/src/placeos-core/healthcheck.cr +++ b/src/placeos-core/healthcheck.cr @@ -29,7 +29,7 @@ module PlaceOS::Core::Healthcheck @@pg_healthcheck_url : String? = nil - private def self.pg_healthcheck_url(timeout = 5) + def self.pg_healthcheck_url(timeout = 5) @@pg_healthcheck_url ||= begin url = PgORM::Settings.to_uri uri = URI.parse(url)