diff --git a/src/common/persistence/persistence.service.ts b/src/common/persistence/persistence.service.ts index 64061323d..3ea8bfe86 100644 --- a/src/common/persistence/persistence.service.ts +++ b/src/common/persistence/persistence.service.ts @@ -153,6 +153,10 @@ export class PersistenceService { return await this.execute(this.saveTags.name, this.tagsRepository.saveTags(tags)); } + async saveTagsOrIgnore(tags: TagEntity[]): Promise { + await this.execute(this.saveTagsOrIgnore.name, this.tagsRepository.saveTagsOrIgnore(tags)); + } + async getCollectionStats( identifier: string, marketplaceKey: string = undefined, @@ -456,6 +460,13 @@ export class PersistenceService { return await this.execute(this.getLastOrdersByAuctionIds.name, this.ordersRepository.getLastOrdersByAuctionIds(auctionIds)); } + async getOrdersByAuctionIdsGroupByAuctionId(auctionIds: number[]): Promise { + return await this.execute( + this.getOrdersByAuctionIdsGroupByAuctionId.name, + this.ordersRepository.getOrdersByAuctionIdsGroupByAuctionId(auctionIds), + ); + } + async getOrdersByAuctionIds(auctionIds: number[]): Promise { return await this.execute(this.getOrdersByAuctionIds.name, this.ordersRepository.getOrdersByAuctionIds(auctionIds)); } @@ -468,8 +479,8 @@ export class PersistenceService { return await this.execute(this.saveOrder.name, this.ordersRepository.saveOrder(order)); } - async saveBulkOrders(orders: OrderEntity[]) { - return await this.execute(this.saveBulkOrders.name, this.ordersRepository.saveBulkOrders(orders)); + async saveBulkOrdersOrUpdateAndFillId(orders: OrderEntity[]) { + return await this.execute(this.saveBulkOrdersOrUpdateAndFillId.name, this.ordersRepository.saveBulkOrdersOrUpdateAndFillId(orders)); } async updateOrderWithStatus(order: OrderEntity, status: OrderStatusEnum) { @@ -640,8 +651,11 @@ export class PersistenceService { return await this.execute(this.insertAuction.name, this.auctionsRepository.insertAuction(auction)); } - async saveBulkAuctions(auctions: AuctionEntity[]): Promise { - return await this.execute(this.saveBulkAuctions.name, this.auctionsRepository.saveBulkAuctions(auctions)); + async saveBulkAuctionsOrUpdateAndFillId(auctions: AuctionEntity[]): Promise { + return await this.execute( + this.saveBulkAuctionsOrUpdateAndFillId.name, + this.auctionsRepository.saveBulkAuctionsOrUpdateAndFillId(auctions), + ); } async rollbackAuctionAndOrdersByHash(blockHash: string): Promise { @@ -701,8 +715,8 @@ export class PersistenceService { return await this.execute(this.saveOffer.name, this.offersRepository.saveOffer(offer)); } - async saveBulkOffers(offers: OfferEntity[]): Promise { - return await this.execute(this.saveBulkOffers.name, this.offersRepository.saveBulkOffers(offers)); + async saveBulkOffersOrUpdateAndFillId(offers: OfferEntity[]): Promise { + return await this.execute(this.saveBulkOffersOrUpdateAndFillId.name, this.offersRepository.saveBulkOffersOrUpdateAndFillId(offers)); } async getOffersThatReachedDeadline(): Promise { diff --git a/src/config/default.json b/src/config/default.json index caaf03bfa..972b09535 100644 --- a/src/config/default.json +++ b/src/config/default.json @@ -76,7 +76,8 @@ "defaultPageOffset": 0, "defaultPageSize": 10, "dbMaxDenominatedValue": 99999999999999999, - "dbMaxTagLength": 20 + "dbMaxTagLength": 20, + "marketplaceReindexDataMaxInMemoryItems": 25000 }, "elasticDictionary": { "scamInfo": { diff --git a/src/modules/marketplaces/marketplaces-reindex-events-summary.service.ts b/src/modules/marketplaces/marketplaces-reindex-events-summary.service.ts index 9afba12dc..51057d11e 100644 --- a/src/modules/marketplaces/marketplaces-reindex-events-summary.service.ts +++ b/src/modules/marketplaces/marketplaces-reindex-events-summary.service.ts @@ -40,13 +40,15 @@ export class MarketplacesReindexEventsSummaryService { }); const tx = eventsSet[0].isTx ? eventsSet[0] : undefined; + const eventsStartIdx = tx ? 1 : 0; + + const txData = tx?.data?.txData; + if (eventsOrderedByOrderAsc.length === 1 && tx) { - return [undefined, undefined]; + return [undefined, txData]; } - const eventsStartIdx = tx ? 1 : 0; - - return [eventsOrderedByOrderAsc.slice(eventsStartIdx), tx?.data?.txData]; + return [eventsOrderedByOrderAsc.slice(eventsStartIdx), txData]; } private getEventSummary(event: MarketplaceEventsEntity, txData: MarketplaceTransactionData, marketplace: Marketplace): any { diff --git a/src/modules/marketplaces/marketplaces-reindex.service.ts b/src/modules/marketplaces/marketplaces-reindex.service.ts index 7ec907d54..8acd478e1 100644 --- a/src/modules/marketplaces/marketplaces-reindex.service.ts +++ b/src/modules/marketplaces/marketplaces-reindex.service.ts @@ -28,6 +28,7 @@ import { DateUtils } from 'src/utils/date-utils'; import { Locker } from '@multiversx/sdk-nestjs-common'; import { TagEntity } from 'src/db/auctions/tags.entity'; import { MarketplaceTypeEnum } from './models/MarketplaceType.enum'; +import { OrdersService } from '../orders/order.service'; import { Token } from '../usdPrice/Token.model'; @Injectable() @@ -37,6 +38,7 @@ export class MarketplacesReindexService { private readonly marketplacesService: MarketplacesService, private readonly usdPriceService: UsdPriceService, private readonly auctionSetterService: AuctionsSetterService, + private readonly ordersService: OrdersService, private readonly marketplacesReindexEventsSummaryService: MarketplacesReindexEventsSummaryService, private readonly reindexAuctionStartedHandler: ReindexAuctionStartedHandler, private readonly reindexAuctionBidHandler: ReindexAuctionBidHandler, @@ -60,16 +62,7 @@ export class MarketplacesReindexService { try { let marketplaceReindexStates: MarketplaceReindexState[] = await this.getInitialMarketplaceReindexStates(input); - await this.processMarketplaceEventsInBatches(marketplaceReindexStates, input); - - marketplaceReindexStates.map((s) => - s.setStateItemsToExpiredIfOlderThanTimestamp(input.beforeTimestamp ?? DateUtils.getCurrentTimestamp()), - ); - - for (let state of marketplaceReindexStates) { - await this.populateAuctionAssetTags(state.auctions); - await this.addMarketplaceStateToDb(state); - } + await this.processMarketplaceEventsInBatchesAndAddToDb(marketplaceReindexStates, input); this.logger.log(`Reindexing marketplace data/state for ${input.marketplaceAddress} ended`); } catch (error) { @@ -115,7 +108,7 @@ export class MarketplacesReindexService { return marketplaceReindexStates; } - private async processMarketplaceEventsInBatches( + private async processMarketplaceEventsInBatchesAndAddToDb( marketplaceReindexStates: MarketplaceReindexState[], input: MarketplaceReindexDataArgs, ): Promise { @@ -154,6 +147,8 @@ export class MarketplacesReindexService { isFinalBatch, ); + await this.addInactiveStateItemsToDb(marketplaceReindexStates, isFinalBatch); + if (processInNextBatch.length > 0) { this.logger.warn(`Could not handle ${processInNextBatch.length} events`); } @@ -216,12 +211,8 @@ export class MarketplacesReindexService { eventOrdersAndTx, ); - if (!marketplaceReindexStates[0].isFullStateInMemory) { - await Promise.all( - marketplaceReindexStates.map((state) => { - return this.getStateFromDbIfMissing(state, eventsSetSummaries); - }), - ); + for (const state of marketplaceReindexStates) { + await this.getStateFromDbIfMissing(state, eventsSetSummaries); } const areMultipleMarketplaces = marketplaceReindexStates.length !== 1; @@ -244,15 +235,19 @@ export class MarketplacesReindexService { } private async getStateFromDbIfMissing(marketplaceReindexState: MarketplaceReindexState, eventsSetSummaries: any[]): Promise { - const [missingAuctionIds, missingOfferIds, missingStateForIdentifiers] = this.getMissingStateIds( + if (marketplaceReindexState.isFullStateInMemory) { + return; + } + + const [missingMarketplaceAuctionsIds, missingMarketplaceOffersIds, missingStateForIdentifiers] = this.getMissingStateIds( marketplaceReindexState, eventsSetSummaries, ); let auctions: AuctionEntity[]; - if (missingAuctionIds.length > 0) { + if (missingMarketplaceAuctionsIds.length > 0) { auctions = await this.persistenceService.getBulkAuctionsByAuctionIdsAndMarketplace( - missingAuctionIds, + missingMarketplaceAuctionsIds, marketplaceReindexState.marketplace.key, ); } else if (missingStateForIdentifiers.length > 0) { @@ -262,14 +257,21 @@ export class MarketplacesReindexService { ); } - const auctionIds = auctions?.map((a) => a.id); + const missingAuctionsIds = auctions?.map((a) => a.id); + const [orders, offers] = await Promise.all([ - auctionIds?.length > 0 ? this.persistenceService.getOrdersByAuctionIds(auctionIds) : [], - missingOfferIds?.length > 0 - ? this.persistenceService.getBulkOffersByOfferIdsAndMarketplace(missingOfferIds, marketplaceReindexState.marketplace.key) + missingAuctionsIds?.length > 0 ? this.ordersService.getOrdersByAuctionIds(missingAuctionsIds) : [], + missingMarketplaceOffersIds?.length > 0 + ? this.persistenceService.getBulkOffersByOfferIdsAndMarketplace( + missingMarketplaceOffersIds, + marketplaceReindexState.marketplace.key, + ) : [], ]); + if (auctions?.length > 0) { + marketplaceReindexState.auctions = marketplaceReindexState.auctions.concat(auctions); + } if (orders?.length > 0) { marketplaceReindexState.orders = marketplaceReindexState.orders.concat(orders); } @@ -288,7 +290,11 @@ export class MarketplacesReindexService { continue; } - if (eventsSetSummaries[i].auctionId && eventsSetSummaries[i].action !== AssetActionEnum.StartedAuction) { + if ( + eventsSetSummaries[i].auctionId && + eventsSetSummaries[i].action !== AssetActionEnum.StartedAuction && + eventsSetSummaries[i].action !== AssetOfferEnum.Created + ) { const auctionIndex = marketplaceReindexState.marketplace.key !== ELRONDNFTSWAP_KEY ? marketplaceReindexState.getAuctionIndexByAuctionId(eventsSetSummaries[i].auctionId) @@ -346,7 +352,7 @@ export class MarketplacesReindexService { break; } case AssetActionEnum.Updated: { - const paymentToken = await this.usdPriceService.getToken(eventsSetSummary.paymentToken); + const [paymentToken] = await this.getPaymentTokenAndNonce(marketplaceReindexState, eventsSetSummary); this.reindexAuctionUpdatedHandler.handle(marketplaceReindexState, eventsSetSummary, paymentToken.decimals); break; } @@ -409,102 +415,105 @@ export class MarketplacesReindexService { } } - private async addInactiveStateItemsToDb(marketplaceReindexStates: MarketplaceReindexState[]): Promise { - for (const marketplaceReindexState of marketplaceReindexStates) { - marketplaceReindexState.setStateItemsToExpiredIfOlderThanTimestamp(DateUtils.getCurrentTimestamp()); + private async addInactiveStateItemsToDb(marketplaceReindexStates: MarketplaceReindexState[], isFinalBatch?: boolean): Promise { + try { + for (const marketplaceReindexState of marketplaceReindexStates) { + marketplaceReindexState.setStateItemsToExpiredIfOlderThanTimestamp(DateUtils.getCurrentTimestamp()); - const [inactiveAuctions, inactiveOrders, inactiveOffers] = marketplaceReindexState.popInactiveItems(); + let [inactiveAuctions, inactiveOrders, inactiveOffers] = isFinalBatch + ? marketplaceReindexState.popAllItems() + : marketplaceReindexState.popInactiveItems(); - await this.populateAuctionAssetTags(inactiveAuctions); + if (inactiveAuctions.length === 0 && inactiveOffers.length === 0) { + continue; + } - for (let i = 0; i < inactiveOrders.length; i++) { - inactiveOrders[i].auctionId = inactiveAuctions.findIndex((a) => a.id === inactiveOrders[i].auctionId); - delete inactiveOrders[i].id; - } + marketplaceReindexState.isFullStateInMemory = false; - for (let i = 0; i < inactiveAuctions.length; i++) { - delete inactiveAuctions[i].id; - } + await this.populateAuctionMissingAssetTags(inactiveAuctions); - await this.auctionSetterService.saveBulkAuctions(inactiveAuctions); - - let tags: TagEntity[] = []; - inactiveAuctions.map((auction) => { - const assetTags = auction.tags.split(','); - assetTags.map((assetTag) => { - if (assetTag !== '') { - tags.push( - new TagEntity({ - auctionId: auction.id, - tag: assetTag.trim().slice(0, constants.dbMaxTagLength), - auction: auction, - }), - ); + for (let i = 0; i < inactiveOrders.length; i++) { + if (inactiveOrders[i].auctionId < 0) { + const auctionIndex = inactiveAuctions.findIndex((a) => a.id === inactiveOrders[i].auctionId); + if (auctionIndex !== -1) { + inactiveOrders[i].auctionId = -inactiveAuctions[auctionIndex].marketplaceAuctionId; + } else { + this.logger.warn(`Corresponding auction not found`); + } } - }); - }); - const saveTagsPromise = this.persistenceService.saveTags(tags); + if (inactiveOrders[i].id < 0) { + delete inactiveOrders[i].id; + } + } - for (let i = 0; i < inactiveOrders.length; i++) { - inactiveOrders[i].auction = inactiveAuctions[inactiveOrders[i].auctionId]; - inactiveOrders[i].auctionId = inactiveAuctions[inactiveOrders[i].auctionId].id; - } - inactiveOffers.map((o) => delete o.id); + for (let i = 0; i < inactiveAuctions.length; i++) { + if (inactiveAuctions[i].id < 0) { + delete inactiveAuctions[i].id; + } + } - await Promise.all([ - saveTagsPromise, - this.persistenceService.saveBulkOrders(inactiveOrders), - this.persistenceService.saveBulkOffers(inactiveOffers), - ]); - } - } + await this.auctionSetterService.saveBulkAuctionsOrUpdateAndFillId(inactiveAuctions); + + let tags: TagEntity[] = []; + inactiveAuctions.map((auction) => { + const assetTags = auction.tags.split(','); + assetTags.map((assetTag) => { + if (assetTag !== '') { + tags.push( + new TagEntity({ + auctionId: auction.id, + tag: assetTag.trim().slice(0, constants.dbMaxTagLength), + auction: auction, + }), + ); + } + }); + }); - private async addMarketplaceStateToDb(marketplaceReindexState: MarketplaceReindexState): Promise { - marketplaceReindexState.auctions.map((a) => { - delete a.id; - }); - marketplaceReindexState.orders.map((o) => delete o.id); - marketplaceReindexState.offers.map((o) => delete o.id); + const saveTagsPromise = this.persistenceService.saveTagsOrIgnore(tags); + + for (let i = 0; i < inactiveOrders.length; i++) { + if (inactiveOrders[i].auctionId < 0) { + const auctionIndex = inactiveAuctions.findIndex((a) => a.marketplaceAuctionId === -inactiveOrders[i].auctionId); + if (auctionIndex === -1) { + this.logger.warn( + `Auction for ${marketplaceReindexState.marketplace.key} with marketplaceAuctionId ${-inactiveOrders[i] + .auctionId} was not found`, + ); + inactiveOrders.splice(i--, 1); + continue; + } + inactiveOrders[i].auction = inactiveAuctions[auctionIndex]; + inactiveOrders[i].auctionId = inactiveAuctions[auctionIndex].id; + } + } - await this.auctionSetterService.saveBulkAuctions(marketplaceReindexState.auctions); + inactiveOffers.map((o) => { + if (o.id < 0) { + delete o.id; + } + }); - for (let i = 0; i < marketplaceReindexState.orders.length; i++) { - marketplaceReindexState.orders[i].auction = marketplaceReindexState.auctions[marketplaceReindexState.orders[i].auctionId]; - marketplaceReindexState.orders[i].auctionId = marketplaceReindexState.auctions[marketplaceReindexState.orders[i].auctionId].id; + await Promise.all([ + saveTagsPromise, + this.persistenceService.saveBulkOrdersOrUpdateAndFillId(inactiveOrders), + this.persistenceService.saveBulkOffersOrUpdateAndFillId(inactiveOffers), + ]); + } + } catch (error) { + throw error; } - - let tags: TagEntity[] = []; - marketplaceReindexState.auctions.map((auction) => { - const assetTags = auction.tags.split(','); - assetTags.map((assetTag) => { - if (assetTag !== '') { - tags.push( - new TagEntity({ - auctionId: auction.id, - tag: assetTag.trim().slice(0, constants.dbMaxTagLength), - auction: auction, - }), - ); - } - }); - }); - - await Promise.all([ - this.persistenceService.saveBulkOrders(marketplaceReindexState.orders), - this.persistenceService.saveBulkOffers(marketplaceReindexState.offers), - this.persistenceService.saveTags(tags), - ]); } - private async populateAuctionAssetTags(auctions: AuctionEntity[]): Promise { + private async populateAuctionMissingAssetTags(auctions: AuctionEntity[]): Promise { const batchSize = constants.getNftsFromApiBatchSize; for (let i = 0; i < auctions.length; i += batchSize) { const assetsWithNoTagsIdentifiers = [ ...new Set( auctions .slice(i, i + batchSize) - .filter((a) => a.tags === '') + .filter((a) => a.tags === '' && a.id < 0) .map((a) => a.identifier), ), ]; diff --git a/src/modules/marketplaces/marketplaces.module.ts b/src/modules/marketplaces/marketplaces.module.ts index 3451f7944..2c373162c 100644 --- a/src/modules/marketplaces/marketplaces.module.ts +++ b/src/modules/marketplaces/marketplaces.module.ts @@ -26,6 +26,7 @@ import { ReindexAuctionPriceUpdatedHandler } from './marketplaces-reindex-handle import { ReindexGlobalOfferAcceptedHandler } from './marketplaces-reindex-handlers/reindex-global-offer-accepted.handler'; import { ReindexAuctionUpdatedHandler } from './marketplaces-reindex-handlers/reindex-auction-updated.handler'; import { MarketplacesMutationsResolver } from './marketplaces-mutations.resolver'; +import { OrdersModuleGraph } from '../orders/orders.module'; @Module({ providers: [ @@ -58,6 +59,7 @@ import { MarketplacesMutationsResolver } from './marketplaces-mutations.resolver MxCommunicationModule, forwardRef(() => CommonModule), forwardRef(() => AuctionsModuleGraph), + forwardRef(() => OrdersModuleGraph), forwardRef(() => OffersModuleGraph), ], exports: [MarketplacesService, MarketplaceEventsIndexingService, MarketplacesReindexService], diff --git a/src/modules/marketplaces/models/MarketplaceReindexState.ts b/src/modules/marketplaces/models/MarketplaceReindexState.ts index 9205231a5..dbcffd7d4 100644 --- a/src/modules/marketplaces/models/MarketplaceReindexState.ts +++ b/src/modules/marketplaces/models/MarketplaceReindexState.ts @@ -1,5 +1,6 @@ import { ObjectType } from '@nestjs/graphql'; import BigNumber from 'bignumber.js'; +import { constants } from 'src/config'; import { AuctionEntity } from 'src/db/auctions'; import { OfferEntity } from 'src/db/offers'; import { OrderEntity } from 'src/db/orders'; @@ -20,10 +21,26 @@ export class MarketplaceReindexState { orders: OrderEntity[] = []; offers: OfferEntity[] = []; + private auctionsTemporaryIdCounter = -1; + private ordersTemporaryIdCounter = -1; + private offersTemporaryIdCounter = -1; + constructor(init?: Partial) { Object.assign(this, init); } + getNewAuctionId(): number { + return this.auctionsTemporaryIdCounter--; + } + + getNewOrderId(): number { + return this.ordersTemporaryIdCounter--; + } + + getNewOfferId(): number { + return this.offersTemporaryIdCounter--; + } + isCollectionListed(collection: string): boolean { return this.listedCollections.includes(collection); } @@ -44,14 +61,14 @@ export class MarketplaceReindexState { const modifiedDate = DateUtils.getUtcDateFromTimestamp(input.timestamp); const price = input.price ?? input.currentBid; return new OrderEntity({ - id: this.orders.length, + id: this.getNewOrderId(), creationDate: modifiedDate, modifiedDate, auctionId: this.auctions[auctionIndex].id, ownerAddress: input.address, priceToken: paymentToken.identifier, priceNonce: paymentNonce ?? 0, - priceAmount: price !== '0' ? price : this.auctions[auctionIndex].maxBid, + priceAmount: new BigNumber(price !== '0' ? price : this.auctions[auctionIndex].maxBid).toFixed(), priceAmountDenominated: price !== '0' ? BigNumberUtils.denominateAmount(price, paymentToken.decimals) : this.auctions[auctionIndex].maxBidDenominated, blockHash: input.blockHash ?? '', @@ -94,6 +111,16 @@ export class MarketplaceReindexState { this.setOffersToExpiredIfOlderThanTimestamp(timestamp); } + popAllItems(): [AuctionEntity[], OrderEntity[], OfferEntity[]] { + const inactiveAuctions = this.auctions; + const inactiveOrders = this.orders; + const inactiveOffers = this.offers; + this.auctions = []; + this.orders = []; + this.offers = []; + return [inactiveAuctions, inactiveOrders, inactiveOffers]; + } + popInactiveItems(): [AuctionEntity[], OrderEntity[], OfferEntity[]] { const inactiveAuctionStatuses = [AuctionStatusEnum.Closed, AuctionStatusEnum.Ended]; const inactiveOfferStatuses = [OfferStatusEnum.Accepted, OfferStatusEnum.Closed, OfferStatusEnum.Expired]; @@ -102,33 +129,86 @@ export class MarketplaceReindexState { let inactiveOrders = []; let inactiveOffers = []; + // if (this.marketplace.key === 'elrondapes') + // console.log( + // `state`, + // JSON.stringify(this.auctions), + // JSON.stringify(this.orders), + // JSON.stringify(this.offers), + // ); + // if (this.marketplace.key === 'elrondapes') + // console.log( + // `inactive`, + // JSON.stringify(inactiveAuctions), + // JSON.stringify(inactiveOrders), + // JSON.stringify(inactiveOffers), + // ); + + if (this.marketplace.key === 'elrondapes') { + console.log( + `orders state`, + this.orders.map((o) => o.id), + this.orders.map((o) => o.auctionId), + ); + } + for (let i = 0; i < this.auctions.length; i++) { - if (inactiveAuctionStatuses.includes(this.auctions[i].status)) { - inactiveAuctions.push(this.auctions[i]); - delete this.auctions[i]; + const isInactiveAuction = inactiveAuctionStatuses.includes(this.auctions[i].status); + const isOldAuction = + this.auctions.length > constants.marketplaceReindexDataMaxInMemoryItems && + i < this.auctions.length - constants.marketplaceReindexDataMaxInMemoryItems; + + if (isInactiveAuction || isOldAuction) { + inactiveAuctions.push(this.auctions.splice(i--, 1)[0]); } } - this.auctions = this.auctions.filter((a) => a); for (let i = 0; i < this.orders.length; i++) { - if (inactiveAuctions.findIndex((a) => a.id === this.orders[i].auctionId) !== -1) { - inactiveOrders.push(this.orders[i]); - delete this.orders[i]; + const isInactiveOrOldOrder = inactiveAuctions.findIndex((a) => a.id === this.orders[i].auctionId) !== -1; + + if (isInactiveOrOldOrder) { + inactiveOrders.push(this.orders.splice(i--, 1)[0]); } } - this.orders = this.orders.filter((o) => o); for (let i = 0; i < this.offers.length; i++) { - if (inactiveOfferStatuses.includes(this.offers[i].status)) { - inactiveOffers.push(this.offers[i]); - delete this.offers[i]; + const isInactiveOffer = inactiveOfferStatuses.includes(this.offers[i].status); + const isOldOffer = + this.offers.length > constants.marketplaceReindexDataMaxInMemoryItems && + i < this.offers.length - constants.marketplaceReindexDataMaxInMemoryItems; + + if (isInactiveOffer || isOldOffer) { + inactiveOffers.push(this.offers.splice(i--, 1)[0]); } } - this.offers = this.offers.filter((o) => o); return [inactiveAuctions, inactiveOrders, inactiveOffers]; } + deleteAuctionIfDuplicates(marketplaceAuctionId: number) { + if (this.isFullStateInMemory) { + return; + } + + let index; + do { + index = this.auctions.findIndex((a) => a.marketplaceAuctionId === marketplaceAuctionId); + this.auctions.splice(index, 1); + } while (index !== -1); + } + + deleteOfferIfDuplicates(marketplaceOfferId: number) { + if (this.isFullStateInMemory) { + return; + } + + let index; + do { + index = this.offers.findIndex((a) => a.marketplaceOfferId === marketplaceOfferId); + this.offers.splice(index, 1); + } while (index !== -1); + } + private setAuctionsAndOrdersToExpiredIfOlderThanTimestamp(timestamp: number): void { const runningAuctions = this.auctions?.filter((a) => a.status === AuctionStatusEnum.Running); for (let i = 0; i < runningAuctions.length; i++) {