|
1 | 1 | var Doc = require('./doc');
|
2 | 2 | var Query = require('./query');
|
| 3 | +var SnapshotRequest = require('./snapshot-request'); |
3 | 4 | var emitter = require('../emitter');
|
4 | 5 | var ShareDBError = require('../error');
|
5 | 6 | var types = require('../types');
|
@@ -33,13 +34,17 @@ function Connection(socket) {
|
33 | 34 | // (created documents MUST BE UNIQUE)
|
34 | 35 | this.collections = {};
|
35 | 36 |
|
36 |
| - // Each query is created with an id that the server uses when it sends us |
37 |
| - // info about the query (updates, etc) |
| 37 | + // Each query and snapshot request is created with an id that the server uses when it sends us |
| 38 | + // info about the request (updates, etc) |
38 | 39 | this.nextQueryId = 1;
|
| 40 | + this.nextSnapshotRequestId = 1; |
39 | 41 |
|
40 | 42 | // Map from query ID -> query object.
|
41 | 43 | this.queries = {};
|
42 | 44 |
|
| 45 | + // Map from snapshot request ID -> snapshot request |
| 46 | + this._snapshotRequests = {}; |
| 47 | + |
43 | 48 | // A unique message number for the given id
|
44 | 49 | this.seq = 1;
|
45 | 50 |
|
@@ -226,6 +231,9 @@ Connection.prototype.handleMessage = function(message) {
|
226 | 231 | case 'bu':
|
227 | 232 | return this._handleBulkMessage(message, '_handleUnsubscribe');
|
228 | 233 |
|
| 234 | + case 'nf': |
| 235 | + return this._handleSnapshotFetch(err, message); |
| 236 | + |
229 | 237 | case 'f':
|
230 | 238 | var doc = this.getExisting(message.c, message.d);
|
231 | 239 | if (doc) doc._handleFetch(err, message.data);
|
@@ -310,6 +318,11 @@ Connection.prototype._setState = function(newState, reason) {
|
310 | 318 | docs[id]._onConnectionStateChanged();
|
311 | 319 | }
|
312 | 320 | }
|
| 321 | + // Emit the event to all snapshots |
| 322 | + for (var id in this._snapshotRequests) { |
| 323 | + var snapshotRequest = this._snapshotRequests[id]; |
| 324 | + snapshotRequest._onConnectionStateChanged(); |
| 325 | + } |
313 | 326 | this.endBulk();
|
314 | 327 |
|
315 | 328 | this.emit(newState, reason);
|
@@ -523,7 +536,8 @@ Connection.prototype.createSubscribeQuery = function(collection, q, options, cal
|
523 | 536 | Connection.prototype.hasPending = function() {
|
524 | 537 | return !!(
|
525 | 538 | this._firstDoc(hasPending) ||
|
526 |
| - this._firstQuery(hasPending) |
| 539 | + this._firstQuery(hasPending) || |
| 540 | + this._firstSnapshotRequest() |
527 | 541 | );
|
528 | 542 | };
|
529 | 543 | function hasPending(object) {
|
@@ -552,6 +566,11 @@ Connection.prototype.whenNothingPending = function(callback) {
|
552 | 566 | query.once('ready', this._nothingPendingRetry(callback));
|
553 | 567 | return;
|
554 | 568 | }
|
| 569 | + var snapshotRequest = this._firstSnapshotRequest(); |
| 570 | + if (snapshotRequest) { |
| 571 | + snapshotRequest.once('ready', this._nothingPendingRetry(callback)); |
| 572 | + return; |
| 573 | + } |
555 | 574 | // Call back when no pending operations
|
556 | 575 | process.nextTick(callback);
|
557 | 576 | };
|
@@ -584,3 +603,44 @@ Connection.prototype._firstQuery = function(fn) {
|
584 | 603 | }
|
585 | 604 | }
|
586 | 605 | };
|
| 606 | + |
| 607 | +Connection.prototype._firstSnapshotRequest = function () { |
| 608 | + for (var id in this._snapshotRequests) { |
| 609 | + return this._snapshotRequests[id]; |
| 610 | + } |
| 611 | +}; |
| 612 | + |
| 613 | +/** |
| 614 | + * Fetch a read-only snapshot at a given version |
| 615 | + * |
| 616 | + * @param collection - the collection name of the snapshot |
| 617 | + * @param id - the ID of the snapshot |
| 618 | + * @param version (optional) - the version number to fetch |
| 619 | + * @param callback - (error, snapshot) => void, where snapshot takes the following schema: |
| 620 | + * |
| 621 | + * { |
| 622 | + * id: string; // ID of the snapshot |
| 623 | + * v: number; // version number of the snapshot |
| 624 | + * type: string; // the OT type of the snapshot, or null if it doesn't exist or is deleted |
| 625 | + * data: any; // the snapshot |
| 626 | + * } |
| 627 | + * |
| 628 | + */ |
| 629 | +Connection.prototype.fetchSnapshot = function(collection, id, version, callback) { |
| 630 | + if (typeof version === 'function') { |
| 631 | + callback = version; |
| 632 | + version = null; |
| 633 | + } |
| 634 | + |
| 635 | + var requestId = this.nextSnapshotRequestId++; |
| 636 | + var snapshotRequest = new SnapshotRequest(this, requestId, collection, id, version, callback); |
| 637 | + this._snapshotRequests[snapshotRequest.requestId] = snapshotRequest; |
| 638 | + snapshotRequest.send(); |
| 639 | +}; |
| 640 | + |
| 641 | +Connection.prototype._handleSnapshotFetch = function (error, message) { |
| 642 | + var snapshotRequest = this._snapshotRequests[message.id]; |
| 643 | + if (!snapshotRequest) return; |
| 644 | + delete this._snapshotRequests[message.id]; |
| 645 | + snapshotRequest._handleResponse(error, message); |
| 646 | +}; |
0 commit comments