░▒▓████████████████████████████████▓▒░ ░▒▓█ ▓▒░ ░▒▓█ ~ S W A M P ~ ▓▒░ ░▒▓█ ▓▒░ ░▒▓████████████████████████████████▓▒░
pplmvsvm
LOCATION:
/var/www/canvas/gems/canvas_panda_pub/lib/canvas_panda_pub
☗ ROOT
↻ REFRESH
✎ CARVE FLESH
EDITING: async_worker.rb
# frozen_string_literal: true # # Copyright (C) 2014 - present Instructure, Inc. # # This file is part of Canvas. # # Canvas is free software: you can redistribute it and/or modify it under # the terms of the GNU Affero General Public License as published by the Free # Software Foundation, version 3 of the License. # # Canvas is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Affero General Public License for more # details. # # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see <http://www.gnu.org/licenses/>. # require "set" module CanvasPandaPub # Internal: Helper for performing PandaPub HTTP requests in a separate # thread. The only type of pushes we currently support are ones where later # pushes take precedence over earlier pushes. class AsyncWorker def initialize(start_thread = true) @queue = Queue.new @logger = CanvasPandaPub.logger @interval = CanvasPandaPub.process_interval start! if start_thread end def push(tag, p) if @queue.length >= CanvasPandaPub.max_queue_size return false end # first element is the channel # second the Proc that gets run # third is a flag of whether or not to actually run it. We may # change it to false later @queue << [tag, p, true] true end def stop! @queue << :stop @thread.join end def start! @thread = Thread.new { run_thread } end def run_thread stop = false loop do work = [] # We let push requests build up every interval, and then coalesce. # This gives us some cheap throttling. sleep @interval # Block until an item shows up... work << @queue.pop # .. then pop items off the queue. New items may show up (so this # doesn't completely empty the queue) but that's fine - if we kept # popping until empty, we could theoretically end up popping forever. @queue.length.times do work << @queue.pop end # Mark all but the last instance of each tag as "false" to not # execute. Doing it this way, rather than building up a Hash of # channel -> p, keeps ordering such that each item of work # will be executed in the order it was queued. It also gives # future flexibility for adding more modes (like pushing all updates, # instead of just the most recent). seen_channels = Set.new work.reverse_each do |ary| if seen_channels.include? ary[0] ary[2] = false else seen_channels << ary[0] end end work.each do |ary| if ary == :stop stop = true break end tag, p, execute = *ary next unless execute begin # We could use Canvas.timeout_protection here, but I'd rather not # since a) that incurs a Redis hit for every use, and b) we're # already protected from blocking Canvas since we're in a thread. p.call rescue => e @logger.error("Exception making PandaPub call to channel #{tag}: #{e}") end CanvasPandaPub.on_work_unit_end&.call end break if stop end end end end
CANCEL
Name
Type
Size
Modified
Actions
↩ ..
DIR
—
—
📄 async_worker.rb
RB
3.4 KB
2023-09-24 03:36
EDIT
📄 client.rb
RB
4.1 KB
2023-09-24 03:36
EDIT