[Perf] API: Batch updates into single postMessage
This commit is contained in:
parent
06098dd821
commit
19e02501af
@ -1,7 +1,7 @@
|
|||||||
import type { Api } from '../../../lib/gramjs';
|
import type { Api } from '../../../lib/gramjs';
|
||||||
import type { ApiInitialArgs, ApiOnProgress, OnApiUpdate } from '../../types';
|
import type { ApiInitialArgs, ApiOnProgress, OnApiUpdate } from '../../types';
|
||||||
import type { Methods, MethodArgs, MethodResponse } from '../methods/types';
|
import type { MethodArgs, MethodResponse, Methods } from '../methods/types';
|
||||||
import type { WorkerMessageEvent, OriginRequest, ThenArg } from './types';
|
import type { OriginRequest, ThenArg, WorkerMessageEvent } from './types';
|
||||||
import type { LocalDb } from '../localDb';
|
import type { LocalDb } from '../localDb';
|
||||||
import type { TypedBroadcastChannel } from '../../../util/multitab';
|
import type { TypedBroadcastChannel } from '../../../util/multitab';
|
||||||
|
|
||||||
@ -254,8 +254,22 @@ export function cancelApiProgressMaster(messageId: string) {
|
|||||||
function subscribeToWorker(onUpdate: OnApiUpdate) {
|
function subscribeToWorker(onUpdate: OnApiUpdate) {
|
||||||
worker?.addEventListener('message', ({ data }: WorkerMessageEvent) => {
|
worker?.addEventListener('message', ({ data }: WorkerMessageEvent) => {
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
if (data.type === 'update') {
|
if (data.type === 'updates') {
|
||||||
onUpdate(data.update);
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
|
let DEBUG_startAt: number | undefined;
|
||||||
|
if (DEBUG) {
|
||||||
|
DEBUG_startAt = performance.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
data.updates.forEach(onUpdate);
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
const duration = performance.now() - DEBUG_startAt!;
|
||||||
|
if (duration > 5) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.warn(`[API] Slow updates processing: ${data.updates.length} updates in ${duration} ms`);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (data.type === 'methodResponse') {
|
} else if (data.type === 'methodResponse') {
|
||||||
handleMethodResponse(data);
|
handleMethodResponse(data);
|
||||||
} else if (data.type === 'methodCallback') {
|
} else if (data.type === 'methodCallback') {
|
||||||
|
|||||||
@ -6,8 +6,8 @@ import type { DebugLevel } from '../../../util/debugConsole';
|
|||||||
export type ThenArg<T> = T extends Promise<infer U> ? U : T;
|
export type ThenArg<T> = T extends Promise<infer U> ? U : T;
|
||||||
|
|
||||||
export type WorkerMessageData = {
|
export type WorkerMessageData = {
|
||||||
type: 'update';
|
type: 'updates';
|
||||||
update: ApiUpdate;
|
updates: ApiUpdate[];
|
||||||
} | {
|
} | {
|
||||||
type: 'methodResponse';
|
type: 'methodResponse';
|
||||||
messageId: string;
|
messageId: string;
|
||||||
|
|||||||
@ -4,10 +4,11 @@ import type { ApiOnProgress, ApiUpdate } from '../../types';
|
|||||||
import type { OriginMessageEvent, WorkerMessageData } from './types';
|
import type { OriginMessageEvent, WorkerMessageData } from './types';
|
||||||
|
|
||||||
import { DEBUG } from '../../../config';
|
import { DEBUG } from '../../../config';
|
||||||
import { initApi, callApi, cancelApiProgress } from '../provider';
|
import { callApi, cancelApiProgress, initApi } from '../provider';
|
||||||
import { log } from '../helpers';
|
import { log } from '../helpers';
|
||||||
import type { DebugLevel } from '../../../util/debugConsole';
|
import type { DebugLevel } from '../../../util/debugConsole';
|
||||||
import { DEBUG_LEVELS } from '../../../util/debugConsole';
|
import { DEBUG_LEVELS } from '../../../util/debugConsole';
|
||||||
|
import { throttleWithTickEnd } from '../../../util/schedulers';
|
||||||
|
|
||||||
declare const self: WorkerGlobalScope;
|
declare const self: WorkerGlobalScope;
|
||||||
|
|
||||||
@ -154,15 +155,25 @@ function handleErrors() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onUpdate(update: ApiUpdate) {
|
let pendingUpdates: ApiUpdate[] = [];
|
||||||
sendToOrigin({
|
|
||||||
type: 'update',
|
|
||||||
update,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
const sendUpdatesOnTickEnd = throttleWithTickEnd(() => {
|
||||||
|
const currentUpdates = pendingUpdates;
|
||||||
|
pendingUpdates = [];
|
||||||
|
|
||||||
|
sendToOrigin({
|
||||||
|
type: 'updates',
|
||||||
|
updates: currentUpdates,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function onUpdate(update: ApiUpdate) {
|
||||||
if (DEBUG && update['@type'] !== 'updateUserStatus' && update['@type'] !== 'updateServerTimeOffset') {
|
if (DEBUG && update['@type'] !== 'updateUserStatus' && update['@type'] !== 'updateServerTimeOffset') {
|
||||||
log('UPDATE', update['@type'], update);
|
log('UPDATE', update['@type'], update);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pendingUpdates.push(update);
|
||||||
|
sendUpdatesOnTickEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sendToOrigin(data: WorkerMessageData, arrayBuffer?: ArrayBuffer) {
|
export function sendToOrigin(data: WorkerMessageData, arrayBuffer?: ArrayBuffer) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user