Replace Promise.all with createMany to handle duplicate dates in the
data array when atomically replacing market data.
The previous implementation used multiple parallel create() operations
which caused a P2002 unique constraint violation when the data array
contained duplicate dates (e.g., when market prices are forward-filled
for non-trading days).
Changes:
- Replace Promise.all of individual create() operations with createMany()
- Add skipDuplicates: true to silently handle duplicate records
- Add data.length check to avoid empty createMany call
This maintains the atomic transaction behavior while efficiently handling
batch inserts with potential duplicates.
Replace delete-then-fetch pattern with atomic transaction to prevent data loss when manually gathering historical market data fails.
Previously, when triggering "Gather Historical Market Data" from the Admin panel, the system would immediately delete all existing market
data before queueing the fetch job. If the external data provider was down or returned an error, the asset would be left with no historical
data and the original data was permanently lost.
Changes:
- Add `replaceAllForSymbol()` method to MarketDataService that performs delete and insert within a Prisma transaction
- Remove upfront `deleteMany()` call from `gatherSymbol()` method
- Add `replaceExistingData` flag to DataGatheringItem interface to distinguish manual refresh from scheduled updates
- Update data gathering processor to use atomic replace only for manual operations while keeping normal upsert behavior for scheduled
updates
- Remove unused MarketDataService dependency from DataGatheringService
The atomic transaction ensures that if the fetch operation fails, the original market data remains untouched. Regular scheduled data gathering continues to use upsert operations and is unaffected by this change.
* Extend benchmarks in the markets overview by 50-Day and 200-Day trends
* Update changelog
---------
Co-authored-by: Thomas <4159106+dtslvr@users.noreply.github.com>