Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(backend): backend error handling strategy #89

Merged
merged 28 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5d3a8e7
feat(backend): update chatSync calls to use structured message format…
Sma1lboy Jan 7, 2025
52d587a
refactor(backend): simplify chat input type and clean up unused embed…
Sma1lboy Jan 7, 2025
47d7e43
feat(backend): enhance test utilities and improve markdown output for…
Sma1lboy Jan 7, 2025
d5bf1b9
chore: update documentation for improved clarity and consistency
Sma1lboy Jan 7, 2025
89fd2f3
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 7, 2025
88d79db
fix: deleting useless embedding module and adding tests for openai em…
NarwhalChen Jan 7, 2025
1ff5a5d
feat: adding retryable error handler
NarwhalChen Jan 11, 2025
ebc2daa
Merge branch 'main' of https://github.com/Sma1lboy/codefox into featu…
NarwhalChen Jan 11, 2025
169556e
feat: merging useless promise set and updating ux handler to newet ve…
NarwhalChen Jan 11, 2025
18b12ad
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 11, 2025
269d740
fix: Undelete false delete during merge
NarwhalChen Jan 12, 2025
ce77412
Merge branch 'feature-backend-error-handling-strategy' of https://git…
NarwhalChen Jan 12, 2025
988b0ba
Merge branch 'main' of https://github.com/Sma1lboy/codefox into featu…
NarwhalChen Jan 12, 2025
bbba977
feat: deleting repeat retry in file arch
NarwhalChen Jan 12, 2025
7c4d783
feat: adding retryable error and non retryable error for retry handler
NarwhalChen Jan 12, 2025
5ed11e7
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 12, 2025
2daed38
feat: adapting all handlers to retry handler
NarwhalChen Jan 13, 2025
3296a80
Merge branch 'feature-backend-error-handling-strategy' of https://git…
NarwhalChen Jan 13, 2025
317c690
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 13, 2025
bb7b3d7
feat: support detail error in handler
NarwhalChen Jan 13, 2025
2d2bb8d
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 13, 2025
cf221cb
feat: removing useless error
NarwhalChen Jan 13, 2025
370a453
fix: fixing wrong version of fullstack test
NarwhalChen Jan 13, 2025
4718272
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 14, 2025
0654d78
fix: update prompt handling and improve regex for section extraction
Sma1lboy Jan 15, 2025
25ac7d8
fix: add handling for ResponseParsingError in retry logic
Sma1lboy Jan 15, 2025
3f3dc91
refactor: remove unused error classes and improve error handling in r…
Sma1lboy Jan 15, 2025
85c09f1
refactor: introduce base error classes for retryable and non-retryabl…
Sma1lboy Jan 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions backend/src/build-system/__tests__/test.model-provider.spec.ts

This file was deleted.

60 changes: 0 additions & 60 deletions backend/src/build-system/__tests__/test.spec.ts

This file was deleted.

34 changes: 27 additions & 7 deletions backend/src/build-system/context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
BuildExecutionState,
BuildHandler,
BuildNode,
BuildResult,
BuildSequence,
Expand All @@ -12,6 +13,7 @@ import { ModelProvider } from 'src/common/model-provider';
import { v4 as uuidv4 } from 'uuid';
import { BuildMonitor } from './monitor';
import { BuildHandlerManager } from './hanlder-manager';
import { RetryHandler } from './retry-handler';

/**
* Global data keys used throughout the build process
Expand Down Expand Up @@ -50,11 +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 monitor: BuildMonitor;
public model: ModelProvider;
public virtualDirectory: VirtualDirectory;
Expand All @@ -63,6 +67,7 @@ export class BuilderContext {
private sequence: BuildSequence,
id: string,
) {
this.retryHandler = RetryHandler.getInstance();
this.handlerManager = BuildHandlerManager.getInstance();
this.model = ModelProvider.getInstance();
this.monitor = BuildMonitor.getInstance();
Expand Down Expand Up @@ -157,7 +162,7 @@ export class BuilderContext {
const batch = executableNodes.slice(i, i + concurrencyLimit);

try {
const nodeExecutionPromises = batch.map(async (node) => {
batch.map(async (node) => {
if (this.executionState.completed.has(node.id)) {
return;
}
Expand All @@ -169,6 +174,7 @@ export class BuilderContext {
currentStep.id,
);

let res;
try {
if (!this.canExecute(node.id)) {
this.logger.log(
Expand All @@ -185,7 +191,8 @@ export class BuilderContext {
}

this.logger.log(`Executing node ${node.id} in parallel batch`);
await this.executeNodeById(node.id);
res = this.executeNodeById(node.id);
this.globalPromises.add(res);

this.monitor.endNodeExecution(
node.id,
Expand All @@ -205,8 +212,7 @@ export class BuilderContext {
}
});

await Promise.all(nodeExecutionPromises);

await Promise.all(this.globalPromises);
const activeModelPromises = this.model.getAllActivePromises();
if (activeModelPromises.length > 0) {
this.logger.debug(
Expand Down Expand Up @@ -336,7 +342,7 @@ export class BuilderContext {
this.executionState.completed.has(nodeId) ||
this.executionState.pending.has(nodeId)
) {
this.logger.debug(`Node ${nodeId} is already completed or pending.`);
//this.logger.debug(`Node ${nodeId} is already completed or pending.`);
NarwhalChen marked this conversation as resolved.
Show resolved Hide resolved
return false;
}

Expand All @@ -361,6 +367,7 @@ export class BuilderContext {
this.executionState.pending.add(nodeId);
const result = await this.invokeNodeHandler<T>(node);
this.executionState.completed.add(nodeId);
this.logger.log(`${nodeId} is completed`);
this.executionState.pending.delete(nodeId);

this.nodeData.set(node.id, result.data);
Expand Down Expand Up @@ -438,10 +445,23 @@ export class BuilderContext {

private async invokeNodeHandler<T>(node: BuildNode): Promise<BuildResult<T>> {
const handler = this.handlerManager.getHandler(node.id);
this.logger.log(`sovling ${node.id}`);
if (!handler) {
throw new Error(`No handler found for node: ${node.id}`);
}

return handler.run(this, node.options);
try {
return await handler.run(this, node.options);
} catch (e) {
this.logger.error(`retrying ${node.id}`);
const result = await this.retryHandler.retryMethod(
e,
(node) => this.invokeNodeHandler(node),
[node],
);
if (result === undefined) {
throw e;
}
return result as unknown as BuildResult<T>;
}
}
}
149 changes: 149 additions & 0 deletions backend/src/build-system/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// error.ts

/**
* Base class representing retryable errors.
* Inherits from JavaScript's built-in Error class.
* Suitable for errors where the system can attempt to retry the operation.
*/
export class RetryableError extends Error {
constructor(message: string) {
super(message);
this.name = 'RetryableError';
Object.setPrototypeOf(this, new.target.prototype); // Fixes the inheritance chain for instanceof checks
}
}

/**
* Base class representing non-retryable errors.
* Inherits from JavaScript's built-in Error class.
* Suitable for errors where the system should not attempt to retry the operation.
*/
export class NonRetryableError extends Error {
constructor(message: string) {
super(message);
this.name = 'NonRetryableError';
Object.setPrototypeOf(this, new.target.prototype); // Fixes the inheritance chain for instanceof checks
}
}

// Below are specific error classes inheriting from the appropriate base classes

/**
* Error: File Not Found.
* Indicates that a required file could not be found during file operations.
* Non-retryable error.
*/
export class FileNotFoundError extends NonRetryableError {
constructor(message: string) {
super(message);
this.name = 'FileNotFoundError';
}
}

/**
* Error: File Modification Failed.
* Indicates issues encountered while modifying a file, such as insufficient permissions or disk errors.
* Non-retryable error.
*/
export class FileModificationError extends NonRetryableError {
constructor(message: string) {
super(message);
this.name = 'FileModificationError';
}
}

/**
* Error: Model Service Unavailable.
* Indicates that the underlying model service cannot be reached or is down.
* Retryable error, typically temporary.
*/
export class ModelUnavailableError extends RetryableError {
constructor(message: string) {
super(message);
this.name = 'ModelUnavailableError';
}
}

/**
* Error: Response Parsing Failed.
* Indicates that the system could not properly parse the response data.
* Retryable error, possibly due to temporary data format issues.
*/
export class ResponseParsingError extends RetryableError {
constructor(message: string) {
super(message);
this.name = 'ResponseParsingError';
}
}

/**
* Error: Response Tag Error.
* Indicates that expected tags in the response are missing or invalid during content generation or parsing.
* Non-retryable error.
*/
export class ResponseTagError extends NonRetryableError {
constructor(message: string) {
super(message);
this.name = 'ResponseTagError';
}
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding long description for each erorr

/**
* Error: Temporary Service Unavailable.
* Indicates that the service is unavailable due to temporary issues like server overload or maintenance.
* Retryable error, typically temporary.
*/
export class TemporaryServiceUnavailableError extends RetryableError {
constructor(message: string) {
super(message);
this.name = 'TemporaryServiceUnavailableError';
}
}

/**
* Error: Rate Limit Exceeded.
* Indicates that too many requests have been sent within a given time frame.
* Retryable error, may require waiting before retrying.
*/
export class RateLimitExceededError extends RetryableError {
constructor(message: string) {
super(message);
this.name = 'RateLimitExceededError';
}
}

/**
* Error: Missing Configuration.
* Indicates issues with system setup or missing configuration parameters.
* Non-retryable error, typically requires manual configuration fixes.
*/
export class MissingConfigurationError extends NonRetryableError {
constructor(message: string) {
super(message);
this.name = 'MissingConfigurationError';
}
}

/**
* Error: Invalid Parameter.
* Indicates that a function argument or configuration parameter is invalid.
* Non-retryable error, typically requires correcting the input parameters.
*/
export class InvalidParameterError extends NonRetryableError {
constructor(message: string) {
super(message);
this.name = 'InvalidParameterError';
}
}

/**
* Error: File Write Failed.
* Indicates issues encountered while writing to a file, such as insufficient permissions or disk errors.
* Non-retryable error.
*/
export class FileWriteError extends NonRetryableError {
constructor(message: string) {
super(message);
this.name = 'FileWriteError';
}
}
Loading
Loading