diff --git a/record-and-playback/core/lib/recordandplayback/workers/events_worker.rb b/record-and-playback/core/lib/recordandplayback/workers/events_worker.rb old mode 100644 new mode 100755 index 555380e8f3ff6bf4a37e7f4e059c23b39916e9e0..43c5d8070e449cd984377e303601b471a8873d45 --- a/record-and-playback/core/lib/recordandplayback/workers/events_worker.rb +++ b/record-and-playback/core/lib/recordandplayback/workers/events_worker.rb @@ -20,10 +20,10 @@ module BigBlueButton module Resque class EventsWorker < BaseWorker - @queue = 'rap:archive' + @queue = 'rap:events' def store_events(target_dir) - @logger.info("Keeping events for #{meeting_id}") + @logger.info("Keeping events for #{@meeting_id}") redis = BigBlueButton::RedisWrapper.new(@props['redis_host'], @props['redis_port'], @props['redis_password']) events_archiver = BigBlueButton::RedisEventsArchiver.new(redis) @@ -32,7 +32,7 @@ module BigBlueButton # When the events script is responsible for archiving events, the sanity script (which normally clears the events # from redis) will not get run, so we have to clear them here. - events_archiver.delete_events(meeting_id) if @break_timestamp.nil? + events_archiver.delete_events(@meeting_id) if @break_timestamp.nil? end def perform @@ -43,20 +43,21 @@ module BigBlueButton next true # We're inside a block and want to return to the block's caller, not return from perform end + remove_status_files + target_dir = "#{@events_dir}/#{@meeting_id}" FileUtils.mkdir_p(target_dir) + raw_events_xml = "#{@recording_dir}/raw/#{@meeting_id}/events.xml" if File.exist?(raw_events_xml) # This is a recorded meeting. The archive step should have already run, so copy the events.xml from the raw # recording directory. - FileUtils.cp("#{@recording_dir}/raw/#{@meeting_id}/events.xml", "#{target_dir}/events.xml") + FileUtils.cp(raw_events_xml, "#{target_dir}/events.xml") else # This meeting was not recorded. We need to run the (incremental, if break_timestamp was provided) events archiving. store_events(target_dir) end - FileUtils.rm_f(@ended_done) - # Only run post events scripts after full meeting ends, not during segments run_post_scripts(@post_scripts_path) if @break_timestamp.nil? @@ -64,8 +65,13 @@ module BigBlueButton end end + def remove_status_files + FileUtils.rm_f(@ended_done) + end + def initialize(opts) super(opts) + @single_step = true @step_name = 'events' @events_dir = @props['events_dir'] @post_scripts_path = File.join(BigBlueButton.rap_scripts_path, 'post_events') diff --git a/record-and-playback/core/scripts/rap-starter.rb b/record-and-playback/core/scripts/rap-starter.rb index 2bd2686bf7594cbe3cc7cdf0a4dc1e31b80825f4..ecd459deb8dd3552bebd889506866897060e0df1 100755 --- a/record-and-playback/core/scripts/rap-starter.rb +++ b/record-and-playback/core/scripts/rap-starter.rb @@ -42,23 +42,30 @@ def parse_meeting_id(done_file) end end -def keep_meeting_events(recording_dir, ended_done_file) - id = File.basename(ended_done_file, '.done') - BigBlueButton.logger.debug("Seen new ended done file for #{id}") - attrs = parse_meeting_id(id) +def keep_meeting_events(recording_dir, file, from_archive) + # When keeping events from archive: + # - <meeting_id>.done + # - <meeting_id>.norecord + id = File.basename(file).split('.').first + attrs = parse_meeting_id("#{id}.done") # Inject .done to use the same parser return if attrs.nil? - # If a meeting was recorded, the events will be archived by the archive step, and - # the events script will be run after that (it'll grab the already archived events - # from the recording raw directory) - if File.exist?("#{recording_dir}/status/recorded/#{id}.done") || File.exist?("#{recording_dir}/raw/#{attrs[:meeting_id]}") - BigBlueButton.logger.info("Meeting #{id} had recording enabled, events will be handled after recording archive") - return - end + if from_archive + ended_done_file = "#{recording_dir}/status/ended/#{attrs[:meeting_id]}.done" + # Skip if keep events is not enabled for this meeting + return unless File.exist?(ended_done_file) + + BigBlueButton.logger.info("Enqueueing job to keep events from archive #{attrs.inspect}") + Resque.enqueue(BigBlueButton::Resque::EventsWorker, attrs) + else + recorded_done_file = "#{recording_dir}/status/recorded/#{attrs[:meeting_id]}.done" + raw_dir = "#{recording_dir}/raw/#{attrs[:meeting_id]}" + # Skip if events will be archived + return if File.exist?(recorded_done_file) || File.exist?(raw_dir) - BigBlueButton.logger.info("Enqueueing job to keep events #{attrs.inspect}") - Resque.enqueue(BigBlueButton::Resque::EventsWorker, attrs) - FileUtils.rm_f(ended_done_file) + BigBlueButton.logger.info("Enqueueing job to keep events #{attrs.inspect}") + Resque.enqueue(BigBlueButton::Resque::EventsWorker, attrs) + end end def archive_recorded_meetings(recording_dir, done_file) @@ -86,29 +93,45 @@ begin BigBlueButton.logger.debug('Running rap-starter...') recording_dir = props['recording_dir'] - ended_status_dir = "#{recording_dir}/status/ended" recorded_status_dir = "#{recording_dir}/status/recorded" - # Check for missed "ended" .done files - ended_done_files = Dir.glob("#{ended_status_dir}/*.done") - ended_done_files.each do |ended_done_file| - keep_meeting_events(recording_dir, ended_done_file) - end - # Check for missed "recorded" .done files recorded_done_files = Dir.glob("#{recorded_status_dir}/*.done") recorded_done_files.each do |recorded_done_file| archive_recorded_meetings(recording_dir, recorded_done_file) end + ended_status_dir = "#{recording_dir}/status/ended" + + # Check for missed "ended" .done files + ended_done_files = Dir.glob("#{ended_status_dir}/*.done") + ended_done_files.each do |ended_done_file| + keep_meeting_events(recording_dir, ended_done_file, false) + end + # Listen the directories for when new files are created - BigBlueButton.logger.info("Setting up inotify watch on #{ended_status_dir}") notifier = INotify::Notifier.new + + # - record=false + # - events.xml will be created from redis records + BigBlueButton.logger.info("Setting up inotify watch on #{ended_status_dir}") notifier.watch(ended_status_dir, :moved_to, :create) do |event| next unless event.name.end_with?('.done') - keep_meeting_events(recording_dir, event.absolute_name) + keep_meeting_events(recording_dir, event.absolute_name, false) + end + + archived_status_dir = "#{recording_dir}/status/archived" + + # - record=true + # - events.xml will be copied from archived + BigBlueButton.logger.info("Setting up inotify watch on #{archived_status_dir}") + notifier.watch(archived_status_dir, :moved_to, :create) do |event| + next if event.name.end_with?('.fail') + + keep_meeting_events(recording_dir, event.absolute_name, true) end + BigBlueButton.logger.info("Setting up inotify watch on #{recorded_status_dir}") notifier.watch(recorded_status_dir, :moved_to, :create) do |event| next unless event.name.end_with?('.done') diff --git a/record-and-playback/core/systemd/bbb-rap-resque-worker.service b/record-and-playback/core/systemd/bbb-rap-resque-worker.service index 71467bfc8ff03aa0cf34b5882467f7aa257042bd..d092b65a80e67fb6498397cec47fa8fef7c369b4 100644 --- a/record-and-playback/core/systemd/bbb-rap-resque-worker.service +++ b/record-and-playback/core/systemd/bbb-rap-resque-worker.service @@ -5,7 +5,7 @@ Description=BigBlueButton resque worker for recordings Type=simple ExecStart=/bin/sh -c '/usr/bin/rake -f ../Rakefile resque:workers >> /var/log/bigbluebutton/bbb-rap-worker.log' WorkingDirectory=/usr/local/bigbluebutton/core/scripts -Environment=QUEUE=rap:archive,rap:publish,rap:process,rap:sanity,rap:captions +Environment=QUEUE=rap:archive,rap:publish,rap:process,rap:sanity,rap:captions,rap:events Environment=COUNT=1 # Environment=VVERBOSE=1 User=bigbluebutton