Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated email agent fork #4

Open
wants to merge 93 commits into
base: email-agent-fork
Choose a base branch
from
Open
Changes from 7 commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
8ca20dd
[Docs] Indicate create*Query options.results is a Doc[]
ericyhwang Mar 1, 2022
5337969
Fix typos in query docs
curran Mar 17, 2022
cb3aaed
📝 Remove `id` from `getOpsBulk()` documentation
alecgibson Mar 22, 2022
c4a42ed
Merge branch 'share:master' into patch-16
curran Mar 30, 2022
b7eae5c
Merge pull request #555 from curran/patch-16
ericyhwang Apr 5, 2022
40c87bf
Merge pull request #558 from share/get-ops-bulk-docs
alecgibson Apr 5, 2022
c49ad21
More detail on create*Query prior results
ericyhwang Apr 5, 2022
92479d2
Merge pull request #546 from share/docs-createQuery-options-types
alecgibson Apr 12, 2022
c7e63b1
💥 Update Node.js test matrix
alecgibson May 3, 2022
6b5b038
Bump nokogiri from 1.13.3 to 1.13.4 in /docs
dependabot[bot] May 3, 2022
4d7f0d8
Merge pull request #563 from share/dependabot/bundler/docs/nokogiri-1…
alecgibson May 3, 2022
d535855
Merge pull request #562 from share/node-18
alecgibson May 3, 2022
7bf6781
3.0.0
alecgibson May 3, 2022
99b5519
👷 Bump GH actions
alecgibson Jul 12, 2022
16d7431
👷 Verbose GH Actions installation
alecgibson Jul 12, 2022
e71c91b
👷 Increase GH Actions timeout
alecgibson Jul 12, 2022
400ec52
👷 Use HTTPS to fetch `json0`
alecgibson Jul 12, 2022
b1c10d6
👷 Fix `json0` URL
alecgibson Jul 12, 2022
df19240
Revert "👷 Increase GH Actions timeout"
alecgibson Jul 12, 2022
8ed35d5
Revert "👷 Verbose GH Actions installation"
alecgibson Jul 12, 2022
bec7e6d
📌 Pin `json0` dev dependency
alecgibson Jul 12, 2022
8ec5279
📝 Update presence documentation
alecgibson Jul 12, 2022
b681366
Bump nokogiri from 1.13.4 to 1.13.7 in /docs
dependabot[bot] Jul 12, 2022
106e959
Merge pull request #567 from share/pin-json0
alecgibson Jul 12, 2022
5302bc7
Merge pull request #568 from share/dependabot/bundler/docs/nokogiri-1…
alecgibson Jul 12, 2022
8950626
Merge pull request #566 from share/docs-null-presence
alecgibson Jul 12, 2022
95297e5
Bump tzinfo from 1.2.9 to 1.2.10 in /docs
dependabot[bot] Jul 22, 2022
2532faa
Merge pull request #569 from share/dependabot/bundler/docs/tzinfo-1.2.10
alecgibson Jul 22, 2022
e91488d
Refactor action code strings into an enum-like object
ericyhwang Aug 9, 2022
461662d
Updates to message-actios from code review feedback
ericyhwang Aug 9, 2022
c4e82d6
Update action refactoring missed in automated renames
ericyhwang Aug 9, 2022
8879b28
Rename queryReply to queryUpdate, use shared action object from query.js
ericyhwang Aug 9, 2022
55fa1f3
Catch missed actions
alecgibson Aug 9, 2022
bbeaeb9
Add top-level export for MESSAGE_ACTIONS
ericyhwang Aug 9, 2022
28460e3
Merge pull request #570 from share/refactor-action-codes
ericyhwang Aug 9, 2022
8b531be
Refactor message action codes into a shared file
ericyhwang Aug 9, 2022
56ac7a8
✨ Add ping/pong
alecgibson Sep 27, 2022
9157342
Merge pull request #576 from share/ping-pong
alecgibson Sep 27, 2022
791937b
3.2.0
alecgibson Sep 27, 2022
aa9bf9c
Bump commonmarker from 0.23.4 to 0.23.6 in /docs
dependabot[bot] Sep 27, 2022
e3704a7
📝 Add `connection.ping()` to the documentation
alecgibson Sep 27, 2022
1231351
Merge pull request #577 from share/dependabot/bundler/docs/commonmark…
alecgibson Sep 27, 2022
5176283
Merge pull request #578 from share/ping-pong-docs
alecgibson Sep 27, 2022
d121a3e
🐛 Allow getting a `Doc` while it's being destroyed
alecgibson Oct 18, 2022
c9e773d
Merge pull request #580 from share/destroying-docs
alecgibson Oct 25, 2022
c3f7030
🐛 Allow getting `Presence` while it's being destroyed
alecgibson Oct 18, 2022
c22c4ff
Merge pull request #579 from share/destroying-presence
alecgibson Oct 25, 2022
2cdf094
3.2.1
alecgibson Oct 25, 2022
7bac0e9
👷‍♀️ Move to `ruby/setup-ruby` action
alecgibson Nov 23, 2022
9743fd1
Merge pull request #582 from share/bump-actions-versions
alecgibson Nov 29, 2022
8a8447b
Bump nokogiri from 1.13.7 to 1.13.9 in /docs
dependabot[bot] Nov 29, 2022
cc0e338
Merge pull request #583 from share/dependabot/bundler/docs/nokogiri-1…
alecgibson Nov 29, 2022
3db7070
✨ Allow middleware to mutate submitted ops
alecgibson Nov 23, 2022
2c04a08
🔇 Fix sensitive memory leak warnings when using presence
alecgibson Feb 1, 2023
a321275
Merge pull request #588 from share/presence-events
alecgibson Feb 7, 2023
b84290f
3.2.2
alecgibson Feb 7, 2023
7681077
✅ Fix flaky tests
alecgibson Feb 15, 2023
bd7ec3f
Merge pull request #590 from share/flaky-query-test-fix
alecgibson Feb 16, 2023
9c0f1c6
3.2.3
alecgibson Feb 16, 2023
36c8e65
Add missing import in hello world example
jameshfisher Feb 21, 2023
1ffa38a
Merge pull request #591 from jameshfisher/patch-1
ericyhwang Feb 21, 2023
daf3a25
✅ Remove order dependence from test
alecgibson Feb 21, 2023
a263d57
Merge pull request #592 from share/fix-test
alecgibson Feb 21, 2023
f4845fd
3.2.4
alecgibson Feb 21, 2023
ad23bf0
Upgrade deps in examples. Closes #594
curran Mar 2, 2023
2690ecb
Fix leaderboard example
curran Mar 2, 2023
9b4c9f4
Fix rich-text-presence example
curran Mar 2, 2023
72e47b1
Start on Vite example
curran Mar 2, 2023
280d681
Fix CI
curran Mar 2, 2023
628de99
✨ Add multi channel query subscription.
Dawidpol Jan 30, 2023
20f1fa7
Merge pull request #587 from share/feature/multi-channel-subscription
dawidreedsy Mar 3, 2023
812994f
Merge pull request #581 from share/server-fixup
alecgibson Mar 6, 2023
c587181
3.3.0
alecgibson Mar 6, 2023
0f4b211
Got Vite example to work
curran Mar 8, 2023
265840d
Upgrade ShareDB in examples. Fix presence API warning.
curran Mar 9, 2023
f783dec
Fix React warnings
curran Mar 9, 2023
404cde5
Merge pull request #595 from curran/upgrade-deps-in-examples
alecgibson Mar 28, 2023
a7c7697
✅ Try to fix flaky Milestone DB tests
alecgibson Mar 28, 2023
0166274
Merge pull request #602 from share/flaky-milestone-test-fix
alecgibson Mar 28, 2023
d21c26a
3.3.1
alecgibson Mar 28, 2023
ff5d515
Use glob override for .eslintrc
curran Mar 29, 2023
c637650
Make it work
curran Mar 29, 2023
c219205
Lint
curran Mar 29, 2023
ab2341e
Merge pull request #598 from curran/counter-json1-vite
ericyhwang Mar 30, 2023
ec12c16
Merge branch 'master' of github.com:lever/sharedb into email-agent-fork
distracteddev Apr 11, 2023
27dcfe3
Fix bad merge in test files
distracteddev Apr 13, 2023
ac490e0
💥 Drop Node.js 14 and add Node.js 20
alecgibson Apr 21, 2023
c1f1474
Merge pull request #606 from share/bump-node
alecgibson Apr 25, 2023
3e1e7f0
📝 Update docs around `reconnecting-websocket`
alecgibson May 2, 2023
6ee645d
🔊 Warn when messages are sent before the v1.1 handshake
alecgibson May 2, 2023
26d5d49
Merge pull request #607 from share/pre-handshake-warning
alecgibson May 2, 2023
21750e3
Merge pull request #608 from share/reconnecting-socket-docs
alecgibson May 2, 2023
59bce08
Merge branch 'master' of github.com:lever/sharedb into updated-email-…
distracteddev May 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 44 additions & 31 deletions lib/agent.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
var hat = require('hat');
var ShareDBError = require('./error');
var logger = require('./logger');
var ACTIONS = require('./message-actions').ACTIONS;
var types = require('./types');
var util = require('./util');
var logger = require('./logger');
var ShareDBError = require('./error');

var ERROR_CODE = ShareDBError.CODES;

@@ -58,7 +59,7 @@ function Agent(backend, stream) {
this.custom = {};

// Send the legacy message to initialize old clients with the random agent Id
this.send(this._initMessage('init'));
this.send(this._initMessage(ACTIONS.initLegacy));
}
module.exports = Agent;

@@ -174,7 +175,7 @@ Agent.prototype._subscribeToQuery = function(emitter, queryId, collection, query

var agent = this;
emitter.onExtra = function(extra) {
agent.send({a: 'q', id: queryId, extra: extra});
agent.send({a: ACTIONS.queryUpdate, id: queryId, extra: extra});
};

emitter.onDiff = function(diff) {
@@ -186,7 +187,7 @@ Agent.prototype._subscribeToQuery = function(emitter, queryId, collection, query
}
// Consider stripping the collection out of the data we send here
// if it matches the query's collection.
agent.send({a: 'q', id: queryId, diff: diff});
agent.send({a: ACTIONS.queryUpdate, id: queryId, diff: diff});
};

emitter.onError = function(err) {
@@ -250,7 +251,7 @@ Agent.prototype.send = function(message) {

Agent.prototype._sendOp = function(collection, id, op) {
var message = {
a: 'op',
a: ACTIONS.op,
c: collection,
d: id,
v: op.v,
@@ -354,22 +355,34 @@ Agent.prototype._open = function() {

// Check a request to see if its valid. Returns an error if there's a problem.
Agent.prototype._checkRequest = function(request) {
if (request.a === 'qf' || request.a === 'qs' || request.a === 'qu') {
if (
request.a === ACTIONS.queryFetch ||
request.a === ACTIONS.querySubscribe ||
request.a === ACTIONS.queryUnsubscribe
) {
// Query messages need an ID property.
if (typeof request.id !== 'number') return 'Missing query ID';
} else if (request.a === 'op' || request.a === 'f' || request.a === 's' || request.a === 'u' || request.a === 'p') {
} else if (request.a === ACTIONS.op ||
request.a === ACTIONS.fetch ||
request.a === ACTIONS.subscribe ||
request.a === ACTIONS.unsubscribe ||
request.a === ACTIONS.presence) {
// Doc-based request.
if (request.c != null && typeof request.c !== 'string') return 'Invalid collection';
if (request.d != null && typeof request.d !== 'string') return 'Invalid id';

if (request.a === 'op' || request.a === 'p') {
if (request.a === ACTIONS.op || request.a === ACTIONS.presence) {
if (request.v != null && (typeof request.v !== 'number' || request.v < 0)) return 'Invalid version';
}

if (request.a === 'p') {
if (request.a === ACTIONS.presence) {
if (typeof request.id !== 'string') return 'Missing presence ID';
}
} else if (request.a === 'bf' || request.a === 'bs' || request.a === 'bu') {
} else if (
request.a === ACTIONS.bulkFetch ||
request.a === ACTIONS.bulkSubscribe ||
request.a === ACTIONS.bulkUnsubscribe
) {
// Bulk request
if (request.c != null && typeof request.c !== 'string') return 'Invalid collection';
if (typeof request.b !== 'object') return 'Invalid bulk subscribe data';
@@ -383,28 +396,28 @@ Agent.prototype._handleMessage = function(request, callback) {
if (errMessage) return callback(new ShareDBError(ERROR_CODE.ERR_MESSAGE_BADLY_FORMED, errMessage));

switch (request.a) {
case 'hs':
case ACTIONS.handshake:
if (request.id) this.src = request.id;
return callback(null, this._initMessage('hs'));
case 'qf':
return callback(null, this._initMessage(ACTIONS.handshake));
case ACTIONS.queryFetch:
return this._queryFetch(request.id, request.c, request.q, getQueryOptions(request), callback);
case 'qs':
case ACTIONS.querySubscribe:
return this._querySubscribe(request.id, request.c, request.q, getQueryOptions(request), callback);
case 'qu':
case ACTIONS.queryUnsubscribe:
return this._queryUnsubscribe(request.id, callback);
case 'bf':
case ACTIONS.bulkFetch:
return this._fetchBulk(request.c, request.b, callback);
case 'bs':
case ACTIONS.bulkSubscribe:
return this._subscribeBulk(request.c, request.b, callback);
case 'bu':
case ACTIONS.bulkUnsubscribe:
return this._unsubscribeBulk(request.c, request.b, callback);
case 'f':
case ACTIONS.fetch:
return this._fetch(request.c, request.d, request.v, callback);
case 's':
case ACTIONS.subscribe:
return this._subscribe(request.c, request.d, request.v, callback);
case 'u':
case ACTIONS.unsubscribe:
return this._unsubscribe(request.c, request.d, callback);
case 'op':
case ACTIONS.op:
// Normalize the properties submitted
var op = createClientOp(request, this._src());
if (op.seq >= util.MAX_SAFE_INTEGER) {
@@ -415,11 +428,11 @@ Agent.prototype._handleMessage = function(request, callback) {
}
if (!op) return callback(new ShareDBError(ERROR_CODE.ERR_MESSAGE_BADLY_FORMED, 'Invalid op message'));
return this._submit(request.c, request.d, op, callback);
case 'nf':
case ACTIONS.snapshotFetch:
return this._fetchSnapshot(request.c, request.d, request.v, callback);
case 'nt':
case ACTIONS.snapshotFetchByTimestamp:
return this._fetchSnapshotByTimestamp(request.c, request.d, request.ts, callback);
case 'p':
case ACTIONS.presence:
if (!this.backend.presenceEnabled) return;
var presence = this._createPresence(request);
if (presence.t && !util.supportsPresence(types.map[presence.t])) {
@@ -429,10 +442,10 @@ Agent.prototype._handleMessage = function(request, callback) {
});
}
return this._broadcastPresence(presence, callback);
case 'ps':
case ACTIONS.presenceSubscribe:
if (!this.backend.presenceEnabled) return;
return this._subscribePresence(request.ch, request.seq, callback);
case 'pu':
case ACTIONS.presenceUnsubscribe:
return this._unsubscribePresence(request.ch, request.seq, callback);
default:
callback(new ShareDBError(ERROR_CODE.ERR_MESSAGE_BADLY_FORMED, 'Invalid or unknown message'));
@@ -761,7 +774,7 @@ Agent.prototype._broadcastPresence = function(presence, callback) {

Agent.prototype._createPresence = function(request) {
return {
a: 'p',
a: ACTIONS.presence,
ch: request.ch,
src: this._src(),
id: request.id, // Presence ID, not Doc ID (which is 'd')
@@ -813,7 +826,7 @@ Agent.prototype._requestPresence = function(channel, callback) {
Agent.prototype._handlePresenceData = function(presence) {
if (presence.src === this._src()) return;

if (presence.r) return this.send({a: 'pr', ch: presence.ch});
if (presence.r) return this.send({a: ACTIONS.presenceRequest, ch: presence.ch});

var backend = this.backend;
var context = {
@@ -824,7 +837,7 @@ Agent.prototype._handlePresenceData = function(presence) {
backend.trigger(backend.MIDDLEWARE_ACTIONS.sendPresence, this, context, function(error) {
if (error) {
if (backend.doNotForwardSendPresenceErrorsToClient) backend.errorHandler(error, {agent: agent});
else agent.send({a: 'p', ch: presence.ch, id: presence.id, error: getReplyErrorObject(error)});
else agent.send({a: ACTIONS.presence, ch: presence.ch, id: presence.id, error: getReplyErrorObject(error)});
return;
}
agent.send(presence);
55 changes: 28 additions & 27 deletions lib/client/connection.js
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ var SnapshotVersionRequest = require('./snapshot-request/snapshot-version-reques
var SnapshotTimestampRequest = require('./snapshot-request/snapshot-timestamp-request');
var emitter = require('../emitter');
var ShareDBError = require('../error');
var ACTIONS = require('../message-actions').ACTIONS;
var types = require('../types');
var util = require('../util');
var logger = require('../logger');
@@ -194,25 +195,25 @@ Connection.prototype.handleMessage = function(message) {
// Switch on the message action. Most messages are for documents and are
// handled in the doc class.
switch (message.a) {
case 'init':
case ACTIONS.initLegacy:
// Client initialization packet
return this._handleLegacyInit(message);
case 'hs':
case ACTIONS.handshake:
return this._handleHandshake(err, message);
case 'qf':
case ACTIONS.queryFetch:
var query = this.queries[message.id];
if (query) query._handleFetch(err, message.data, message.extra);
return;
case 'qs':
case ACTIONS.querySubscribe:
var query = this.queries[message.id];
if (query) query._handleSubscribe(err, message.data, message.extra);
return;
case 'qu':
case ACTIONS.queryUnsubscribe:
// Queries are removed immediately on calls to destroy, so we ignore
// replies to query unsubscribes. Perhaps there should be a callback for
// destroy, but this is currently unimplemented
return;
case 'q':
case ACTIONS.queryUpdate:
// Query message. Pass this to the appropriate query object.
var query = this.queries[message.id];
if (!query) return;
@@ -221,36 +222,36 @@ Connection.prototype.handleMessage = function(message) {
if (message.hasOwnProperty('extra')) query._handleExtra(message.extra);
return;

case 'bf':
case ACTIONS.bulkFetch:
return this._handleBulkMessage(err, message, '_handleFetch');
case 'bs':
case 'bu':
case ACTIONS.bulkSubscribe:
case ACTIONS.bulkUnsubscribe:
return this._handleBulkMessage(err, message, '_handleSubscribe');

case 'nf':
case 'nt':
case ACTIONS.snapshotFetch:
case ACTIONS.snapshotFetchByTimestamp:
return this._handleSnapshotFetch(err, message);

case 'f':
case ACTIONS.fetch:
var doc = this.getExisting(message.c, message.d);
if (doc) doc._handleFetch(err, message.data);
return;
case 's':
case 'u':
case ACTIONS.subscribe:
case ACTIONS.unsubscribe:
var doc = this.getExisting(message.c, message.d);
if (doc) doc._handleSubscribe(err, message.data);
return;
case 'op':
case ACTIONS.op:
var doc = this.getExisting(message.c, message.d);
if (doc) doc._handleOp(err, message);
return;
case 'p':
case ACTIONS.presence:
return this._handlePresence(err, message);
case 'ps':
case ACTIONS.presenceSubscribe:
return this._handlePresenceSubscribe(err, message);
case 'pu':
case ACTIONS.presenceUnsubscribe:
return this._handlePresenceUnsubscribe(err, message);
case 'pr':
case ACTIONS.presenceRequest:
return this._handlePresenceRequest(err, message);

default:
@@ -416,7 +417,7 @@ Connection.prototype._sendBulk = function(action, collection, values) {
}
};

Connection.prototype._sendAction = function(action, doc, version) {
Connection.prototype._sendActions = function(action, doc, version) {
// Ensure the doc is registered so that it receives the reply message
this._addDoc(doc);
if (this.bulk) {
@@ -434,22 +435,22 @@ Connection.prototype._sendAction = function(action, doc, version) {
};

Connection.prototype.sendFetch = function(doc) {
return this._sendAction('f', doc, doc.version);
return this._sendActions(ACTIONS.fetch, doc, doc.version);
};

Connection.prototype.sendSubscribe = function(doc) {
return this._sendAction('s', doc, doc.version);
return this._sendActions(ACTIONS.subscribe, doc, doc.version);
};

Connection.prototype.sendUnsubscribe = function(doc) {
return this._sendAction('u', doc);
return this._sendActions(ACTIONS.unsubscribe, doc);
};

Connection.prototype.sendOp = function(doc, op) {
// Ensure the doc is registered so that it receives the reply message
this._addDoc(doc);
var message = {
a: 'op',
a: ACTIONS.op,
c: doc.collection,
d: doc.id,
v: doc.version,
@@ -553,7 +554,7 @@ Connection.prototype._destroyQuery = function(query) {
// The callback should have the signature function(error, results, extra)
// where results is a list of Doc objects.
Connection.prototype.createFetchQuery = function(collection, q, options, callback) {
return this._createQuery('qf', collection, q, options, callback);
return this._createQuery(ACTIONS.queryFetch, collection, q, options, callback);
};

// Create a subscribe query. Subscribe queries return with the initial data
@@ -563,7 +564,7 @@ Connection.prototype.createFetchQuery = function(collection, q, options, callbac
// If present, the callback should have the signature function(error, results, extra)
// where results is a list of Doc objects.
Connection.prototype.createSubscribeQuery = function(collection, q, options, callback) {
return this._createQuery('qs', collection, q, options, callback);
return this._createQuery(ACTIONS.querySubscribe, collection, q, options, callback);
};

Connection.prototype.hasPending = function() {
@@ -716,7 +717,7 @@ Connection.prototype._handleLegacyInit = function(message) {
};

Connection.prototype._initializeHandshake = function() {
this.send({a: 'hs', id: this.id});
this.send({a: ACTIONS.handshake, id: this.id});
};

Connection.prototype._handleHandshake = function(error, message) {
3 changes: 2 additions & 1 deletion lib/client/presence/local-presence.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var emitter = require('../../emitter');
var ACTIONS = require('../../message-actions').ACTIONS;
var util = require('../../util');

module.exports = LocalPresence;
@@ -59,7 +60,7 @@ LocalPresence.prototype._ack = function(error, presenceVersion) {

LocalPresence.prototype._message = function() {
return {
a: 'p',
a: ACTIONS.presence,
ch: this.presence.channel,
id: this.presenceId,
p: this.value,
3 changes: 2 additions & 1 deletion lib/client/presence/presence.js
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ var RemotePresence = require('./remote-presence');
var util = require('../../util');
var async = require('async');
var hat = require('hat');
var ACTIONS = require('../../message-actions').ACTIONS;

module.exports = Presence;
function Presence(connection, channel) {
@@ -70,7 +71,7 @@ Presence.prototype.destroy = function(callback) {

Presence.prototype._sendSubscriptionAction = function(wantSubscribe, callback) {
this.wantSubscribe = !!wantSubscribe;
var action = this.wantSubscribe ? 'ps' : 'pu';
var action = this.wantSubscribe ? ACTIONS.presenceSubscribe : ACTIONS.presenceUnsubscribe;
var seq = this.connection._presenceSeq++;
this._subscriptionCallbacksBySeq[seq] = callback;
if (this.connection.canSend) {
5 changes: 3 additions & 2 deletions lib/client/query.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var emitter = require('../emitter');
var ACTIONS = require('../message-actions').ACTIONS;
var util = require('../util');

// Queries are live requests to the database for particular sets of fields.
@@ -75,8 +76,8 @@ Query.prototype.send = function() {
// Destroy the query object. Any subsequent messages for the query will be
// ignored by the connection.
Query.prototype.destroy = function(callback) {
if (this.connection.canSend && this.action === 'qs') {
this.connection.send({a: 'qu', id: this.id});
if (this.connection.canSend && this.action === ACTIONS.querySubscribe) {
this.connection.send({a: ACTIONS.queryUnsubscribe, id: this.id});
}
this.connection._destroyQuery(this);
// There is a callback for consistency, but we don't actually wait for the
Loading