Skip to content

Commit

Permalink
Merge branch 'feature-backend-error-handling-strategy' of https://git…
Browse files Browse the repository at this point in the history
…hub.com/Sma1lboy/codefox into feature-backend-error-handling-strategy
  • Loading branch information
NarwhalChen committed Jan 12, 2025
2 parents 269d740 + 18b12ad commit ce77412
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 54 deletions.
18 changes: 10 additions & 8 deletions backend/src/build-system/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,13 @@ export class BuilderContext {
waiting: new Set(),
};


private globalPromises: Set<Promise<any>> = new Set();
private logger: Logger;
private globalContext: Map<GlobalDataKeys | string, any> = new Map();
private nodeData: Map<string, any> = new Map();

private handlerManager: BuildHandlerManager;
private retryHandler : RetryHandler;
private retryHandler: RetryHandler;
private monitor: BuildMonitor;
public model: ModelProvider;
public virtualDirectory: VirtualDirectory;
Expand Down Expand Up @@ -194,7 +193,7 @@ export class BuilderContext {
this.logger.log(`Executing node ${node.id} in parallel batch`);
res = this.executeNodeById(node.id);
this.globalPromises.add(res);

this.monitor.endNodeExecution(
node.id,
this.sequence.id,
Expand All @@ -212,7 +211,7 @@ export class BuilderContext {
throw error;
}
});

await Promise.all(this.globalPromises);
const activeModelPromises = this.model.getAllActivePromises();
if (activeModelPromises.length > 0) {
Expand Down Expand Up @@ -450,16 +449,19 @@ export class BuilderContext {
if (!handler) {
throw new Error(`No handler found for node: ${node.id}`);
}
try{
try {
return await handler.run(this, node.options);
}catch(e){
} catch (e) {
this.logger.error(`retrying ${node.id}`);
const result = await this.retryHandler.retryMethod(e, (node) => this.invokeNodeHandler(node), [node]);
const result = await this.retryHandler.retryMethod(
e,
(node) => this.invokeNodeHandler(node),
[node],
);
if (result === undefined) {
throw e;
}
return result as unknown as BuildResult<T>;
}
}

}
98 changes: 55 additions & 43 deletions backend/src/build-system/retry-handler.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,59 @@
import { Logger } from "@nestjs/common";
import { Logger } from '@nestjs/common';

export class RetryHandler {
private readonly logger = new Logger(RetryHandler.name);
private static instance: RetryHandler;
private retryCounts: Map<string, number> = new Map();
public static getInstance(){
if(this.instance)return this.instance;
return new RetryHandler();
}
async retryMethod(error: Error, upperMethod: (...args: any[]) => void, args: any[]): Promise<void>{
const errorName = error.name;
let retryCount = this.retryCounts.get(errorName) || 0;
let isRetrying = this.retryCounts.has(errorName);
let res ;
switch (errorName) {
case 'GeneratedTagError':
case 'TimeoutError':
this.logger.warn(`Retryable error occurred: ${error.message}. Retrying...`);
if(!isRetrying)this.retryCounts.set(errorName, 0);
else this.retryCounts.set(errorName, this.retryCounts.get(errorName)+1);
while (retryCount < 3) {
try {
this.logger.log(`retryCount: ${retryCount}`)
res = await upperMethod(...args);

} catch (e) {
if (e.name === errorName) {
retryCount++;
this.retryCounts.set(errorName, retryCount);
this.logger.warn(`Retryable error occurred: ${e.name}: ${e.message}. Retrying attempt ${retryCount}...`);
} else {
this.logger.error(`Non-retryable error occurred: ${e.name}: ${e.message}. Terminating process.`);
throw e;
}
}
}
this.retryCounts.delete(errorName);
if(res)return res;
this.logger.error('Max retry attempts reached. Terminating process.');
throw new Error('Max retry attempts reached');
default:
this.logger.error(`Non-retryable error occurred: ${error.name}: ${error.message}. Terminating process.`);
throw error;
private readonly logger = new Logger(RetryHandler.name);
private static instance: RetryHandler;
private retryCounts: Map<string, number> = new Map();
public static getInstance() {
if (this.instance) return this.instance;
return new RetryHandler();
}
async retryMethod(
error: Error,
upperMethod: (...args: any[]) => void,
args: any[],
): Promise<void> {
const errorName = error.name;
let retryCount = this.retryCounts.get(errorName) || 0;
const isRetrying = this.retryCounts.has(errorName);
let res;
switch (errorName) {
case 'GeneratedTagError':
case 'TimeoutError':
this.logger.warn(
`Retryable error occurred: ${error.message}. Retrying...`,
);
if (!isRetrying) this.retryCounts.set(errorName, 0);
else
this.retryCounts.set(errorName, this.retryCounts.get(errorName) + 1);
while (retryCount < 3) {
try {
this.logger.log(`retryCount: ${retryCount}`);
res = await upperMethod(...args);
} catch (e) {
if (e.name === errorName) {
retryCount++;
this.retryCounts.set(errorName, retryCount);
this.logger.warn(
`Retryable error occurred: ${e.name}: ${e.message}. Retrying attempt ${retryCount}...`,
);
} else {
this.logger.error(
`Non-retryable error occurred: ${e.name}: ${e.message}. Terminating process.`,
);
throw e;
}
}
}
this.retryCounts.delete(errorName);
if (res) return res;
this.logger.error('Max retry attempts reached. Terminating process.');
throw new Error('Max retry attempts reached');
default:
this.logger.error(
`Non-retryable error occurred: ${error.name}: ${error.message}. Terminating process.`,
);
throw error;
}
}
}
}
6 changes: 3 additions & 3 deletions backend/src/embedding/openai-embbeding-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ export class OpenAIEmbProvider {
private static instance: OpenAIEmbProvider;
private openAi: OpenAI;
static openAi: any;
static getInstance(){
if(this.instance){
static getInstance() {
if (this.instance) {
return this.instance;
}
return new OpenAIEmbProvider();
}
constructor(){
constructor() {
this.openAi = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
Expand Down

0 comments on commit ce77412

Please sign in to comment.