Skip to content

Commit ef8c673

Browse files
committed
feat: implement comprehensive error handling system
- Update error handling to match hub's error structure - Add support for parsing standardized error codes - Implement error data structure compatibility - Add detailed error handling documentation - Document error structure and standard error codes - Include usage examples and best practices - Add common error scenarios and solutions
1 parent d5e67ec commit ef8c673

File tree

3 files changed

+148
-7
lines changed

3 files changed

+148
-7
lines changed

README.md

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ License: [MIT](./LICENSE)
4848
- [Usage 🚀](#usage-)
4949
- [Configuration Options ⚙️](#configuration-options-)
5050
- [Log Levels 📊](#log-levels-)
51+
- [Error Handling 🚨](#error-handling-)
5152
- [MicroStream Hub 🏢](#microstream-hub-)
5253
- [Author 👨‍💻](#author-)
5354
- [Contributing 🤝](#contributing-)
@@ -225,9 +226,94 @@ try {
225226

226227
<hr>
227228

229+
## Error Handling 🚨
230+
231+
**[MicroStream Client](https://github.com/arijitcodes/microstream-client)** implements standardized error handling using a `CustomError` class. All errors follow a consistent structure to help with error management and debugging.
232+
233+
### Error Structure 📋
234+
235+
```typescript
236+
{
237+
code: string; // Error identification code
238+
message: string; // Human readable error message
239+
errorData?: any; // Optional contextual data
240+
}
241+
```
242+
243+
### Standard Error Codes 📝
244+
245+
The **[Client](https://github.com/arijitcodes/microstream-client)** may throw the following error types:
246+
247+
| Error Code | Description |
248+
| -------------------------------- | ----------------------------------------------------------------------- |
249+
| `INTERNAL_SERVER_ERROR` | Occurs when an event handler fails during execution |
250+
| `EVENT_NOT_FOUND` | Thrown when no handler is registered for the requested event |
251+
| `REQUEST_TIMEOUT` | Occurs when a request exceeds the configured timeout period |
252+
| `DUPLICATE_SERVICE_REGISTRATION` | Thrown when attempting to register a service name that's already in use |
253+
254+
### Usage Examples 💡
255+
256+
```javascript
257+
// Example: Handling request errors
258+
try {
259+
const response = await client.sendRequest("auth-service", "validate-token", {
260+
token: "xyz",
261+
});
262+
} catch (error) {
263+
switch (error.code) {
264+
case "REQUEST_TIMEOUT":
265+
console.error(`Request timed out: ${error.message}`);
266+
console.log("Request details:", error.errorData);
267+
break;
268+
case "EVENT_NOT_FOUND":
269+
console.error(`Event handler not found: ${error.message}`);
270+
break;
271+
case "INTERNAL_SERVER_ERROR":
272+
console.error(`Service error: ${error.message}`);
273+
console.log("Error context:", error.errorData);
274+
break;
275+
}
276+
}
277+
```
278+
279+
### Error Handling Best Practices 🎯
280+
281+
1. Always wrap requests in try-catch blocks
282+
2. Check error codes for specific error handling
283+
3. Use error.errorData for additional context in debugging
284+
4. Handle REQUEST_TIMEOUT errors with appropriate retry logic
285+
5. Implement proper logging for INTERNAL_SERVER_ERROR cases
286+
287+
### Common Error Scenarios 🔄
288+
289+
1. **Timeout Errors**
290+
291+
- Occurs when target service doesn't respond within timeout period
292+
- Default timeout: 5000ms (configurable via options)
293+
- Includes target service and event details in errorData
294+
295+
2. **Event Not Found**
296+
297+
- Happens when requesting non-existent event handlers
298+
- Includes event name and service details in errorData
299+
- Check event name and target service configuration
300+
301+
3. **Internal Server Errors**
302+
303+
- Triggered by exceptions in event handlers
304+
- Contains original error details in errorData
305+
- Useful for debugging service-side issues
306+
307+
4. **Service Registration Errors**
308+
- Occurs during initial connection
309+
- Critical errors that may require process termination
310+
- Check for duplicate service names in your network
311+
312+
<hr>
313+
228314
## MicroStream Hub 🏢
229315

230-
We also provide a central hub for easy integration with the MicroStream Client SDK.
316+
Here is the central hub for easy integration with the MicroStream Client SDK.
231317

232318
- [MicroStream Hub on GitHub](https://github.com/arijitcodes/microstream-hub)
233319
- [MicroStream Hub Documentation](https://github.com/arijitcodes/microstream-hub#readme)
@@ -264,3 +350,4 @@ We welcome contributions! Please see our [CONTRIBUTING.md](./CONTRIBUTING.md) fo
264350
This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for details.
265351

266352
<hr>
353+
```

src/index.ts

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { io, Socket } from "socket.io-client";
22
import { nanoid } from "nanoid";
33
import Logger from "./utils/logger"; // Import the logger
44
import { exit } from "process";
5+
import CustomError from "./utils/customError"; // Import the custom error class
56

67
/**
78
* Options for initializing the MicrostreamClient.
@@ -79,7 +80,7 @@ export class MicrostreamClient {
7980
});
8081

8182
// Handle incoming requests
82-
this.socket.on("request", ({ id, event, data }) => {
83+
this.socket.on("request", ({ id, event, data }: RequestPayload) => {
8384
this.logger.debug(
8485
`[${this.serviceName}] Received request for event "${event}" (ID: ${id})`,
8586
data
@@ -102,14 +103,43 @@ export class MicrostreamClient {
102103
error
103104
);
104105
// Handle any errors that occur during handler execution
105-
this.socket.emit("response", { id, error: "Internal server error" });
106+
// this.socket.emit("response", { id, error: "Internal server error" });
107+
// Send a CustomError for internal server errors
108+
this.socket.emit("response", {
109+
id,
110+
response: {
111+
error: new CustomError(
112+
"INTERNAL_SERVER_ERROR",
113+
"Internal server error",
114+
{
115+
event,
116+
requestID: id,
117+
error:
118+
error instanceof Error || error instanceof CustomError
119+
? error.message
120+
: "UNKNOWN",
121+
}
122+
),
123+
},
124+
});
106125
}
107126
} else {
108127
this.logger.warn(
109128
`[${this.serviceName}] No handler found for event "${event}" (ID: ${id})`
110129
);
111130
// No handler found for the event
112-
this.socket.emit("response", { id, error: "Event not found" });
131+
// this.socket.emit("response", { id, error: "Event not found" });
132+
// Send a CustomError for event not found errors
133+
this.socket.emit("response", {
134+
id,
135+
response: {
136+
error: new CustomError(
137+
"EVENT_NOT_FOUND",
138+
`Event "${event}" not found`,
139+
{ event, requestID: id, serviceName: this.serviceName }
140+
),
141+
},
142+
});
113143
}
114144
});
115145

@@ -139,7 +169,7 @@ export class MicrostreamClient {
139169
// If yes, then it's a custom connection error/rejection from the hub
140170
this.logger.error(
141171
`[${this.serviceName}] Connection error to MicroStream Hub: ${customError.data?.code}:`,
142-
customError.data?.content
172+
customError.data?.message
143173
);
144174

145175
// Special cases for handling specific error codes
@@ -196,8 +226,13 @@ export class MicrostreamClient {
196226
const timeoutHandler = setTimeout(() => {
197227
// reject(new Error("Request timeout"));
198228
reject(
199-
new Error(
229+
/* new Error(
200230
`Request to ${targetService} timed out after ${this.timeout}ms`
231+
) */
232+
new CustomError(
233+
"REQUEST_TIMEOUT",
234+
`Request to ${targetService} timed out after ${this.timeout}ms`,
235+
{ targetService, event, data }
201236
)
202237
);
203238
delete this.pendingRequests[requestId]; // Clean up
@@ -208,7 +243,7 @@ export class MicrostreamClient {
208243
clearTimeout(timeoutHandler);
209244
// resolve(response);
210245
if (response.error) {
211-
reject(new Error(response.error)); // Reject if the response contains an error
246+
reject(response.error); // Reject if the response contains an error
212247
} else {
213248
resolve(response); // Resolve with the response data
214249
}

src/utils/customError.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export default class CustomError extends Error {
2+
code: string;
3+
errorData?: any;
4+
5+
constructor(code: string, message: string, errorData?: any) {
6+
super(message);
7+
this.code = code;
8+
this.errorData = errorData;
9+
this.name = "CustomError";
10+
}
11+
12+
toJSON() {
13+
return {
14+
code: this.code,
15+
message: this.message,
16+
errorData: this.errorData,
17+
};
18+
}
19+
}

0 commit comments

Comments
 (0)