public function execute() {
        global $DB;

        $userid = $this->get_custom_data()->userid;

        // Get the user's preference.
        $hasbeenmigrated = get_user_preferences('core_message_migrate_data', false, $userid);

        if (!$hasbeenmigrated) {
            // To determine if we should update the preference.
            $updatepreference = true;

            // Get all the users the current user has received a message from.
            $sql = "SELECT DISTINCT(useridfrom)
                      FROM {message} m
                     WHERE useridto = ?
                     UNION
                    SELECT DISTINCT(useridfrom)
                      FROM {message_read} m
                     WHERE useridto = ?";
            $users = $DB->get_records_sql($sql, [$userid, $userid]);

            // Get all the users the current user has messaged.
            $sql = "SELECT DISTINCT(useridto)
                      FROM {message} m
                     WHERE useridfrom = ?
                     UNION
                    SELECT DISTINCT(useridto)
                      FROM {message_read} m
                     WHERE useridfrom = ?";
            $users = $users + $DB->get_records_sql($sql, [$userid, $userid]);
            if (!empty($users)) {
                // Loop through each user and migrate the data.
                foreach ($users as $otheruserid => $user) {
                    $ids = [$userid, $otheruserid];
                    sort($ids);
                    $key = implode('_', $ids);

                    // Set the lock data.
                    $timeout = 5; // In seconds.
                    $locktype = 'core_message_migrate_data';

                    // Get an instance of the currently configured lock factory.
                    $lockfactory = \core\lock\lock_config::get_lock_factory($locktype);

                    // See if we can grab this lock.
                    if ($lock = $lockfactory->get_lock($key, $timeout)) {
                        try {
                            $transaction = $DB->start_delegated_transaction();
                            $this->migrate_data($userid, $otheruserid);
                            $transaction->allow_commit();
                        } catch (\Throwable $e) {
                            throw $e;
                        } finally {
                            $lock->release();
                        }
                    } else {
                        // Couldn't get a lock, move on to next user but make sure we don't update user preference so
                        // we still try again.
                        $updatepreference = false;
                        continue;
                    }
                }
            }

            if ($updatepreference) {
                set_user_preference('core_message_migrate_data', true, $userid);
            } else {
                // Throwing an exception in the task will mean that it isn't removed from the queue and is tried again.
                throw new \moodle_exception('Task failed.');
            }
        }
    }