# 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 'digest' Rails.application.config.to_prepare do Model # Zeitwerk autoload model ModelFile class ModelFile # The macro is now run within the context of the existing Model class. after_save :run_cli_hooks def run_cli_hooks file = "#{self.model.library.path}/#{self.path_within_library()}" if File.exist?(file) && (ENV['BOOT_SCAN'].present? || file.match?("datapackage") ) 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 + 3.second) puts "[app/config/initializers/xrforge.rb] running hook\n" Bundler.with_unbundled_env do #`TS_SLOTS=5 ts /manyfold/cli/manyfold.sh hook experience_updated #{file} &` `/manyfold/cli/manyfold.sh hook experience_updated #{file}` end Model.find(self.model.id).add_new_files_later(include_all_subfolders:false) else puts "[app/config/initializers/xrforge.rb] skipping hook\n" end end end end end #class XRForgeRoutes # # Rack endpoints must implement a #call method that accepts the Rack environment hash (env). # def call(env) # # Wrap the environment in a Rails Request object for easier parameter access # request = ActionDispatch::Request.new(env) # # # 1. Access the model ID from the route parameters # # The route path parameters are stored in the routing information # model_id = request.path_parameters[:id] # # begin # # 2. Find the model # # Note: We are outside the controller, so we access Model directly. # model = Model.find(model_id) # # puts "-------------------------" # Rails.logger.info("build process for Model ID: #{model.id}") # url_helpers = Rails.application.routes.url_helpers # redirect_path = url_helpers.model_path(model) # # # 302 Found response for a temporary redirect # [ # 302, # { # 'Content-Type' => 'text/html', # 'Location' => redirect_path # }, # ['Build process started successfully.'] # ] # # rescue ActiveRecord::RecordNotFound # # Handle model not found error # [ # 404, # { 'Content-Type' => 'text/plain' }, # ["Model with ID #{model_id} not found."] # ] # rescue => e # # Handle other errors # Rails.logger.error("Build Rack App Error: #{e.message}") # [ # 500, # { 'Content-Type' => 'text/plain' }, # ["Internal Server Error: Could not initiate build."] # ] # end # end #end # #Rails.configuration.to_prepare do # Rails.application.routes.draw do # resources :models, only: [] do # member do # # Point the route directly to an instance of the Rack application class. # # The route is: POST /models/:id/build # match 'build', to: XRForgeRoutes.new, via: :post # end # end # end #end