Skip to content

Error Handling and Resilience

levi edited this page Nov 6, 2025 · 2 revisions

Error Handling and Resilience

Table of Contents

  1. Introduction
  2. Error Handling in Datafeed Implementation
  3. Propagating Errors Through TVBridge
  4. Using TVEventBus for Error Event Emission
  5. Handling Network Failures and Authentication Errors
  6. Strategies for Automatic Reconnection and Exponential Backoff
  7. Health Monitoring and Stale Stream Detection
  8. Preventing Memory Leaks and Resource Cleanup
  9. Conclusion

Introduction

This document provides a comprehensive guide on implementing robust error handling and fault tolerance in custom datafeeds for the PyTradingView framework. It covers best practices for catching and propagating errors through the TVBridge, ensuring graceful degradation in the UI. The guide also details how to use the TVEventBus to emit error events that can be captured by indicators or logging systems. Strategies for handling network failures, authentication errors, and malformed responses from upstream data sources are discussed, along with techniques for automatic reconnection, exponential backoff, and health monitoring. Additionally, the document addresses data integrity validation, stale stream detection, deserialization error recovery, memory leak prevention, and proper cleanup of subscription resources.

Error Handling in Datafeed Implementation

The TVDatafeed class serves as the base implementation for custom datafeeds, providing a framework for handling errors in data retrieval operations. Each method in the datafeed API includes error callback parameters that should be invoked when an error occurs. For example, the resolveSymbol method accepts an onError callback of type TVDatafeedErrorCallback, which is called when symbol resolution fails. Similarly, the getBars method includes an onError parameter to handle errors during historical data retrieval.

In the BADatafeed implementation, error handling is demonstrated through try-except blocks that catch exceptions during symbol resolution and bar data retrieval. When an error occurs, it is logged using the logger.error method, and the onError callback is invoked with a string representation of the error. This ensures that errors are both logged for debugging purposes and propagated to the client application for appropriate handling.

flowchart TD
Start([Start Operation]) --> ValidateInput["Validate Input Parameters"]
ValidateInput --> InputValid{"Input Valid?"}
InputValid --> |No| HandleError["Invoke onError Callback"]
InputValid --> |Yes| ExecuteOperation["Execute Data Retrieval"]
ExecuteOperation --> OperationSuccess{"Operation Successful?"}
OperationSuccess --> |No| LogError["Log Error and Invoke onError"]
OperationSuccess --> |Yes| ReturnSuccess["Invoke onResult Callback"]
HandleError --> End([End])
LogError --> End
ReturnSuccess --> End
Loading

Propagating Errors Through TVBridge

The TVBridge class acts as a communication layer between the Python backend and the JavaScript frontend, facilitating the propagation of errors from the datafeed to the UI. When an error occurs in the datafeed, it is propagated through the TVBridge, which can then trigger appropriate UI responses to ensure graceful degradation.

The TVBridge class includes methods for handling RPC calls from the web frontend, such as _handle_web_to_python_call, which processes incoming requests and routes them to the appropriate handlers. If an error occurs during the execution of a remote call, it is caught and returned as part of the response, ensuring that the frontend is aware of the failure. The call_node_server method also includes error handling to manage failures when communicating with the Node server, logging exceptions and returning error responses.

sequenceDiagram
participant Frontend as "Web Frontend"
participant TVBridge as "TVBridge"
participant Datafeed as "Custom Datafeed"
Frontend->>TVBridge : RPC Request
TVBridge->>Datafeed : Execute Operation
Datafeed-->>TVBridge : Error Occurs
TVBridge->>TVBridge : Log Error and Prepare Response
TVBridge-->>Frontend : Error Response
Frontend->>Frontend : Handle Error Gracefully
Loading

Using TVEventBus for Error Event Emission

The TVEventBus class provides a publish-subscribe mechanism for emitting and handling events across different components of the application. It can be used to emit error events that can be captured by indicators or logging systems, enabling centralized error handling and monitoring.

The EventBus class is implemented as a singleton, ensuring that all components subscribe to and publish events through a single instance. Events are defined using the EventType enum, which includes predefined event types such as BRIDGE_CONNECTED and CHART_READY. Custom error events can be defined and emitted using the publish method, which asynchronously notifies all subscribers of the event. The publish_sync method is also available for use in synchronous contexts.

classDiagram
class EventBus {
+get_instance() EventBus
+subscribe(event_type, callback) void
+unsubscribe(event_type, callback) void
+publish(event_type, data, source) void
+publish_sync(event_type, data, source) void
}
class Event {
+type : EventType
+data : Dict[str, Any]
+source : Optional[str]
}
class EventType {
+WIDGET_CREATED : str
+WIDGET_READY : str
+BRIDGE_CONNECTED : str
+BRIDGE_DISCONNECTED : str
}
EventBus --> Event : emits
Event --> EventType : has type
Loading

Handling Network Failures and Authentication Errors

Network failures and authentication errors are common issues when interacting with upstream data sources. The TVBridge class includes mechanisms for handling these errors, particularly in the connect_to_node_server method, which attempts to establish a connection to the Node server with exponential backoff and retry logic.

The connect_to_node_server method uses a loop to retry the connection attempt up to a specified number of times, with a delay that increases exponentially between attempts. This approach helps to avoid overwhelming the server with repeated requests and allows time for transient network issues to resolve. If the connection fails after all retries, an error is logged, and the method returns False, indicating that the connection was not established.

flowchart TD
Start([Start Connection]) --> AttemptConnection["Attempt Connection"]
AttemptConnection --> ConnectionSuccess{"Connection Successful?"}
ConnectionSuccess --> |Yes| ReturnSuccess["Return True"]
ConnectionSuccess --> |No| CheckRetries{"Max Retries Reached?"}
CheckRetries --> |No| CalculateDelay["Calculate Exponential Backoff Delay"]
CalculateDelay --> Wait["Wait for Delay Period"]
Wait --> AttemptConnection
CheckRetries --> |Yes| LogError["Log Connection Failure"]
LogError --> ReturnFailure["Return False"]
ReturnSuccess --> End([End])
ReturnFailure --> End
Loading

Strategies for Automatic Reconnection and Exponential Backoff

Automatic reconnection and exponential backoff are essential strategies for maintaining resilience in the face of network instability. The connect_to_node_server method in the TVBridge class implements these strategies to ensure that the application can recover from temporary network outages.

The method uses a loop to attempt the connection multiple times, with a delay between attempts that increases exponentially. The delay is calculated using the formula min(base_delay * (2 ** min(retry, 5)), 5.0), which ensures that the delay does not grow too large. This approach balances the need to avoid overwhelming the server with the need to give the network time to recover.

sequenceDiagram
participant TVBridge as "TVBridge"
participant NodeServer as "Node Server"
TVBridge->>NodeServer : Connect Request
NodeServer-->>TVBridge : Connection Failed
TVBridge->>TVBridge : Wait 0.1s
TVBridge->>NodeServer : Connect Request
NodeServer-->>TVBridge : Connection Failed
TVBridge->>TVBridge : Wait 0.2s
TVBridge->>NodeServer : Connect Request
NodeServer-->>TVBridge : Connection Failed
TVBridge->>TVBridge : Wait 0.4s
TVBridge->>NodeServer : Connect Request
NodeServer-->>TVBridge : Connection Successful
Loading

Health Monitoring and Stale Stream Detection

Health monitoring and stale stream detection are critical for ensuring the reliability of datafeeds. While the provided code does not include explicit health monitoring mechanisms, the TVEventBus can be leveraged to implement such functionality by emitting periodic health check events and monitoring the responsiveness of data sources.

Stale stream detection can be implemented by tracking the timestamp of the last received data update and comparing it to the current time. If the difference exceeds a predefined threshold, the stream can be considered stale, and appropriate actions can be taken, such as reconnecting or alerting the user.

flowchart TD
Start([Start Monitoring]) --> GetLastUpdate["Get Last Update Time"]
GetLastUpdate --> CalculateAge["Calculate Time Since Last Update"]
CalculateAge --> IsStale{"Time Since Last Update > Threshold?"}
IsStale --> |Yes| HandleStale["Handle Stale Stream"]
IsStale --> |No| Wait["Wait for Next Check"]
Wait --> GetLastUpdate
HandleStale --> End([End])
Loading

Preventing Memory Leaks and Resource Cleanup

Preventing memory leaks and ensuring proper resource cleanup are essential for maintaining the stability of long-running applications. The TVSubscribeManager class includes mechanisms for managing event subscriptions and ensuring that resources are properly cleaned up when they are no longer needed.

The publish_async method in TVSubscribeManager adds tasks to a set of cleanup tasks, which are automatically removed when the tasks are completed. This ensures that completed tasks do not accumulate and consume memory. The unsubscribe method allows subscribers to remove themselves from the event handlers, preventing memory leaks caused by dangling references.

classDiagram
class TVSubscribeManager {
+subscribe(event_name, handler) void
+subscribe_async(event_name, handler) void
+publish(event_name, args) void
+publish_async(event_name, args) void
+unsubscribe(event_name, handler) void
}
class TVSubscribePublisher {
+setSymbol(symbol) void
}
class TVSubscribeListener {
+dispose() void
}
TVSubscribeManager --> TVSubscribePublisher : manages
TVSubscribeManager --> TVSubscribeListener : manages
TVSubscribeListener --> TVSubscribeManager : unsubscribes
Loading

Conclusion

Implementing robust error handling and fault tolerance in custom datafeeds is essential for ensuring a reliable and user-friendly experience in the PyTradingView framework. By leveraging the TVDatafeed base class, propagating errors through the TVBridge, and using the TVEventBus for event emission, developers can create resilient applications that gracefully handle errors and maintain stability in the face of network failures and other issues. Strategies such as automatic reconnection, exponential backoff, and proper resource cleanup further enhance the reliability of the system, ensuring that it can recover from transient issues and continue to provide accurate data to users.

Clone this wiki locally