application.event_handlers.portfolio_event_handler¶
src.application.event_handlers.portfolio_event_handler
¶
Portfolio event handler for net worth calculation.
Reacts to balance and holdings changes, recalculates net worth, and emits PortfolioNetWorthRecalculated events.
Architecture
- Application layer (coordination/aggregation logic)
- App-scoped singleton (created once at startup)
- Subscribes to AccountBalanceUpdated and AccountHoldingsUpdated
- Emits PortfolioNetWorthRecalculated when net worth changes
Pattern
This is a REACTIVE AGGREGATION handler: 1. Listens to AccountBalanceUpdated and AccountHoldingsUpdated 2. Queries repository to calculate current net worth 3. Compares with cached previous value 4. Emits PortfolioNetWorthRecalculated if changed
Reference
- docs/architecture/domain-events-architecture.md
- Implementation Plan: Issue #257, Phase 6
Classes¶
PortfolioEventHandler
¶
Event handler for portfolio net worth calculation.
Reacts to balance/holdings changes and emits net worth events. Follows same pattern as LoggingEventHandler, AuditEventHandler.
App-scoped singleton, subscribed at container startup.
Creates database sessions on-demand (same pattern as AuditEventHandler). Gets session from event_bus context when handling events.
Attributes:
| Name | Type | Description |
|---|---|---|
_database |
Database instance for creating sessions. |
|
_cache |
For storing previous net worth values. |
|
_event_bus |
For publishing PortfolioNetWorthRecalculated and getting sessions. |
|
_logger |
For structured logging. |
Example
Container creates and subscribes at startup¶
handler = PortfolioEventHandler( ... database=get_database(), ... cache=get_cache(), ... event_bus=get_event_bus(), ... logger=get_logger(), ... ) event_bus.subscribe(AccountBalanceUpdated, handler.handle_balance_updated) event_bus.subscribe(AccountHoldingsUpdated, handler.handle_holdings_updated)
Source code in src/application/event_handlers/portfolio_event_handler.py
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | |
Functions¶
__init__
¶
__init__(
database: Database,
cache: CacheProtocol,
event_bus: EventBusProtocol,
logger: LoggerProtocol,
) -> None
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
database
|
Database
|
Database instance for creating sessions on-demand. |
required |
cache
|
CacheProtocol
|
Cache for storing previous net worth values. |
required |
event_bus
|
EventBusProtocol
|
Event bus for publishing derived events and getting session context. |
required |
logger
|
LoggerProtocol
|
Logger protocol implementation from container. |
required |
Source code in src/application/event_handlers/portfolio_event_handler.py
handle_balance_updated
async
¶
React to balance change, recalculate net worth.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AccountBalanceUpdated
|
AccountBalanceUpdated event with user_id. |
required |
Source code in src/application/event_handlers/portfolio_event_handler.py
handle_holdings_updated
async
¶
React to holdings change, recalculate net worth.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
AccountHoldingsUpdated
|
AccountHoldingsUpdated event with user_id. |
required |