From ed6f0176ef2e9b7628edc1aa69ea0c80e66dca24 Mon Sep 17 00:00:00 2001 From: Michael Aherne <michael.aherne@strath.ac.uk> Date: Fri, 11 Sep 2015 14:15:47 +0100 Subject: [PATCH] Added background mode --- classes/log/store.php | 24 +++++++++++- classes/task/emit_task.php | 59 +++++++++++++++++++++++++++++ db/install.xml | 41 ++++++++++++++++++++ db/tasks.php | 37 +++++++++++++++++++ db/upgrade.php | 76 ++++++++++++++++++++++++++++++++++++++ lang/en/logstore_xapi.php | 7 +++- settings.php | 13 +++++-- version.php | 2 +- 8 files changed, 252 insertions(+), 7 deletions(-) create mode 100644 classes/task/emit_task.php create mode 100644 db/install.xml create mode 100644 db/tasks.php create mode 100644 db/upgrade.php diff --git a/classes/log/store.php b/classes/log/store.php index 566be02..d3d35bd 100644 --- a/classes/log/store.php +++ b/classes/log/store.php @@ -63,7 +63,7 @@ class store extends php_obj implements log_writer { * Should the event be ignored (not logged)? Overrides helper_writer. * @param event_base $event * @return bool - * + * */ protected function is_event_ignored(event_base $event) { return false; @@ -75,6 +75,19 @@ class store extends php_obj implements log_writer { * */ protected function insert_event_entries(array $events) { + global $DB; + + // If in background mode, just save them in the database + if (get_config('logstore_xapi', 'backgroundmode')) { + $DB->insert_records('logstore_xapi_log', $events); + } else { + $this->process_events($events); + } + + } + + public function process_events(array $events) { + // Initializes required services. $xapicontroller = new xapi_controller($this->connect_xapi_repository()); $moodlecontroller = new moodle_controller($this->connect_moodle_repository()); @@ -82,11 +95,20 @@ class store extends php_obj implements log_writer { // Emits events to other APIs. foreach ($events as $event) { + $event = (array) $event; // $this->error_log(''); // $this->error_log_value('event', $event); $moodleevent = $moodlecontroller->createEvent($event); + if (is_null($moodleevent)) { + continue; + } + // $this->error_log_value('moodleevent', $moodleevent); $translatorevent = $translatorcontroller->createEvent($moodleevent); + if (is_null($translatorevent)) { + continue; + } + // $this->error_log_value('translatorevent', $translatorevent); $xapievent = $xapicontroller->createEvent($translatorevent); // $this->error_log_value('xapievent', $xapievent); diff --git a/classes/task/emit_task.php b/classes/task/emit_task.php new file mode 100644 index 0000000..fd4b06b --- /dev/null +++ b/classes/task/emit_task.php @@ -0,0 +1,59 @@ +<?php +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see <http://www.gnu.org/licenses/>. + +/** + * Process events in queue. + * + * @package logstore_xapi + * @copyright 2015 Michael Aherne + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace logstore_xapi\task; + +use tool_log\log\manager; +use logstore_xapi\log\store; +defined('MOODLE_INTERNAL') || die(); + +class emit_task extends \core\task\scheduled_task { + + /** + * Get a descriptive name for this task (shown to admins). + * + * @return string + */ + public function get_name() { + return get_string('taskemit', 'logstore_xapi'); + } + + /** + * Do the job. + * Throw exceptions on errors (the job will be retried). + */ + public function execute() { + global $DB; + + $manager = get_log_manager(); + $store = new store($manager); + + $events = $DB->get_records('logstore_xapi_log'); + $store->process_events($events); + + $DB->delete_records_list('logstore_xapi_log', 'id', array_keys($events)); + + mtrace("Sent learning records to LRS."); + } +} diff --git a/db/install.xml b/db/install.xml new file mode 100644 index 0000000..d09c1e9 --- /dev/null +++ b/db/install.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<XMLDB PATH="admin/tool/log/store/xapi/db" VERSION="20140415" COMMENT="XMLDB file for Moodle admin/tool/log/store/xapi" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../lib/xmldb/xmldb.xsd" +> + <TABLES> + <TABLE NAME="logstore_xapi_log" COMMENT="xAPI holding table for cron processing"> + <FIELDS> + <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/> + <FIELD NAME="eventname" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/> + <FIELD NAME="component" TYPE="char" LENGTH="100" NOTNULL="true" SEQUENCE="false"/> + <FIELD NAME="action" TYPE="char" LENGTH="100" NOTNULL="true" SEQUENCE="false"/> + <FIELD NAME="target" TYPE="char" LENGTH="100" NOTNULL="true" SEQUENCE="false"/> + <FIELD NAME="objecttable" TYPE="char" LENGTH="50" NOTNULL="false" SEQUENCE="false"/> + <FIELD NAME="objectid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/> + <FIELD NAME="crud" TYPE="char" LENGTH="1" NOTNULL="true" SEQUENCE="false"/> + <FIELD NAME="edulevel" TYPE="int" LENGTH="1" NOTNULL="true" SEQUENCE="false"/> + <FIELD NAME="contextid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/> + <FIELD NAME="contextlevel" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/> + <FIELD NAME="contextinstanceid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/> + <FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/> + <FIELD NAME="courseid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/> + <FIELD NAME="relateduserid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/> + <FIELD NAME="anonymous" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Was this event anonymous at the time of triggering?"/> + <FIELD NAME="other" TYPE="text" NOTNULL="false" SEQUENCE="false"/> + <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/> + <FIELD NAME="origin" TYPE="char" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="cli, cron, ws, etc."/> + <FIELD NAME="ip" TYPE="char" LENGTH="45" NOTNULL="false" SEQUENCE="false" COMMENT="IP address"/> + <FIELD NAME="realuserid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="real user id when logged-in-as"/> + </FIELDS> + <KEYS> + <KEY NAME="primary" TYPE="primary" FIELDS="id"/> + </KEYS> + <INDEXES> + <INDEX NAME="timecreated" UNIQUE="false" FIELDS="timecreated"/> + <INDEX NAME="course-time" UNIQUE="false" FIELDS="courseid, anonymous, timecreated"/> + <INDEX NAME="user-module" UNIQUE="false" FIELDS="userid, contextlevel, contextinstanceid, crud, edulevel, timecreated"/> + </INDEXES> + </TABLE> + </TABLES> +</XMLDB> \ No newline at end of file diff --git a/db/tasks.php b/db/tasks.php new file mode 100644 index 0000000..f1ddd49 --- /dev/null +++ b/db/tasks.php @@ -0,0 +1,37 @@ +<?php +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see <http://www.gnu.org/licenses/>. + +/** + * Standard log reader/writer cron task. + * + * @package logstore_xapi + * @copyright 2015 Michael Aherne + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$tasks = array( + array( + 'classname' => '\logstore_xapi\task\emit_task', + 'blocking' => 0, + 'minute' => '*/5', + 'hour' => '*', + 'day' => '*', + 'dayofweek' => '*', + 'month' => '*' + ), +); \ No newline at end of file diff --git a/db/upgrade.php b/db/upgrade.php new file mode 100644 index 0000000..abb333f --- /dev/null +++ b/db/upgrade.php @@ -0,0 +1,76 @@ +<?php +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see <http://www.gnu.org/licenses/>. + +/** + * xAPI log store upgrade. + * + * @package logstore_xapi + * @copyright 2015 Michael Aherne + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +function xmldb_logstore_xapi_upgrade($oldversion) { + global $CFG, $DB; + + $dbman = $DB->get_manager(); + + if ($oldversion < 2015081001) { + + // Define table logstore_xapi_log to be created. + $table = new xmldb_table('logstore_xapi_log'); + + // Adding fields to table logstore_xapi_log. + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table->add_field('eventname', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); + $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); + $table->add_field('action', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); + $table->add_field('target', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); + $table->add_field('objecttable', XMLDB_TYPE_CHAR, '50', null, null, null, null); + $table->add_field('objectid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); + $table->add_field('crud', XMLDB_TYPE_CHAR, '1', null, XMLDB_NOTNULL, null, null); + $table->add_field('edulevel', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, null); + $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('contextlevel', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('contextinstanceid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); + $table->add_field('relateduserid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); + $table->add_field('anonymous', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0'); + $table->add_field('other', XMLDB_TYPE_TEXT, null, null, null, null, null); + $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('origin', XMLDB_TYPE_CHAR, '10', null, null, null, null); + $table->add_field('ip', XMLDB_TYPE_CHAR, '45', null, null, null, null); + $table->add_field('realuserid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); + + // Adding keys to table logstore_xapi_log. + $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); + + // Adding indexes to table logstore_xapi_log. + $table->add_index('timecreated', XMLDB_INDEX_NOTUNIQUE, array('timecreated')); + $table->add_index('course-time', XMLDB_INDEX_NOTUNIQUE, array('courseid', 'anonymous', 'timecreated')); + $table->add_index('user-module', XMLDB_INDEX_NOTUNIQUE, array('userid', 'contextlevel', 'contextinstanceid', 'crud', 'edulevel', 'timecreated')); + + // Conditionally launch create table for logstore_xapi_log. + if (!$dbman->table_exists($table)) { + $dbman->create_table($table); + } + + // Xapi savepoint reached. + upgrade_plugin_savepoint(true, 2015081001, 'logstore', 'xapi'); + } + + return true; +} diff --git a/lang/en/logstore_xapi.php b/lang/en/logstore_xapi.php index 1f27a2b..f8d450c 100644 --- a/lang/en/logstore_xapi.php +++ b/lang/en/logstore_xapi.php @@ -34,4 +34,9 @@ $string['pluginadministration'] = 'Logstore xAPI administration'; $string['pluginname'] = 'Logstore xAPI'; $string['submit'] = 'Submit'; $string['username'] = 'Username'; -$string['xapisettingstitle'] = 'Logstore xAPI Settings'; \ No newline at end of file +$string['xapisettingstitle'] = 'Logstore xAPI Settings'; +$string['backgroundmode'] = 'Send statements by scheduled task?'; +$string['backgroundmode_desc'] = 'This will force Moodle to send the statements to the LRS in the background, + via a cron task. This will make the process less close to real time, but will help to prevent unpredictable + Moodle performance linked to the performance of the LRS.'; +$string['taskemit'] = 'Emit records to LRS'; \ No newline at end of file diff --git a/settings.php b/settings.php index d1a49a6..269603c 100644 --- a/settings.php +++ b/settings.php @@ -27,13 +27,18 @@ defined('MOODLE_INTERNAL') || die(); if ($hassiteconfig) { // Endpoint. - $settings->add(new admin_setting_configtext('logstore_xapi/endpoint', - get_string('endpoint', 'logstore_xapi'), '', + $settings->add(new admin_setting_configtext('logstore_xapi/endpoint', + get_string('endpoint', 'logstore_xapi'), '', 'http://your.domain.com/endpoint/location/', PARAM_URL)); // Username. - $settings->add(new admin_setting_configtext('logstore_xapi/username', + $settings->add(new admin_setting_configtext('logstore_xapi/username', get_string('username', 'logstore_xapi'), '', 'username', PARAM_TEXT)); // Key or password. - $settings->add(new admin_setting_configtext('logstore_xapi/password', + $settings->add(new admin_setting_configtext('logstore_xapi/password', get_string('password', 'logstore_xapi'), '', 'password', PARAM_TEXT)); + + // Switch background batch mode on + $settings->add(new admin_setting_configcheckbox('logstore_xapi/backgroundmode', + get_string('backgroundmode', 'logstore_xapi'), + get_string('backgroundmode_desc', 'logstore_xapi'), 0)); } diff --git a/version.php b/version.php index e0d4417..2f3ea82 100644 --- a/version.php +++ b/version.php @@ -26,7 +26,7 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'logstore_xapi'; -$plugin->version = 2015081000; +$plugin->version = 2015081002; $plugin->release = '0.3.0'; $plugin->requires = 2014111000; $plugin->maturity = MATURITY_BETA; -- GitLab