mirror of
https://github.com/stackblitz/bolt.new
synced 2025-02-06 04:48:04 +00:00
fix: added more controlled rate for code streaming
This commit is contained in:
parent
bfaa3f7065
commit
97b886abf0
@ -16,6 +16,7 @@ import * as nodePath from 'node:path';
|
|||||||
import { extractRelativePath } from '~/utils/diff';
|
import { extractRelativePath } from '~/utils/diff';
|
||||||
import { description } from '~/lib/persistence';
|
import { description } from '~/lib/persistence';
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
|
import { createSampler } from '~/utils/sampler';
|
||||||
|
|
||||||
export interface ArtifactState {
|
export interface ArtifactState {
|
||||||
id: string;
|
id: string;
|
||||||
@ -262,9 +263,9 @@ export class WorkbenchStore {
|
|||||||
this.artifacts.setKey(messageId, { ...artifact, ...state });
|
this.artifacts.setKey(messageId, { ...artifact, ...state });
|
||||||
}
|
}
|
||||||
addAction(data: ActionCallbackData) {
|
addAction(data: ActionCallbackData) {
|
||||||
this._addAction(data);
|
// this._addAction(data);
|
||||||
|
|
||||||
// this.addToExecutionQueue(()=>this._addAction(data))
|
this.addToExecutionQueue(() => this._addAction(data));
|
||||||
}
|
}
|
||||||
async _addAction(data: ActionCallbackData) {
|
async _addAction(data: ActionCallbackData) {
|
||||||
const { messageId } = data;
|
const { messageId } = data;
|
||||||
@ -280,7 +281,7 @@ export class WorkbenchStore {
|
|||||||
|
|
||||||
runAction(data: ActionCallbackData, isStreaming: boolean = false) {
|
runAction(data: ActionCallbackData, isStreaming: boolean = false) {
|
||||||
if (isStreaming) {
|
if (isStreaming) {
|
||||||
this._runAction(data, isStreaming);
|
this.actionStreamSampler(data, isStreaming);
|
||||||
} else {
|
} else {
|
||||||
this.addToExecutionQueue(() => this._runAction(data, isStreaming));
|
this.addToExecutionQueue(() => this._runAction(data, isStreaming));
|
||||||
}
|
}
|
||||||
@ -294,6 +295,12 @@ export class WorkbenchStore {
|
|||||||
unreachable('Artifact not found');
|
unreachable('Artifact not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const action = artifact.runner.actions.get()[data.actionId];
|
||||||
|
|
||||||
|
if (!action || action.executed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (data.action.type === 'file') {
|
if (data.action.type === 'file') {
|
||||||
const wc = await webcontainer;
|
const wc = await webcontainer;
|
||||||
const fullPath = nodePath.join(wc.workdir, data.action.filePath);
|
const fullPath = nodePath.join(wc.workdir, data.action.filePath);
|
||||||
@ -323,6 +330,10 @@ export class WorkbenchStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actionStreamSampler = createSampler(async (data: ActionCallbackData, isStreaming: boolean = false) => {
|
||||||
|
return await this._runAction(data, isStreaming);
|
||||||
|
}, 100); // TODO: remove this magic number to have it configurable
|
||||||
|
|
||||||
#getArtifact(id: string) {
|
#getArtifact(id: string) {
|
||||||
const artifacts = this.artifacts.get();
|
const artifacts = this.artifacts.get();
|
||||||
return artifacts[id];
|
return artifacts[id];
|
||||||
|
49
app/utils/sampler.ts
Normal file
49
app/utils/sampler.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* Creates a function that samples calls at regular intervals and captures trailing calls.
|
||||||
|
* - Drops calls that occur between sampling intervals
|
||||||
|
* - Takes one call per sampling interval if available
|
||||||
|
* - Captures the last call if no call was made during the interval
|
||||||
|
*
|
||||||
|
* @param fn The function to sample
|
||||||
|
* @param sampleInterval How often to sample calls (in ms)
|
||||||
|
* @returns The sampled function
|
||||||
|
*/
|
||||||
|
export function createSampler<T extends (...args: any[]) => any>(fn: T, sampleInterval: number): T {
|
||||||
|
let lastArgs: Parameters<T> | null = null;
|
||||||
|
let lastTime = 0;
|
||||||
|
let timeout: NodeJS.Timeout | null = null;
|
||||||
|
|
||||||
|
// Create a function with the same type as the input function
|
||||||
|
const sampled = function (this: any, ...args: Parameters<T>) {
|
||||||
|
const now = Date.now();
|
||||||
|
lastArgs = args;
|
||||||
|
|
||||||
|
// If we're within the sample interval, just store the args
|
||||||
|
if (now - lastTime < sampleInterval) {
|
||||||
|
// Set up trailing call if not already set
|
||||||
|
if (!timeout) {
|
||||||
|
timeout = setTimeout(
|
||||||
|
() => {
|
||||||
|
timeout = null;
|
||||||
|
lastTime = Date.now();
|
||||||
|
|
||||||
|
if (lastArgs) {
|
||||||
|
fn.apply(this, lastArgs);
|
||||||
|
lastArgs = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sampleInterval - (now - lastTime),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're outside the interval, execute immediately
|
||||||
|
lastTime = now;
|
||||||
|
fn.apply(this, args);
|
||||||
|
lastArgs = null;
|
||||||
|
} as T;
|
||||||
|
|
||||||
|
return sampled;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user