mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-27 10:56:16 -04:00
Working changesetloader (no caching)
This commit is contained in:
parent
47a6c74bde
commit
78eb0c7410
3 changed files with 165 additions and 54 deletions
|
@ -525,8 +525,8 @@ function loadBroadcastJS(tsclient, fireWhenAllScriptsAreLoaded, BroadcastSlider)
|
|||
}
|
||||
}
|
||||
};
|
||||
tsclient.on("CHANGESET_REQ", changesetLoader.handle_CHANGESET_REQ);
|
||||
tsclient.on("COLLABROOM", changesetLoader.handle_COLLABROOM);
|
||||
//tsclient.on("CHANGESET_REQ", changesetLoader.handle_CHANGESET_REQ);
|
||||
//tsclient.on("COLLABROOM", changesetLoader.handle_COLLABROOM);
|
||||
|
||||
// to start upon window load, just push a function onto this array
|
||||
//window['onloadFuncts'].push(setUpSocket);
|
||||
|
|
|
@ -199,8 +199,9 @@ $.Class("Thread",
|
|||
}
|
||||
_this._run.apply(_this);
|
||||
};
|
||||
this._interval_id = setInterval(wrapper, this._interval);
|
||||
this._is_running = true;
|
||||
this._is_stopping = false;
|
||||
this._interval_id = setInterval(wrapper, this._interval);
|
||||
},
|
||||
// stop the run loop
|
||||
stop: function () {
|
||||
|
@ -217,10 +218,21 @@ $.Class("ChangesetRequest",
|
|||
{//statics
|
||||
},
|
||||
{//instance
|
||||
init: function (start, end) {
|
||||
init: function (start, granularity, callback) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.granularity = granularity;
|
||||
this.request_id = (this.start << 16) + granularity;
|
||||
this.fulfill_callback = callback;
|
||||
},
|
||||
getRequestID: function () {
|
||||
return this.request_id;
|
||||
},
|
||||
fulfill: function (data) {
|
||||
console.log("[changesetrequest] Fulfilling request %d", this.getRequestID());
|
||||
if (this.fulfill_callback)
|
||||
this.fulfill_callback(data);
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -228,41 +240,117 @@ Thread("ChangesetLoader",
|
|||
{//statics
|
||||
},
|
||||
{//instance
|
||||
init: function () {
|
||||
/**
|
||||
* Create a new ChangesetLoader.
|
||||
* @constructor
|
||||
* @param {TimesliderClient} client - a TimesliderClient object to be used
|
||||
* for communication with the server.
|
||||
*/
|
||||
init: function (client) {
|
||||
this._super(100);
|
||||
this.queue_large = [];
|
||||
this.queue_medium = [];
|
||||
this.queue_small = [];
|
||||
this.client = client;
|
||||
this.queues = {
|
||||
small: [],
|
||||
medium: [],
|
||||
large: [],
|
||||
}
|
||||
this.pending = {};
|
||||
var _this = this;
|
||||
this.client.on("CHANGESET_REQ", function () {
|
||||
_this.on_response.apply(_this, arguments);
|
||||
});
|
||||
},
|
||||
enqueue: function (start, count) {
|
||||
/**
|
||||
* Enqueue a request for changesets. The changesets will be retrieved
|
||||
* asynchronously.
|
||||
* @param {number} start - The revision from which to start.
|
||||
* @param {number} granularity - The granularity of the changesets. If this
|
||||
* is 1, the response will include changesets which
|
||||
* can be applied to go from revision r to r+1.
|
||||
* If 10 is specified, the resulting changesets will
|
||||
* be 'condensed', so that each changeset will go from
|
||||
* r to r+10.
|
||||
* If any other number is specified, that granularity will
|
||||
* apply.
|
||||
*
|
||||
* TODO: there is currently no 'END' revision implemented
|
||||
* in the server. The 'END' calculated at the server is:
|
||||
* start + (100 * granularity)
|
||||
* We should probably fix this so that you can specify
|
||||
* exact ranges. Right now, the minimum number of
|
||||
* changesets/revisions you can retrieve is 100, which
|
||||
* feels broken.
|
||||
* @param {function} callback - A callback which will be triggered when the request has
|
||||
* been fulfilled.
|
||||
*/
|
||||
enqueue: function (start, granularity, callback) {
|
||||
//TODO: check cache to see if we really need to fetch this
|
||||
// maybe even to splices if we just need a smaller range
|
||||
// in the middle
|
||||
var queue = null;
|
||||
if (count >= 100)
|
||||
queue = this.queue_large;
|
||||
else if (count >= 10)
|
||||
queue = this.queue_medium;
|
||||
if (granularity == 1)
|
||||
queue = this.queues.small;
|
||||
else if (granularity == 10)
|
||||
queue = this.queues.medium;
|
||||
else
|
||||
queue = this.queue_small;
|
||||
queue = this.queues.large;
|
||||
|
||||
queue.push(new ChangesetRequest(start, start+count));
|
||||
queue.push(new ChangesetRequest(start, granularity, callback));
|
||||
},
|
||||
_run: function () {
|
||||
console.log("[changesetloader] tick");
|
||||
//TODO: pop an item from the queue and perform a request.
|
||||
for (q in this.queues) {
|
||||
var queue = this.queues[q];
|
||||
if (queue.length > 0) {
|
||||
// TODO: pop and handle
|
||||
var request = queue.pop();
|
||||
//TODO: test AGAIN to make sure that it hasn't been retrieved and cached by
|
||||
//a previous request. This should handle the case when two requests for the
|
||||
//same changesets are enqueued (which would be fine, as at enqueue time, we
|
||||
//only check the cache of AVAILABLE changesets, not the pending requests),
|
||||
//the first one is fulfilled, and then we pop the second one, and don't
|
||||
//need to perform a server request. Note: it might be worth changing enqueue
|
||||
//to check the pending requests queue to avoid this situation entirely.
|
||||
|
||||
var _this = this;
|
||||
this.client.sendMessage("CHANGESET_REQ", {
|
||||
start: request.start,
|
||||
granularity: request.granularity,
|
||||
requestID: request.getRequestID(),
|
||||
}, function () {
|
||||
_this.pending[request.getRequestID()] = request;
|
||||
});
|
||||
};
|
||||
};
|
||||
//TODO: this stop is just for debugging!!!!
|
||||
//FIXME: remove when done testing
|
||||
this.stop();
|
||||
},
|
||||
on_response: function (data) {
|
||||
console.log("on_response: ", data)
|
||||
if (!data.requestID in this.pending) {
|
||||
console.log("[changesetloader] WTF? changeset not pending: ", data.requestID);
|
||||
return;
|
||||
}
|
||||
|
||||
// pop it from the pending list:
|
||||
var request = this.pending[data.requestID];
|
||||
delete this.pending[data.requestID];
|
||||
//fulfill the request
|
||||
request.fulfill(data);
|
||||
},
|
||||
}
|
||||
);
|
||||
function loadBroadcastRevisionsJS(clientVars)
|
||||
function loadBroadcastRevisionsJS(clientVars, client)
|
||||
{
|
||||
|
||||
console.log("here")
|
||||
revisionCache = new RevisionCache(clientVars.collab_client_vars.rev || 0);
|
||||
revisionInfo.latest = clientVars.collab_client_vars.rev || -1;
|
||||
// revisionCache = new RevisionCache(clientVars.collab_client_vars.rev || 0);
|
||||
// revisionInfo.latest = clientVars.collab_client_vars.rev || -1;
|
||||
|
||||
// cl = new ChangesetLoader();
|
||||
cl = new ChangesetLoader(client);
|
||||
return cl;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -45,30 +45,41 @@ $.Class("SocketClient",
|
|||
// setup the socket callbacks:
|
||||
_this = this;
|
||||
|
||||
this.socket.on("connect", function(callback) {
|
||||
_this.onConnect(callback);
|
||||
this.socket.on("connect", function() {
|
||||
_this.onConnect.apply(_this, arguments);
|
||||
});
|
||||
this.socket.on("disconnect", function(callback) {
|
||||
_this.onDisconnect(callback);
|
||||
this.socket.on("disconnect", function() {
|
||||
_this.onDisconnect.apply(_this, arguments);
|
||||
});
|
||||
this.socket.on("message", function(message, callback) {
|
||||
_this.onMessage(message, callback);
|
||||
this.socket.on("message", function(message) {
|
||||
_this.onMessage.apply(_this, arguments);
|
||||
});
|
||||
},
|
||||
|
||||
onConnect: function(callback) {
|
||||
onConnect: function() {
|
||||
console.log("[socket_client] > onConnect");
|
||||
},
|
||||
|
||||
onDisconnect: function(callback) {
|
||||
onDisconnect: function() {
|
||||
console.log("[socket_client] > onDisconnect");
|
||||
},
|
||||
|
||||
onMessage: function(message, callback) {
|
||||
/**
|
||||
* Triggered when a new message arrives from the server.
|
||||
* @param {object} message - The message.
|
||||
*/
|
||||
onMessage: function(message) {
|
||||
console.log("[socket_client] > onMessage: ", message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends a message to the server.
|
||||
* @param {object} message - The message to send
|
||||
* @param {function} callback - A callback function which will be called after
|
||||
* the message has been sent to the socket.
|
||||
*/
|
||||
sendMessage: function(message, callback) {
|
||||
console.log("[socket_client] > sendMessage: ", message);
|
||||
this.socket.json.send(message);
|
||||
if (callback)
|
||||
callback();
|
||||
|
@ -97,6 +108,15 @@ SocketClient("AuthenticatedSocketClient",
|
|||
this._super(baseurl);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends a pad message to the server, including all the neccessary
|
||||
* session info and tokens.
|
||||
* @param {string} type - The message type to send. See the server code for
|
||||
* valid message types.
|
||||
* @param {object} data - The data payload to be sent to the server.
|
||||
* @param {function} callback - A callback function which will be called after
|
||||
* the message has been sent to the socket.
|
||||
*/
|
||||
sendMessage: function (type, data, callback) {
|
||||
this.sessionID = decodeURIComponent(readCookie("sessionID"));
|
||||
this.password = readCookie("password");
|
||||
|
@ -111,49 +131,50 @@ SocketClient("AuthenticatedSocketClient",
|
|||
this._super(msg, callback);
|
||||
},
|
||||
|
||||
onMessage: function (message, callback) {
|
||||
onMessage: function (message) {
|
||||
console.log("[authorized_client] > onMessage:", message);
|
||||
if (message.accessStatus)
|
||||
{ //access denied?
|
||||
//TODO raise some kind of error?
|
||||
console.log("ACCESS ERROR!");
|
||||
}
|
||||
this.dispatchMessage(message.type, message.data, callback);
|
||||
this.dispatchMessage(message.type, message.data);
|
||||
},
|
||||
|
||||
dispatchMessage: function(type, data, callback) {
|
||||
/**
|
||||
* Dispatch incoming messages to handlers in subclasses or registered
|
||||
* as event handlers.
|
||||
* @param {string} type - The type of the message. See the server code
|
||||
* for possible values.
|
||||
* @param {object} data - The message payload.
|
||||
*/
|
||||
dispatchMessage: function(type, data) {
|
||||
console.log("[authorized_client] > dispatchMessage('%s', %s)", type, data);
|
||||
// first call local handlers
|
||||
if ("handle_" + type in this)
|
||||
this["handle_" + type](data, callback);
|
||||
this["handle_" + type](data);
|
||||
// then call registered handlers
|
||||
if (type in this.handlers)
|
||||
for(var h in this.handlers[type])
|
||||
{ //TODO: maybe chain the handlers into some kind of chain-of-responsibility?
|
||||
var handler = this.handlers[type][h];
|
||||
handler.handler.call(this, data, handler.context, callback);
|
||||
handler.handler.call(this, data, handler.context);
|
||||
}
|
||||
},
|
||||
|
||||
on: function(type, callback, context) {
|
||||
/**
|
||||
* Register an event handler for a given message type.
|
||||
* @param {string} type - The message type.
|
||||
* @param {function} handler - The handler function.
|
||||
* @param {object} context - Optionally, some context to be passed to the handler.
|
||||
*/
|
||||
on: function(type, handler, context) {
|
||||
if (!(type in this.handlers))
|
||||
this.handlers[type] = [];
|
||||
this.handlers[type].push({handler: callback, context: context});
|
||||
this.handlers[type].push({handler: handler, context: context});
|
||||
return this;
|
||||
},
|
||||
|
||||
registerHandler: this.on,
|
||||
unregisterHandler: function(type, context) {
|
||||
if(type in this.handlers)
|
||||
{
|
||||
for(var h in this.handlers[type])
|
||||
if (this.handlers[type][h].context == context)
|
||||
{
|
||||
delete this.handlers[type][h];
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -165,25 +186,25 @@ AuthenticatedSocketClient("TimesliderClient",
|
|||
this._super(baseurl, padID);
|
||||
},
|
||||
|
||||
onConnect: function (callback) {
|
||||
onConnect: function () {
|
||||
this.sendMessage("CLIENT_READY", {}, function() { console.log("CLIENT_READY sent");});
|
||||
},
|
||||
|
||||
// ------------------------------------------
|
||||
// Handling events
|
||||
handle_CLIENT_VARS: function(data, callback) {
|
||||
handle_CLIENT_VARS: function(data) {
|
||||
console.log("[timeslider_client] handle_CLIENT_VARS: ", data);
|
||||
this.clientVars = data;
|
||||
this.current_revision = this.head_revision = this.clientVars.collab_client_vars.rev;
|
||||
this.savedRevisions = this.clientVars.savedRevisions;
|
||||
},
|
||||
|
||||
handle_COLLABROOM: function(data, callback) {
|
||||
handle_COLLABROOM: function(data) {
|
||||
console.log("[timeslider_client] handle_COLLABROOM: ", data);
|
||||
},
|
||||
|
||||
handle_CHANGESET_REQ: function(data, callback) {
|
||||
console.log("[timeslider_client] handle_COLLABROOM: ", data);
|
||||
handle_CHANGESET_REQ: function(data) {
|
||||
console.log("[timeslider_client] handle_CHANGESET_REQ: ", data);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
@ -217,12 +238,14 @@ function init(baseURL) {
|
|||
//find out in which subfolder we are
|
||||
var resource = baseURL.substring(1) + 'socket.io';
|
||||
|
||||
var cl;
|
||||
console.log(url, baseURL, resource, padId);
|
||||
var timesliderclient = new TimesliderClient(url, padId)
|
||||
.on("CLIENT_VARS", function(data, context, callback) {
|
||||
//load all script that doesn't work without the clientVars
|
||||
BroadcastSlider = require('./broadcast_slider').loadBroadcastSliderJS(this,fireWhenAllScriptsAreLoaded);
|
||||
require('./broadcast_revisions').loadBroadcastRevisionsJS(this.clientVars);
|
||||
cl = require('./revisioncache').loadBroadcastRevisionsJS(this.clientVars, this);
|
||||
//require('./broadcast_revisions').loadBroadcastRevisionsJS(this.clientVars);
|
||||
changesetLoader = require('./broadcast').loadBroadcastJS(this, fireWhenAllScriptsAreLoaded, BroadcastSlider);
|
||||
|
||||
//initialize export ui
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue