-
Notifications
You must be signed in to change notification settings - Fork 31
Live price fetcher RPC #620
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
base: main
Are you sure you want to change the base?
Conversation
🤖 Claude AI Code ReviewLast reviewed on: 14:23:47 SummaryThis PR introduces a client-server RPC architecture for the LivePriceFetcher service, moves several manager components to daemon processes, implements a sync coordination mechanism using shared memory flags, adds message cooldown to Slack notifications, and enhances health monitoring. The changes aim to improve process isolation, prevent data corruption during sync operations, and reduce notification spam. ✅ Strengths
|
6aef91b to
27cfc21
Compare
jbonilla-tao
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One open question i have is if we should allow consumers to use live price fetcher directly as it was before if they are only making REST requests (perf ledger manager, emissions ledger manager, backtest manager) and then for consumers like validator.py (order fill), mdd checker and limit orders manager, we have them use RPC
3678600 to
3d27793
Compare
| self.contract_manager = contract_manager | ||
| self.cached_miner_account_sizes = {} # Deepcopy of contract_manager.miner_account_sizes | ||
| self.cache_last_refreshed_date = None # 'YYYY-MM-DD' format, refresh daily | ||
| self.pds = live_price_fetcher.polygon_data_service if live_price_fetcher else None # Load it later once the process starts so ipc works. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ward-taoshi why do we need this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RPC client couldn't directly reference objects, so the methods used through polygon had to be wrapped as a pass method.
161e8ef to
76a6ff0
Compare
- Update PositionLocks to use ipc_manager for cross-process synchronization - Add run_update_loop to MDDChecker for daemon process execution - Pass position_locks to MDDChecker via constructor - Start MDD checker as separate process in validator initialization - Remove mdd_check call from main validator loop - Add MDD checker process to graceful shutdown sequence This refactor prevents the MDD checker from blocking the main validator loop while maintaining proper lock synchronization across processes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Update EliminationManager.__init__ to accept position_locks parameter - Add run_update_loop to EliminationManager for daemon process execution - Set position_locks on elimination_manager after creation in validator - Start elimination manager as separate process in validator initialization - Remove process_eliminations call from main validator loop - Add elimination manager process to graceful shutdown sequence - Renumber initialization steps from 11 to 12 This refactor prevents the elimination manager from blocking the main validator loop while maintaining proper lock synchronization across processes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Similar to MDDChecker and EliminationManager, move ChallengePeriodManager to run in its own process to prevent blocking the main validator loop. Changes: - Added shutdown_dict parameter to ChallengePeriodManager.__init__ - Updated refresh() to accept optional current_time parameter with default using TimeUtil.now_in_millis() - Added run_update_loop() method with setproctitle, 1-second sleep, and error handling - Started challengeperiod_manager_process as daemon Process in validator - Removed challengeperiod_manager.refresh() call from main loop - Added challengeperiod_manager_process.join() to shutdown sequence - Renumbered initialization steps from 12 to 13 This improves validator performance by preventing blocking operations during challenge period evaluations. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Implement comprehensive synchronization mechanism for daemon processes: 1. sync_in_progress flag (IPC Value): - Blocks new iterations from starting when auto sync runs - Set BEFORE epoch increment to prevent race condition 2. sync_epoch counter (IPC Value): - Incremented each time auto sync runs - Managers capture at START of iteration - Validated BEFORE save to detect stale data - If epoch changed, abort save to prevent corruption 3. Deadlock prevention: - Wrapped all operations in try/finally - Guarantees sync_in_progress flag is always cleared Updated components: - PositionSyncer: Set flag then increment epoch, with try/finally - MDDChecker: Check flag and validate epoch before save - EliminationManager: Check flag and validate epoch before save - ChallengePeriodManager: Check flag and validate epoch before save - All managers: Added Slack error notifications This replaces threading-based signal_sync_lock/condition which don't work across processes. Two-phase protection (flag + epoch) ensures data integrity by preventing both new iterations from starting AND invalidating in-flight iterations that could write stale data. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Refactored daemon classes to be nested within their respective parent classes: Changes to live_price_fetcher.py: - Added LivePriceFetcherClient.HealthChecker as nested class - Daemon monitors LivePriceFetcher server health every 60 seconds - Includes Slack error logging and graceful shutdown handling Changes to price_slippage_model.py: - Added PriceSlippageModel.FeatureRefresher as nested class - Daemon refreshes daily slippage features every 10 minutes - Added `import time` for sleep() calls - Includes Slack error logging and graceful shutdown handling Changes to validator.py: - Updated to use LivePriceFetcherClient.HealthChecker instead of standalone class - Updated to use PriceSlippageModel.FeatureRefresher instead of standalone class - Removed import of deleted health_checker module Benefits: - Better encapsulation - daemons are co-located with their parent classes - Clearer code organization and ownership - No standalone health_checker.py module needed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Remove is_alive() check from health_check() method to fix "can only test a child process" error. The RPC health check is sufficient to detect server failures. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Add message_cooldown_seconds (default 5 minutes) - Track last send time per message type (based on first line) - Suppress duplicate messages within cooldown period - Add bypass_cooldown parameter for critical messages - Log suppressed messages at debug level 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Issue #2: Remove is_alive() checks from LivePriceFetcher._start_server() - Removed all is_alive() checks that would crash when called from HealthChecker daemon - Use terminate() and kill() directly (safe to call on dead processes) - Rely on connect() to verify server is working instead of process checks - Simplified startup logic with 2s wait + connection attempt Issue #4: Move timestamp update inside lock in auto_sync.py - Moved last_signal_sync_time_ms update into finally block inside lock - Prevents race condition where second sync starts before timestamp updates - Ensures timestamp is always updated even if sync fails Issue #5: Remove unused shutdown_dict logic from daemons - Removed shutdown_dict parameter from HealthChecker.__init__() - Removed shutdown_dict parameter from FeatureRefresher.__init__() - Changed while loops from "while not self.shutdown_dict" to "while True" - Daemons run indefinitely and terminate when main process exits (daemon=True) - Updated validator.py to not pass shutdown_dict to daemon initializations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
c1011bd to
9377d82
Compare
Taoshi Pull Request
Description
[Provide a brief description of the changes introduced by this pull request.]
Related Issues (JIRA)
[Reference any related issues or tasks that this pull request addresses or closes.]
Checklist
Reviewer Instructions
[Provide any specific instructions or areas you would like the reviewer to focus on.]
Definition of Done
Checklist (for the reviewer)
Optional: Deploy Notes
[Any instructions or notes related to deployment, if applicable.]
/cc @mention_reviewer