From 299ddaf2534e9265cc3329400c26ce35e8728a2c Mon Sep 17 00:00:00 2001 From: Leon van Kammen Date: Wed, 29 Oct 2025 21:20:29 +0100 Subject: [PATCH] improved hook-runner (ttl + duplicate-check) --- .../src/app/config/initializers/xrforge.rb | 50 ++++++++++--------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/manyfold/usr/src/app/config/initializers/xrforge.rb b/manyfold/usr/src/app/config/initializers/xrforge.rb index 1ea8729..571ee48 100644 --- a/manyfold/usr/src/app/config/initializers/xrforge.rb +++ b/manyfold/usr/src/app/config/initializers/xrforge.rb @@ -1,40 +1,44 @@ +# this calls the xrforge unix file-hooks in /root/hook.d/experience_updated (but in a safe way) +# why: the database-write are sometimes chatty/duplicated. +# therefore it ratelimits and prevents processing unchanged files. + require 'pp' +require 'digest' Rails.application.config.to_prepare do Model # Zeitwerk autoload model ModelFile - # extend by adding listeners - class Model - - attr_accessor :last_action_execution_time + class ModelFile # The macro is now run within the context of the existing Model class. - after_commit :run_cli_hooks + after_save :run_cli_hooks - # Define the new method to be executed on save. def run_cli_hooks - # Your custom logic to execute after Model.save or Model.update! goes here. - - now = Time.current - rate_limit_seconds = 2.0 - last_run_time = @last_action_execution_time - - if self.path.match('#') - if last_run_time.nil? || (now - last_run_time) > rate_limit_seconds - self.last_action_execution_time = now - - # 📝 Example Logic: - puts "\n-------- MODEL --------- #{self.id} #{self.path}\n\n" - pp self - puts "\n\n" - command = "TS_SLOTS=5 ts /manyfold/cli/manyfold.sh hook experience_updated #{self.library.path}/#{self.path} &" + file = "#{self.model.library.path}/#{self.path_within_library()}" + + if File.exist?(file) + cache_key = "ttl:file:cli_hook:#{self.id}#{Digest::MD5.file(file).hexdigest}" + ttl = 60.0 # dont trigger hook twice for the same file within 60 seconds + now = Time.current + + # 1. Read the last run time from the shared cache + last_run_time_str = Rails.cache.read(cache_key) + last_run_time = last_run_time_str ? Time.parse(last_run_time_str) : nil + + if last_run_time.nil? || (now - last_run_time) > ttl + # 2. Write the new execution time to the shared cache + # Use `write` to set the new time. Caching a string representation is often safer/easier. + Rails.cache.write(cache_key, now.to_s, expires_in: ttl + 1.minute) + + puts "[app/config/initializers/xrforge.rb] runnin hook\n" + command = "TS_SLOTS=5 ts /manyfold/cli/manyfold.sh hook experience_updated #{file} &" system(command) + else + puts "[app/config/initializers/xrforge.rb] skipping hook\n" end end - end end - end