ابدأ أو تأكد من تشغيل المهمة المتأخرة عند إعادة تشغيل التطبيق/الخادم

StackOverflow https://stackoverflow.com/questions/2580871

سؤال

يتعين علينا استخدام eveleded_job (أو بعض معالج خلفية آخر) لتشغيل الوظائف في الخلفية ، لكن لا يُسمح لنا بتغيير البرامج النصية/مستويات التمهيد على الخادم. هذا يعني أن الخفي غير مضمون للبقاء متاحًا إذا قام الموفر بإعادة تشغيل الخادم (نظرًا لأن الخفي كان سيبدأ من خلال وصفة Capistrano التي يتم تشغيلها مرة واحدة فقط لكل عملية نشر).

حاليًا ، تتمثل أفضل طريقة يمكنني التفكير فيها لضمان تشغيل Develed_Job Daemon دائمًا ، في إضافة مُعمى إلى تطبيق Rails الخاص بنا يتحقق مما إذا كان الخفي قيد التشغيل. إذا لم يكن قيد التشغيل ، فإن المُهيئ يبدأ الخفي ، وإلا فإنه يتركه.

والسؤال ، بالتالي ، هو كيف يمكننا اكتشاف أن Develed_Job Daemon يمتد من داخل البرنامج النصي؟ (يجب أن نكون قادرين على بدء تشغيل الخفي بسهولة إلى حد ما ، ولا أعرف شيئًا ما إذا كان يكتشف ما إذا كان أحدهم نشطًا بالفعل).

هل لدي احد اى افكار؟

التحيات ، بيرني

بناءً على الإجابة أدناه ، هذا ما توصلت إليه. ما عليك سوى وضعه في التكوين/المبتدئين وأنت كل ما يلي:

#config/initializers/delayed_job.rb

DELAYED_JOB_PID_PATH = "#{Rails.root}/tmp/pids/delayed_job.pid"

def start_delayed_job
  Thread.new do 
    `ruby script/delayed_job start`
  end
end

def process_is_dead?
  begin
    pid = File.read(DELAYED_JOB_PID_PATH).strip
    Process.kill(0, pid.to_i)
    false
  rescue
    true
  end
end

if !File.exist?(DELAYED_JOB_PID_PATH) && process_is_dead?
  start_delayed_job
end
هل كانت مفيدة؟

المحلول

تحقق من وجود ملف PID Daemons (File.exist? ...). إذا كان هناك ثم افترض أنه يعمل آخر ، ابدأه.

نصائح أخرى

بعض أفكار التنظيف الأخرى: ليست هناك حاجة إلى "البداية". يجب أن تنقذ "لا توجد عملية مثل هذه" حتى لا تطلق عمليات جديدة عندما يحدث خطأ آخر. إنقاذ "لا يوجد ملف أو دليل" وكذلك لتبسيط الشرط.

DELAYED_JOB_PID_PATH = "#{Rails.root}/tmp/pids/delayed_job.pid"

def start_delayed_job
  Thread.new do 
    `ruby script/delayed_job start`
  end
end

def daemon_is_running?
  pid = File.read(DELAYED_JOB_PID_PATH).strip
  Process.kill(0, pid.to_i)
  true
rescue Errno::ENOENT, Errno::ESRCH   # file or process not found
  false
end

start_delayed_job unless daemon_is_running?

ضع في اعتبارك أن هذا الرمز لن يعمل إذا بدأت أكثر من عامل واحد. وتحقق من وسيطة "-M" من البرنامج النصي/تأخيرها والتي تولد عملية شاشة جنبا إلى جنب مع الخفي (s).

شكرًا لك على الحل المقدم في السؤال (والإجابة التي ألهمته :-)) ، فهو يعمل بالنسبة لي ، حتى مع وجود العديد من العمال (Rails 3.2.9 ، Ruby 1.9.3p327).

يقلقني من أنني قد أنسى إعادة تشغيل تأخير _job بعد إجراء بعض التغييرات على LIB على سبيل المثال ، مما تسبب لي في تصحيحها لساعات قبل أن أدرك ذلك.

أضفت ما يلي إلى بلدي script/rails ملف للسماح للرمز المقدم في السؤال بالتنفيذ في كل مرة نبدأ فيها القضبان ولكن ليس في كل مرة يبدأ فيها العامل:

puts "cleaning up delayed job pid..."
dj_pid_path = File.expand_path('../../tmp/pids/delayed_job.pid',  __FILE__)
begin
  File.delete(dj_pid_path)
rescue Errno::ENOENT # file does not exist
end
puts "delayed_job ready."

هناك القليل من العيب الذي أواجهه مع هذا هو أنه يتم استدعاؤه أيضًا rails generate علي سبيل المثال. لم أقضي الكثير من الوقت في البحث عن حل لذلك ولكن الاقتراحات مرحب بها :-)

لاحظ أنه إذا كنت تستخدم Unicorn ، فقد ترغب في إضافة نفس الرمز إلى config/unicorn.rb قبل before_fork يتصل.

- تحرير:بعد اللعب أكثر قليلاً مع الحلول أعلاه ، انتهى بي الأمر بما يلي:

لقد قمت بإنشاء ملف script/start_delayed_job.rb مع المحتوى:

puts "cleaning up delayed job pid..."
dj_pid_path = File.expand_path('../../tmp/pids/delayed_job.pid',  __FILE__)

def kill_delayed(path)
  begin
    pid = File.read(path).strip
    Process.kill(0, pid.to_i)
    false
  rescue
    true
  end
end

kill_delayed(dj_pid_path)

begin
  File.delete(dj_pid_path)
rescue Errno::ENOENT # file does not exist
end

# spawn delayed
env = ARGV[1]
puts "spawing delayed job in the same env: #{env}" 

# edited, next line has been replaced with the following on in order to ensure delayed job is running in the same environment as the one that spawned it
#Process.spawn("ruby script/delayed_job start")
system({ "RAILS_ENV" => env}, "ruby script/delayed_job start")

puts "delayed_job ready."

الآن يمكنني أن أطلب هذا الملف في أي مكان أريده ، بما في ذلك "البرنامج النصي/القضبان" و "config/unicorn.rb" عن طريق العمل:

# in top of script/rails
START_DELAYED_PATH = File.expand_path('../start_delayed_job',  __FILE__)
require "#{START_DELAYED_PATH}"

# in config/unicorn.rb, before before_fork, different expand_path
START_DELAYED_PATH = File.expand_path('../../script/start_delayed_job',  __FILE__)
require "#{START_DELAYED_PATH}"

ليس رائعا ، ولكن يعمل

إخلاء المسئولية: أنا لا أقول رائع لأن هذا يسبب إعادة تشغيل دورية ، والتي لن تكون مرغوبة بالنسبة للكثيرين. يمكن أن تسبب محاولة البدء ببساطة مشاكل لأن تنفيذ DJ يمكن أن يحبس قائمة الانتظار في حالة إنشاء مثيلات مكررة.

يمكنك جدولة cron المهام التي تعمل بشكل دوري لبدء الوظيفة (الوظائف) المعنية. نظرًا لأن DJ يتعامل مع الأوامر start باعتبارها عدم وجود OPS عند تشغيل المهمة بالفعل ، فهي تعمل فقط. يعتني هذا النهج أيضًا بالحالة التي يموت فيها DJ لسبب آخر غير إعادة تشغيل المضيف.

# crontab example 
0 * * * * /bin/bash -l -c 'cd /var/your-app/releases/20151207224034 && RAILS_ENV=production bundle exec script/delayed_job --queue=default -i=1 restart'

إذا كنت تستخدم جوهرة مثل whenever هذا صريح جدا.

every 1.hour do
  script "delayed_job --queue=default -i=1 restart"
  script "delayed_job --queue=lowpri -i=2 restart"
end
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top