Skip to content

Commit e8f2ad3

Browse files
committed
CQRS 4.5 - TransitAnalyzer - podpięcie nowego modelu
1 parent 7b81b0f commit e8f2ad3

File tree

10 files changed

+144
-30
lines changed

10 files changed

+144
-30
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package io.legacyfighter.cabs.common;
2+
3+
public interface Event {
4+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.legacyfighter.cabs.common;
2+
3+
4+
import org.springframework.context.ApplicationEventPublisher;
5+
6+
public class EventsPublisher {
7+
8+
private final ApplicationEventPublisher applicationEventPublisher;
9+
10+
public EventsPublisher(ApplicationEventPublisher applicationEventPublisher) {
11+
this.applicationEventPublisher = applicationEventPublisher;
12+
}
13+
14+
public void publish(Event event) {
15+
applicationEventPublisher.publishEvent(event);
16+
}
17+
}
18+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package io.legacyfighter.cabs.config;
2+
3+
4+
import io.legacyfighter.cabs.common.EventsPublisher;
5+
import org.springframework.context.ApplicationEventPublisher;
6+
import org.springframework.context.annotation.Bean;
7+
import org.springframework.context.annotation.Configuration;
8+
9+
@Configuration
10+
class EventPublisherConfiguration {
11+
12+
@Bean
13+
EventsPublisher eventsPublisher(ApplicationEventPublisher applicationEventPublisher) {
14+
return new EventsPublisher(applicationEventPublisher);
15+
}
16+
}
17+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package io.legacyfighter.cabs.entity.events;
2+
3+
import io.legacyfighter.cabs.common.Event;
4+
5+
import java.time.Instant;
6+
7+
public class TransitCompleted implements Event {
8+
9+
public final Long clientId;
10+
public final Long transitId;
11+
public final Integer addressFromHash;
12+
public final Integer addressToHash;
13+
public final Instant started;
14+
public final Instant completeAt;
15+
public final Instant eventTimestamp;
16+
17+
public TransitCompleted(Long clientId, Long transitId, Integer addressFromHash, Integer addressToHash, Instant started, Instant completeAt, Instant eventTimestamp) {
18+
this.clientId = clientId;
19+
this.transitId = transitId;
20+
this.addressFromHash = addressFromHash;
21+
this.addressToHash = addressToHash;
22+
this.started = started;
23+
this.completeAt = completeAt;
24+
this.eventTimestamp = eventTimestamp;
25+
}
26+
}

src/main/java/io/legacyfighter/cabs/repository/AddressRepository.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import org.springframework.beans.factory.annotation.Autowired;
55
import org.springframework.data.jpa.repository.JpaRepository;
66
import org.springframework.stereotype.Repository;
7+
import org.springframework.transaction.annotation.Transactional;
78

89
@Repository
910
public class AddressRepository {
@@ -29,4 +30,13 @@ public Address save(Address address) {
2930
public Address getOne(Long id) {
3031
return addressRepositoryInterface.getOne(id);
3132
}
33+
34+
@Transactional
35+
public Integer findHashById(Long addressId) {
36+
return addressRepositoryInterface.findHashById(addressId);
37+
}
38+
39+
public Address getByHash(int hash) {
40+
return addressRepositoryInterface.findByHash(hash);
41+
}
3242
}

src/main/java/io/legacyfighter/cabs/repository/AddressRepositoryInterface.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,8 @@
55

66
public interface AddressRepositoryInterface extends JpaRepository<Address, Long> {
77
Address findByHash(Integer hash);
8+
9+
default Integer findHashById(Long id) {
10+
return getOne(id).getHash();
11+
}
812
}

src/main/java/io/legacyfighter/cabs/service/TransitService.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package io.legacyfighter.cabs.service;
22

3+
import io.legacyfighter.cabs.common.EventsPublisher;
34
import io.legacyfighter.cabs.distance.Distance;
45
import io.legacyfighter.cabs.dto.AddressDTO;
56
import io.legacyfighter.cabs.dto.DriverPositionDTOV2;
67
import io.legacyfighter.cabs.dto.TransitDTO;
78
import io.legacyfighter.cabs.entity.*;
9+
import io.legacyfighter.cabs.entity.events.TransitCompleted;
810
import io.legacyfighter.cabs.money.Money;
911
import io.legacyfighter.cabs.repository.*;
1012
import org.springframework.beans.factory.annotation.Autowired;
@@ -63,6 +65,9 @@ public class TransitService {
6365
@Autowired
6466
private AwardsService awardsService;
6567

68+
@Autowired
69+
private EventsPublisher eventsPublisher;
70+
6671
@Transactional
6772
public Transit createTransit(TransitDTO transitDTO) {
6873
Address from = addressFromDto(transitDTO.getFrom());
@@ -417,6 +422,10 @@ public void completeTransit(Long driverId, Long transitId, Address destinationAd
417422
awardsService.registerMiles(transit.getClient().getId(), transitId);
418423
transitRepository.save(transit);
419424
invoiceGenerator.generate(transit.getPrice().toInt(), transit.getClient().getName() + " " + transit.getClient().getLastName());
425+
eventsPublisher.publish(new TransitCompleted(
426+
transit.getClient().getId(), transitId, transit.getFrom().getHash(), transit.getTo().getHash(), transit.getStarted(), transit.getCompleteAt(), Instant.now(clock))
427+
);
428+
420429
}
421430

422431
@Transactional

src/main/java/io/legacyfighter/cabs/transitanalyzer/GraphTransitAnalyzer.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package io.legacyfighter.cabs.transitanalyzer;
22

33

4+
import io.legacyfighter.cabs.entity.events.TransitCompleted;
45
import org.neo4j.graphdb.*;
6+
import org.springframework.transaction.event.TransactionalEventListener;
57

68
import java.time.Instant;
79
import java.time.ZoneId;
@@ -46,6 +48,11 @@ public void addTransitBetweenAddresses(Long clientId, Long transitId, Integer ad
4648
}
4749
}
4850

51+
@TransactionalEventListener
52+
public void handle(TransitCompleted transitCompleted) {
53+
addTransitBetweenAddresses(transitCompleted.clientId, transitCompleted.transitId, transitCompleted.addressFromHash, transitCompleted.addressToHash, transitCompleted.started, transitCompleted.completeAt);
54+
}
55+
4956
public void onClose() {
5057
if (graphDb != null) {
5158
graphDb.shutdown();

src/main/java/io/legacyfighter/cabs/ui/TransitAnalyzerController.java

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22

33
import io.legacyfighter.cabs.dto.AddressDTO;
44
import io.legacyfighter.cabs.dto.AnalyzedAddressesDTO;
5-
import io.legacyfighter.cabs.entity.Address;
6-
import io.legacyfighter.cabs.service.TransitAnalyzer;
7-
import org.springframework.beans.factory.annotation.Autowired;
5+
import io.legacyfighter.cabs.repository.AddressRepository;
6+
import io.legacyfighter.cabs.transitanalyzer.GraphTransitAnalyzer;
87
import org.springframework.web.bind.annotation.GetMapping;
98
import org.springframework.web.bind.annotation.PathVariable;
109
import org.springframework.web.bind.annotation.RestController;
@@ -14,17 +13,27 @@
1413

1514
@RestController
1615
public class TransitAnalyzerController {
17-
@Autowired
18-
TransitAnalyzer transitAnalyzer;
16+
17+
private final GraphTransitAnalyzer graphTransitAnalyzer;
18+
private final AddressRepository addressRepository;
19+
20+
public TransitAnalyzerController(GraphTransitAnalyzer graphTransitAnalyzer, AddressRepository addressRepository) {
21+
this.graphTransitAnalyzer = graphTransitAnalyzer;
22+
this.addressRepository = addressRepository;
23+
}
1924

2025
@GetMapping("/transitAnalyze/{clientId}/{addressId}")
2126
public AnalyzedAddressesDTO analyze(@PathVariable Long clientId, @PathVariable Long addressId) {
22-
List<Address> addresses = transitAnalyzer.analyze(clientId, addressId);
23-
List<AddressDTO> addressDTOs = addresses
27+
List<Long> hashes = graphTransitAnalyzer.analyze(clientId, addressRepository.findHashById(addressId));
28+
List<AddressDTO> addressDTOs = hashes
2429
.stream()
25-
.map(a -> new AddressDTO(a))
30+
.map(this::mapToAddressDTO)
2631
.collect(Collectors.toList());
2732

2833
return new AnalyzedAddressesDTO(addressDTOs);
2934
}
35+
36+
private AddressDTO mapToAddressDTO(Long hash) {
37+
return new AddressDTO(addressRepository.getByHash(hash.intValue()));
38+
}
3039
}

src/test/java/io/legacyfighter/cabs/integration/AnalyzeNearbyTransitsIntegrationTest.java

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,37 @@
11
package io.legacyfighter.cabs.integration;
22

33
import io.legacyfighter.cabs.common.Fixtures;
4+
import io.legacyfighter.cabs.common.TestWithGraphDB;
45
import io.legacyfighter.cabs.dto.AddressDTO;
56
import io.legacyfighter.cabs.dto.AnalyzedAddressesDTO;
67
import io.legacyfighter.cabs.entity.Address;
78
import io.legacyfighter.cabs.entity.Client;
89
import io.legacyfighter.cabs.entity.Driver;
910
import io.legacyfighter.cabs.service.GeocodingService;
1011
import io.legacyfighter.cabs.ui.TransitAnalyzerController;
12+
import org.awaitility.Awaitility;
13+
import org.jetbrains.annotations.NotNull;
1114
import org.junit.jupiter.api.BeforeEach;
1215
import org.junit.jupiter.api.Test;
1316
import org.springframework.beans.factory.annotation.Autowired;
14-
import org.springframework.boot.test.context.SpringBootTest;
1517
import org.springframework.boot.test.mock.mockito.MockBean;
1618

1719
import java.time.Clock;
20+
import java.util.Arrays;
21+
import java.util.List;
1822
import java.util.stream.Collectors;
23+
import java.util.stream.Stream;
1924

2025
import static io.legacyfighter.cabs.entity.CarType.CarClass.VAN;
2126
import static java.time.LocalDateTime.of;
2227
import static java.time.ZoneOffset.UTC;
28+
import static java.util.Arrays.asList;
29+
import static org.assertj.core.api.Assertions.*;
30+
import static org.awaitility.Awaitility.await;
2331
import static org.mockito.ArgumentMatchers.any;
2432
import static org.mockito.Mockito.when;
2533

26-
@SpringBootTest
27-
public class AnalyzeNearbyTransitsIntegrationTest {
34+
public class AnalyzeNearbyTransitsIntegrationTest extends TestWithGraphDB {
2835

2936
@Autowired
3037
Fixtures fixtures;
@@ -77,11 +84,10 @@ void canFindLongestTravel() {
7784
//when
7885
AnalyzedAddressesDTO analyzedAddressesDTO = transitAnalyzerController.analyze(client.getId(), address1.getId());
7986

87+
8088
//then
8189
// 1-2-5-4-5
82-
org.assertj.core.api.Assertions
83-
.assertThat(analyzedAddressesDTO.getAddresses().stream().map(AddressDTO::getHash).collect(Collectors.toList()))
84-
.containsExactly(address1.getHash(), address2.getHash(), address5.getHash(), address4.getHash(), address5.getHash());
90+
addressesContainExactly(analyzedAddressesDTO, address1, address2, address5, address4, address5);
8591
}
8692

8793
@Test
@@ -122,9 +128,7 @@ void canFindLongestTravelFromMultipleClients() {
122128

123129
//then
124130
// 1-2-3-4
125-
org.assertj.core.api.Assertions
126-
.assertThat(analyzedAddressesDTO.getAddresses().stream().map(AddressDTO::getHash).collect(Collectors.toList()))
127-
.containsExactly(address1.getHash(), address2.getHash(), address3.getHash(), address4.getHash());
131+
addressesContainExactly(analyzedAddressesDTO, address1, address2, address3, address4);
128132
}
129133

130134
@Test
@@ -153,9 +157,7 @@ void canFindLongestTravelWithLongStops() {
153157

154158
//then
155159
// 1-2-3-4
156-
org.assertj.core.api.Assertions
157-
.assertThat(analyzedAddressesDTO.getAddresses().stream().map(AddressDTO::getHash).collect(Collectors.toList()))
158-
.containsExactly(address1.getHash(), address2.getHash(), address3.getHash(), address4.getHash());
160+
addressesContainExactly(analyzedAddressesDTO, address1, address2, address3, address4);
159161
}
160162

161163
@Test
@@ -193,15 +195,11 @@ void canFindLongestTravelWithLoops() {
193195

194196
//then
195197
// 5-1-2-3
196-
org.assertj.core.api.Assertions
197-
.assertThat(analyzedAddressesDTO.getAddresses().stream().map(AddressDTO::getHash).collect(Collectors.toList()))
198-
.containsExactly(address5.getHash(), address1.getHash(), address2.getHash(), address3.getHash());
198+
addressesContainExactly(analyzedAddressesDTO, address5, address1, address2, address3);
199199
}
200200

201201
@Test
202-
// pytanie za 100 punktów, czy ten test będzie działał na grafie, bo tam jest warunek na ścieżkę o długości przynajmniej 1...
203-
void canFindLongTravelBetweenOthers()
204-
{
202+
void canFindLongTravelBetweenOthers() {
205203
//given
206204
Client client = fixtures.aClient();
207205
//and
@@ -224,10 +222,22 @@ void canFindLongTravelBetweenOthers()
224222
AnalyzedAddressesDTO analyzedAddressesDTO = transitAnalyzerController.analyze(client.getId(), address1.getId());
225223

226224
//then
227-
//1-2
228-
org.assertj.core.api.Assertions
229-
.assertThat(analyzedAddressesDTO.getAddresses().stream().map(AddressDTO::getHash).collect(Collectors.toList()))
230-
.containsExactly(address1.getHash(), address2.getHash(), address3.getHash());
225+
//1-2-3
226+
addressesContainExactly(analyzedAddressesDTO, address1, address2, address3);
227+
}
228+
229+
void addressesContainExactly(AnalyzedAddressesDTO analyzedAddressesDTO, Address... expectedAddresses) {
230+
List<Integer> expectedHashes = Stream.of(expectedAddresses)
231+
.map(Address::getHash)
232+
.collect(Collectors.toList());
233+
await().ignoreExceptions().until(() -> {
234+
assertThat(hashesOfAddresses(analyzedAddressesDTO)).containsExactlyElementsOf(expectedHashes);
235+
return true;
236+
});
237+
}
238+
239+
List<Integer> hashesOfAddresses(AnalyzedAddressesDTO analyzedAddressesDTO) {
240+
return analyzedAddressesDTO.getAddresses().stream().map(AddressDTO::getHash).collect(Collectors.toList());
231241
}
232242

233243
}

0 commit comments

Comments
 (0)