কম্পিউটার

কলব্যাক গোটচাসের একটি দম্পতি (এবং একটি রেল 5 ফিক্স)

ActiveRecord কলব্যাক হল আপনার মডেলের জীবনের বিভিন্ন পর্যায়ে কোড চালানোর একটি সহজ উপায়।

উদাহরণস্বরূপ, বলুন আপনার একটি প্রশ্নোত্তর সাইট আছে এবং আপনি সমস্ত প্রশ্নের মাধ্যমে অনুসন্ধান করতে সক্ষম হতে চান৷ প্রতিবার যখন আপনি একটি প্রশ্নে পরিবর্তন করবেন, আপনি এটিকে ইলাস্টিক সার্চের মতো কিছুতে সূচী করতে চাইবেন। ইন্ডেক্সিং করতে একটু সময় লাগে এবং জরুরী নয়, তাই আপনি Sidekiq-এর সাথে ব্যাকগ্রাউন্ডে এটি করবেন।

এটি একটি after_save ব্যবহার করার উপযুক্ত সময় বলে মনে হচ্ছে কলব্যাক! তাই আপনার মডেলে, আপনি এরকম কিছু লিখবেন:

app/models/question.rb
class Question < ActiveRecord::Base
  after_save :index_for_search

  # ...

  private
  
  def index_for_search
    QuestionIndexerJob.perform_later(self)
  end
end
app/jobs/question_indexer_job.rb
class QuestionIndexerJob < ActiveJob::Base
  queue_as :default

  def perform(question)
    # ... index the question ...
  end
end

এই মহান কাজ! বা, অন্তত, এটা মনে হয়. যতক্ষণ না আপনি আরও অনেক কাজের সারিবদ্ধ হন এবং এই ত্রুটিগুলি দেখতে না পান:

2015-03-10T05:29:02.881Z 52530 TID-oupf889w4 WARN: Error while trying to deserialize arguments: Couldn't find Question with 'id'=3

অবশ্যই, Sidekiq কাজটি আবার চেষ্টা করবে এবং এটি সম্ভবত পরের বার কাজ করবে। কিন্তু এটা এখনও একটু অদ্ভুত। কেন Sidekiq আপনি এইমাত্র সংরক্ষিত প্রশ্নটি খুঁজে পাচ্ছেন না?

প্রক্রিয়াগুলির মধ্যে একটি রেস শর্ত

রেল কল after_save রেকর্ড সংরক্ষণ করার সাথে সাথেই কলব্যাক। কিন্তু সেই রেকর্ডটি অন্যান্য ডাটাবেস সংযোগ দ্বারা দেখা যাবে না, যেমন একটি Sidekiq ব্যবহার করছে, যতক্ষণ না ডাটাবেস লেনদেন প্রতিশ্রুতিবদ্ধ, যা একটু পরে ঘটে। এর মানে এমন একটি সুযোগ রয়েছে যে Sidekiq আপনার প্রশ্নটি সংরক্ষণ করার পরে, কিন্তু আপনি এটি করার আগে খুঁজে বের করার চেষ্টা করবে। এটি আপনার রেকর্ড খুঁজে পায় না, এবং এটি বিস্ফোরিত হয়।

এই সমস্যাটি এতটাই সাধারণ যে Sidekiq-এর কাছে এটি সম্পর্কে একটি FAQ এন্ট্রি রয়েছে৷ এবং একটি সহজ সমাধান আছে।

after_save এর পরিবর্তে :

app/models/question.rb
class Question < ActiveRecord::Base
  after_save :index_for_search

  # ...
end

after_commit ব্যবহার করুন :

app/models/question.rb
class Question < ActiveRecord::Base
  after_commit :index_for_search

  # ...
end

এবং Sidekiq আপনার মডেল দেখতে না পাওয়া পর্যন্ত আপনার কাজ সারিবদ্ধ হবে না৷

সুতরাং, যখন আপনি একটি ব্যাকগ্রাউন্ড জব সারিবদ্ধ করেন বা আপনার এইমাত্র করা পরিবর্তন সম্পর্কে অন্য একটি প্রক্রিয়া জানান, after_commit ব্যবহার করুন . যদি আপনি না করেন, তাহলে আপনি এইমাত্র স্পর্শ করা রেকর্ডটি তারা খুঁজে নাও পেতে পারেন৷

কিন্তু আরও একটি সমস্যা আছে...

ঠিক আছে, আপনি আপনার after_save এর একগুচ্ছ পরিবর্তন করেছেন after_commit ব্যবহার করার জন্য হুক পরিবর্তে. সবকিছু কাজ বলে মনে হচ্ছে. সবকিছু চেক করার এবং বাড়িতে যাওয়ার সময়, তাই না?

প্রথমে, আপনি আপনার পরীক্ষা চালাতে চাইবেন:

test/models/question_test.rb
require 'test_helper'

class QuestionTest < ActiveSupport::TestCase
  test "A saved question is queued for indexing" do
    assert_enqueued_with(job: QuestionIndexerJob) do
      Question.create(title: "Is it legal to kill a zombie?")
    end
  end
end
  1) Failure:
QuestionTest#test_A_saved_question_is_queued_for_indexing [/Users/jweiss/Source/testapps/after_commit/test/models/question_test.rb:7]:
No enqueued job found with {:job=>QuestionIndexerJob}

উফফফ! পরীক্ষা কি চাকরির সারিবদ্ধ হওয়া উচিত ছিল না? ওখানে কি হয়েছিল?

ডিফল্টরূপে, রেল প্রতিটি টেস্ট কেসকে তার নিজস্ব ডাটাবেস লেনদেনে মোড়ক করে। এই সত্যিই জিনিস দ্রুত করতে পারেন. পরীক্ষার সময় আপনার করা সমস্ত পরিবর্তনগুলি পূর্বাবস্থায় ফিরিয়ে আনতে শুধুমাত্র একটি ডাটাবেস কমান্ড লাগে৷

কিন্তু এর মানে আপনার after_commit কলব্যাক চলবে না। কারণ after_commit কলব্যাক শুধুমাত্র তখনই চলে যখন সর্বোত্তম লেনদেন করা হয়েছে৷

যখন আপনি কল করুন save একটি পরীক্ষার ক্ষেত্রে, এটি এখনও একটি লেনদেন করে (কম বা কম), তবে এটি দ্বিতীয়-সবচেয়ে বাইরের এখন লেনদেন। তাই আপনার after_commit আপনি যখন আশা করেন তখন কলব্যাক চালানো হবে না। এবং আপনি তাদের ভিতরে কি ঘটছে তা পরীক্ষা করতে পারবেন না।

এই সমস্যাটিও একটি সহজ সমাধান আছে। test_after_commit অন্তর্ভুক্ত করুন আপনার জেমফাইলে রত্ন:

Gemfile
group :test do
  gem "test_after_commit"
end

এবং আপনার after_commit আপনার দ্বিতীয় থেকে শেষের পরে হুক চলবে লেনদেন কমিট। যা আপনি ঘটবে বলে আশা করেছিলেন।

আপনি হয়তো ভাবছেন, "এটি অদ্ভুত। রেলের সাথে আসা একটি কলব্যাক পরীক্ষা করার জন্য আমাকে কেন একটি সম্পূর্ণ পৃথক রত্ন ব্যবহার করতে হবে? এটা কি স্বয়ংক্রিয়ভাবে হওয়া উচিত নয়?”

তুমি ঠিক বলছো. এটি অস্বাভাবিক. তবে এটি বেশি দিন অদ্ভুত থাকবে না।

একবার Rails 5 শিপ, আপনাকে test_after_commit নিয়ে চিন্তা করতে হবে না . কারণ এই সমস্যাটি প্রায় এক মাস আগে রেলে ঠিক করা হয়েছিল।

আমার নিজের কোডে, আমি after_commit ব্যবহার করি অনেক. আমি after_save ব্যবহার করার চেয়ে সম্ভবত এটি বেশি ব্যবহার করি ! তবে এটি এর সমস্যা এবং অদ্ভুত প্রান্তের কেস ছাড়া আসেনি।

সংস্করণ অনুসারে সংস্করণ, যদিও, এটি আরও ভাল হচ্ছে৷৷ এবং যখন আপনি after_commit ব্যবহার করেন সঠিক জায়গায়, অনেক অদ্ভুত, এলোমেলো ব্যতিক্রম আর ঘটবে না।


  1. ActionCable এবং Turbo ব্যবহার করে রেলে একটি রিয়েল-টাইম চ্যাট অ্যাপ তৈরি করা

  2. বাইবাগ, রেল এবং পা দিয়ে রিমোট ডিবাগিং

  3. Vue, Vuex এবং Rails সহ একটি সম্পূর্ণ-স্ট্যাক অ্যাপ্লিকেশন তৈরি করা

  4. Chrome এবং Edge-এ RESULT_CODE_HUNG ঠিক করুন