From 1866ace49d8b11583ffe1422a92f1ed4ce397e3d Mon Sep 17 00:00:00 2001 From: Junh-b Date: Fri, 13 Jun 2025 12:56:22 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=ED=98=B8=EA=B0=80=20=EA=B0=B1?= =?UTF-8?q?=EC=8B=A0=EC=8B=9C=20sync=20+=20null=20=EB=8C=80=EC=9D=91=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit orderbook을 갱신, 삭제할 때 syncrhonized를 추가해, 동시 접근시 이슈가 발생하지 않도록 했습니다. --- .../coin/orderbook/domain/OrderBook.java | 56 +++++++++++++++---- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/cleanengine/coin/orderbook/domain/OrderBook.java b/src/main/java/com/cleanengine/coin/orderbook/domain/OrderBook.java index adc60911..666b3209 100644 --- a/src/main/java/com/cleanengine/coin/orderbook/domain/OrderBook.java +++ b/src/main/java/com/cleanengine/coin/orderbook/domain/OrderBook.java @@ -22,18 +22,14 @@ public void updateOrderBookOnNewOrder(boolean isBuyOrder, Double price, Double o if(isBuyOrder){ BuyOrderBookUnit buyOrderBookUnit = buyOrderBookUnitMap.get(price); if(buyOrderBookUnit == null){ - buyOrderBookUnit = new BuyOrderBookUnit(price, orderSize); - buyOrderBookUnitMap.put(price, buyOrderBookUnit); - buyOrderBookUnitListSet.add(buyOrderBookUnit); + addBuyOrderBookUnit(price, orderSize); } else { buyOrderBookUnit.addOrder(orderSize); } } else { SellOrderBookUnit sellOrderBookUnit = sellOrderBookUnitMap.get(price); if(sellOrderBookUnit == null){ - sellOrderBookUnit = new SellOrderBookUnit(price, orderSize); - sellOrderBookUnitMap.put(price, sellOrderBookUnit); - sellOrderBookUnitListSet.add(sellOrderBookUnit); + addSellOrderBookUnit(price, orderSize); } else { sellOrderBookUnit.addOrder(orderSize); } @@ -43,17 +39,21 @@ public void updateOrderBookOnNewOrder(boolean isBuyOrder, Double price, Double o public void updateOrderBookOnTradeExecuted(boolean isBuyOrder, Double price, Double orderSize) { if(isBuyOrder){ BuyOrderBookUnit buyOrderBookUnit = buyOrderBookUnitMap.get(price); + if(buyOrderBookUnit == null) { + return; + } buyOrderBookUnit.executeTrade(orderSize); if(approxEquals(buyOrderBookUnit.getSize(), 0.0)){ - buyOrderBookUnitMap.remove(price); - buyOrderBookUnitListSet.remove(buyOrderBookUnit); + removeBuyOrderBookUnit(buyOrderBookUnit, price); } } else { SellOrderBookUnit sellOrderBookUnit = sellOrderBookUnitMap.get(price); + if(sellOrderBookUnit == null) { + return; + } sellOrderBookUnit.executeTrade(orderSize); if(approxEquals(sellOrderBookUnit.getSize(), 0.0)){ - sellOrderBookUnitMap.remove(price); - sellOrderBookUnitListSet.remove(sellOrderBookUnit); + removeSellOrderBookUnit(sellOrderBookUnit, price); } } } @@ -71,4 +71,40 @@ public List getSellOrderBookList(int size){ .limit(size) .collect(Collectors.toList()); } + + protected synchronized void addBuyOrderBookUnit(Double price, Double size) { + BuyOrderBookUnit buyOrderBookUnit = buyOrderBookUnitMap.get(price); + if(buyOrderBookUnit != null){ + return; + } + + buyOrderBookUnit = new BuyOrderBookUnit(price, size); + buyOrderBookUnitMap.put(price, buyOrderBookUnit); + buyOrderBookUnitListSet.add(buyOrderBookUnit); + } + + protected synchronized void addSellOrderBookUnit(Double price, Double size) { + SellOrderBookUnit sellOrderBookUnit = sellOrderBookUnitMap.get(price); + if(sellOrderBookUnit != null){ + return; + } + + sellOrderBookUnit = new SellOrderBookUnit(price, size); + sellOrderBookUnitMap.put(price, sellOrderBookUnit); + sellOrderBookUnitListSet.add(sellOrderBookUnit); + } + + protected synchronized void removeBuyOrderBookUnit(BuyOrderBookUnit buyOrderBookUnit, Double price) { + if(approxEquals(buyOrderBookUnit.getSize(), 0.0)) { + buyOrderBookUnitMap.remove(price); + buyOrderBookUnitListSet.remove(buyOrderBookUnitMap.get(price)); + } + } + + protected synchronized void removeSellOrderBookUnit(SellOrderBookUnit sellOrderBookUnit, Double price) { + if(approxEquals(sellOrderBookUnit.getSize(), 0.0)) { + sellOrderBookUnitMap.remove(price); + sellOrderBookUnitListSet.remove(sellOrderBookUnitMap.get(price)); + } + } } From b3c13b5bb14d100892979cc304fea2b9b9dc19f5 Mon Sep 17 00:00:00 2001 From: Junh-b Date: Fri, 13 Jun 2025 12:57:29 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=EC=A3=BC=EB=AC=B8=20=EC=88=98?= =?UTF-8?q?=EB=9F=89=EC=9D=B4=EB=82=98=20=EA=B0=80=EA=B2=A9=EC=9D=B4=200?= =?UTF-8?q?=EC=9D=BC=20=EB=95=8C=EC=97=90=20=ED=98=B8=EA=B0=80=20=EA=B0=B1?= =?UTF-8?q?=EC=8B=A0=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 체결이 이루어졌을 때의 주문 수량이나 가격이 0원이었을 경우에는 호가를 갱신하지 않도록 수정했습니다 --- .../com/cleanengine/coin/orderbook/domain/OrderBook.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/cleanengine/coin/orderbook/domain/OrderBook.java b/src/main/java/com/cleanengine/coin/orderbook/domain/OrderBook.java index 666b3209..f09725b6 100644 --- a/src/main/java/com/cleanengine/coin/orderbook/domain/OrderBook.java +++ b/src/main/java/com/cleanengine/coin/orderbook/domain/OrderBook.java @@ -37,7 +37,11 @@ public void updateOrderBookOnNewOrder(boolean isBuyOrder, Double price, Double o } public void updateOrderBookOnTradeExecuted(boolean isBuyOrder, Double price, Double orderSize) { - if(isBuyOrder){ + if(approxEquals(orderSize, 0.0) || approxEquals(price, 0.0)){ + throw new IllegalArgumentException("orderSize or price cannot be 0.0"); + } + + if(isBuyOrder) { BuyOrderBookUnit buyOrderBookUnit = buyOrderBookUnitMap.get(price); if(buyOrderBookUnit == null) { return;