. /** * Track Adobe Connect room occupancy for auto MP4 after the class actually ends. * * @package mod_meetletacbmarketplace * @copyright 2026 MeetLet * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace mod_meetletacbmarketplace\local; defined('MOODLE_INTERNAL') || die(); /** * Persist live/closed room state on meetlet_marketplace_meetings and decide when to sweep recordings. */ class roomsession { /** Seconds to keep looking for new recordings after the room empties. */ public const SWEEP_GRACE = 20 * MINSECS; /** * Record occupancy. Returns true for an opportunistic queue (just closed / grace window). * * Open = at least one person in the Adobe room. Closed = it was open, then empty. * Moodle schedule endtime is intentionally ignored here. * Cron retries leftover recordings forever while the room is empty; this return * only gates page-view / join-status opportunistic queues during the grace window. */ public static function note_presence(instance $instance, bool $islive): bool { global $DB; $map = $instance->meetingmap; if (!$map || empty($map->id)) { return false; } $row = $DB->get_record('meetlet_marketplace_meetings', ['id' => (int)$map->id]); if (!$row) { return false; } $now = time(); $waslive = !empty($row->islive); if ($islive) { $row->islive = 1; $row->liveat = $now; $DB->update_record('meetlet_marketplace_meetings', $row); $instance->meetingmap = $row; return false; } if ($waslive) { $row->islive = 0; $row->closedat = $now; $row->sweepuntil = $now + self::sweep_window(); } $insweep = !empty($row->sweepuntil) && $now <= (int)$row->sweepuntil; $due = $insweep && $instance->auto_offline_enabled() && ($now - (int)($row->sweptat ?? 0) >= 45); if ($due) { $row->sweptat = $now; } if ($waslive || $due) { $DB->update_record('meetlet_marketplace_meetings', $row); } $instance->meetingmap = $row; return $due; } protected static function sweep_window(): int { $mins = config::cron_interval_minutes(); return max(self::SWEEP_GRACE, $mins * MINSECS * 4); } }