feat: speed up snapshot emission
This commit is contained in:
@@ -201,6 +201,11 @@ export class RemoteBrowser {
|
|||||||
private networkRequestTimeout: NodeJS.Timeout | null = null;
|
private networkRequestTimeout: NodeJS.Timeout | null = null;
|
||||||
private pendingNetworkRequests: string[] = [];
|
private pendingNetworkRequests: string[] = [];
|
||||||
private readonly NETWORK_QUIET_PERIOD = 8000;
|
private readonly NETWORK_QUIET_PERIOD = 8000;
|
||||||
|
private readonly INITIAL_LOAD_QUIET_PERIOD = 3000;
|
||||||
|
private networkWaitStartTime: number = 0;
|
||||||
|
private progressInterval: NodeJS.Timeout | null = null;
|
||||||
|
private hasShownInitialLoader: boolean = false;
|
||||||
|
private isInitialLoadInProgress: boolean = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new instances of the {@link Generator} and {@link WorkflowInterpreter} classes and
|
* Initializes a new instances of the {@link Generator} and {@link WorkflowInterpreter} classes and
|
||||||
@@ -432,17 +437,19 @@ export class RemoteBrowser {
|
|||||||
if (!this.currentPage) return;
|
if (!this.currentPage) return;
|
||||||
|
|
||||||
this.currentPage.on("domcontentloaded", async () => {
|
this.currentPage.on("domcontentloaded", async () => {
|
||||||
logger.info("DOM content loaded - triggering snapshot");
|
if (!this.isInitialLoadInProgress) {
|
||||||
await this.makeAndEmitDOMSnapshot();
|
logger.info("DOM content loaded - triggering snapshot");
|
||||||
|
await this.makeAndEmitDOMSnapshot();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.currentPage.on("response", async (response) => {
|
this.currentPage.on("response", async (response) => {
|
||||||
const url = response.url();
|
const url = response.url();
|
||||||
if (
|
const isDocumentRequest = response.request().resourceType() === "document";
|
||||||
response.request().resourceType() === "document" ||
|
|
||||||
url.includes("api/") ||
|
if (!this.hasShownInitialLoader && isDocumentRequest && !url.includes("about:blank")) {
|
||||||
url.includes("ajax")
|
this.hasShownInitialLoader = true;
|
||||||
) {
|
this.isInitialLoadInProgress = true;
|
||||||
this.pendingNetworkRequests.push(url);
|
this.pendingNetworkRequests.push(url);
|
||||||
|
|
||||||
if (this.networkRequestTimeout) {
|
if (this.networkRequestTimeout) {
|
||||||
@@ -450,24 +457,54 @@ export class RemoteBrowser {
|
|||||||
this.networkRequestTimeout = null;
|
this.networkRequestTimeout = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.progressInterval) {
|
||||||
|
clearInterval(this.progressInterval);
|
||||||
|
this.progressInterval = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.networkWaitStartTime = Date.now();
|
||||||
|
this.progressInterval = setInterval(() => {
|
||||||
|
const elapsed = Date.now() - this.networkWaitStartTime;
|
||||||
|
const navigationProgress = Math.min((elapsed / this.INITIAL_LOAD_QUIET_PERIOD) * 40, 35);
|
||||||
|
const totalProgress = 60 + navigationProgress;
|
||||||
|
this.emitLoadingProgress(totalProgress, this.pendingNetworkRequests.length);
|
||||||
|
}, 500);
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`Network request received: ${url}. Total pending: ${this.pendingNetworkRequests.length}`
|
`Initial load network request received: ${url}. Using ${this.INITIAL_LOAD_QUIET_PERIOD}ms quiet period`
|
||||||
);
|
);
|
||||||
|
|
||||||
this.networkRequestTimeout = setTimeout(async () => {
|
this.networkRequestTimeout = setTimeout(async () => {
|
||||||
logger.info(
|
logger.info(
|
||||||
`Network quiet period reached. Processing ${this.pendingNetworkRequests.length} requests`
|
`Initial load network quiet period reached (${this.INITIAL_LOAD_QUIET_PERIOD}ms)`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (this.progressInterval) {
|
||||||
|
clearInterval(this.progressInterval);
|
||||||
|
this.progressInterval = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.emitLoadingProgress(100, this.pendingNetworkRequests.length);
|
||||||
|
|
||||||
this.pendingNetworkRequests = [];
|
this.pendingNetworkRequests = [];
|
||||||
this.networkRequestTimeout = null;
|
this.networkRequestTimeout = null;
|
||||||
|
this.isInitialLoadInProgress = false;
|
||||||
|
|
||||||
await this.makeAndEmitDOMSnapshot();
|
await this.makeAndEmitDOMSnapshot();
|
||||||
}, this.NETWORK_QUIET_PERIOD);
|
}, this.INITIAL_LOAD_QUIET_PERIOD);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private emitLoadingProgress(progress: number, pendingRequests: number): void {
|
||||||
|
this.socket.emit("domLoadingProgress", {
|
||||||
|
progress: Math.round(progress),
|
||||||
|
pendingRequests,
|
||||||
|
userId: this.userId,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private async setupPageEventListeners(page: Page) {
|
private async setupPageEventListeners(page: Page) {
|
||||||
page.on('framenavigated', async (frame) => {
|
page.on('framenavigated', async (frame) => {
|
||||||
if (frame === page.mainFrame()) {
|
if (frame === page.mainFrame()) {
|
||||||
@@ -522,6 +559,12 @@ export class RemoteBrowser {
|
|||||||
let retryCount = 0;
|
let retryCount = 0;
|
||||||
let success = false;
|
let success = false;
|
||||||
|
|
||||||
|
this.socket.emit("dom-snapshot-loading", {
|
||||||
|
userId: this.userId,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
});
|
||||||
|
this.emitLoadingProgress(0, 0);
|
||||||
|
|
||||||
while (!success && retryCount < MAX_RETRIES) {
|
while (!success && retryCount < MAX_RETRIES) {
|
||||||
try {
|
try {
|
||||||
this.browser = <Browser>(await chromium.launch({
|
this.browser = <Browser>(await chromium.launch({
|
||||||
@@ -546,6 +589,8 @@ export class RemoteBrowser {
|
|||||||
throw new Error('Browser failed to launch or is not connected');
|
throw new Error('Browser failed to launch or is not connected');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.emitLoadingProgress(20, 0);
|
||||||
|
|
||||||
const proxyConfig = await getDecryptedProxyConfig(userId);
|
const proxyConfig = await getDecryptedProxyConfig(userId);
|
||||||
let proxyOptions: { server: string, username?: string, password?: string } = { server: '' };
|
let proxyOptions: { server: string, username?: string, password?: string } = { server: '' };
|
||||||
|
|
||||||
@@ -623,6 +668,8 @@ export class RemoteBrowser {
|
|||||||
|
|
||||||
this.currentPage = await this.context.newPage();
|
this.currentPage = await this.context.newPage();
|
||||||
|
|
||||||
|
this.emitLoadingProgress(40, 0);
|
||||||
|
|
||||||
await this.setupPageEventListeners(this.currentPage);
|
await this.setupPageEventListeners(this.currentPage);
|
||||||
|
|
||||||
const viewportSize = await this.currentPage.viewportSize();
|
const viewportSize = await this.currentPage.viewportSize();
|
||||||
@@ -646,6 +693,8 @@ export class RemoteBrowser {
|
|||||||
this.client = await this.currentPage.context().newCDPSession(this.currentPage);
|
this.client = await this.currentPage.context().newCDPSession(this.currentPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.emitLoadingProgress(60, 0);
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
logger.log('debug', `Browser initialized successfully for user ${userId}`);
|
logger.log('debug', `Browser initialized successfully for user ${userId}`);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@@ -1521,9 +1570,6 @@ export class RemoteBrowser {
|
|||||||
this.isDOMStreamingActive = true;
|
this.isDOMStreamingActive = true;
|
||||||
logger.info("DOM streaming started successfully");
|
logger.info("DOM streaming started successfully");
|
||||||
|
|
||||||
// Initial DOM snapshot
|
|
||||||
await this.makeAndEmitDOMSnapshot();
|
|
||||||
|
|
||||||
this.setupScrollEventListener();
|
this.setupScrollEventListener();
|
||||||
this.setupPageChangeListeners();
|
this.setupPageChangeListeners();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user