Do app -> client communication more like tfrpc so that it's easier to get responses.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3956 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
Cory McWilliams 2022-08-13 18:58:06 +00:00
parent 41590921c3
commit d70dba021a
3 changed files with 71 additions and 28 deletions

View File

@ -1,7 +1,10 @@
import * as auth from './auth.js';
import * as core from './core.js';
var gSessionIndex = 0;
let g_next_id = 1;
let g_calls = {};
let gSessionIndex = 0;
function makeSessionId() {
return (gSessionIndex++).toString();
@ -19,31 +22,45 @@ App.prototype.readOutput = function(callback) {
App.prototype.makeFunction = function(api) {
let self = this;
let result = function() {
let message = {action: api[0]};
for (let i = 1; i < api.length; i++) {
message[api[i]] = arguments[i - 1];
let id = g_next_id++;
while (!id || g_calls[id]) {
id = g_next_id++;
}
let promise = new Promise(function(resolve, reject) {
g_calls[id] = {resolve: resolve, reject: reject};
});
let result = function() {
let message = {
message: 'tfrpc',
method: api[0],
params: [...arguments],
id: id,
};
self.send(message);
return promise;
};
Object.defineProperty(result, 'name', {value: api[0], writable: false});
return result;
}
App.prototype.send = function(message) {
if (message) {
if (this._send_queue) {
if (this._on_output) {
this._send_queue.forEach(x => this._on_output(x));
this._send_queue = null;
} else if (message) {
this._send_queue.push(message);
}
if (this._on_output) {
this._send_queue.forEach(message => this._on_output(message));
this._send_queue = [];
}
if (message && this._on_output) {
this._on_output(message);
}
}
function socket(request, response, client) {
var process;
var options = {};
var credentials = auth.query(request.headers);
let process;
let options = {};
let credentials = auth.query(request.headers);
response.onClose = async function() {
if (process && process.task) {
@ -59,7 +76,7 @@ function socket(request, response, client) {
response.onMessage = async function(event) {
if (event.opCode == 0x1 || event.opCode == 0x2) {
var message;
let message;
try {
message = JSON.parse(event.data);
} catch (error) {
@ -67,11 +84,11 @@ function socket(request, response, client) {
return;
}
if (message.action == "hello") {
var packageOwner;
var packageName;
var blobId;
var match;
var parentApp;
let packageOwner;
let packageName;
let blobId;
let match;
let parentApp;
if (match = /^\/([&%][^\.]{44}(?:\.\w+)?)(\/?.*)/.exec(message.path)) {
blobId = match[1];
} else if (match = /^\/\~([^\/]+)\/([^\/]+)\/$/.exec(message.path)) {
@ -83,7 +100,7 @@ function socket(request, response, client) {
return;
}
if (packageOwner != 'core') {
var coreId = await new Database('core').get('path:' + packageName);
let coreId = await new Database('core').get('path:' + packageName);
parentApp = {
path: '/~core/' + packageName + '/',
id: coreId,
@ -101,7 +118,7 @@ function socket(request, response, client) {
options.credentials = credentials;
options.packageOwner = packageOwner;
options.packageName = packageName;
var sessionId = makeSessionId();
let sessionId = makeSessionId();
if (blobId) {
process = await core.getSessionProcessBlob(blobId, sessionId, options);
}
@ -112,9 +129,9 @@ function socket(request, response, client) {
process.app.send();
}
var ping = function() {
var now = Date.now();
var again = true;
let ping = function() {
let now = Date.now();
let again = true;
if (now - process.lastActive < process.timeout) {
// Active.
} else if (process.lastPing > process.lastActive) {
@ -143,6 +160,15 @@ function socket(request, response, client) {
}
} else if (message.action == 'permission') {
core.setPermission(process, message.id, message.granted);
} else if (message.message == 'tfrpc') {
if (message.id && g_calls[message.id]) {
if (message.error !== undefined) {
g_calls[message.id].reject(message.error);
} else {
g_calls[message.id].resolve(message.result);
}
delete g_calls[message.id];
}
} else {
if (process && process.eventHandlers['message']) {
await core.invoke(process.eventHandlers['message'], [message]);

View File

@ -438,7 +438,7 @@ function api_localStorageSet(key, value) {
}
function api_localStorageGet(key, value) {
send({message: 'localStorage', key: key, value: window.localStorage.getItem('app:' + key)});
return window.localStorage.getItem('app:' + key);
}
function api_requestPermission(permission, id) {
@ -594,10 +594,24 @@ function receive(message) {
}
timeseries.append(now, message.stats[key]);
}
} else if (message && message.action) {
let api = k_api[message.action];
} else if (message &&
message.message === 'tfrpc' &&
message.method) {
let api = k_api[message.method];
if (api) {
api.func(...api.args.map(x => message[x]));
Promise.resolve(api.func(...message.params)).then(function(result) {
send({
message: 'tfrpc',
id: message.id,
result: result,
});
}).catch(function(error) {
send({
message: 'tfrpc',
id: message.id,
error: error,
});
});
}
}
}

View File

@ -14,6 +14,9 @@ if (k_is_browser) {
function make_rpc(target, prop, receiver) {
return function() {
let id = g_next_id++;
while (!id || g_calls[id]) {
id = g_next_id++;
}
let promise = new Promise(function(resolve, reject) {
g_calls[id] = {resolve: resolve, reject: reject};
});