Move accounts query to a web worker.

This commit is contained in:
Spencer Ofwiti 2021-07-12 13:18:33 +03:00
parent 0ee8c7e6c8
commit 1411116d24
7 changed files with 100 additions and 30 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@
/dist /dist
/tmp /tmp
/out-tsc /out-tsc
/tests
# Only exists if Bazel was run # Only exists if Bazel was run
/bazel-out /bazel-out

View File

@ -37,7 +37,8 @@
"scripts": [ "scripts": [
"node_modules/jquery/dist/jquery.js", "node_modules/jquery/dist/jquery.js",
"node_modules/bootstrap/dist/js/bootstrap.js" "node_modules/bootstrap/dist/js/bootstrap.js"
] ],
"webWorkerTsConfig": "tsconfig.worker.json"
}, },
"configurations": { "configurations": {
"production": { "production": {
@ -126,7 +127,8 @@
"tsConfig": [ "tsConfig": [
"tsconfig.app.json", "tsconfig.app.json",
"tsconfig.spec.json", "tsconfig.spec.json",
"e2e/tsconfig.json" "e2e/tsconfig.json",
"tsconfig.worker.json"
], ],
"exclude": [ "exclude": [
"**/node_modules/**" "**/node_modules/**"

View File

@ -48,7 +48,7 @@ export class AuthService {
} }
getWithToken(): Promise<boolean> { getWithToken(): Promise<boolean> {
const sessionToken = this.getSessionToken() const sessionToken = this.getSessionToken();
const headers = { const headers = {
Authorization: 'Bearer ' + sessionToken, Authorization: 'Bearer ' + sessionToken,
'Content-Type': 'application/json;charset=utf-8', 'Content-Type': 'application/json;charset=utf-8',
@ -94,33 +94,32 @@ export class AuthService {
async login(): Promise<boolean> { async login(): Promise<boolean> {
if (this.getSessionToken()) { if (this.getSessionToken()) {
sessionStorage.removeItem(btoa('CICADA_SESSION_TOKEN')); sessionStorage.removeItem(btoa('CICADA_SESSION_TOKEN'));
} }
const o = await this.getChallenge(); const o = await this.getChallenge();
const r = await signChallenge( const r = await signChallenge(
o.challenge, o.challenge,
o.realm, o.realm,
environment.cicMetaUrl, environment.cicMetaUrl,
this.mutableKeyStore this.mutableKeyStore
); );
const tokenResponse = await this.sendSignedChallenge(r) const tokenResponse = await this.sendSignedChallenge(r).then((response) => {
.then((response) => { const token = response.headers.get('Token');
const token = response.headers.get('Token'); if (token) {
if (token) { return token;
return token; }
} if (response.status === 401) {
if (response.status === 401) { throw new HttpError('You are not authorized to use this system', response.status);
throw new HttpError('You are not authorized to use this system', response.status); }
} if (!response.ok) {
if (!response.ok) { throw new HttpError('Unknown error from authentication server', response.status);
throw new HttpError('Unknown error from authentication server', response.status); }
}
}); });
if (tokenResponse) { if (tokenResponse) {
this.setSessionToken(tokenResponse); this.setSessionToken(tokenResponse);
//this.setState('Click button to log in'); // this.setState('Click button to log in');
return true; return true;
} }
return false; return false;

View File

@ -204,17 +204,26 @@ export class UserService {
async loadAccounts(limit: number = 100, offset: number = 0): Promise<void> { async loadAccounts(limit: number = 100, offset: number = 0): Promise<void> {
this.resetAccountsList(); this.resetAccountsList();
// const accountIndexAddress: string = await this.registry.getContractAddressByName(
// 'AccountRegistry'
// );
// const accountIndexQuery = new AccountIndex(accountIndexAddress);
// const accountAddresses: Array<string> = await accountIndexQuery.last(limit);
try { try {
const accountRegistry = await RegistryService.getAccountRegistry(); const accountRegistry = await RegistryService.getAccountRegistry();
const accountAddresses: Array<string> = await accountRegistry.last(limit); const accountAddresses: Array<string> = await accountRegistry.last(offset + limit);
this.loggingService.sendInfoLevelMessage(accountAddresses); this.loggingService.sendInfoLevelMessage(accountAddresses);
for (const accountAddress of accountAddresses.slice(offset, offset + limit)) { if (typeof Worker !== 'undefined') {
await this.getAccountByAddress(accountAddress, limit); const worker = new Worker('@app/_workers/fetch-accounts.worker', { type: 'module' });
worker.onmessage = ({ data }) => {
this.addAccount(data, limit);
};
worker.postMessage({
addresses: accountAddresses.slice(offset, offset + limit),
url: environment.cicMetaUrl,
});
} else {
this.loggingService.sendInfoLevelMessage(
'Web workers are not supported in this environment'
);
for (const accountAddress of accountAddresses.slice(offset, offset + limit)) {
await this.getAccountByAddress(accountAddress, limit);
}
} }
} catch (error) { } catch (error) {
this.loggingService.sendErrorLevelMessage('Unable to load accounts.', 'user.service', error); this.loggingService.sendErrorLevelMessage('Unable to load accounts.', 'user.service', error);

View File

@ -0,0 +1,44 @@
/// <reference lib="webworker" />
import { Envelope, Syncable, User } from 'cic-client-meta';
import { add0x } from '@src/assets/js/ethtx/dist/hex';
import { personValidation, vcardValidation } from '@app/_helpers/schema-validation';
// const vCard = require('vcard-parser');
import * as vCard from 'vcard-parser';
const headers = {
'x-cic-automerge': 'client',
};
const options = {
headers,
};
addEventListener('message', async ({ data }) => {
if (data.addresses instanceof Array) {
for (const accountAddress of data.addresses) {
const account = await getAccountByAddress(accountAddress, data.url);
postMessage(account);
}
}
});
async function getAccountByAddress(accountAddress: string, metaUrl: string): Promise<any> {
const userKey = await User.toKey(add0x(accountAddress));
return new Promise((resolve, reject) => {
fetch(`${metaUrl}/${userKey}`, options).then(async (response) => {
if (!response.ok) {
return reject({
status: response.status,
statusText: response.statusText,
});
} else {
const account: Syncable = Envelope.fromJSON(JSON.stringify(response.text())).unwrap();
const accountInfo = account.m.data;
await personValidation(accountInfo);
accountInfo.vcard = vCard.parse(atob(accountInfo.vcard));
await vcardValidation(accountInfo.vcard);
return resolve(accountInfo);
}
});
});
}

View File

@ -58,7 +58,7 @@ export class AuthComponent implements OnInit {
} }
} catch (HttpError) { } catch (HttpError) {
this.errorDialogService.openDialog({ this.errorDialogService.openDialog({
message: "Failed to login please try again.", message: 'Failed to login please try again.',
}); });
} }
} }

15
tsconfig.worker.json Normal file
View File

@ -0,0 +1,15 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/worker",
"lib": [
"es2018",
"webworker"
],
"types": []
},
"include": [
"src/**/*.worker.ts"
]
}