Skip to content

Commit 3a00c6b

Browse files
fix order processor concurrency issue (#11)
* fix order processor concurrency issue * delete duplicate docker build config * remove unused import
1 parent 3e1cc8a commit 3a00c6b

File tree

11 files changed

+32
-70
lines changed

11 files changed

+32
-70
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=Puneethkumarck_trading-api&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=Puneethkumarck_trading-api)
55
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=Puneethkumarck_trading-api&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=Puneethkumarck_trading-api)
66
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=Puneethkumarck_trading-api&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=Puneethkumarck_trading-api)
7-
7+
[<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://god.gw.postman.com/run-collection/685178-34771dde-0c1a-4fa2-8613-14a572120e88?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D685178-34771dde-0c1a-4fa2-8613-14a572120e88%26entityType%3Dcollection%26workspaceId%3De03b2ab3-447a-4a5f-8818-be163b36a6e7#?env%5Brailway%5D=W3sia2V5IjoidXJsIiwidmFsdWUiOiJodHRwczovL2NyeXB0by1hcGktcHJvZHVjdGlvbi00NzNhLnVwLnJhaWx3YXkuYXBwIiwiZW5hYmxlZCI6dHJ1ZSwidHlwZSI6ImRlZmF1bHQifV0=)
88

99
# Trading API
1010

@@ -370,7 +370,7 @@ sequenceDiagram
370370
```
371371

372372
### API Documentation
373-
The API documentation is available at : [swagger](http://localhost:8080/swagger-ui.html)
373+
The API documentation is available at : [swagger](https://trading-api-production-057a.up.railway.app/swagger-ui/index.html)
374374

375375
### Code Style
376376
The project uses Spotless with Eclipse formatter for consistent code style. Format the code using:

deploy/Dockerfile

Lines changed: 0 additions & 39 deletions
This file was deleted.

deploy/entrypoint.sh

Lines changed: 0 additions & 5 deletions
This file was deleted.

trading-app/src/main/java/com/xchange/valr/trading/api/application/orderbook/OrderBookDtoMapper.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.math.BigDecimal;
1010
import java.util.List;
1111
import java.util.TreeMap;
12+
import java.util.concurrent.ConcurrentNavigableMap;
1213

1314
@Mapper
1415
public interface OrderBookDtoMapper {
@@ -19,7 +20,7 @@ public interface OrderBookDtoMapper {
1920

2021
@Named("mapOrderBookLevels")
2122
default List<OrderBookResponseDto.OrderBookEntryDto> mapOrderBookLevels(
22-
TreeMap<BigDecimal, OrderBook.OrderBookLevel> levels
23+
ConcurrentNavigableMap<BigDecimal, OrderBook.OrderBookLevel> levels
2324
) {
2425

2526
if (levels == null || levels.isEmpty()) {

trading-app/src/main/java/com/xchange/valr/trading/api/domain/limitorder/BuyOrderProcessor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@
33
import com.xchange.valr.trading.api.domain.orderbook.OrderBook;
44

55
import java.math.BigDecimal;
6-
import java.util.TreeMap;
6+
import java.util.concurrent.ConcurrentNavigableMap;
77

88
public class BuyOrderProcessor extends OrderProcessor {
99
@Override
10-
protected TreeMap<BigDecimal, OrderBook.OrderBookLevel> getMatchingSide(OrderBook orderBook) {
10+
protected ConcurrentNavigableMap<BigDecimal, OrderBook.OrderBookLevel> getMatchingSide(OrderBook orderBook) {
1111
return orderBook.asks();
1212
}
1313

1414
@Override
15-
protected TreeMap<BigDecimal, OrderBook.OrderBookLevel> getPlacementSide(OrderBook orderBook) {
15+
protected ConcurrentNavigableMap<BigDecimal, OrderBook.OrderBookLevel> getPlacementSide(OrderBook orderBook) {
1616
return orderBook.bids();
1717
}
1818

trading-app/src/main/java/com/xchange/valr/trading/api/domain/limitorder/LimitOrderCommandHandler.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
import java.time.Instant;
1313
import java.util.Map;
1414
import java.util.Optional;
15-
import java.util.TreeMap;
15+
import java.util.concurrent.ConcurrentSkipListMap;
16+
1617
import static com.xchange.valr.trading.api.domain.limitorder.LimitOrderCommand.LimitOrder.OrderBookSide.BUY;
1718
import static com.xchange.valr.trading.api.domain.limitorder.LimitOrderCommand.LimitOrder.OrderBookSide.SELL;
1819
import static java.util.UUID.randomUUID;
@@ -55,8 +56,8 @@ private OrderBook getOrCreateOrderBook(String currencyPair) {
5556
.orElseGet(
5657
() -> OrderBook.builder()
5758
.currencyPair(currencyPair)
58-
.asks(new TreeMap<>())
59-
.bids(new TreeMap<>())
59+
.asks(new ConcurrentSkipListMap<>())
60+
.bids(new ConcurrentSkipListMap<>())
6061
.build()
6162
);
6263
}

trading-app/src/main/java/com/xchange/valr/trading/api/domain/limitorder/OrderProcessor.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44

55
import java.math.BigDecimal;
66
import java.util.TreeMap;
7+
import java.util.concurrent.ConcurrentNavigableMap;
78

89
abstract class OrderProcessor {
9-
protected abstract TreeMap<BigDecimal, OrderBook.OrderBookLevel> getMatchingSide(OrderBook orderBook);
10+
protected abstract ConcurrentNavigableMap<BigDecimal, OrderBook.OrderBookLevel> getMatchingSide(OrderBook orderBook);
1011

11-
protected abstract TreeMap<BigDecimal, OrderBook.OrderBookLevel> getPlacementSide(OrderBook orderBook);
12+
protected abstract ConcurrentNavigableMap<BigDecimal, OrderBook.OrderBookLevel> getPlacementSide(OrderBook orderBook);
1213

1314
protected abstract boolean canMatch(BigDecimal orderPrice, BigDecimal matchPrice);
1415

@@ -60,7 +61,7 @@ private BigDecimal matchOrders(
6061
}
6162

6263
private void updateMatchLevel(
63-
TreeMap<BigDecimal, OrderBook.OrderBookLevel> side,
64+
ConcurrentNavigableMap<BigDecimal, OrderBook.OrderBookLevel> side,
6465
BigDecimal price,
6566
OrderBook.OrderBookLevel level,
6667
BigDecimal matchedQuantity
@@ -82,7 +83,7 @@ private void placeOrder(
8283
String currencyPair,
8384
BigDecimal price,
8485
BigDecimal quantity,
85-
TreeMap<BigDecimal, OrderBook.OrderBookLevel> side
86+
ConcurrentNavigableMap<BigDecimal, OrderBook.OrderBookLevel> side
8687
) {
8788
var existingLevel = side.get(price);
8889
if (existingLevel != null) {

trading-app/src/main/java/com/xchange/valr/trading/api/domain/limitorder/SellOrderProcessor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@
33
import com.xchange.valr.trading.api.domain.orderbook.OrderBook;
44

55
import java.math.BigDecimal;
6-
import java.util.TreeMap;
6+
import java.util.concurrent.ConcurrentNavigableMap;
77

88
public class SellOrderProcessor extends OrderProcessor {
99
@Override
10-
protected TreeMap<BigDecimal, OrderBook.OrderBookLevel> getMatchingSide(OrderBook orderBook) {
10+
protected ConcurrentNavigableMap<BigDecimal, OrderBook.OrderBookLevel> getMatchingSide(OrderBook orderBook) {
1111
return orderBook.bids();
1212
}
1313

1414
@Override
15-
protected TreeMap<BigDecimal, OrderBook.OrderBookLevel> getPlacementSide(OrderBook orderBook) {
15+
protected ConcurrentNavigableMap<BigDecimal, OrderBook.OrderBookLevel> getPlacementSide(OrderBook orderBook) {
1616
return orderBook.asks();
1717
}
1818

trading-app/src/main/java/com/xchange/valr/trading/api/domain/orderbook/OrderBook.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
import java.math.BigDecimal;
99
import java.time.Instant;
1010
import java.util.TreeMap;
11+
import java.util.concurrent.ConcurrentNavigableMap;
1112

1213
@Slf4j
1314
@Builder(toBuilder = true)
1415
public record OrderBook(
1516
String currencyPair,
16-
TreeMap<BigDecimal, OrderBookLevel> asks,
17-
TreeMap<BigDecimal, OrderBookLevel> bids,
17+
ConcurrentNavigableMap<BigDecimal, OrderBookLevel> asks,
18+
ConcurrentNavigableMap<BigDecimal, OrderBookLevel> bids,
1819
Instant lastChange,
1920
Long sequenceNumber
2021
) {

trading-app/src/test/java/com/xchange/valr/trading/api/domain/limitorder/OrderProcessorBaseTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import java.math.BigDecimal;
77
import java.util.TreeMap;
8+
import java.util.concurrent.ConcurrentSkipListMap;
89

910
import static com.xchange.valr.trading.api.domain.model.CurrencyPair.BTCZAR;
1011
import static org.assertj.core.api.Assertions.assertThat;
@@ -23,8 +24,8 @@ void shouldReturnCorrectOrderSide() {
2324
protected OrderBook createOrderBook() {
2425
return OrderBook.builder()
2526
.currencyPair(BTCZAR.name())
26-
.asks(new TreeMap<>())
27-
.bids(new TreeMap<>())
27+
.asks(new ConcurrentSkipListMap<>())
28+
.bids(new ConcurrentSkipListMap<>())
2829
.build();
2930
}
3031

trading-app/src/test/java/com/xchange/valr/trading/fixtures/OrderBookFixtures.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.math.BigDecimal;
77
import java.util.Map;
88
import java.util.TreeMap;
9+
import java.util.concurrent.ConcurrentSkipListMap;
910

1011
import static com.xchange.valr.trading.api.domain.orderbook.OrderBook.OrderBookSide.BUY;
1112
import static com.xchange.valr.trading.api.domain.orderbook.OrderBook.OrderBookSide.SELL;
@@ -18,7 +19,7 @@ public static OrderBook orderBook(String currencyPair) {
1819
return OrderBook.builder()
1920
.currencyPair(currencyPair)
2021
.asks(
21-
new TreeMap<>(
22+
new ConcurrentSkipListMap<>(
2223
Map.of(
2324
new BigDecimal("1000000"),
2425
OrderBook.OrderBookLevel.builder()
@@ -32,7 +33,7 @@ public static OrderBook orderBook(String currencyPair) {
3233
)
3334
)
3435
.bids(
35-
new TreeMap<>(
36+
new ConcurrentSkipListMap<>(
3637
Map.of(
3738
new BigDecimal("900000"),
3839
OrderBook.OrderBookLevel.builder()
@@ -70,13 +71,13 @@ public static OrderBook createOrderBook(
7071
.currencyPair(currencyPair)
7172
.asks(
7273
side == OrderBook.OrderBookSide.SELL
73-
? new TreeMap<>(Map.of(price, orderBookLevel))
74-
: new TreeMap<>()
74+
? new ConcurrentSkipListMap<>(Map.of(price, orderBookLevel))
75+
: new ConcurrentSkipListMap<>()
7576
)
7677
.bids(
7778
side == OrderBook.OrderBookSide.BUY
78-
? new TreeMap<>(Map.of(price, orderBookLevel))
79-
: new TreeMap<>()
79+
? new ConcurrentSkipListMap<>(Map.of(price, orderBookLevel))
80+
: new ConcurrentSkipListMap<>()
8081
)
8182
.build();
8283
}

0 commit comments

Comments
 (0)