Repository navigation
Conversation
📋 PR Checklist Validation Failed
What to do:
This check ensures all PR requirements are met before merging. If you believe this check should not apply to your PR, please discuss with the team. |
🚀 Prerelease PublishedVersion: Update package.json:"@elliottech/react-native-kline-view": "0.22.0-furkando.bda3095.fix-time-aware-commands"Previous prereleases for this PR have been cleaned up. This prerelease will be automatically cleaned up when the PR is merged. |
| if (generation != containerView.optionListGeneration) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
🔴 Late option replacement drops live candle
When updateLastCandlestick appends before pending optionList work finishes, the replacement overwrites that candle. optionListGeneration tracks only option calls, so the live candle disappears on both platforms.
Learn more
Option parsing runs asynchronously, while candle commands mutate the current native array immediately. The generation check rejects an option result only when another option call supersedes it. A candle command does not change the generation, so an older snapshot can still replace modelArray after that command. Android performs the replacement in reloadOptionList, and iOS has the same replacement behavior in reloadOptionList. Timestamp checks inside the commands only protect the opposite ordering, where the replacement lands first.
Example: The native array ends at 10:00. An option snapshot ending at 10:00 starts parsing, then updateLastCandlestick appends 10:01. The pending snapshot subsequently replaces the array, removing 10:01 even though no newer option call changed the generation.
Recommended fix: Parse off-thread, but serialize dataset application and candle commands on the UI thread. Before replacing modelArray, reconcile bars added or updated since the snapshot was scheduled by timestamp. Apply the equivalent ordering or reconciliation on iOS.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Valid for Android, fixed in bda3095. A bar delivered by a live command while an option list is still being parsed is now recorded per chart and merged back by time on the UI thread when that snapshot lands (onOptionListScheduled / onOptionListApplied / mergeBar), so a late replacement can no longer remove it. Only bars delivered after the latest option list was scheduled are replayed, so bars from a previous market or timeframe are never carried into a new dataset. Not applicable on iOS: optionList is applied synchronously in the prop setter there, so there is no pending window between a command and a replacement.
| if (incomingTime > 0 && currentTime > 0 && incomingTime > currentTime) { | ||
| configManager.modelArray.add(newEntity); |
There was a problem hiding this comment.
🟡 New candles inherit stale indicators
When newer updateLastCandlestick data omits indicators, the appended model retains the previous candle’s values. Both platforms render stale overlays for the new candle.
Learn more
The existing fallback copies empty indicator lists from the current last candle because this command previously replaced that same candle. The new timestamp branch changes the operation to an append after those copies have already happened. The iOS branch follows the same sequence in updateLastCandlestick. Values derived for one candle are therefore attached to a different timestamp.
Example: The 10:00 candle has MA5 100 and RSI 45. A 10:01 update contains OHLCV but no maList or rsiList. The new 10:01 candle is appended with MA5 100 and RSI 45 instead of values for 10:01 or empty indicators.
Recommended fix: Decide whether the command will replace or append before preserving indicators. Preserve missing lists only for equal timestamps. For a newer timestamp, leave missing lists empty or calculate them from the expanded dataset on both platforms.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Valid, fixed in bda3095 on both platforms. The indicator fallback now runs only when the update is for the same bar (sameBar); a newer bar that gets appended keeps its own lists, empty if the caller sent none.
| private static final java.util.concurrent.ExecutorService OPTION_LIST_EXECUTOR = | ||
| java.util.concurrent.Executors.newSingleThreadExecutor(); |
There was a problem hiding this comment.
Agreed, fixed in bda3095. The executor is now a per-chart field on HTKLineContainerView and is shut down in onDropViewInstance, so one chart's large option list cannot delay another chart.
|
For the record: shelved. The original report was a single intermittent sighting that nobody could reproduce on the current mobile build (iOS simulator and an Android device). The impact is visual only and clears on the next timeframe, market or settings change. The branch |
Summary
Hardening for the native dataset, prompted by a report on perps-fe-mobile #2236 (native KLine, Android, return to a retained Trade tab: a candle disappeared from the canvas while its OHLC was still correct in the JS data).
Two properties of the native side make that possible:
updateLastCandlestickandaddCandlesticksAtTheEndare position-based on both platforms.updateLastCandlestickoverwrites the last native bar without comparing timestamps, so whenever the native array is behind the JS data (commands dropped while the view was detached, or a bar appended while a replacement was in flight), the first live update overwrites an older candle and every later update lands one slot off until the next full replacement.optionListon a new thread per call and swapsmodelArrayfrom that thread, while commands apply immediately on the UI thread. A command can therefore run before an earlier replacement, and two replacements can finish out of order. iOS applies the prop synchronously.Changes:
addCandlesticksAtTheEndskips bars the array already has. Replacements and commands can now arrive in either order without dropping or overwriting a candle. When the native array and the JS data agree (the normal case) behaviour is unchanged.updateLastCandlestickreloads the content size; an append call that only replaces the last bar still redraws.No JS, prop or command API change; consumers need no code change. It is native code, so it ships with a new binary, not OTA.
Linear ticket: PRO-4970
Validation
swiftc -parse; the two Java files show no syntax errors underjavac(only missing React Native dependency symbols, as expected outside a Gradle build).Author Checklist