MDL-56139 core: changes after peer review
- No longer use the Fibonacci sequence for delaying the timeout. It is too aggressive. - The backoff_timer AMD module now expects the callback AND the backoff function to be passed to the constructor. - Added ability to specify polling frequency in config.php. - Added helper function to return the cache key. - Reworded the parameters for clarity.
This commit is contained in:
+1
-1
@@ -52,7 +52,7 @@ $string['cachedef_suspended_userids'] = 'List of suspended users per course';
|
||||
$string['cachedef_groupdata'] = 'Course group information';
|
||||
$string['cachedef_htmlpurifier'] = 'HTML Purifier - cleaned content';
|
||||
$string['cachedef_langmenu'] = 'List of available languages';
|
||||
$string['cachedef_message_last_created'] = 'Time created for most recent message between users';
|
||||
$string['cachedef_message_time_last_message_between_users'] = 'Time created for most recent message between users';
|
||||
$string['cachedef_locking'] = 'Locking';
|
||||
$string['cachedef_message_processors_enabled'] = "Message processors enabled status";
|
||||
$string['cachedef_navigation_expandcourse'] = 'Navigation expandable courses';
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
define(function(){var a=1e3,b=function(b,c){if(!b)return a;if(c.length){var d=c[c.length-1];return b+d}return a},c=function(a){this.reset(),this.setCallback(a),this.setBackOffFunction(b)};return c.prototype.setCallback=function(a){return this.callback=a,this},c.prototype.getCallback=function(){return this.callback},c.prototype.setBackOffFunction=function(a){return this.backOffFunction=a,this},c.prototype.getBackOffFunction=function(){return this.backOffFunction},c.prototype.generateNextTime=function(){var a=this.getBackOffFunction().call(this.getBackOffFunction(),this.time,this.previousTimes);return this.previousTimes.push(this.time),this.time=a,a},c.prototype.reset=function(){return this.time=null,this.previousTimes=[],this.stop(),this},c.prototype.stop=function(){return this.timeout&&(window.clearTimeout(this.timeout),this.timeout=null),this},c.prototype.start=function(){if(!this.timeout){var a=this.generateNextTime();this.timeout=window.setTimeout(function(){this.getCallback().call(),this.stop(),this.start()}.bind(this),a)}return this},c.prototype.restart=function(){return this.reset().start()},c});
|
||||
define(function(){var a=function(a,b){this.callback=a,this.backOffFunction=b};return a.prototype.callback=null,a.prototype.backOffFunction=null,a.prototype.time=null,a.prototype.timeout=null,a.prototype.generateNextTime=function(){var a=this.backOffFunction(this.time);return this.time=a,a},a.prototype.reset=function(){return this.time=null,this.stop(),this},a.prototype.stop=function(){return this.timeout&&(window.clearTimeout(this.timeout),this.timeout=null),this},a.prototype.start=function(){if(!this.timeout){var a=this.generateNextTime();this.timeout=window.setTimeout(function(){this.callback(),this.stop(),this.start()}.bind(this),a)}return this},a.prototype.restart=function(){return this.reset().start()},a.getIncrementalCallback=function(a,b,c,d){return function(e){return e?e+b>c?d:e+b:a}},a});
|
||||
@@ -25,92 +25,36 @@
|
||||
*/
|
||||
define(function() {
|
||||
|
||||
// Default to one second.
|
||||
var DEFAULT_TIME = 1000;
|
||||
|
||||
/**
|
||||
* The default back off function for the timer. It uses the Fibonacci
|
||||
* sequence to determine what the next timeout value should be.
|
||||
*
|
||||
* @param {(int|null)} time The current timeout value or null if none set
|
||||
* @param {array} previousTimes An array containing all previous timeout values
|
||||
* @return {int} The new timeout value
|
||||
*/
|
||||
var fibonacciBackOff = function(time, previousTimes) {
|
||||
if (!time) {
|
||||
return DEFAULT_TIME;
|
||||
}
|
||||
|
||||
if (previousTimes.length) {
|
||||
var lastTime = previousTimes[previousTimes.length - 1];
|
||||
return time + lastTime;
|
||||
} else {
|
||||
return DEFAULT_TIME;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor for the back off timer.
|
||||
*
|
||||
* @param {function} callback The function to execute after each tick
|
||||
* @param {function} backoffFunction The function to determine what the next timeout value should be
|
||||
*/
|
||||
var Timer = function(callback) {
|
||||
this.reset();
|
||||
this.setCallback(callback);
|
||||
// Set the default backoff function to be the Fibonacci sequence.
|
||||
this.setBackOffFunction(fibonacciBackOff);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the callback function to be executed after each tick of the
|
||||
* timer.
|
||||
*
|
||||
* @method setCallback
|
||||
* @param {function} callback The callback function
|
||||
* @return {object} this
|
||||
*/
|
||||
Timer.prototype.setCallback = function(callback) {
|
||||
var BackoffTimer = function(callback, backoffFunction) {
|
||||
this.callback = callback;
|
||||
|
||||
return this;
|
||||
this.backOffFunction = backoffFunction;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the callback function for this timer.
|
||||
*
|
||||
* @method getCallback
|
||||
* @return {function}
|
||||
* @type {function} callback The function to execute after each tick
|
||||
*/
|
||||
Timer.prototype.getCallback = function() {
|
||||
return this.callback;
|
||||
};
|
||||
BackoffTimer.prototype.callback = null;
|
||||
|
||||
/**
|
||||
* Set the function to be used when calculating the back off time
|
||||
* for each tick of the timer.
|
||||
*
|
||||
* The back off function will be given two parameters: the current
|
||||
* time and an array containing all previous times.
|
||||
*
|
||||
* @method setBackOffFunction
|
||||
* @param {function} backOffFunction The function to calculate back off times
|
||||
* @return {object} this
|
||||
* @type {function} backoffFunction The function to determine what the next timeout value should be
|
||||
*/
|
||||
Timer.prototype.setBackOffFunction = function(backOffFunction) {
|
||||
this.backOffFunction = backOffFunction;
|
||||
|
||||
return this;
|
||||
};
|
||||
BackoffTimer.prototype.backOffFunction = null;
|
||||
|
||||
/**
|
||||
* Get the current back off function.
|
||||
*
|
||||
* @method getBackOffFunction
|
||||
* @return {function}
|
||||
* @type {int} time The timeout value to use
|
||||
*/
|
||||
Timer.prototype.getBackOffFunction = function() {
|
||||
return this.backOffFunction;
|
||||
};
|
||||
BackoffTimer.prototype.time = null;
|
||||
|
||||
/**
|
||||
* @type {numeric} timeout The timeout identifier
|
||||
*/
|
||||
BackoffTimer.prototype.timeout = null;
|
||||
|
||||
/**
|
||||
* Generate the next timeout in the back off time sequence
|
||||
@@ -122,13 +66,8 @@ define(function() {
|
||||
* @method generateNextTime
|
||||
* @return {int} The new timeout value (in milliseconds)
|
||||
*/
|
||||
Timer.prototype.generateNextTime = function() {
|
||||
var newTime = this.getBackOffFunction().call(
|
||||
this.getBackOffFunction(),
|
||||
this.time,
|
||||
this.previousTimes
|
||||
);
|
||||
this.previousTimes.push(this.time);
|
||||
BackoffTimer.prototype.generateNextTime = function() {
|
||||
var newTime = this.backOffFunction(this.time);
|
||||
this.time = newTime;
|
||||
|
||||
return newTime;
|
||||
@@ -140,9 +79,8 @@ define(function() {
|
||||
* @method reset
|
||||
* @return {object} this
|
||||
*/
|
||||
Timer.prototype.reset = function() {
|
||||
BackoffTimer.prototype.reset = function() {
|
||||
this.time = null;
|
||||
this.previousTimes = [];
|
||||
this.stop();
|
||||
|
||||
return this;
|
||||
@@ -154,7 +92,7 @@ define(function() {
|
||||
* @method stop
|
||||
* @return {object} this
|
||||
*/
|
||||
Timer.prototype.stop = function() {
|
||||
BackoffTimer.prototype.stop = function() {
|
||||
if (this.timeout) {
|
||||
window.clearTimeout(this.timeout);
|
||||
this.timeout = null;
|
||||
@@ -175,12 +113,12 @@ define(function() {
|
||||
* @method start
|
||||
* @return {object} this
|
||||
*/
|
||||
Timer.prototype.start = function() {
|
||||
BackoffTimer.prototype.start = function() {
|
||||
// If we haven't already started.
|
||||
if (!this.timeout) {
|
||||
var time = this.generateNextTime();
|
||||
this.timeout = window.setTimeout(function() {
|
||||
this.getCallback().call();
|
||||
this.callback();
|
||||
// Clear the existing timer.
|
||||
this.stop();
|
||||
// Start the next timer.
|
||||
@@ -198,9 +136,40 @@ define(function() {
|
||||
* @method restart
|
||||
* @return {object} this
|
||||
*/
|
||||
Timer.prototype.restart = function() {
|
||||
BackoffTimer.prototype.restart = function() {
|
||||
return this.reset().start();
|
||||
};
|
||||
|
||||
return Timer;
|
||||
/**
|
||||
* Returns an incremental function for the timer.
|
||||
*
|
||||
* @param {int} minamount The minimum amount of time we wait before checking
|
||||
* @param {int} incrementamount The amount to increment the timer by
|
||||
* @param {int} maxamount The max amount to ever increment to
|
||||
* @param {int} timeoutamount The timeout to use once we reach the max amount
|
||||
* @return {function}
|
||||
*/
|
||||
BackoffTimer.getIncrementalCallback = function(minamount, incrementamount, maxamount, timeoutamount) {
|
||||
|
||||
/**
|
||||
* An incremental function for the timer.
|
||||
*
|
||||
* @param {(int|null)} time The current timeout value or null if none set
|
||||
* @return {int} The new timeout value
|
||||
*/
|
||||
return function(time) {
|
||||
if (!time) {
|
||||
return minamount;
|
||||
}
|
||||
|
||||
// Don't go over the max amount.
|
||||
if (time + incrementamount > maxamount) {
|
||||
return timeoutamount;
|
||||
}
|
||||
|
||||
return time + incrementamount;
|
||||
};
|
||||
};
|
||||
|
||||
return BackoffTimer;
|
||||
});
|
||||
|
||||
+3
-4
@@ -302,12 +302,11 @@ $definitions = array(
|
||||
'staticaccelerationsize' => 3
|
||||
),
|
||||
|
||||
// Cache for storing the user's last received message time.
|
||||
'message_last_created' => array(
|
||||
// Caches the time of the last message between two users.
|
||||
'message_time_last_message_between_users' => array(
|
||||
'mode' => cache_store::MODE_APPLICATION,
|
||||
'simplekeys' => true, // The id of the sender and recipient is used.
|
||||
'simplevalues' => true,
|
||||
'datasource' => 'message_last_created_cache_source',
|
||||
'datasourcefile' => 'message/classes/message_last_created_cache_source.php'
|
||||
'datasource' => '\core_message\time_last_message_between_users',
|
||||
),
|
||||
);
|
||||
|
||||
+3
-4
@@ -237,10 +237,9 @@ function message_send($eventdata) {
|
||||
// Only cache messages, not notifications.
|
||||
if (empty($savemessage->notification)) {
|
||||
// Cache the timecreated value of the last message between these two users.
|
||||
$cache = cache::make('core', 'message_last_created');
|
||||
$ids = [$savemessage->useridfrom, $savemessage->useridto];
|
||||
sort($ids);
|
||||
$key = implode('_', $ids);
|
||||
$cache = cache::make('core', 'message_time_last_message_between_users');
|
||||
$key = \core_message\helper::get_last_message_time_created_cache_key($savemessage->useridfrom,
|
||||
$savemessage->useridto);
|
||||
$cache->set($key, $savemessage->timecreated);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
define(["jquery","core_message/message_area_contacts","core_message/message_area_messages","core_message/message_area_profile","core_message/message_area_tabs","core_message/message_area_search"],function(a,b,c,d,e,f){function g(b){this.node=a(b),this._init()}return g.prototype.node=null,g.prototype._init=function(){new b(this),new c(this),new d(this),new e(this),new f(this)},g.prototype.onDelegateEvent=function(a,b,c){this.node.on(a,b,c)},g.prototype.onCustomEvent=function(a,b){this.node.on(a,b)},g.prototype.trigger=function(a,b){"undefined"==typeof b&&(b=""),this.node.trigger(a,b)},g.prototype.find=function(a){return this.node.find(a)},g.prototype.getCurrentUserId=function(){return this.node.data("userid")},g});
|
||||
define(["jquery","core_message/message_area_contacts","core_message/message_area_messages","core_message/message_area_profile","core_message/message_area_tabs","core_message/message_area_search"],function(a,b,c,d,e,f){function g(b,c,d,e){this.node=a(b),this.pollmin=c,this.pollmax=d,this.polltimeout=e,this._init()}return g.prototype.node=null,g.prototype.pollmin=null,g.prototype.pollmax=null,g.prototype.polltimeout=null,g.prototype._init=function(){new b(this),new c(this),new d(this),new e(this),new f(this)},g.prototype.onDelegateEvent=function(a,b,c){this.node.on(a,b,c)},g.prototype.onCustomEvent=function(a,b){this.node.on(a,b)},g.prototype.trigger=function(a,b){"undefined"==typeof b&&(b=""),this.node.trigger(a,b)},g.prototype.find=function(a){return this.node.find(a)},g.prototype.getCurrentUserId=function(){return this.node.data("userid")},g});
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -29,15 +29,30 @@ define(['jquery', 'core_message/message_area_contacts', 'core_message/message_ar
|
||||
* Messagearea class.
|
||||
*
|
||||
* @param {String} selector The selector for the page region containing the message area.
|
||||
* @param {int} pollmin
|
||||
* @param {int} pollmax
|
||||
* @param {int} polltimeout
|
||||
*/
|
||||
function Messagearea(selector) {
|
||||
function Messagearea(selector, pollmin, pollmax, polltimeout) {
|
||||
this.node = $(selector);
|
||||
this.pollmin = pollmin;
|
||||
this.pollmax = pollmax;
|
||||
this.polltimeout = polltimeout;
|
||||
this._init();
|
||||
}
|
||||
|
||||
/** @type {jQuery} The jQuery node for the page region containing the message area. */
|
||||
Messagearea.prototype.node = null;
|
||||
|
||||
/** @type {int} The minimum time to poll for messages. */
|
||||
Messagearea.prototype.pollmin = null;
|
||||
|
||||
/** @type {int} The maximum time to poll for messages. */
|
||||
Messagearea.prototype.pollmax = null;
|
||||
|
||||
/** @type {int} The time used once we have reached the maximum polling time. */
|
||||
Messagearea.prototype.polltimeout = null;
|
||||
|
||||
/**
|
||||
* Initialise the other objects we require.
|
||||
*/
|
||||
|
||||
@@ -53,6 +53,9 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
|
||||
STARTDELETEMESSAGES: "[data-action='start-delete-messages']"
|
||||
};
|
||||
|
||||
/** @type {int} The number of milliseconds in a second. */
|
||||
var MILLISECONDSINSEC = 1000;
|
||||
|
||||
/**
|
||||
* Messages class.
|
||||
*
|
||||
@@ -81,8 +84,8 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
|
||||
/** @type {int} the timestamp for the earliest visible message */
|
||||
Messages.prototype._earliestMessageTimestamp = 0;
|
||||
|
||||
/** @type {BackOffTime} the backoff timer */
|
||||
Messages.prototype._timer = null;
|
||||
/** @type {BackOffTimer} the backoff timer */
|
||||
Messages.prototype._backoffTimer = null;
|
||||
|
||||
/** @type {Messagearea} The messaging area object. */
|
||||
Messages.prototype.messageArea = null;
|
||||
@@ -146,12 +149,12 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
|
||||
}
|
||||
|
||||
// Create a timer to poll the server for new messages.
|
||||
this._timer = new BackOffTimer(function() {
|
||||
this._loadNewMessages();
|
||||
}.bind(this));
|
||||
this._backoffTimer = new BackOffTimer(this._loadNewMessages.bind(this),
|
||||
BackOffTimer.getIncrementalCallback(this.messageArea.pollmin * MILLISECONDSINSEC, MILLISECONDSINSEC,
|
||||
this.messageArea.pollmax * MILLISECONDSINSEC, this.messageArea.polltimeout * MILLISECONDSINSEC));
|
||||
|
||||
// Start the timer.
|
||||
this._timer.start();
|
||||
this._backoffTimer.start();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -166,7 +169,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
|
||||
// We are viewing another user, or re-loading the panel, so set number of messages displayed to 0.
|
||||
this._numMessagesDisplayed = 0;
|
||||
// Stop the existing timer so we can set up the new user's messages.
|
||||
this._timer.stop();
|
||||
this._backoffTimer.stop();
|
||||
// Reset the earliest timestamp when we change the messages view.
|
||||
this._earliestMessageTimestamp = 0;
|
||||
|
||||
@@ -203,7 +206,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
|
||||
Templates.replaceNodeContents(this.messageArea.find(SELECTORS.MESSAGESAREA), html, js);
|
||||
this._addScrollEventListener(numberreceived);
|
||||
// Restart the poll timer.
|
||||
this._timer.restart();
|
||||
this._backoffTimer.restart();
|
||||
}.bind(this)).fail(Notification.exception);
|
||||
};
|
||||
|
||||
@@ -321,7 +324,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
|
||||
// Increment the number of messages displayed.
|
||||
this._numMessagesDisplayed += numberreceived;
|
||||
// Reset the poll timer because the user may be active.
|
||||
this._timer.restart();
|
||||
this._backoffTimer.restart();
|
||||
}
|
||||
}.bind(this)).always(function() {
|
||||
// Mark that we are no longer busy loading data.
|
||||
@@ -349,7 +352,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
|
||||
// If we're trying to load new messages since the message UI was
|
||||
// rendered. Used for ajax polling while user is on the message UI.
|
||||
if (fromTimestamp) {
|
||||
args.createdfrom = this._earliestMessageTimestamp;
|
||||
args.timefrom = this._earliestMessageTimestamp;
|
||||
// Remove limit and offset. We want all new messages.
|
||||
args.limitfrom = 0;
|
||||
args.limitnum = 0;
|
||||
@@ -381,10 +384,11 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
|
||||
}
|
||||
|
||||
return data;
|
||||
}.bind(this)).fail(function() {
|
||||
}.bind(this)).fail(function(ex) {
|
||||
// Stop the timer if we received an error so that we don't keep spamming the server.
|
||||
this._timer.stop();
|
||||
}.bind(this)).fail(Notification.exception);
|
||||
this._backoffTimer.stop();
|
||||
Notification.exception(ex);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+8
-10
@@ -291,31 +291,29 @@ class api {
|
||||
* @param int $limitfrom
|
||||
* @param int $limitnum
|
||||
* @param string $sort
|
||||
* @param int $createdfrom the timestamp from which the messages were created
|
||||
* @param int $createdto the time up until which the message was created
|
||||
* @param int $timefrom the time from the message being sent
|
||||
* @param int $timeto the time up until the message being sent
|
||||
* @return array
|
||||
*/
|
||||
public static function get_messages($userid, $otheruserid, $limitfrom = 0, $limitnum = 0,
|
||||
$sort = 'timecreated ASC', $createdfrom = 0, $createdto = 0) {
|
||||
$sort = 'timecreated ASC', $timefrom = 0, $timeto = 0) {
|
||||
|
||||
if (!empty($createdfrom)) {
|
||||
if (!empty($timefrom)) {
|
||||
// Check the cache to see if we even need to do a DB query.
|
||||
$cache = \cache::make('core', 'message_last_created');
|
||||
$ids = [$otheruserid, $userid];
|
||||
sort($ids);
|
||||
$key = implode('_', $ids);
|
||||
$cache = \cache::make('core', 'message_time_last_message_between_users');
|
||||
$key = helper::get_last_message_time_created_cache_key($otheruserid, $userid);
|
||||
$lastcreated = $cache->get($key);
|
||||
|
||||
// The last known message time is earlier than the one being requested so we can
|
||||
// just return an empty result set rather than having to query the DB.
|
||||
if ($lastcreated && $lastcreated < $createdfrom) {
|
||||
if ($lastcreated && $lastcreated < $timefrom) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
$arrmessages = array();
|
||||
if ($messages = helper::get_messages($userid, $otheruserid, 0, $limitfrom, $limitnum,
|
||||
$sort, $createdfrom, $createdto)) {
|
||||
$sort, $timefrom, $timeto)) {
|
||||
|
||||
$arrmessages = helper::create_messages($userid, $messages);
|
||||
}
|
||||
|
||||
@@ -43,12 +43,12 @@ class helper {
|
||||
* @param int $limitfrom
|
||||
* @param int $limitnum
|
||||
* @param string $sort
|
||||
* @param int $createdfrom the time from which the message was created
|
||||
* @param int $createdto the time up until which the message was created
|
||||
* @param int $timefrom the time from the message being sent
|
||||
* @param int $timeto the time up until the message being sent
|
||||
* @return array of messages
|
||||
*/
|
||||
public static function get_messages($userid, $otheruserid, $timedeleted = 0, $limitfrom = 0, $limitnum = 0,
|
||||
$sort = 'timecreated ASC', $createdfrom = 0, $createdto = 0) {
|
||||
$sort = 'timecreated ASC', $timefrom = 0, $timeto = 0) {
|
||||
global $DB;
|
||||
|
||||
$messageid = $DB->sql_concat("'message_'", 'id');
|
||||
@@ -77,16 +77,16 @@ class helper {
|
||||
$otheruserid, $userid, $timedeleted);
|
||||
$where = array();
|
||||
|
||||
if (!empty($createdfrom)) {
|
||||
if (!empty($timefrom)) {
|
||||
$where[] = 'AND timecreated >= ?';
|
||||
$params1[] = $createdfrom;
|
||||
$params2[] = $createdfrom;
|
||||
$params1[] = $timefrom;
|
||||
$params2[] = $timefrom;
|
||||
}
|
||||
|
||||
if (!empty($createdto)) {
|
||||
if (!empty($timeto)) {
|
||||
$where[] = 'AND timecreated <= ?';
|
||||
$params1[] = $createdto;
|
||||
$params2[] = $createdto;
|
||||
$params1[] = $timeto;
|
||||
$params2[] = $timeto;
|
||||
}
|
||||
|
||||
$sql = str_replace('%where%', implode(' ', $where), $sql);
|
||||
@@ -270,4 +270,17 @@ class helper {
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cache key for the time created value of the last message between two users.
|
||||
*
|
||||
* @param int $userid
|
||||
* @param int $user2id
|
||||
* @return string
|
||||
*/
|
||||
public static function get_last_message_time_created_cache_key($userid, $user2id) {
|
||||
$ids = [$userid, $user2id];
|
||||
sort($ids);
|
||||
return implode('_', $ids);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,21 @@ class message_area implements templatable, renderable {
|
||||
*/
|
||||
public $requestedconversation;
|
||||
|
||||
/**
|
||||
* @var int The minimum time to poll for messages.
|
||||
*/
|
||||
public $pollmin;
|
||||
|
||||
/**
|
||||
* @var int The maximum time to poll for messages.
|
||||
*/
|
||||
public $pollmax;
|
||||
|
||||
/**
|
||||
* @var int The time used once we have reached the maximum polling time.
|
||||
*/
|
||||
public $polltimeout;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -71,13 +86,20 @@ class message_area implements templatable, renderable {
|
||||
* @param array $contacts
|
||||
* @param array|null $messages
|
||||
* @param bool $requestedconversation
|
||||
* @param int $pollmin
|
||||
* @param int $pollmax
|
||||
* @param int $polltimeout
|
||||
*/
|
||||
public function __construct($userid, $otheruserid, $contacts, $messages, $requestedconversation) {
|
||||
public function __construct($userid, $otheruserid, $contacts, $messages, $requestedconversation, $pollmin, $pollmax,
|
||||
$polltimeout) {
|
||||
$this->userid = $userid;
|
||||
$this->otheruserid = $otheruserid;
|
||||
$this->contacts = $contacts;
|
||||
$this->messages = $messages;
|
||||
$this->requestedconversation = $requestedconversation;
|
||||
$this->pollmin = $pollmin;
|
||||
$this->pollmax = $pollmax;
|
||||
$this->polltimeout = $polltimeout;
|
||||
}
|
||||
|
||||
public function export_for_template(\renderer_base $output) {
|
||||
@@ -89,6 +111,9 @@ class message_area implements templatable, renderable {
|
||||
$data->messages = $messages->export_for_template($output);
|
||||
$data->isconversation = true;
|
||||
$data->requestedconversation = $this->requestedconversation;
|
||||
$data->pollmin = $this->pollmin;
|
||||
$data->pollmax = $this->pollmax;
|
||||
$data->polltimeout = $this->polltimeout;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
+9
-8
@@ -15,7 +15,7 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Cache data source for the last created message between users.
|
||||
* Cache data source for the time of the last message between users.
|
||||
*
|
||||
* @package core_message
|
||||
* @category cache
|
||||
@@ -23,32 +23,33 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_message;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Cache data source for the last created message between users.
|
||||
* Cache data source for the time of the last message between users.
|
||||
*
|
||||
* @package core_message
|
||||
* @category cache
|
||||
* @copyright 2016 Ryan Wyllie <ryan@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class message_last_created_cache_source implements \cache_data_source {
|
||||
class time_last_message_between_users implements \cache_data_source {
|
||||
|
||||
/** @var message_last_created_cache_source the singleton instance of this class. */
|
||||
/** @var time_last_message_between_users the singleton instance of this class. */
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
* Returns an instance of the data source class that the cache can use for loading data using the other methods
|
||||
* specified by the cache_data_source interface.
|
||||
*
|
||||
* @param cache_definition $definition
|
||||
* @param \cache_definition $definition
|
||||
* @return object
|
||||
*/
|
||||
public static function get_instance_for_cache(cache_definition $definition) {
|
||||
public static function get_instance_for_cache(\cache_definition $definition) {
|
||||
if (is_null(self::$instance)) {
|
||||
self::$instance = new message_last_created_cache_source();
|
||||
self::$instance = new time_last_message_between_users();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
@@ -62,7 +63,7 @@ class message_last_created_cache_source implements \cache_data_source {
|
||||
public function load_for_cache($key) {
|
||||
list($userid1, $userid2) = explode('_', $key);
|
||||
|
||||
$message = \core_message\api::get_most_recent_message($userid1, $userid2);
|
||||
$message = api::get_most_recent_message($userid1, $userid2);
|
||||
|
||||
if ($message) {
|
||||
return $message->timecreated;
|
||||
@@ -901,7 +901,7 @@ class core_message_external extends external_api {
|
||||
'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
|
||||
'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
|
||||
'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
|
||||
'createdfrom' => new external_value(PARAM_INT,
|
||||
'timefrom' => new external_value(PARAM_INT,
|
||||
'The timestamp from which the messages were created', VALUE_DEFAULT, 0),
|
||||
)
|
||||
);
|
||||
@@ -920,7 +920,7 @@ class core_message_external extends external_api {
|
||||
* @since 3.2
|
||||
*/
|
||||
public static function data_for_messagearea_messages($currentuserid, $otheruserid, $limitfrom = 0, $limitnum = 0,
|
||||
$newest = false, $createdfrom = 0) {
|
||||
$newest = false, $timefrom = 0) {
|
||||
global $CFG, $PAGE, $USER;
|
||||
|
||||
// Check if messaging is enabled.
|
||||
@@ -936,7 +936,7 @@ class core_message_external extends external_api {
|
||||
'limitfrom' => $limitfrom,
|
||||
'limitnum' => $limitnum,
|
||||
'newest' => $newest,
|
||||
'createdfrom' => $createdfrom,
|
||||
'timefrom' => $timefrom,
|
||||
);
|
||||
self::validate_parameters(self::data_for_messagearea_messages_parameters(), $params);
|
||||
self::validate_context($systemcontext);
|
||||
@@ -959,18 +959,18 @@ class core_message_external extends external_api {
|
||||
// case those messages will be lost.
|
||||
//
|
||||
// Instead we ignore the current time in the result set to ensure that second is allowed to finish.
|
||||
if (!empty($createdfrom)) {
|
||||
$createdto = time() - 1;
|
||||
if (!empty($timefrom)) {
|
||||
$timeto = time() - 1;
|
||||
} else {
|
||||
$createdto = 0;
|
||||
$timeto = 0;
|
||||
}
|
||||
|
||||
// No requesting messages from the current time, as stated above.
|
||||
if ($createdfrom == time()) {
|
||||
$mesages = [];
|
||||
if ($timefrom == time()) {
|
||||
$messages = [];
|
||||
} else {
|
||||
$messages = \core_message\api::get_messages($currentuserid, $otheruserid, $limitfrom,
|
||||
$limitnum, $sort, $createdfrom, $createdto);
|
||||
$limitnum, $sort, $timefrom, $timeto);
|
||||
}
|
||||
|
||||
$messages = new \core_message\output\messagearea\messages($currentuserid, $otheruserid, $messages);
|
||||
|
||||
+4
-1
@@ -127,8 +127,11 @@ if (!empty($user2->id)) {
|
||||
$messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 20, 'timecreated DESC');
|
||||
}
|
||||
|
||||
$pollmin = !empty($CFG->messagingminpoll) ? $CFG->messagingminpoll : MESSAGE_DEFAULT_MIN_POLL_IN_SECONDS;
|
||||
$pollmax = !empty($CFG->messagingmaxpoll) ? $CFG->messagingmaxpoll : MESSAGE_DEFAULT_MAX_POLL_IN_SECONDS;
|
||||
$polltimeout = !empty($CFG->messagingtimeoutpoll) ? $CFG->messagingtimeoutpoll : MESSAGE_DEFAULT_TIMEOUT_POLL_IN_SECONDS;
|
||||
$messagearea = new \core_message\output\messagearea\message_area($user1->id, $user2->id, $conversations, $messages,
|
||||
$requestedconversation);
|
||||
$requestedconversation, $pollmin, $pollmax, $polltimeout);
|
||||
|
||||
// Now the page contents.
|
||||
echo $OUTPUT->header();
|
||||
|
||||
@@ -76,6 +76,13 @@ define('MESSAGE_PERMITTED_MASK', 0x0c); // 1100
|
||||
*/
|
||||
define('MESSAGE_DEFAULT_PERMITTED', 'permitted');
|
||||
|
||||
/**
|
||||
* Set default values for polling.
|
||||
*/
|
||||
define('MESSAGE_DEFAULT_MIN_POLL_IN_SECONDS', 10);
|
||||
define('MESSAGE_DEFAULT_MAX_POLL_IN_SECONDS', 2 * MINSECS);
|
||||
define('MESSAGE_DEFAULT_TIMEOUT_POLL_IN_SECONDS', 5 * MINSECS);
|
||||
|
||||
/**
|
||||
* Retrieve users blocked by $user1
|
||||
*
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
{{#js}}
|
||||
require(['core_message/message_area'],
|
||||
function(Messagearea) {
|
||||
new Messagearea('.messaging-area-container');
|
||||
new Messagearea('.messaging-area-container', {{pollmin}}, {{pollmax}}, {{polltimeout}});
|
||||
}
|
||||
);
|
||||
{{/js}}
|
||||
|
||||
@@ -957,7 +957,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
/**
|
||||
* Test retrieving messages by providing a minimum timecreated value.
|
||||
*/
|
||||
public function test_get_messages_created_from_only() {
|
||||
public function test_get_messages_time_from_only() {
|
||||
// Create some users.
|
||||
$user1 = self::getDataGenerator()->create_user();
|
||||
$user2 = self::getDataGenerator()->create_user();
|
||||
@@ -972,7 +972,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
$this->send_fake_message($user1, $user2, 'Message 3', 0, $time + 3);
|
||||
$this->send_fake_message($user2, $user1, 'Message 4', 0, $time + 4);
|
||||
|
||||
// Retrieve the messages.
|
||||
// Retrieve the messages from $time, which should be all of them.
|
||||
$messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', $time);
|
||||
|
||||
// Confirm the message data is correct.
|
||||
@@ -988,7 +988,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
$this->assertContains('Message 3', $message3->text);
|
||||
$this->assertContains('Message 4', $message4->text);
|
||||
|
||||
// Retrieve the messages.
|
||||
// Retrieve the messages from $time + 3, which should only be the 2 last messages.
|
||||
$messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', $time + 3);
|
||||
|
||||
// Confirm the message data is correct.
|
||||
@@ -1004,7 +1004,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
/**
|
||||
* Test retrieving messages by providing a maximum timecreated value.
|
||||
*/
|
||||
public function test_get_messages_created_to_only() {
|
||||
public function test_get_messages_time_to_only() {
|
||||
// Create some users.
|
||||
$user1 = self::getDataGenerator()->create_user();
|
||||
$user2 = self::getDataGenerator()->create_user();
|
||||
@@ -1019,7 +1019,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
$this->send_fake_message($user1, $user2, 'Message 3', 0, $time + 3);
|
||||
$this->send_fake_message($user2, $user1, 'Message 4', 0, $time + 4);
|
||||
|
||||
// Retrieve the messages.
|
||||
// Retrieve the messages up until $time + 4, which should be all of them.
|
||||
$messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', 0, $time + 4);
|
||||
|
||||
// Confirm the message data is correct.
|
||||
@@ -1035,7 +1035,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
$this->assertContains('Message 3', $message3->text);
|
||||
$this->assertContains('Message 4', $message4->text);
|
||||
|
||||
// Retrieve the messages.
|
||||
// Retrieve the messages up until $time + 2, which should be the first two.
|
||||
$messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', 0, $time + 2);
|
||||
|
||||
// Confirm the message data is correct.
|
||||
@@ -1051,7 +1051,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
/**
|
||||
* Test retrieving messages by providing a minimum and maximum timecreated value.
|
||||
*/
|
||||
public function test_get_messages_created_from_and_to() {
|
||||
public function test_get_messages_time_from_and_to() {
|
||||
// Create some users.
|
||||
$user1 = self::getDataGenerator()->create_user();
|
||||
$user2 = self::getDataGenerator()->create_user();
|
||||
@@ -1066,7 +1066,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
$this->send_fake_message($user1, $user2, 'Message 3', 0, $time + 3);
|
||||
$this->send_fake_message($user2, $user1, 'Message 4', 0, $time + 4);
|
||||
|
||||
// Retrieve the messages.
|
||||
// Retrieve the messages from $time + 2 up until $time + 3, which should be 2nd and 3rd message.
|
||||
$messages = \core_message\api::get_messages($user1->id, $user2->id, 0, 0, 'timecreated ASC', $time + 2, $time + 3);
|
||||
|
||||
// Confirm the message data is correct.
|
||||
|
||||
@@ -1982,7 +1982,7 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
/**
|
||||
* Tests retrieving messages.
|
||||
*/
|
||||
public function test_messagearea_messages_createfrom() {
|
||||
public function test_messagearea_messages_timefrom() {
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
// Create some users.
|
||||
@@ -1999,7 +1999,7 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
|
||||
$this->send_message($user1, $user2, 'Message 3', 0, $time - 2);
|
||||
$this->send_message($user2, $user1, 'Message 4', 0, $time - 1);
|
||||
|
||||
// Retrieve the messages.
|
||||
// Retrieve the messages from $time - 3, which should be the 3 most recent messages.
|
||||
$result = core_message_external::data_for_messagearea_messages($user1->id, $user2->id, 0, 0, false, $time - 3);
|
||||
|
||||
// We need to execute the return values cleaning process to simulate the web service server.
|
||||
|
||||
Reference in New Issue
Block a user