Skip to content

Commit

Permalink
fix: added more controlled rate for code streaming
Browse files Browse the repository at this point in the history
  • Loading branch information
thecodacus committed Dec 11, 2024
1 parent bfaa3f7 commit 97b886a
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 3 deletions.
17 changes: 14 additions & 3 deletions app/lib/stores/workbench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import * as nodePath from 'node:path';
import { extractRelativePath } from '~/utils/diff';
import { description } from '~/lib/persistence';
import Cookies from 'js-cookie';
import { createSampler } from '~/utils/sampler';

export interface ArtifactState {
id: string;
Expand Down Expand Up @@ -262,9 +263,9 @@ export class WorkbenchStore {
this.artifacts.setKey(messageId, { ...artifact, ...state });
}
addAction(data: ActionCallbackData) {
this._addAction(data);
// this._addAction(data);

// this.addToExecutionQueue(()=>this._addAction(data))
this.addToExecutionQueue(() => this._addAction(data));
}
async _addAction(data: ActionCallbackData) {
const { messageId } = data;
Expand All @@ -280,7 +281,7 @@ export class WorkbenchStore {

runAction(data: ActionCallbackData, isStreaming: boolean = false) {
if (isStreaming) {
this._runAction(data, isStreaming);
this.actionStreamSampler(data, isStreaming);
} else {
this.addToExecutionQueue(() => this._runAction(data, isStreaming));
}
Expand All @@ -294,6 +295,12 @@ export class WorkbenchStore {
unreachable('Artifact not found');
}

const action = artifact.runner.actions.get()[data.actionId];

if (!action || action.executed) {
return;
}

if (data.action.type === 'file') {
const wc = await webcontainer;
const fullPath = nodePath.join(wc.workdir, data.action.filePath);
Expand Down Expand Up @@ -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) {
const artifacts = this.artifacts.get();
return artifacts[id];
Expand Down
49 changes: 49 additions & 0 deletions app/utils/sampler.ts
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit 97b886a

Please sign in to comment.