func schedule()

in glean-core/ios/Glean/Scheduler/MetricsPingScheduler.swift [117:179]


    func schedule() -> Bool {
        let now = Date()

        // If the version of the app is different from the last time we ran the app,
        // schedule the metrics ping for immediate collection. We only need to perform
        // this check at startup (when overduePingAsFirst is true).
        if isDifferentVersion() {
            self.collectPingAndReschedule(
                now,
                startupPing: true,
                reason: .upgrade
            )
            return true
        }

        let lastSentDate = getLastCollectedDate()
        logger.debug("The 'metrics' ping was last sent on \(String(describing: lastSentDate))")

        // We expect to cover 3 cases here:
        //
        // (1) - the ping was already collected on the current calendar day; only schedule
        //       one for collecting the next calendar day at the due time;
        // (2) - the ping was NOT collected on the current calendar day, and we're later than
        //       the due time; collect the ping immediately;
        // (3) - the ping was NOT collected on the current calendar day, but we still have
        //       some time to the due time; schedule for sending the current calendar day.

        let alreadySentToday = lastSentDate != nil && Calendar.current.isDateInToday(lastSentDate!)
        if alreadySentToday {
            // The metrics ping was already sent today. Schedule it for the next
            // calendar day. This addresses (1).
            logger.info("The 'metrics' ping was already sent today, \(now).")
            schedulePingCollection(
                now,
                sendTheNextCalendarDay: true,
                reason: .tomorrow
            )
            return false
        } else if isAfterDueTime(now) {
            logger.info("The 'metrics' ping is scheduled for immediate collection, \(now)")
            // **IMPORTANT**
            //
            // We want to make sure no other metric API adds data before the ping is collected.
            // `schedule` should be called off of the main thread.  As long as `schedule` is
            // invoked before replaying any queued recording API call, it guarantees this step
            // is completed before anything else is recorded.
            self.collectPingAndReschedule(
                now,
                startupPing: true,
                reason: .overdue
            )
            return true
        } else {
            // This covers (3).
            logger.info("The 'metrics' collection is scheduled for today, \(now)")
            schedulePingCollection(
                now,
                sendTheNextCalendarDay: false,
                reason: .today
            )
            return false
        }
    }