mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) Process new user info in /welcome/info post without waiting for it to be written to the collecting document
Summary: The document collecting new user info (https://docs.getgrist.com/doc/GristNewUserInfo) got very slow, taking 40+ seconds for cold open. Sign-up submissions had to wait this time to proceed to next step, because they waited for the write to this doc, which was blocked on the Calculate action to complete. Two changes were made: one to remove all expensive columns and summaries in the actual doc, so the doc is back to opening in single seconds, and times should be acceptable now. The second change is this diff: to avoid waiting for the write step, so that it doesn't affect users even if it gets slow again. Test Plan: Existing test continues to work with a minor reliability tweak. Reviewers: paulfitz Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D3103
This commit is contained in:
parent
6c53f3e820
commit
c5db65d1d2
@ -1059,44 +1059,13 @@ export class FlexServer implements GristServer {
|
|||||||
redirectPath = '/welcome/info';
|
redirectPath = '/welcome/info';
|
||||||
|
|
||||||
} else if (req.params.page === 'info') {
|
} else if (req.params.page === 'info') {
|
||||||
const urlId = DOC_ID_NEW_USER_INFO;
|
|
||||||
let body: string|undefined;
|
|
||||||
let permitKey: string|undefined;
|
|
||||||
try {
|
|
||||||
const user = getUser(req);
|
const user = getUser(req);
|
||||||
const row = {...req.body, UserID: userId, Name: user.name, Email: user.loginEmail};
|
const row = {...req.body, UserID: userId, Name: user.name, Email: user.loginEmail};
|
||||||
body = JSON.stringify(mapValues(row, value => [value]));
|
this._recordNewUserInfo(row)
|
||||||
|
.catch(e => {
|
||||||
// Take an extra step to translate the special urlId to a docId. This is helpful to
|
|
||||||
// allow the same urlId to be used in production and in test. We need the docId for the
|
|
||||||
// specialPermit below, which we need to be able to write to this doc.
|
|
||||||
//
|
|
||||||
// TODO With proper forms support, we could give an origin-based permission to submit a
|
|
||||||
// form to this doc, and do it from the client directly.
|
|
||||||
const previewerUserId = this._dbManager.getPreviewerUserId();
|
|
||||||
const docAuth = await this._dbManager.getDocAuthCached({urlId, userId: previewerUserId});
|
|
||||||
const docId = docAuth.docId;
|
|
||||||
if (!docId) {
|
|
||||||
throw new Error(`Can't resolve ${urlId}: ${docAuth.error}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
permitKey = await this._internalPermitStore.setPermit({docId});
|
|
||||||
const res = await fetch(await this.getHomeUrlByDocId(docId, `/api/docs/${docId}/tables/Responses/data`), {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {'Permit': permitKey, 'Content-Type': 'application/json'},
|
|
||||||
body,
|
|
||||||
});
|
|
||||||
if (res.status !== 200) {
|
|
||||||
throw new Error(`API call failed with ${res.status}`);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// If we failed to record, at least log the data, so we could potentially recover it.
|
// If we failed to record, at least log the data, so we could potentially recover it.
|
||||||
log.rawWarn(`Failed to record new user info: ${e.message}`, {newUserQuestions: body});
|
log.rawWarn(`Failed to record new user info: ${e.message}`, {newUserQuestions: row});
|
||||||
} finally {
|
});
|
||||||
if (permitKey) {
|
|
||||||
await this._internalPermitStore.removePermit(permitKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// redirect to teams page if users has access to more than one org. Otherwise redirect to
|
// redirect to teams page if users has access to more than one org. Otherwise redirect to
|
||||||
// personal org.
|
// personal org.
|
||||||
@ -1571,6 +1540,43 @@ export class FlexServer implements GristServer {
|
|||||||
if (verbose) { log.info(`${name} available at https://${this.host}:${httpsPort}`); }
|
if (verbose) { log.info(`${name} available at https://${this.host}:${httpsPort}`); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _recordNewUserInfo(row: object) {
|
||||||
|
const urlId = DOC_ID_NEW_USER_INFO;
|
||||||
|
let body: string|undefined;
|
||||||
|
let permitKey: string|undefined;
|
||||||
|
try {
|
||||||
|
body = JSON.stringify(mapValues(row, value => [value]));
|
||||||
|
|
||||||
|
// Take an extra step to translate the special urlId to a docId. This is helpful to
|
||||||
|
// allow the same urlId to be used in production and in test. We need the docId for the
|
||||||
|
// specialPermit below, which we need to be able to write to this doc.
|
||||||
|
//
|
||||||
|
// TODO With proper forms support, we could give an origin-based permission to submit a
|
||||||
|
// form to this doc, and do it from the client directly.
|
||||||
|
const previewerUserId = this._dbManager.getPreviewerUserId();
|
||||||
|
const docAuth = await this._dbManager.getDocAuthCached({urlId, userId: previewerUserId});
|
||||||
|
const docId = docAuth.docId;
|
||||||
|
if (!docId) {
|
||||||
|
throw new Error(`Can't resolve ${urlId}: ${docAuth.error}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
permitKey = await this._internalPermitStore.setPermit({docId});
|
||||||
|
const res = await fetch(await this.getHomeUrlByDocId(docId, `/api/docs/${docId}/tables/Responses/data`), {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Permit': permitKey, 'Content-Type': 'application/json'},
|
||||||
|
body,
|
||||||
|
});
|
||||||
|
if (res.status !== 200) {
|
||||||
|
throw new Error(`API call failed with ${res.status}`);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (permitKey) {
|
||||||
|
await this._internalPermitStore.removePermit(permitKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user