@@ -84,6 +84,17 @@ public override void OnAdd(IQuote item, bool notify, int? indexHint)
8484 {
8585 ArgumentNullException . ThrowIfNull ( item ) ;
8686
87+ // Reject additions that precede the current cache timeline
88+ // (applies to both standalone and non-standalone QuoteHub)
89+ lock ( CacheLock )
90+ {
91+ if ( Cache . Count > 0 && item . Timestamp < Cache [ 0 ] . Timestamp )
92+ {
93+ // Silently ignore - this prevents indeterminate gaps in the timeline
94+ return ;
95+ }
96+ }
97+
8798 // for non-standalone QuoteHub, use standard behavior (which handles locking)
8899 if ( ! _isStandalone )
89100 {
@@ -94,9 +105,19 @@ public override void OnAdd(IQuote item, bool notify, int? indexHint)
94105 // Lock for standalone QuoteHub operations
95106 lock ( CacheLock )
96107 {
108+
97109 // get result and position
98110 ( IQuote result , int index ) = ToIndicator ( item , indexHint ) ;
99111
112+ // Reject modifications that would affect indices before MinCacheSize
113+ // to prevent corrupted rebuilds in subscribers
114+ // This includes both insertions and same-timestamp replacements
115+ if ( index >= 0 && index < MinCacheSize && index < Cache . Count )
116+ {
117+ // Silently ignore all modifications before MinCacheSize
118+ return ;
119+ }
120+
100121 // check if this is a same-timestamp update (not a new item at the end)
101122 if ( Cache . Count > 0 && index < Cache . Count && Cache [ index ] . Timestamp == result . Timestamp )
102123 {
@@ -119,6 +140,23 @@ public override void OnAdd(IQuote item, bool notify, int? indexHint)
119140 }
120141 else
121142 {
143+ // if out-of-order insert, insert and trigger rebuild
144+ if ( index >= 0 && index < Cache . Count )
145+ {
146+ Cache . Insert ( index , result ) ;
147+
148+ // For standalone QuoteHub, notify observers to rebuild from this timestamp
149+ // For non-standalone, this won't be reached due to earlier branch
150+ if ( notify )
151+ {
152+ // Notify observers directly - they will rebuild from the updated cache
153+ // No need to call Rebuild on QuoteHub itself since cache is already updated
154+ NotifyObserversOnRebuild ( result . Timestamp ) ;
155+ }
156+
157+ return ;
158+ }
159+
122160 // standard add behavior for new items
123161 AppendCache ( result , notify ) ;
124162 }
0 commit comments