Skip to content

Commit d2041af

Browse files
committed
add feature flags to await for response from table() and view()
1 parent e73ed41 commit d2041af

File tree

5 files changed

+50
-9
lines changed

5 files changed

+50
-9
lines changed

packages/perspective/src/js/api/client.js

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export class Client {
4444
}
4545

4646
/**
47-
* Process an asynchronous message.
47+
* Send a message to the server.
4848
*/
4949
post(msg, resolve, reject, keep_alive = false) {
5050
++this._worker.msg_id;
@@ -55,7 +55,13 @@ export class Client {
5555
if (this._worker.initialized.value) {
5656
this.send(msg);
5757
} else {
58-
this._worker.messages.push(() => this.send(msg));
58+
this._worker.messages.push(() => {
59+
this.send(msg);
60+
61+
if ((msg.cmd === "table" || msg.cmd === "view") && !this._features?.wait_for_response && resolve) {
62+
resolve();
63+
}
64+
});
5965
}
6066
}
6167

@@ -87,10 +93,8 @@ export class Client {
8793
}
8894

8995
/**
90-
* Handle a command from Perspective. If the Client is not initialized,
91-
* initialize it and dispatch the `perspective-ready` event.
92-
*
93-
* Otherwise, reject or resolve the incoming command.
96+
* Receive a message from the server, and resolve/reject the promise that
97+
* is awaiting the content of the message.
9498
*/
9599
_handle(e) {
96100
if (!this._worker.initialized.value) {
@@ -107,6 +111,16 @@ export class Client {
107111
this._worker.initialized.value = true;
108112
this._worker.messages = [];
109113

114+
// If the `data` attribute of the init message is set, then
115+
// set the `features` dictionary with the flags from the server.
116+
if (e.data?.data) {
117+
this._features = {};
118+
119+
for (const feature of e.data.data) {
120+
this._features[feature] = true;
121+
}
122+
}
123+
110124
if (msgs) {
111125
for (const m in msgs) {
112126
if (msgs.hasOwnProperty(m)) {
@@ -117,13 +131,15 @@ export class Client {
117131
}
118132

119133
if (e.data.id) {
120-
var handler = this._worker.handlers[e.data.id];
134+
const handler = this._worker.handlers[e.data.id];
135+
121136
if (handler) {
122137
if (e.data.error) {
123138
handler.reject(e.data.error);
124139
} else {
125140
handler.resolve(e.data.data);
126141
}
142+
127143
if (!handler.keep_alive) {
128144
delete this._worker.handlers[e.data.id];
129145
}

packages/perspective/src/js/api/server.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,24 @@ export class Server {
4040
}
4141

4242
/**
43+
* Return an initialization message to the client for confirmation.
4344
* `Server` must be extended and the `post` method implemented before the
4445
* server can successfully be initialized.
4546
*/
4647
init(msg) {
4748
if (msg.config) {
4849
override_config(msg.config);
4950
}
51+
52+
// The client will wait for a response message on table() and
53+
// view(). If this flag is not set, the table() and view()
54+
// constructors will resolve automatically and errors from the
55+
// server will not be caught in those constructors. This allows
56+
// for backwards compatibility between newer frontends (those
57+
// with async table/view constructors) and older servers (which
58+
// do not send the response message to the client).
59+
msg.data = ["wait_for_response"];
60+
5061
this.post(msg);
5162
}
5263

packages/perspective/src/js/api/table_api.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ export function table(worker, data, options) {
6767
reject
6868
);
6969
}
70+
71+
if (this._worker._initialized === true && !this._worker._features?.wait_for_response) {
72+
resolve(this);
73+
}
7074
});
7175
}
7276

packages/perspective/src/js/api/view_api.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ export function view(worker, table_name, config) {
4040
},
4141
reject
4242
);
43+
44+
if (this._worker._initialized === true && !this._worker._features?.wait_for_response) {
45+
resolve(this);
46+
}
4347
});
4448
}
4549

python/perspective/perspective/manager/manager_internal.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,14 @@ def __process(self, msg, post_callback, client_id=None):
122122

123123
try:
124124
if cmd == "init":
125-
# return empty response
126-
message = self._make_message(msg["id"], None)
125+
# The client should wait for the return message on table()
126+
# and view() to confirm successful creation.
127+
flags = ["wait_for_response"]
128+
129+
# Return a message to the client to confirm initialization with
130+
# a list of feature flags that the client will use to enable
131+
# or disable behavior depending on its version.
132+
message = self._make_message(msg["id"], flags)
127133
post_callback(self._message_to_json(msg["id"], message))
128134
elif cmd == "table":
129135
try:

0 commit comments

Comments
 (0)