From 2c8ae22b87e26eeeffdda19a353ea46594b21672 Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 17 Mar 2014 11:59:34 +1100 Subject: [PATCH] FEATURE: add a simple queue Scheduler::Defer.later {} For quick jobs that do not need to be sent to sidekiq, runs inline in a single thread but does not block --- lib/auth/default_current_user_provider.rb | 9 +++-- lib/scheduler/defer.rb | 48 +++++++++++++++++++++++ lib/scheduler/scheduler.rb | 1 + spec/components/scheduler/defer_spec.rb | 40 +++++++++++++++++++ 4 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 lib/scheduler/defer.rb create mode 100644 spec/components/scheduler/defer_spec.rb diff --git a/lib/auth/default_current_user_provider.rb b/lib/auth/default_current_user_provider.rb index b48472e91af..835c9586c39 100644 --- a/lib/auth/default_current_user_provider.rb +++ b/lib/auth/default_current_user_provider.rb @@ -33,9 +33,12 @@ class Auth::DefaultCurrentUserProvider if current_user - Jobs.enqueue(:update_user_info, - user_id: current_user.id, - ip: request.ip) + u = current_user + Scheduler::Defer.later do + u.update_last_seen! + u.update_ip_address!(request.ip) + end + end # possible we have an api call, impersonate diff --git a/lib/scheduler/defer.rb b/lib/scheduler/defer.rb new file mode 100644 index 00000000000..46b94ee508d --- /dev/null +++ b/lib/scheduler/defer.rb @@ -0,0 +1,48 @@ +module Scheduler + module Deferrable + def initialize + @async = Rails.env != "test" + @queue = Queue.new + @thread = Thread.new { + while true + do_work + end + } + end + + # for test + def async=(val) + @async = val + end + + def later(&blk) + if @async + @queue << [RailsMultisite::ConnectionManagement.current_db, blk] + else + blk.call + end + end + + def stop! + @thread.kill + end + + private + + def do_work + db, job = @queue.deq + RailsMultisite::ConnectionManagement.establish_connection(db: db) + job.call + rescue => ex + Discourse.handle_exception(ex) + ensure + ActiveRecord::Base.connection_handler.clear_active_connections! + end + + end + + class Defer + extend Deferrable + initialize + end +end diff --git a/lib/scheduler/scheduler.rb b/lib/scheduler/scheduler.rb index a69b1f7a5ce..e9f389194f0 100644 --- a/lib/scheduler/scheduler.rb +++ b/lib/scheduler/scheduler.rb @@ -4,3 +4,4 @@ end require_dependency 'scheduler/schedule' require_dependency 'scheduler/schedule_info' require_dependency 'scheduler/manager' +require_dependency 'scheduler/defer' diff --git a/spec/components/scheduler/defer_spec.rb b/spec/components/scheduler/defer_spec.rb new file mode 100644 index 00000000000..b27c36c3a7b --- /dev/null +++ b/spec/components/scheduler/defer_spec.rb @@ -0,0 +1,40 @@ +# encoding: utf-8 +require 'spec_helper' +require 'scheduler/scheduler' + +describe Scheduler::Defer do + class DeferInstance + include Scheduler::Deferrable + end + + def wait_for(timeout, &blk) + till = Time.now + (timeout.to_f / 1000) + while Time.now < till && !blk.call + sleep 0.001 + end + end + + before do + @defer = DeferInstance.new + @defer.async = true + end + + after do + @defer.stop! + end + + it "can queue jobs properly" do + s = nil + + @defer.later do + s = "good" + end + + wait_for(10) do + s == "good" + end + + s.should == "good" + end + +end