├── .github └── workflows │ └── maven.yml ├── .gitignore ├── Jenkinsfile ├── README.md ├── cloud-native.jpg ├── devops ├── dev │ └── docker-compose.yml └── k8s │ ├── README.md │ ├── happyride │ ├── apps │ │ ├── address-service │ │ │ ├── address-service-config.yaml │ │ │ ├── charts │ │ │ │ ├── address-service-common │ │ │ │ │ ├── .helmignore │ │ │ │ │ ├── Chart.yaml │ │ │ │ │ ├── templates │ │ │ │ │ │ ├── NOTES.txt │ │ │ │ │ │ ├── _helpers.tpl │ │ │ │ │ │ └── service.yaml │ │ │ │ │ └── values.yaml │ │ │ │ └── address-service │ │ │ │ │ ├── .helmignore │ │ │ │ │ ├── Chart.yaml │ │ │ │ │ ├── templates │ │ │ │ │ ├── NOTES.txt │ │ │ │ │ ├── _helpers.tpl │ │ │ │ │ ├── deployment.yaml │ │ │ │ │ ├── hpa.yaml │ │ │ │ │ └── serviceaccount.yaml │ │ │ │ │ └── values.yaml │ │ │ ├── config.yaml │ │ │ └── helmfile.yaml │ │ ├── axon │ │ │ ├── charts │ │ │ │ └── axon │ │ │ │ │ ├── .helmignore │ │ │ │ │ ├── Chart.yaml │ │ │ │ │ ├── templates │ │ │ │ │ ├── NOTES.txt │ │ │ │ │ ├── _helpers.tpl │ │ │ │ │ ├── deployment.yaml │ │ │ │ │ ├── hpa.yaml │ │ │ │ │ ├── ingress.yaml │ │ │ │ │ ├── service.yaml │ │ │ │ │ ├── serviceaccount.yaml │ │ │ │ │ └── tests │ │ │ │ │ │ └── test-connection.yaml │ │ │ │ │ └── values.yaml │ │ │ └── helmfile.yaml │ │ ├── common │ │ │ ├── charts │ │ │ │ └── common │ │ │ │ │ ├── .helmignore │ │ │ │ │ ├── Chart.yaml │ │ │ │ │ ├── spring-config │ │ │ │ │ └── management.yml │ │ │ │ │ ├── templates │ │ │ │ │ ├── NOTES.txt │ │ │ │ │ ├── _helpers.tpl │ │ │ │ │ └── spring-config.yaml │ │ │ │ │ └── values.yaml │ │ │ └── helmfile.yaml │ │ ├── kafka │ │ │ └── helmfile.yaml │ │ ├── passenger-api-graphql │ │ │ ├── charts │ │ │ │ └── passenger-api-graphql │ │ │ │ │ ├── .helmignore │ │ │ │ │ ├── Chart.yaml │ │ │ │ │ ├── templates │ │ │ │ │ ├── NOTES.txt │ │ │ │ │ ├── _helpers.tpl │ │ │ │ │ ├── deployment.yaml │ │ │ │ │ ├── hpa.yaml │ │ │ │ │ ├── ingress.yaml │ │ │ │ │ ├── service.yaml │ │ │ │ │ ├── serviceaccount.yaml │ │ │ │ │ └── tests │ │ │ │ │ │ └── test-connection.yaml │ │ │ │ │ └── values.yaml │ │ │ └── helmfile.yaml │ │ ├── passenger-service │ │ │ ├── charts │ │ │ │ └── passenger-service │ │ │ │ │ ├── .helmignore │ │ │ │ │ ├── Chart.yaml │ │ │ │ │ ├── templates │ │ │ │ │ ├── NOTES.txt │ │ │ │ │ ├── _helpers.tpl │ │ │ │ │ ├── deployment.yaml │ │ │ │ │ ├── hpa.yaml │ │ │ │ │ ├── ingress.yaml │ │ │ │ │ ├── service.yaml │ │ │ │ │ ├── serviceaccount.yaml │ │ │ │ │ └── tests │ │ │ │ │ │ └── test-connection.yaml │ │ │ │ │ └── values.yaml │ │ │ ├── config.yaml │ │ │ └── helmfile.yaml │ │ ├── postgresql-config.yaml │ │ ├── redis │ │ │ └── helmfile.yaml │ │ └── trip-service │ │ │ ├── charts │ │ │ └── trip-service │ │ │ │ ├── .helmignore │ │ │ │ ├── Chart.yaml │ │ │ │ ├── templates │ │ │ │ ├── NOTES.txt │ │ │ │ ├── _helpers.tpl │ │ │ │ ├── deployment.yaml │ │ │ │ ├── hpa.yaml │ │ │ │ ├── ingress.yaml │ │ │ │ ├── service.yaml │ │ │ │ ├── serviceaccount.yaml │ │ │ │ └── tests │ │ │ │ │ └── test-connection.yaml │ │ │ │ └── values.yaml │ │ │ ├── config.yaml │ │ │ └── helmfile.yaml │ └── helmfile.yaml │ ├── istio │ ├── address-service-abort.yaml │ ├── address-service-auth.yaml │ ├── address-service-cb-destination-rule.yaml │ ├── address-service-delay.yaml │ ├── address-service-deployment-user.yaml │ ├── address-service-deployment.yaml │ ├── address-service-destination-rule-deployment.yaml │ ├── address-service-destination-rule.yaml │ ├── address-service-external.yaml │ ├── address-service-retry.yaml │ ├── address-service-versioned.yaml │ ├── address-service.yaml │ ├── egress-gateway.yaml │ ├── ingress-gateway.yaml │ ├── keycloak-virtual-service.yaml │ ├── keycloak.yaml │ ├── mtls-passenger-service.yaml │ ├── mtls.yaml │ ├── passenger-api-graphql-auth.yaml │ ├── passenger-api-graphql-cb-service.yaml │ ├── payment-service-destination-rule.yaml │ ├── payment-service-entry.yaml │ ├── payment-service.yaml │ ├── sleep-no-proxy.yaml │ ├── sleep.yaml │ └── virtual-service.yaml │ └── ops │ ├── apps │ ├── docker-registry │ │ └── helmfile.yaml │ └── jenkins │ │ └── helmfile.yaml │ ├── deploy-account.yaml │ └── helmfile.yaml ├── example-projects ├── passenger-web-api-falcor │ ├── .gitignore │ ├── README.md │ ├── datasource_test.js │ ├── debug.js │ ├── index.html │ ├── index.js │ ├── model_test.js │ ├── package.json │ ├── pom.xml │ ├── sample_json_graph.json │ └── yarn.lock ├── security-jwt │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── vividcode │ │ └── happyride │ │ └── security │ │ ├── JWTAuthenticationFilter.java │ │ ├── JWTFilter.java │ │ ├── JWTKeyHolder.java │ │ ├── LoginRequest.java │ │ ├── ProtectedController.java │ │ ├── ProtectedService.java │ │ ├── SecurityApplication.java │ │ ├── SecurityConstants.java │ │ ├── UserController.java │ │ └── UserInfo.java ├── trip-service-cqrs-api │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── vividcode │ │ └── happyride │ │ └── tripservice │ │ └── cqrs │ │ └── api │ │ ├── CancelTripCommand.java │ │ ├── ConfirmTripCommand.java │ │ ├── CreateTripCommand.java │ │ ├── FetchTripQuery.java │ │ ├── TripCancelledEvent.java │ │ ├── TripConfirmedEvent.java │ │ ├── TripCreatedEvent.java │ │ └── TripSummary.java └── trip-service-cqrs │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── io │ │ └── vividcode │ │ └── happyride │ │ └── tripservice │ │ └── cqrs │ │ ├── TripCqrsApplication.java │ │ ├── TripCqrsConfiguration.java │ │ ├── dataaccess │ │ ├── TripView.java │ │ ├── TripViewEventHandler.java │ │ └── TripViewRepository.java │ │ ├── domain │ │ ├── IllegalTripStateException.java │ │ ├── Trip.java │ │ ├── TripNotFoundException.java │ │ └── TripService.java │ │ └── web │ │ └── TripController.java │ └── resources │ └── application-dev.yml ├── gongzhonghao.jpg ├── happyride ├── api-client │ ├── address-service-client │ │ ├── README.md │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ └── resources │ │ │ └── openapi.yml │ ├── passenger-service-client │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ └── resources │ │ │ └── openapi.yml │ ├── pom.xml │ └── trip-service-client │ │ ├── pom.xml │ │ └── src │ │ └── main │ │ └── resources │ │ └── openapi.yml ├── api │ ├── address-service-api │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── io │ │ │ │ └── vividcode │ │ │ │ └── happyride │ │ │ │ └── addressservice │ │ │ │ └── api │ │ │ │ ├── AddressVO.java │ │ │ │ ├── AreaVO.java │ │ │ │ └── web │ │ │ │ └── AddressBatchRequest.java │ │ │ └── proto │ │ │ └── address.proto │ ├── dispatch-service-api │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ └── java │ │ │ └── io │ │ │ └── vividcode │ │ │ └── happyride │ │ │ └── dispatchservice │ │ │ └── api │ │ │ ├── DispatchServiceChannels.java │ │ │ └── events │ │ │ ├── DispatchDomainEvent.java │ │ │ ├── DriverLocation.java │ │ │ ├── DriverLocationUpdatedEvent.java │ │ │ ├── InvalidDispatchRequestReply.java │ │ │ ├── TripAcceptanceDeclinedEvent.java │ │ │ ├── TripAcceptanceDeclinedReason.java │ │ │ ├── TripAcceptanceSelectedEvent.java │ │ │ ├── TripDispatchFailedEvent.java │ │ │ ├── TripDispatchFailedReason.java │ │ │ ├── TripDispatchedEvent.java │ │ │ └── VerifyDispatchCommand.java │ ├── driver-service-api │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ └── java │ │ │ └── io │ │ │ └── vividcode │ │ │ └── happyride │ │ │ └── driverservice │ │ │ └── api │ │ │ └── web │ │ │ ├── CreateDriverRequest.java │ │ │ ├── CreateVehicleRequest.java │ │ │ ├── DriverView.java │ │ │ └── VehicleView.java │ ├── passenger-service-api │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ └── java │ │ │ └── io │ │ │ └── vividcode │ │ │ └── happyride │ │ │ └── passengerservice │ │ │ └── api │ │ │ ├── events │ │ │ ├── PassengerDetails.java │ │ │ └── PassengerDetailsUpdatedEvent.java │ │ │ └── web │ │ │ ├── CreatePassengerRequest.java │ │ │ ├── CreateUserAddressRequest.java │ │ │ ├── PassengerVO.java │ │ │ └── UserAddressVO.java │ ├── passenger-web-api │ │ ├── README.md │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── io │ │ │ │ └── vividcode │ │ │ │ └── happyride │ │ │ │ └── passengerwebapi │ │ │ │ ├── AddressServiceProxy.java │ │ │ │ ├── ApplicationConfig.java │ │ │ │ ├── DestinationConfig.java │ │ │ │ ├── PassengerHandler.java │ │ │ │ ├── PassengerResponse.java │ │ │ │ ├── PassengerServiceProxy.java │ │ │ │ ├── PassengerWebApiApplication.java │ │ │ │ ├── UserAddressResponse.java │ │ │ │ └── WebConfig.java │ │ │ └── resources │ │ │ ├── application.yml │ │ │ └── openapi.yml │ ├── payment-service-api │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ └── java │ │ │ └── io │ │ │ └── vividcode │ │ │ └── happyride │ │ │ └── paymentservice │ │ │ └── api │ │ │ ├── PaymentServiceChannels.java │ │ │ ├── events │ │ │ ├── CreatePaymentCommand.java │ │ │ ├── MakePaymentCommand.java │ │ │ └── PaymentFailedReply.java │ │ │ └── web │ │ │ └── MakePaymentRequest.java │ ├── trip-service-api │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ └── java │ │ │ └── io │ │ │ └── vividcode │ │ │ └── happyride │ │ │ └── tripservice │ │ │ └── api │ │ │ ├── TripServiceChannels.java │ │ │ ├── TripState.java │ │ │ ├── events │ │ │ ├── CancellationParty.java │ │ │ ├── DriverAcceptTripDetails.java │ │ │ ├── DriverAcceptTripEvent.java │ │ │ ├── TripCancellationResolutionRequiredEvent.java │ │ │ ├── TripCancelledEvent.java │ │ │ ├── TripConfirmedEvent.java │ │ │ ├── TripCreatedEvent.java │ │ │ ├── TripDetails.java │ │ │ ├── TripDispatchedEvent.java │ │ │ ├── TripDomainEvent.java │ │ │ ├── TripFinishedEvent.java │ │ │ ├── TripRejectedEvent.java │ │ │ └── TripStartedEvent.java │ │ │ └── web │ │ │ ├── AcceptTripRequest.java │ │ │ ├── CreateTripRequest.java │ │ │ └── TripVO.java │ └── trip-validation-service-api │ │ ├── pom.xml │ │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── vividcode │ │ └── happyride │ │ └── tripvalidationservice │ │ └── api │ │ ├── InvalidTripReply.java │ │ ├── TripValidationServiceChannels.java │ │ └── ValidateTripCommand.java ├── lib │ ├── common │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ └── java │ │ │ └── io │ │ │ └── vividcode │ │ │ └── happyride │ │ │ └── common │ │ │ ├── AbstractEntity.java │ │ │ ├── BaseEntityWithGeneratedId.java │ │ │ ├── DatabaseRuntimeHintsRegistrar.java │ │ │ ├── DriverState.java │ │ │ ├── EntityWithGeneratedId.java │ │ │ ├── Position.java │ │ │ ├── PositionVO.java │ │ │ └── Utils.java │ └── postgres-common │ │ ├── pom.xml │ │ └── src │ │ └── test │ │ └── java │ │ └── io │ │ └── vividcode │ │ └── happyride │ │ └── postgres │ │ └── common │ │ └── EmbeddedPostgresConfiguration.java ├── pom.xml ├── service │ ├── address-service │ │ ├── README.md │ │ ├── pom.xml │ │ └── src │ │ │ ├── docker │ │ │ └── Dockerfile │ │ │ ├── k8s │ │ │ ├── app.yml │ │ │ ├── config.yml │ │ │ ├── postgres.yml │ │ │ ├── secret.yml │ │ │ └── service-monitor.yml │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── io │ │ │ │ │ └── vividcode │ │ │ │ │ └── happyride │ │ │ │ │ └── addressservice │ │ │ │ │ ├── AddressServiceApplication.java │ │ │ │ │ ├── ApplicationConfig.java │ │ │ │ │ ├── dataaccess │ │ │ │ │ ├── AddressRepository.java │ │ │ │ │ └── AreaRepository.java │ │ │ │ │ ├── domain │ │ │ │ │ ├── Address.java │ │ │ │ │ └── Area.java │ │ │ │ │ ├── grpc │ │ │ │ │ └── AddressGrpcService.java │ │ │ │ │ ├── service │ │ │ │ │ ├── AddressHelper.java │ │ │ │ │ ├── AddressLoader.java │ │ │ │ │ ├── AddressService.java │ │ │ │ │ └── AreaService.java │ │ │ │ │ └── web │ │ │ │ │ └── AddressController.java │ │ │ └── resources │ │ │ │ ├── application-dev.yml │ │ │ │ ├── application.yml │ │ │ │ └── db │ │ │ │ └── migration │ │ │ │ ├── V1__init_schema.sql │ │ │ │ └── V2__init_area_data.sql │ │ │ └── test │ │ │ ├── java │ │ │ └── io │ │ │ │ └── vividcode │ │ │ │ └── happyride │ │ │ │ └── addressservice │ │ │ │ ├── AddressGrpcServiceTest.java │ │ │ │ └── AddressServiceTest.java │ │ │ └── resources │ │ │ └── application.yml │ ├── dispatch-service │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── io │ │ │ │ │ └── vividcode │ │ │ │ │ └── happyride │ │ │ │ │ └── dispatchservice │ │ │ │ │ ├── ApplicationConfig.java │ │ │ │ │ ├── AvailableDriver.java │ │ │ │ │ ├── DispatchService.java │ │ │ │ │ ├── DispatchServiceApplication.java │ │ │ │ │ ├── DispatchVerificationException.java │ │ │ │ │ ├── DriverLocationService.java │ │ │ │ │ ├── DriverLocationUpdater.java │ │ │ │ │ ├── TripAcceptanceService.java │ │ │ │ │ ├── commandhandlers │ │ │ │ │ ├── DispatchCommandHandlers.java │ │ │ │ │ └── DispatchCommandHandlersConfiguration.java │ │ │ │ │ ├── dataaccess │ │ │ │ │ └── DispatchRepository.java │ │ │ │ │ ├── domain │ │ │ │ │ ├── Dispatch.java │ │ │ │ │ ├── DispatchDomainEventPublisher.java │ │ │ │ │ ├── DispatchState.java │ │ │ │ │ ├── TripAcceptance.java │ │ │ │ │ └── TripAcceptanceState.java │ │ │ │ │ └── messagehandlers │ │ │ │ │ ├── DispatchServiceEventConsumer.java │ │ │ │ │ └── DispatchServiceMessageHandlersConfiguration.java │ │ │ └── resources │ │ │ │ ├── application.yml │ │ │ │ └── db │ │ │ │ └── migration │ │ │ │ └── V1__init_schema.sql │ │ │ └── test │ │ │ ├── java │ │ │ └── io │ │ │ │ └── vividcode │ │ │ │ └── happyride │ │ │ │ └── dispatchservice │ │ │ │ ├── DispatchServiceTest.java │ │ │ │ ├── DriverLocationServiceTest.java │ │ │ │ ├── TestUtils.java │ │ │ │ └── TripAcceptanceServiceTest.java │ │ │ └── resources │ │ │ └── application.yml │ ├── driver-service │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── io │ │ │ │ │ └── vividcode │ │ │ │ │ └── happyride │ │ │ │ │ └── driverservice │ │ │ │ │ ├── ApplicationConfig.java │ │ │ │ │ ├── DriverServiceApplication.java │ │ │ │ │ ├── dataaccess │ │ │ │ │ └── DriverRepository.java │ │ │ │ │ ├── model │ │ │ │ │ ├── Driver.java │ │ │ │ │ └── Vehicle.java │ │ │ │ │ ├── service │ │ │ │ │ ├── DriverNotFoundException.java │ │ │ │ │ └── DriverService.java │ │ │ │ │ ├── support │ │ │ │ │ └── DriverUtils.java │ │ │ │ │ └── web │ │ │ │ │ └── DriverController.java │ │ │ └── resources │ │ │ │ ├── application-dev.yml │ │ │ │ ├── application.yml │ │ │ │ └── db │ │ │ │ └── migration │ │ │ │ └── V1__init_schema.sql │ │ │ └── test │ │ │ ├── java │ │ │ └── io │ │ │ │ └── vividcode │ │ │ │ └── happyride │ │ │ │ └── driverservice │ │ │ │ ├── DriverControllerTest.java │ │ │ │ ├── DriverServiceTest.java │ │ │ │ └── DriverTestUtils.java │ │ │ └── resources │ │ │ └── application.yml │ ├── passenger-service │ │ ├── README.md │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── io │ │ │ │ │ └── vividcode │ │ │ │ │ └── happyride │ │ │ │ │ └── passengerservice │ │ │ │ │ ├── ApplicationConfig.java │ │ │ │ │ ├── PassengerServiceApplication.java │ │ │ │ │ ├── dataaccess │ │ │ │ │ └── PassengerRepository.java │ │ │ │ │ ├── domain │ │ │ │ │ ├── Passenger.java │ │ │ │ │ ├── PassengerNotFoundException.java │ │ │ │ │ ├── PassengerService.java │ │ │ │ │ ├── PassengerUtils.java │ │ │ │ │ ├── TripServiceProxy.java │ │ │ │ │ └── UserAddress.java │ │ │ │ │ ├── messagehandlers │ │ │ │ │ ├── PassengerServiceEventConsumer.java │ │ │ │ │ └── PassengerServiceMessageHandlersConfiguration.java │ │ │ │ │ └── web │ │ │ │ │ └── PassengerController.java │ │ │ └── resources │ │ │ │ ├── application-dev.yml │ │ │ │ ├── application.yml │ │ │ │ └── db │ │ │ │ └── migration │ │ │ │ └── V1__init_schema.sql │ │ │ └── test │ │ │ ├── java │ │ │ └── io │ │ │ │ └── vividcode │ │ │ │ └── happyride │ │ │ │ ├── bdd │ │ │ │ ├── BddTestApplication.java │ │ │ │ ├── PassengerIntegrationTest.java │ │ │ │ ├── common │ │ │ │ │ └── PassengerClient.java │ │ │ │ └── stepdefs │ │ │ │ │ └── AddressStepdefs.java │ │ │ │ ├── junit5 │ │ │ │ └── JUnit5Sample.java │ │ │ │ ├── mocktest │ │ │ │ ├── ActionService.java │ │ │ │ ├── ActionServiceTest.java │ │ │ │ ├── EventPublisher.java │ │ │ │ ├── TestConfiguration.java │ │ │ │ ├── ValueUpdatedEvent.java │ │ │ │ └── ValueUpdater.java │ │ │ │ └── passengerservice │ │ │ │ ├── PassengerControllerClientTest.java │ │ │ │ ├── PassengerControllerTest.java │ │ │ │ ├── PassengerServiceTest.java │ │ │ │ ├── PassengerTest.java │ │ │ │ └── PassengerTestApplication.java │ │ │ └── resources │ │ │ ├── application.yml │ │ │ └── features │ │ │ └── address.feature │ ├── payment-service │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── io │ │ │ │ └── vividcode │ │ │ │ └── happyride │ │ │ │ └── paymentservice │ │ │ │ ├── ApplicationConfig.java │ │ │ │ ├── PaymentApplication.java │ │ │ │ ├── commandhandlers │ │ │ │ ├── PaymentCommandHandlers.java │ │ │ │ └── PaymentCommandHandlersConfiguration.java │ │ │ │ ├── dataaccess │ │ │ │ └── PaymentRepository.java │ │ │ │ ├── domain │ │ │ │ ├── Payment.java │ │ │ │ ├── PaymentException.java │ │ │ │ ├── PaymentGateway.java │ │ │ │ ├── PaymentNotFoundException.java │ │ │ │ ├── PaymentResult.java │ │ │ │ ├── PaymentService.java │ │ │ │ └── PaymentState.java │ │ │ │ └── web │ │ │ │ └── PaymentController.java │ │ │ └── resources │ │ │ ├── application-dev.yml │ │ │ ├── application.yml │ │ │ └── db │ │ │ └── migration │ │ │ └── V1__init_schema.sql │ ├── pom.xml │ ├── trip-history-service │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── io │ │ │ │ └── vividcode │ │ │ │ └── happyride │ │ │ │ └── triphistoryservice │ │ │ │ ├── ApplicationConfig.java │ │ │ │ ├── TripHistoryApplication.java │ │ │ │ ├── dataaccess │ │ │ │ └── TripRepository.java │ │ │ │ ├── domain │ │ │ │ ├── Trip.java │ │ │ │ └── TripService.java │ │ │ │ ├── messagehandlers │ │ │ │ ├── TripHistoryServiceEventConsumer.java │ │ │ │ └── TripHistoryServiceMessageHandlersConfiguration.java │ │ │ │ └── web │ │ │ │ └── TripController.java │ │ │ └── resources │ │ │ ├── application-dev.yml │ │ │ ├── application.yml │ │ │ └── db │ │ │ └── migration │ │ │ └── V1__init_schema.sql │ ├── trip-service │ │ ├── README.md │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── io │ │ │ │ │ └── vividcode │ │ │ │ │ └── happyride │ │ │ │ │ └── tripservice │ │ │ │ │ ├── ApplicationConfig.java │ │ │ │ │ ├── TripApplication.java │ │ │ │ │ ├── commandhandlers │ │ │ │ │ ├── TripCommandHandlers.java │ │ │ │ │ └── TripCommandHandlersConfiguration.java │ │ │ │ │ ├── commandsample │ │ │ │ │ ├── CommandTests.java │ │ │ │ │ ├── EchoCommand.java │ │ │ │ │ ├── EchoCommandHandlers.java │ │ │ │ │ ├── EchoConfiguration.java │ │ │ │ │ ├── QueryWeatherCommand.java │ │ │ │ │ ├── QueryWeatherResult.java │ │ │ │ │ ├── WeatherCommandHandlers.java │ │ │ │ │ └── WeatherConfiguration.java │ │ │ │ │ ├── dataaccess │ │ │ │ │ └── TripRepository.java │ │ │ │ │ ├── domain │ │ │ │ │ ├── IllegalTripStateException.java │ │ │ │ │ ├── Trip.java │ │ │ │ │ ├── TripDomainEventPublisher.java │ │ │ │ │ ├── TripFareService.java │ │ │ │ │ └── TripService.java │ │ │ │ │ ├── messagehandlers │ │ │ │ │ ├── TripServiceEventConsumer.java │ │ │ │ │ └── TripServiceMessageHandlersConfiguration.java │ │ │ │ │ ├── sagaparticipants │ │ │ │ │ ├── ConfirmTripCommand.java │ │ │ │ │ ├── PaymentServiceProxy.java │ │ │ │ │ ├── RejectTripCommand.java │ │ │ │ │ ├── TripCommand.java │ │ │ │ │ ├── TripServiceProxy.java │ │ │ │ │ └── TripValidationServiceProxy.java │ │ │ │ │ ├── sagas │ │ │ │ │ └── createtrip │ │ │ │ │ │ ├── CreateTripSaga.java │ │ │ │ │ │ └── CreateTripSagaState.java │ │ │ │ │ └── web │ │ │ │ │ └── TripController.java │ │ │ └── resources │ │ │ │ ├── application-dev.yml │ │ │ │ ├── application.yml │ │ │ │ └── db │ │ │ │ └── migration │ │ │ │ ├── V1__init_schema.sql │ │ │ │ └── V2__init_eventuate_schema.sql │ │ │ └── test │ │ │ ├── java │ │ │ └── io │ │ │ │ └── vividcode │ │ │ │ └── happyride │ │ │ │ └── tripservice │ │ │ │ ├── TripServiceTest.java │ │ │ │ └── sagas │ │ │ │ └── createtrip │ │ │ │ └── CreateTripSagaTest.java │ │ │ └── resources │ │ │ └── application.yml │ └── trip-validation-service │ │ ├── pom.xml │ │ └── src │ │ ├── main │ │ ├── java │ │ │ └── io │ │ │ │ └── vividcode │ │ │ │ └── happyride │ │ │ │ └── tripvalidationservice │ │ │ │ ├── AppConfig.java │ │ │ │ ├── TripValidationServiceApplication.java │ │ │ │ ├── domain │ │ │ │ ├── TripValidationServiceCommandHandlers.java │ │ │ │ └── TripValidationServiceConfiguration.java │ │ │ │ └── service │ │ │ │ ├── PassengerBlockedException.java │ │ │ │ ├── TripDistanceTooLongException.java │ │ │ │ ├── TripValidationException.java │ │ │ │ └── TripValidationService.java │ │ └── resources │ │ │ ├── application-dev.yml │ │ │ └── application.yml │ │ └── test │ │ └── java │ │ └── io │ │ └── vividcode │ │ └── happyride │ │ └── tripvalidationservice │ │ └── service │ │ └── TripValidationServiceTest.java └── tools │ ├── driver-simulator-ui │ ├── app │ │ ├── .editorconfig │ │ ├── .gitignore │ │ ├── .prettierrc │ │ ├── README.md │ │ ├── angular.json │ │ ├── browserslist │ │ ├── e2e │ │ │ ├── protractor.conf.js │ │ │ ├── src │ │ │ │ ├── app.e2e-spec.ts │ │ │ │ └── app.po.ts │ │ │ └── tsconfig.json │ │ ├── karma.conf.js │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app │ │ │ │ ├── app-routing.module.ts │ │ │ │ ├── app.component.html │ │ │ │ ├── app.component.scss │ │ │ │ ├── app.component.spec.ts │ │ │ │ ├── app.component.ts │ │ │ │ ├── app.module.ts │ │ │ │ ├── components │ │ │ │ │ └── drivers-list │ │ │ │ │ │ ├── drivers-list.component.html │ │ │ │ │ │ ├── drivers-list.component.scss │ │ │ │ │ │ └── drivers-list.component.ts │ │ │ │ ├── driver.service.ts │ │ │ │ └── model.ts │ │ │ ├── assets │ │ │ │ └── .gitkeep │ │ │ ├── environments │ │ │ │ ├── environment.prod.ts │ │ │ │ └── environment.ts │ │ │ ├── favicon.ico │ │ │ ├── index.html │ │ │ ├── main.ts │ │ │ ├── polyfills.ts │ │ │ ├── proxy.conf.json │ │ │ ├── styles.scss │ │ │ └── test.ts │ │ ├── tsconfig.app.json │ │ ├── tsconfig.json │ │ ├── tsconfig.spec.json │ │ └── tslint.json │ └── pom.xml │ └── driver-simulator │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── io │ │ └── vividcode │ │ └── happyride │ │ └── driversimulator │ │ ├── ApplicationConfig.java │ │ ├── DriverSimulator.java │ │ ├── DriverSimulatorFactory.java │ │ ├── DriverSimulatorMain.java │ │ ├── DriverSimulatorNotFoundException.java │ │ ├── DriverSimulatorRegistry.java │ │ ├── DriverSimulatorSnapshot.java │ │ └── web │ │ ├── AddDriverRequest.java │ │ ├── DriverSimulatorController.java │ │ ├── IndexController.java │ │ └── ResetPositionRequest.java │ └── resources │ ├── application-dev.yml │ └── application.yml └── pom.xml /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: maven 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | defaults: 13 | run: 14 | working-directory: happyride 15 | 16 | jobs: 17 | build: 18 | 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | - name: Set up JDK 17 24 | uses: actions/setup-java@v1 25 | with: 26 | java-version: 17 27 | - name: Cache Maven packages 28 | uses: actions/cache@v2 29 | with: 30 | path: ~/.m2 31 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 32 | restore-keys: ${{ runner.os }}-m2 33 | - name: Build with Maven 34 | run: mvn -B -ntp package --file pom.xml 35 | -------------------------------------------------------------------------------- /cloud-native.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexcheng1982/happyride/17a507fca213d87dab849b6cef6f1f469433b42e/cloud-native.jpg -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/address-service/address-service-config.yaml: -------------------------------------------------------------------------------- 1 | nameOverride: address-service 2 | 3 | resources: 4 | requests: 5 | memory: "512Mi" 6 | cpu: "500m" 7 | limits: 8 | memory: "1Gi" 9 | cpu: "1" -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/address-service/charts/address-service-common/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/address-service/charts/address-service-common/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: address-service-common 3 | description: Address service common 4 | 5 | type: application 6 | 7 | 8 | version: 0.0.1 9 | 10 | appVersion: 1.0.0 11 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/address-service/charts/address-service-common/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "address-service-common.serviceName" . }} 5 | labels: 6 | {{- include "address-service-common.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "address-service-common.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/address-service/charts/address-service/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/address-service/charts/address-service/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: address-service 3 | description: Address service 4 | 5 | type: application 6 | 7 | version: 0.0.1 8 | 9 | appVersion: 1.1.0 10 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/address-service/charts/address-service/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2beta1 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "address-service.fullname" . }} 6 | labels: 7 | {{- include "address-service.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "address-service.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 21 | {{- end }} 22 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 23 | - type: Resource 24 | resource: 25 | name: memory 26 | targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 27 | {{- end }} 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/address-service/charts/address-service/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "address-service.serviceAccountName" . }} 6 | labels: 7 | {{- include "address-service.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/address-service/config.yaml: -------------------------------------------------------------------------------- 1 | postgresqlDatabase: postgres 2 | postgresqlUsername: postgres 3 | postgresqlPassword: postgres -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/address-service/helmfile.yaml: -------------------------------------------------------------------------------- 1 | repositories: 2 | - name: bitnami 3 | url: https://charts.bitnami.com/bitnami 4 | releases: 5 | - name: postgresql-address 6 | namespace: {{ env "NAMESPACE" | default "happyride" }} 7 | chart: bitnami/postgresql 8 | version: 8.10.13 9 | wait: false 10 | values: 11 | - ../postgresql-config.yaml 12 | - config.yaml 13 | - name: address-service-common 14 | namespace: {{ env "NAMESPACE" | default "happyride" }} 15 | chart: charts/address-service-common 16 | - name: address-service-{{ requiredEnv "DEPLOYMENT_TYPE" }} 17 | namespace: {{ env "NAMESPACE" | default "happyride" }} 18 | chart: charts/address-service 19 | values: 20 | - config.yaml 21 | - address-service-config.yaml 22 | - deploymentType: {{ requiredEnv "DEPLOYMENT_TYPE" | quote }} 23 | appVersion: {{ requiredEnv "ADDRESS_SERVICE_VERSION" | quote }} 24 | image: 25 | repository: {{ printf "%shappyride/happyride-address-service" (env "CONTAINER_REGISTRY" | default "" ) | quote }} -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/axon/charts/axon/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/axon/charts/axon/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: axon 3 | description: Axon 4 | 5 | type: application 6 | 7 | version: 0.0.1 8 | 9 | appVersion: 4.3.3 10 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/axon/charts/axon/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2beta1 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "axon.fullname" . }} 6 | labels: 7 | {{- include "axon.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "axon.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 21 | {{- end }} 22 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 23 | - type: Resource 24 | resource: 25 | name: memory 26 | targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 27 | {{- end }} 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/axon/charts/axon/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "axon.fullname" . }} 5 | labels: 6 | {{- include "axon.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "axon.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/axon/charts/axon/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "axon.serviceAccountName" . }} 6 | labels: 7 | {{- include "axon.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/axon/charts/axon/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "axon.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "axon.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test-success 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "axon.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/axon/charts/axon/values.yaml: -------------------------------------------------------------------------------- 1 | replicaCount: 1 2 | 3 | image: 4 | repository: axoniq/axonserver 5 | pullPolicy: IfNotPresent 6 | tag: "" 7 | 8 | imagePullSecrets: [] 9 | nameOverride: "" 10 | fullnameOverride: "" 11 | 12 | serviceAccount: 13 | create: true 14 | annotations: {} 15 | name: "" 16 | 17 | podAnnotations: {} 18 | 19 | podSecurityContext: {} 20 | 21 | 22 | securityContext: {} 23 | 24 | service: 25 | type: ClusterIP 26 | port: 80 27 | 28 | ingress: 29 | enabled: false 30 | annotations: {} 31 | hosts: 32 | - host: axon.local 33 | paths: [] 34 | tls: [] 35 | 36 | resources: {} 37 | 38 | autoscaling: 39 | enabled: false 40 | minReplicas: 1 41 | maxReplicas: 100 42 | targetCPUUtilizationPercentage: 80 43 | 44 | nodeSelector: {} 45 | 46 | tolerations: [] 47 | 48 | affinity: {} 49 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/axon/helmfile.yaml: -------------------------------------------------------------------------------- 1 | releases: 2 | - name: axon 3 | namespace: {{ env "NAMESPACE" | default "happyride" }} 4 | chart: charts/axon 5 | wait: false 6 | values: 7 | - resources: 8 | limits: 9 | cpu: 500m 10 | memory: 512Mi 11 | requests: 12 | cpu: 200m 13 | memory: 256Mi 14 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/common/charts/common/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/common/charts/common/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: common 3 | description: Common 4 | 5 | type: application 6 | 7 | version: 0.0.1 8 | 9 | appVersion: 1.0.0 10 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/common/charts/common/spring-config/management.yml: -------------------------------------------------------------------------------- 1 | management: 2 | health: 3 | livenessState: 4 | enabled: true 5 | readinessState: 6 | enabled: true 7 | endpoints: 8 | enabled-by-default: false 9 | web: 10 | exposure: 11 | include: prometheus, health 12 | endpoint: 13 | health: 14 | enabled: true 15 | show-components: always 16 | prometheus: 17 | enabled: true -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/common/charts/common/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | Common configs -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/common/charts/common/templates/spring-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ include "common.fullname" . }}-spring-config 5 | labels: 6 | {{- include "common.labels" . | nindent 4 }} 7 | data: 8 | {{ (.Files.Glob "spring-config/**.yml").AsConfig | indent 2 }} 9 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/common/charts/common/values.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexcheng1982/happyride/17a507fca213d87dab849b6cef6f1f469433b42e/devops/k8s/happyride/apps/common/charts/common/values.yaml -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/common/helmfile.yaml: -------------------------------------------------------------------------------- 1 | releases: 2 | - name: common 3 | namespace: {{ env "NAMESPACE" | default "happyride" }} 4 | chart: charts/common -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/kafka/helmfile.yaml: -------------------------------------------------------------------------------- 1 | repositories: 2 | - name: bitnami 3 | url: https://charts.bitnami.com/bitnami 4 | 5 | releases: 6 | - name: kafka 7 | namespace: {{ env "NAMESPACE" | default "happyride" }} 8 | chart: bitnami/kafka 9 | version: 11.3.2 10 | wait: true 11 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/passenger-api-graphql/charts/passenger-api-graphql/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/passenger-api-graphql/charts/passenger-api-graphql/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: passenger-api-graphql 3 | description: GraphQL API for passenger UI 4 | 5 | type: application 6 | 7 | version: 0.0.1 8 | 9 | appVersion: 1.0.0 10 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/passenger-api-graphql/charts/passenger-api-graphql/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2beta1 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "passenger-api-graphql.fullname" . }} 6 | labels: 7 | {{- include "passenger-api-graphql.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "passenger-api-graphql.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 21 | {{- end }} 22 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 23 | - type: Resource 24 | resource: 25 | name: memory 26 | targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 27 | {{- end }} 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/passenger-api-graphql/charts/passenger-api-graphql/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "passenger-api-graphql.fullname" . }} 5 | labels: 6 | {{- include "passenger-api-graphql.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "passenger-api-graphql.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/passenger-api-graphql/charts/passenger-api-graphql/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "passenger-api-graphql.serviceAccountName" . }} 6 | labels: 7 | {{- include "passenger-api-graphql.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/passenger-api-graphql/charts/passenger-api-graphql/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "passenger-api-graphql.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "passenger-api-graphql.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test-success 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "passenger-api-graphql.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/passenger-api-graphql/helmfile.yaml: -------------------------------------------------------------------------------- 1 | releases: 2 | - name: passenger-api-graphql 3 | namespace: {{ env "NAMESPACE" | default "happyride" }} 4 | chart: charts/passenger-api-graphql 5 | values: 6 | - image: 7 | tag: {{ requiredEnv "PASSENGER_API_GRAPHQL_VERSION" | quote }} -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/passenger-service/charts/passenger-service/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/passenger-service/charts/passenger-service/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: passenger-service 3 | description: Passenger service 4 | 5 | type: application 6 | 7 | version: 0.0.1 8 | 9 | appVersion: 1.0.0 10 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/passenger-service/charts/passenger-service/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2beta1 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "passenger-service.fullname" . }} 6 | labels: 7 | {{- include "passenger-service.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "passenger-service.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 21 | {{- end }} 22 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 23 | - type: Resource 24 | resource: 25 | name: memory 26 | targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 27 | {{- end }} 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/passenger-service/charts/passenger-service/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "passenger-service.fullname" . }} 5 | labels: 6 | {{- include "passenger-service.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "passenger-service.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/passenger-service/charts/passenger-service/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "passenger-service.serviceAccountName" . }} 6 | labels: 7 | {{- include "passenger-service.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/passenger-service/charts/passenger-service/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "passenger-service.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "passenger-service.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test-success 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "passenger-service.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/passenger-service/config.yaml: -------------------------------------------------------------------------------- 1 | postgresqlDatabase: postgres 2 | postgresqlUsername: postgres 3 | postgresqlPassword: postgres -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/passenger-service/helmfile.yaml: -------------------------------------------------------------------------------- 1 | repositories: 2 | - name: bitnami 3 | url: https://charts.bitnami.com/bitnami 4 | releases: 5 | - name: postgresql-passenger 6 | namespace: {{ env "NAMESPACE" | default "happyride" }} 7 | chart: bitnami/postgresql 8 | version: 8.10.13 9 | wait: false 10 | values: 11 | - ../postgresql-config.yaml 12 | - config.yaml 13 | - name: passenger-service 14 | namespace: {{ env "NAMESPACE" | default "happyride" }} 15 | chart: charts/passenger-service 16 | values: 17 | - config.yaml 18 | - image: 19 | tag: {{ requiredEnv "PASSENGER_SERVICE_VERSION" | quote }} 20 | resources: 21 | requests: 22 | memory: "512Mi" 23 | cpu: "500m" 24 | limits: 25 | memory: "1Gi" 26 | cpu: "1" -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/postgresql-config.yaml: -------------------------------------------------------------------------------- 1 | image: 2 | repository: eventuateio/eventuate-postgres 3 | tag: 0.9.0.RELEASE -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/redis/helmfile.yaml: -------------------------------------------------------------------------------- 1 | repositories: 2 | - name: bitnami 3 | url: https://charts.bitnami.com/bitnami 4 | 5 | releases: 6 | - name: redis 7 | namespace: {{ env "NAMESPACE" | default "happyride" }} 8 | chart: bitnami/redis 9 | version: 10.7.9 10 | wait: true 11 | values: 12 | - password: redis 13 | cluster: 14 | enabled: false 15 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/trip-service/charts/trip-service/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/trip-service/charts/trip-service/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: trip-service 3 | description: Trip service 4 | 5 | type: application 6 | 7 | version: 0.0.1 8 | 9 | appVersion: 1.0.0 10 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/trip-service/charts/trip-service/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2beta1 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "trip-service.fullname" . }} 6 | labels: 7 | {{- include "trip-service.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "trip-service.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 21 | {{- end }} 22 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 23 | - type: Resource 24 | resource: 25 | name: memory 26 | targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 27 | {{- end }} 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/trip-service/charts/trip-service/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "trip-service.fullname" . }} 5 | labels: 6 | {{- include "trip-service.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "trip-service.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/trip-service/charts/trip-service/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "trip-service.serviceAccountName" . }} 6 | labels: 7 | {{- include "trip-service.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/trip-service/charts/trip-service/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "trip-service.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "trip-service.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test-success 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "trip-service.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/trip-service/config.yaml: -------------------------------------------------------------------------------- 1 | postgresqlDatabase: postgres 2 | postgresqlUsername: postgres 3 | postgresqlPassword: postgres -------------------------------------------------------------------------------- /devops/k8s/happyride/apps/trip-service/helmfile.yaml: -------------------------------------------------------------------------------- 1 | repositories: 2 | - name: bitnami 3 | url: https://charts.bitnami.com/bitnami 4 | releases: 5 | - name: postgresql-trip 6 | namespace: {{ env "NAMESPACE" | default "happyride" }} 7 | chart: bitnami/postgresql 8 | version: 8.10.13 9 | wait: false 10 | values: 11 | - ../postgresql-config.yaml 12 | - config.yaml 13 | - name: trip-service 14 | namespace: {{ env "NAMESPACE" | default "happyride" }} 15 | chart: charts/trip-service 16 | values: 17 | - config.yaml 18 | - image: 19 | tag: {{ requiredEnv "TRIP_SERVICE_VERSION" | quote }} 20 | resources: 21 | requests: 22 | memory: "512Mi" 23 | cpu: "500m" 24 | limits: 25 | memory: "1Gi" 26 | cpu: "1" 27 | -------------------------------------------------------------------------------- /devops/k8s/happyride/helmfile.yaml: -------------------------------------------------------------------------------- 1 | helmfiles: 2 | - apps/*/helmfile.yaml -------------------------------------------------------------------------------- /devops/k8s/istio/address-service-abort.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: VirtualService 3 | metadata: 4 | name: address-service 5 | spec: 6 | hosts: 7 | - address-service.happyride.svc.cluster.local 8 | http: 9 | - name: "address-service-http" 10 | route: 11 | - destination: 12 | host: address-service.happyride.svc.cluster.local 13 | fault: 14 | abort: 15 | httpStatus: 503 16 | percentage: 17 | value: 50 -------------------------------------------------------------------------------- /devops/k8s/istio/address-service-auth.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: security.istio.io/v1beta1 2 | kind: AuthorizationPolicy 3 | metadata: 4 | name: address-service 5 | spec: 6 | action: ALLOW 7 | selector: 8 | matchLabels: 9 | app.kubernetes.io/name: address-service 10 | rules: 11 | - from: 12 | - source: 13 | principals: 14 | - "cluster.local/ns/happyride/sa/passenger-api-graphql" 15 | to: 16 | - operation: 17 | methods: 18 | - GET 19 | - POST 20 | -------------------------------------------------------------------------------- /devops/k8s/istio/address-service-cb-destination-rule.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: DestinationRule 3 | metadata: 4 | name: address-service-cb 5 | spec: 6 | host: address-service.happyride.svc.cluster.local 7 | trafficPolicy: 8 | connectionPool: 9 | tcp: 10 | maxConnections: 1 11 | http: 12 | http1MaxPendingRequests: 1 13 | maxRequestsPerConnection: 1 14 | maxRetries: 1 15 | outlierDetection: 16 | consecutive5xxErrors: 10 17 | baseEjectionTime: 20s 18 | interval: 5s 19 | -------------------------------------------------------------------------------- /devops/k8s/istio/address-service-delay.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: VirtualService 3 | metadata: 4 | name: address-service 5 | spec: 6 | hosts: 7 | - address-service.happyride.svc.cluster.local 8 | http: 9 | - name: "address-service-http" 10 | route: 11 | - destination: 12 | host: address-service.happyride.svc.cluster.local 13 | fault: 14 | delay: 15 | fixedDelay: 500ms 16 | percentage: 17 | value: 100 -------------------------------------------------------------------------------- /devops/k8s/istio/address-service-deployment-user.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: VirtualService 3 | metadata: 4 | name: address-service-deployment 5 | spec: 6 | hosts: 7 | - address-service.happyride.svc.cluster.local 8 | http: 9 | - name: "latest" 10 | match: 11 | - headers: 12 | x-latest-version: 13 | exact: "true" 14 | route: 15 | - destination: 16 | host: address-service.happyride.svc.cluster.local 17 | subset: green 18 | - name: "current" 19 | route: 20 | - destination: 21 | host: address-service.happyride.svc.cluster.local 22 | subset: blue 23 | -------------------------------------------------------------------------------- /devops/k8s/istio/address-service-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: VirtualService 3 | metadata: 4 | name: address-service-deployment 5 | spec: 6 | hosts: 7 | - address-service.happyride.svc.cluster.local 8 | http: 9 | - name: "address-service-http" 10 | route: 11 | - destination: 12 | host: address-service.happyride.svc.cluster.local 13 | subset: blue 14 | weight: 99 15 | - destination: 16 | host: address-service.happyride.svc.cluster.local 17 | subset: green 18 | weight: 1 19 | -------------------------------------------------------------------------------- /devops/k8s/istio/address-service-destination-rule-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: DestinationRule 3 | metadata: 4 | name: address-service 5 | spec: 6 | host: address-service.happyride.svc.cluster.local 7 | subsets: 8 | - name: blue 9 | labels: 10 | app.vividcode.io/deployment-type: "blue" 11 | - name: green 12 | labels: 13 | app.vividcode.io/deployment-type: "green" -------------------------------------------------------------------------------- /devops/k8s/istio/address-service-destination-rule.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: DestinationRule 3 | metadata: 4 | name: address-service 5 | spec: 6 | host: address-service.happyride.svc.cluster.local 7 | trafficPolicy: 8 | loadBalancer: 9 | simple: LEAST_CONN 10 | subsets: 11 | - name: v1 12 | labels: 13 | app.vividcode.io/service-version: "1" 14 | - name: v2 15 | labels: 16 | app.vividcode.io/service-version: "2" -------------------------------------------------------------------------------- /devops/k8s/istio/address-service-external.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: VirtualService 3 | metadata: 4 | name: app-service 5 | spec: 6 | hosts: 7 | - happyride.com 8 | gateways: 9 | - app-gateway 10 | http: 11 | - name: "address-service-external" 12 | match: 13 | - uri: 14 | prefix: "/address" 15 | rewrite: 16 | uri: "/" 17 | route: 18 | - destination: 19 | host: address-service.happyride.svc.cluster.local 20 | - name: "passenger-service-external" 21 | match: 22 | - uri: 23 | prefix: "/passenger" 24 | rewrite: 25 | uri: "/" 26 | route: 27 | - destination: 28 | host: passenger-service.happyride.svc.cluster.local 29 | -------------------------------------------------------------------------------- /devops/k8s/istio/address-service-retry.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: VirtualService 3 | metadata: 4 | name: address-service 5 | spec: 6 | hosts: 7 | - address-service.happyride.svc.cluster.local 8 | http: 9 | - name: "address-service-http" 10 | route: 11 | - destination: 12 | host: address-service.happyride.svc.cluster.local 13 | retries: 14 | attempts: 3 15 | perTryTimeout: 200ms 16 | retryOn: gateway-error,connect-failure,refused-stream -------------------------------------------------------------------------------- /devops/k8s/istio/address-service-versioned.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: VirtualService 3 | metadata: 4 | name: address-service-versioned 5 | spec: 6 | hosts: 7 | - address-service.happyride.svc.cluster.local 8 | http: 9 | - name: "address-service-http" 10 | route: 11 | - destination: 12 | host: address-service.happyride.svc.cluster.local 13 | subset: v1 14 | weight: 50 15 | - destination: 16 | host: address-service.happyride.svc.cluster.local 17 | subset: v2 18 | weight: 50 19 | -------------------------------------------------------------------------------- /devops/k8s/istio/address-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: VirtualService 3 | metadata: 4 | name: address-service 5 | spec: 6 | hosts: 7 | - address-service.happyride.svc.cluster.local 8 | http: 9 | - name: "address-service-http" 10 | route: 11 | - destination: 12 | host: address-service.happyride.svc.cluster.local 13 | headers: 14 | response: 15 | add: 16 | x-hello: world 17 | -------------------------------------------------------------------------------- /devops/k8s/istio/egress-gateway.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: Gateway 3 | metadata: 4 | name: app-external 5 | spec: 6 | selector: 7 | app: istio-egressgateway 8 | servers: 9 | - port: 10 | number: 80 11 | name: http 12 | protocol: HTTP 13 | hosts: 14 | - "*" -------------------------------------------------------------------------------- /devops/k8s/istio/ingress-gateway.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: Gateway 3 | metadata: 4 | name: app-gateway 5 | spec: 6 | selector: 7 | app: istio-ingressgateway 8 | servers: 9 | - port: 10 | number: 80 11 | name: http 12 | protocol: HTTP 13 | hosts: 14 | - "happyride.com" 15 | -------------------------------------------------------------------------------- /devops/k8s/istio/keycloak-virtual-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: VirtualService 3 | metadata: 4 | name: keycloak 5 | spec: 6 | hosts: 7 | - happyride.com 8 | gateways: 9 | - app-gateway 10 | http: 11 | - name: "keycloak-service" 12 | match: 13 | - uri: 14 | prefix: "/auth" 15 | route: 16 | - destination: 17 | host: keycloak.happyride.svc.cluster.local 18 | -------------------------------------------------------------------------------- /devops/k8s/istio/keycloak.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: keycloak 5 | labels: 6 | app: keycloak 7 | spec: 8 | ports: 9 | - name: http 10 | port: 8080 11 | targetPort: 8080 12 | selector: 13 | app: keycloak 14 | type: ClusterIP 15 | --- 16 | apiVersion: apps/v1 17 | kind: Deployment 18 | metadata: 19 | name: keycloak 20 | labels: 21 | app: keycloak 22 | spec: 23 | replicas: 1 24 | selector: 25 | matchLabels: 26 | app: keycloak 27 | template: 28 | metadata: 29 | labels: 30 | app: keycloak 31 | spec: 32 | containers: 33 | - name: keycloak 34 | image: quay.io/keycloak/keycloak:10.0.2 35 | env: 36 | - name: KEYCLOAK_USER 37 | value: "admin" 38 | - name: KEYCLOAK_PASSWORD 39 | value: "admin" 40 | - name: PROXY_ADDRESS_FORWARDING 41 | value: "true" 42 | ports: 43 | - name: http 44 | containerPort: 8080 45 | - name: https 46 | containerPort: 8443 47 | readinessProbe: 48 | httpGet: 49 | path: /auth/realms/master 50 | port: 8080 51 | -------------------------------------------------------------------------------- /devops/k8s/istio/mtls-passenger-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: security.istio.io/v1beta1 2 | kind: PeerAuthentication 3 | metadata: 4 | name: passenger-service 5 | namespace: happyride 6 | spec: 7 | selector: 8 | matchLabels: 9 | app.kubernetes.io/name: passenger-service 10 | mtls: 11 | mode: STRICT 12 | --- 13 | apiVersion: networking.istio.io/v1beta1 14 | kind: DestinationRule 15 | metadata: 16 | name: passenger-service-mtls 17 | spec: 18 | host: passenger-service.happyride.svc.cluster.local 19 | trafficPolicy: 20 | tls: 21 | mode: ISTIO_MUTUAL 22 | -------------------------------------------------------------------------------- /devops/k8s/istio/mtls.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: security.istio.io/v1beta1 2 | kind: PeerAuthentication 3 | metadata: 4 | name: default 5 | namespace: happyride 6 | spec: 7 | mtls: 8 | mode: STRICT -------------------------------------------------------------------------------- /devops/k8s/istio/passenger-api-graphql-auth.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: security.istio.io/v1beta1 2 | kind: RequestAuthentication 3 | metadata: 4 | name: passenger-api-graphql 5 | spec: 6 | selector: 7 | matchLabels: 8 | app.kubernetes.io/name: passenger-api-graphql 9 | jwtRules: 10 | - issuer: "http://happyride.com/auth/realms/master" 11 | audiences: 12 | - web 13 | jwksUri: http://keycloak.happyride.svc.cluster.local:8080/auth/realms/master/protocol/openid-connect/certs 14 | --- 15 | apiVersion: security.istio.io/v1beta1 16 | kind: AuthorizationPolicy 17 | metadata: 18 | name: passenger-api-graphql 19 | spec: 20 | selector: 21 | matchLabels: 22 | app.kubernetes.io/name: passenger-api-graphql 23 | action: DENY 24 | rules: 25 | - from: 26 | - source: 27 | notRequestPrincipals: ["*"] 28 | -------------------------------------------------------------------------------- /devops/k8s/istio/passenger-api-graphql-cb-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: VirtualService 3 | metadata: 4 | name: passenger-api-graphql-service 5 | spec: 6 | hosts: 7 | - happyride.com 8 | gateways: 9 | - app-gateway 10 | http: 11 | - name: "passenger-api-graphql" 12 | route: 13 | - destination: 14 | host: passenger-api-graphql.happyride.svc.cluster.local 15 | --- 16 | apiVersion: networking.istio.io/v1beta1 17 | kind: DestinationRule 18 | metadata: 19 | name: passenger-api-graphql-service-cb 20 | spec: 21 | host: passenger-api-graphql.happyride.svc.cluster.local 22 | trafficPolicy: 23 | connectionPool: 24 | tcp: 25 | maxConnections: 1000 26 | http: 27 | http1MaxPendingRequests: 1000 28 | maxRequestsPerConnection: 1000 29 | maxRetries: 100 30 | -------------------------------------------------------------------------------- /devops/k8s/istio/payment-service-destination-rule.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: VirtualService 3 | metadata: 4 | name: rewrite-port-for-alipay 5 | spec: 6 | hosts: 7 | - www.alipay.com 8 | http: 9 | - match: 10 | - port: 80 11 | route: 12 | - destination: 13 | host: www.alipay.com 14 | port: 15 | number: 443 16 | --- 17 | apiVersion: networking.istio.io/v1beta1 18 | kind: DestinationRule 19 | metadata: 20 | name: payment-service 21 | spec: 22 | host: www.alipay.com 23 | trafficPolicy: 24 | loadBalancer: 25 | simple: ROUND_ROBIN 26 | portLevelSettings: 27 | - port: 28 | number: 443 29 | tls: 30 | mode: SIMPLE 31 | -------------------------------------------------------------------------------- /devops/k8s/istio/payment-service-entry.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: ServiceEntry 3 | metadata: 4 | name: payment-service 5 | spec: 6 | hosts: 7 | - www.alipay.com 8 | location: MESH_EXTERNAL 9 | ports: 10 | - number: 80 11 | name: http 12 | protocol: HTTP 13 | - number: 443 14 | name: https 15 | protocol: HTTPS 16 | resolution: DNS 17 | -------------------------------------------------------------------------------- /devops/k8s/istio/payment-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: VirtualService 3 | metadata: 4 | name: payment-serivce 5 | spec: 6 | hosts: 7 | - www.alipay.com 8 | exportTo: 9 | - "*" 10 | gateways: 11 | - mesh 12 | - app-external 13 | http: 14 | - match: 15 | - port: 80 16 | gateways: 17 | - mesh 18 | route: 19 | - destination: 20 | host: istio-egressgateway.istio-system.svc.cluster.local 21 | - match: 22 | - port: 80 23 | gateways: 24 | - app-external 25 | route: 26 | - destination: 27 | host: www.alipay.com 28 | -------------------------------------------------------------------------------- /devops/k8s/istio/sleep-no-proxy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: sleep-no-proxy 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: sleep-no-proxy 10 | template: 11 | metadata: 12 | annotations: 13 | sidecar.istio.io/inject: "false" 14 | labels: 15 | app: sleep-no-proxy 16 | spec: 17 | containers: 18 | - name: sleep 19 | image: governmentpaas/curl-ssl 20 | command: ["/bin/sleep", "3650d"] 21 | imagePullPolicy: IfNotPresent 22 | -------------------------------------------------------------------------------- /devops/k8s/istio/sleep.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: sleep 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: sleep 10 | template: 11 | metadata: 12 | labels: 13 | app: sleep 14 | spec: 15 | containers: 16 | - name: sleep 17 | image: governmentpaas/curl-ssl 18 | command: ["/bin/sleep", "3650d"] 19 | imagePullPolicy: IfNotPresent 20 | -------------------------------------------------------------------------------- /devops/k8s/istio/virtual-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1beta1 2 | kind: VirtualService 3 | metadata: 4 | name: virtual-service 5 | spec: 6 | hosts: 7 | - virtual-service 8 | http: 9 | - name: "virtual-service-http" 10 | match: 11 | - uri: 12 | prefix: "/test" 13 | headers: 14 | x-myheader: 15 | exact: "hello" 16 | - uri: 17 | exact: "/demo" 18 | queryParams: 19 | from: 20 | prefix: "myserver" 21 | route: 22 | - destination: 23 | host: test-service 24 | -------------------------------------------------------------------------------- /devops/k8s/ops/apps/docker-registry/helmfile.yaml: -------------------------------------------------------------------------------- 1 | repositories: 2 | - name: stable 3 | url: https://kubernetes-charts.storage.googleapis.com 4 | 5 | releases: 6 | - name: docker-registry 7 | namespace: {{ env "NAMESPACE" | default "happyride" }} 8 | chart: stable/docker-registry 9 | version: 1.9.4 10 | wait: true 11 | values: 12 | - service: 13 | type: NodePort 14 | nodePort: 30000 15 | -------------------------------------------------------------------------------- /devops/k8s/ops/apps/jenkins/helmfile.yaml: -------------------------------------------------------------------------------- 1 | repositories: 2 | - name: stable 3 | url: https://kubernetes-charts.storage.googleapis.com 4 | 5 | releases: 6 | - name: jenkins 7 | namespace: {{ env "NAMESPACE" | default "happyride" }} 8 | chart: stable/jenkins 9 | version: 2.4.1 10 | wait: true 11 | values: 12 | - master: 13 | serviceType: NodePort 14 | persistence: 15 | size: 20Gi 16 | additionalPlugins: 17 | - "blueocean:1.23.2" 18 | -------------------------------------------------------------------------------- /devops/k8s/ops/deploy-account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: deploy-user 5 | namespace: happyride 6 | --- 7 | apiVersion: rbac.authorization.k8s.io/v1 8 | kind: ClusterRoleBinding 9 | metadata: 10 | name: deploy-user 11 | roleRef: 12 | apiGroup: "" 13 | kind: ClusterRole 14 | name: cluster-admin 15 | subjects: 16 | - kind: ServiceAccount 17 | name: deploy-user 18 | namespace: happyride -------------------------------------------------------------------------------- /devops/k8s/ops/helmfile.yaml: -------------------------------------------------------------------------------- 1 | helmfiles: 2 | - apps/*/helmfile.yaml -------------------------------------------------------------------------------- /example-projects/passenger-web-api-falcor/README.md: -------------------------------------------------------------------------------- 1 | # Falcor example 2 | 3 | Use the command below to run locally, 4 | 5 | ``` 6 | PASSENGER_SERVICE_URL=http://localhost:8500 ADDRESS_SERVICE_URL=http://localhost:8502 node index.js 7 | ``` 8 | 9 | Open browser to access `http://localhost:3000`. 10 | 11 | -------------------------------------------------------------------------------- /example-projects/passenger-web-api-falcor/datasource_test.js: -------------------------------------------------------------------------------- 1 | const falcor = require('falcor'); 2 | const jsonGraph = require('./sample_json_graph.json'); 3 | const debug = require('./debug').debug; 4 | 5 | const dataSource = new falcor.Model({ 6 | cache: jsonGraph 7 | }).asDataSource(); 8 | 9 | dataSource.get(["passengersById", "p1", "userAddresses", 0, 'address', 'addressLine']).subscribe(debug); -------------------------------------------------------------------------------- /example-projects/passenger-web-api-falcor/debug.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | debug: function debug(obj) { 3 | console.log(JSON.stringify(obj, null, 4)); 4 | } 5 | }; -------------------------------------------------------------------------------- /example-projects/passenger-web-api-falcor/model_test.js: -------------------------------------------------------------------------------- 1 | const falcor = require('falcor'); 2 | const jsong = require("falcor-json-graph"); 3 | const jsonGraph = require('./sample_json_graph.json'); 4 | const debug = require('./debug').debug; 5 | 6 | const model = new falcor.Model({ 7 | cache: jsonGraph 8 | }); 9 | 10 | 11 | model.getValue(["passengersById", "p1", "name"]).then(debug); 12 | model.getValue("passengersById.p1.name").then(debug); 13 | model.getValue(["passengersById", "p1", "userAddresses", 0, 'address', 'addressLine']).then(debug); 14 | 15 | model.setValue(jsong.pathValue(["passengersById", "p1", "name"], "new name")).then(debug); -------------------------------------------------------------------------------- /example-projects/passenger-web-api-falcor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "happyride-passenger-web-api-falcor", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "axios": "^0.21.2", 14 | "bluebird": "^3.7.2", 15 | "body-parser": "^1.19.0", 16 | "bunyan": "^1.8.14", 17 | "express": "^4.17.1", 18 | "falcor": "^2.2.0", 19 | "falcor-express": "^0.1.4", 20 | "falcor-json-graph": "^3.2.1", 21 | "falcor-restify": "^1.1.1", 22 | "falcor-router": "^0.8.3", 23 | "lodash.get": "^4.4.2", 24 | "restify": "^8.5.1" 25 | }, 26 | "devDependencies": { 27 | "prettier": "^2.0.5" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /example-projects/passenger-web-api-falcor/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | io.vividcode.happyride 7 | build-parent 8 | 3.0.0-SNAPSHOT 9 | ../../pom.xml 10 | 11 | 4.0.0 12 | 13 | passenger-web-api-falcor 14 | Example :: Passenger Web API (falcor) 15 | 16 | -------------------------------------------------------------------------------- /example-projects/passenger-web-api-falcor/sample_json_graph.json: -------------------------------------------------------------------------------- 1 | { 2 | "passengersById": { 3 | "p1": { 4 | "name": "Passenger 1", 5 | "email": "passenger1@test.com", 6 | "userAddresses": [ 7 | { 8 | "id": "ua1", 9 | "name": "Home", 10 | "address": { 11 | "$type": "ref", 12 | "value": ["addressesById", "a1"] 13 | } 14 | } 15 | ] 16 | }, 17 | "p2": { 18 | "name": "Passenger 2", 19 | "email": "passenger2@test.com" 20 | } 21 | }, 22 | "addressesById": { 23 | "a1": { 24 | "addressLine": "Address 1", 25 | "lat": 0, 26 | "lng": 0 27 | }, 28 | "a2": { 29 | "addressLine": "Address 2", 30 | "lat": 1, 31 | "lng": 1 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /example-projects/security-jwt/src/main/java/io/vividcode/happyride/security/JWTKeyHolder.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.security; 2 | 3 | import io.jsonwebtoken.impl.crypto.MacProvider; 4 | import java.security.Key; 5 | 6 | public class JWTKeyHolder { 7 | 8 | public static Key KEY = MacProvider.generateKey(); 9 | } 10 | -------------------------------------------------------------------------------- /example-projects/security-jwt/src/main/java/io/vividcode/happyride/security/LoginRequest.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.security; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @RequiredArgsConstructor 11 | public class LoginRequest { 12 | 13 | @NonNull 14 | private String username; 15 | @NonNull 16 | private String password; 17 | } 18 | -------------------------------------------------------------------------------- /example-projects/security-jwt/src/main/java/io/vividcode/happyride/security/ProtectedController.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.security; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @RequestMapping("/protected") 10 | public class ProtectedController { 11 | 12 | @Autowired 13 | ProtectedService protectedService; 14 | 15 | @GetMapping 16 | public void doSomething() { 17 | this.protectedService.doSomething(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /example-projects/security-jwt/src/main/java/io/vividcode/happyride/security/ProtectedService.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.security; 2 | 3 | import org.springframework.security.access.annotation.Secured; 4 | import org.springframework.stereotype.Service; 5 | 6 | @Service 7 | public class ProtectedService { 8 | 9 | @Secured("ROLE_ADMIN") 10 | public void doSomething() { 11 | System.out.println("Do this"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example-projects/security-jwt/src/main/java/io/vividcode/happyride/security/SecurityApplication.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.security; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SecurityApplication { 8 | 9 | public static void main(final String[] args) { 10 | SpringApplication.run(SecurityApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /example-projects/security-jwt/src/main/java/io/vividcode/happyride/security/SecurityConstants.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.security; 2 | 3 | public interface SecurityConstants { 4 | 5 | String AUTHORIZATION_HEADER = "Authorization"; 6 | String TOKEN_PREFIX = "Bearer "; 7 | String AUTH_COOKIE = "happyride-auth"; 8 | } 9 | -------------------------------------------------------------------------------- /example-projects/security-jwt/src/main/java/io/vividcode/happyride/security/UserController.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.security; 2 | 3 | import org.springframework.security.core.context.SecurityContextHolder; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @RequestMapping("/user") 10 | public class UserController { 11 | 12 | @GetMapping 13 | public UserInfo getCurrentUser() { 14 | return new UserInfo( 15 | (String) SecurityContextHolder.getContext().getAuthentication() 16 | .getPrincipal()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /example-projects/security-jwt/src/main/java/io/vividcode/happyride/security/UserInfo.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.security; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @RequiredArgsConstructor 11 | public class UserInfo { 12 | 13 | @NonNull 14 | private String username; 15 | } 16 | -------------------------------------------------------------------------------- /example-projects/trip-service-cqrs-api/src/main/java/io/vividcode/happyride/tripservice/cqrs/api/CancelTripCommand.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.cqrs.api; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | import org.axonframework.modelling.command.TargetAggregateIdentifier; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @RequiredArgsConstructor 12 | public class CancelTripCommand { 13 | @NonNull 14 | @TargetAggregateIdentifier 15 | private String tripId; 16 | } 17 | -------------------------------------------------------------------------------- /example-projects/trip-service-cqrs-api/src/main/java/io/vividcode/happyride/tripservice/cqrs/api/ConfirmTripCommand.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.cqrs.api; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | import org.axonframework.modelling.command.TargetAggregateIdentifier; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @RequiredArgsConstructor 12 | public class ConfirmTripCommand { 13 | @NonNull 14 | @TargetAggregateIdentifier 15 | private String tripId; 16 | } 17 | -------------------------------------------------------------------------------- /example-projects/trip-service-cqrs-api/src/main/java/io/vividcode/happyride/tripservice/cqrs/api/CreateTripCommand.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.cqrs.api; 2 | 3 | import io.vividcode.happyride.tripservice.api.events.TripDetails; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.NonNull; 7 | import lombok.RequiredArgsConstructor; 8 | import org.axonframework.modelling.command.TargetAggregateIdentifier; 9 | 10 | @Data 11 | @NoArgsConstructor 12 | @RequiredArgsConstructor 13 | public class CreateTripCommand { 14 | @NonNull 15 | @TargetAggregateIdentifier 16 | private String tripId; 17 | 18 | @NonNull 19 | private TripDetails tripDetails; 20 | } 21 | -------------------------------------------------------------------------------- /example-projects/trip-service-cqrs-api/src/main/java/io/vividcode/happyride/tripservice/cqrs/api/FetchTripQuery.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.cqrs.api; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @RequiredArgsConstructor 11 | public class FetchTripQuery { 12 | @NonNull 13 | private String tripId; 14 | } 15 | -------------------------------------------------------------------------------- /example-projects/trip-service-cqrs-api/src/main/java/io/vividcode/happyride/tripservice/cqrs/api/TripCancelledEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.cqrs.api; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @RequiredArgsConstructor 11 | public class TripCancelledEvent { 12 | @NonNull 13 | private String tripId; 14 | } 15 | -------------------------------------------------------------------------------- /example-projects/trip-service-cqrs-api/src/main/java/io/vividcode/happyride/tripservice/cqrs/api/TripConfirmedEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.cqrs.api; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @RequiredArgsConstructor 11 | public class TripConfirmedEvent { 12 | @NonNull 13 | private String tripId; 14 | } 15 | -------------------------------------------------------------------------------- /example-projects/trip-service-cqrs-api/src/main/java/io/vividcode/happyride/tripservice/cqrs/api/TripCreatedEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.cqrs.api; 2 | 3 | import io.vividcode.happyride.tripservice.api.events.TripDetails; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.NonNull; 7 | import lombok.RequiredArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @RequiredArgsConstructor 12 | public class TripCreatedEvent { 13 | @NonNull 14 | private String tripId; 15 | 16 | @NonNull 17 | private TripDetails tripDetails; 18 | } 19 | -------------------------------------------------------------------------------- /example-projects/trip-service-cqrs-api/src/main/java/io/vividcode/happyride/tripservice/cqrs/api/TripSummary.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.cqrs.api; 2 | 3 | import io.vividcode.happyride.common.PositionVO; 4 | import io.vividcode.happyride.tripservice.api.TripState; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | public class TripSummary { 11 | 12 | private String id; 13 | 14 | private PositionVO startPos; 15 | 16 | private PositionVO endPos; 17 | 18 | private TripState state; 19 | } 20 | -------------------------------------------------------------------------------- /example-projects/trip-service-cqrs/src/main/java/io/vividcode/happyride/tripservice/cqrs/TripCqrsApplication.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.cqrs; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class TripCqrsApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(TripCqrsApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /example-projects/trip-service-cqrs/src/main/java/io/vividcode/happyride/tripservice/cqrs/TripCqrsConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.cqrs; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 5 | import org.springframework.transaction.annotation.EnableTransactionManagement; 6 | 7 | @Configuration 8 | @EnableJpaRepositories 9 | @EnableTransactionManagement 10 | public class TripCqrsConfiguration { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /example-projects/trip-service-cqrs/src/main/java/io/vividcode/happyride/tripservice/cqrs/dataaccess/TripView.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.cqrs.dataaccess; 2 | 3 | import io.vividcode.happyride.tripservice.api.TripState; 4 | import java.math.BigDecimal; 5 | import jakarta.persistence.Column; 6 | import jakarta.persistence.Entity; 7 | import jakarta.persistence.EnumType; 8 | import jakarta.persistence.Enumerated; 9 | import jakarta.persistence.Id; 10 | import jakarta.persistence.Table; 11 | import lombok.Data; 12 | 13 | @Entity 14 | @Table(name = "trip_view") 15 | @Data 16 | public class TripView { 17 | 18 | @Id 19 | private String id; 20 | 21 | @Column(name = "start_pos_lng") 22 | private BigDecimal startPosLng; 23 | 24 | @Column(name = "start_pos_lat") 25 | private BigDecimal startPosLat; 26 | 27 | @Column(name = "end_pos_lng") 28 | private BigDecimal endPosLng; 29 | 30 | @Column(name = "ent_pos_lat") 31 | private BigDecimal endPosLat; 32 | 33 | @Column(name = "state") 34 | @Enumerated(EnumType.STRING) 35 | private TripState state; 36 | } 37 | -------------------------------------------------------------------------------- /example-projects/trip-service-cqrs/src/main/java/io/vividcode/happyride/tripservice/cqrs/dataaccess/TripViewRepository.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.cqrs.dataaccess; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | @Repository 7 | public interface TripViewRepository extends CrudRepository { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /example-projects/trip-service-cqrs/src/main/java/io/vividcode/happyride/tripservice/cqrs/domain/IllegalTripStateException.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.cqrs.domain; 2 | 3 | import io.vividcode.happyride.tripservice.api.TripState; 4 | 5 | public class IllegalTripStateException extends RuntimeException { 6 | 7 | private final TripState fromState; 8 | private final TripState toState; 9 | 10 | public IllegalTripStateException(TripState fromState, 11 | TripState toState) { 12 | this.fromState = fromState; 13 | this.toState = toState; 14 | } 15 | 16 | @Override 17 | public String getMessage() { 18 | return String 19 | .format("Cannot change trip state from %s to %s", fromState, toState); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example-projects/trip-service-cqrs/src/main/java/io/vividcode/happyride/tripservice/cqrs/domain/TripNotFoundException.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.cqrs.domain; 2 | 3 | public class TripNotFoundException extends RuntimeException { 4 | private final String tripId; 5 | 6 | public TripNotFoundException(String tripId) { 7 | this.tripId = tripId; 8 | } 9 | 10 | @Override 11 | public String getMessage() { 12 | return String.format("Trip %s not found", tripId); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /example-projects/trip-service-cqrs/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8510 3 | spring: 4 | jpa: 5 | hibernate: 6 | ddl-auto: update 7 | properties: 8 | hibernate: 9 | dialect: org.hibernate.dialect.HSQLDialect 10 | axon: 11 | axonserver: 12 | servers: ${DOCKER_HOST_IP:localhost}:8124 13 | serializer: 14 | general: jackson 15 | events: jackson 16 | messages: jackson -------------------------------------------------------------------------------- /gongzhonghao.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexcheng1982/happyride/17a507fca213d87dab849b6cef6f1f469433b42e/gongzhonghao.jpg -------------------------------------------------------------------------------- /happyride/api-client/address-service-client/README.md: -------------------------------------------------------------------------------- 1 | # Address Service Client 2 | 3 | To view the API doc, start the Docker container first, 4 | 5 | ```shell script 6 | docker run --rm -p 8800:8080 \ 7 | -v $(pwd)/src/main/resources/openapi.yml:/openapi.yml \ 8 | -e SWAGGER_JSON=/openapi.yml \ 9 | swaggerapi/swagger-ui 10 | ``` 11 | 12 | then access `http://localhost:8800`. -------------------------------------------------------------------------------- /happyride/api/address-service-api/src/main/java/io/vividcode/happyride/addressservice/api/AddressVO.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.addressservice.api; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.List; 5 | import lombok.Data; 6 | 7 | @Data 8 | public class AddressVO { 9 | 10 | private String id; 11 | 12 | private Integer areaId; 13 | 14 | private String addressLine; 15 | 16 | private BigDecimal lng; 17 | 18 | private BigDecimal lat; 19 | 20 | private List areas; 21 | 22 | public static AddressVO nullObject(String id) { 23 | AddressVO result = new AddressVO(); 24 | result.setId(id); 25 | return result; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /happyride/api/address-service-api/src/main/java/io/vividcode/happyride/addressservice/api/AreaVO.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.addressservice.api; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.List; 5 | import lombok.Data; 6 | 7 | @Data 8 | public class AreaVO { 9 | 10 | private Integer id; 11 | 12 | private Integer level; 13 | 14 | private Long parentCode; 15 | 16 | private Long areaCode; 17 | 18 | private String zipCode; 19 | 20 | private String cityCode; 21 | 22 | private String name; 23 | 24 | private String shortName; 25 | 26 | private String mergerName; 27 | 28 | private String pinyin; 29 | 30 | private BigDecimal lat; 31 | 32 | private BigDecimal lng; 33 | 34 | private List ancestors; 35 | } 36 | -------------------------------------------------------------------------------- /happyride/api/address-service-api/src/main/java/io/vividcode/happyride/addressservice/api/web/AddressBatchRequest.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.addressservice.api.web; 2 | 3 | import java.util.List; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.NonNull; 7 | import lombok.RequiredArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @RequiredArgsConstructor 12 | public class AddressBatchRequest { 13 | 14 | @NonNull 15 | private List addressIds; 16 | } 17 | -------------------------------------------------------------------------------- /happyride/api/dispatch-service-api/src/main/java/io/vividcode/happyride/dispatchservice/api/DispatchServiceChannels.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.api; 2 | 3 | public class DispatchServiceChannels { 4 | 5 | public static final String dispatchServiceChannel = "io.vividcode.happyride.dispatcherservice"; 6 | } 7 | -------------------------------------------------------------------------------- /happyride/api/dispatch-service-api/src/main/java/io/vividcode/happyride/dispatchservice/api/events/DispatchDomainEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.api.events; 2 | 3 | 4 | import io.eventuate.tram.events.common.DomainEvent; 5 | 6 | public interface DispatchDomainEvent extends DomainEvent { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /happyride/api/dispatch-service-api/src/main/java/io/vividcode/happyride/dispatchservice/api/events/DriverLocation.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.api.events; 2 | 3 | import java.math.BigDecimal; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.NonNull; 7 | import lombok.RequiredArgsConstructor; 8 | 9 | @Data 10 | @RequiredArgsConstructor 11 | @NoArgsConstructor 12 | public class DriverLocation { 13 | 14 | @NonNull 15 | private String driverId; 16 | 17 | @NonNull 18 | private String vehicleId; 19 | 20 | @NonNull 21 | private BigDecimal lng; 22 | 23 | @NonNull 24 | private BigDecimal lat; 25 | 26 | public DriverLocation resetTo(BigDecimal lng, BigDecimal lat) { 27 | return new DriverLocation(driverId, vehicleId, lng, lat); 28 | } 29 | 30 | public DriverLocation moveTo(BigDecimal lngDelta, BigDecimal latDelta) { 31 | return new DriverLocation(driverId, vehicleId, lng.add(lngDelta), lat.add(latDelta)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /happyride/api/dispatch-service-api/src/main/java/io/vividcode/happyride/dispatchservice/api/events/DriverLocationUpdatedEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.api.events; 2 | 3 | import io.vividcode.happyride.common.DriverState; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class DriverLocationUpdatedEvent { 8 | 9 | private DriverLocation location; 10 | 11 | private DriverState state; 12 | 13 | private long timestamp; 14 | } 15 | -------------------------------------------------------------------------------- /happyride/api/dispatch-service-api/src/main/java/io/vividcode/happyride/dispatchservice/api/events/InvalidDispatchRequestReply.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.api.events; 2 | 3 | public class InvalidDispatchRequestReply { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /happyride/api/dispatch-service-api/src/main/java/io/vividcode/happyride/dispatchservice/api/events/TripAcceptanceDeclinedEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.api.events; 2 | 3 | import lombok.Data; 4 | import lombok.NonNull; 5 | 6 | @Data 7 | public class TripAcceptanceDeclinedEvent implements DispatchDomainEvent { 8 | @NonNull 9 | private String tripId; 10 | 11 | @NonNull 12 | private String driverId; 13 | 14 | @NonNull 15 | private TripAcceptanceDeclinedReason reason; 16 | } 17 | -------------------------------------------------------------------------------- /happyride/api/dispatch-service-api/src/main/java/io/vividcode/happyride/dispatchservice/api/events/TripAcceptanceDeclinedReason.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.api.events; 2 | 3 | public enum TripAcceptanceDeclinedReason { 4 | OTHER_SELECTED, 5 | TRIP_CANCELLED 6 | } 7 | -------------------------------------------------------------------------------- /happyride/api/dispatch-service-api/src/main/java/io/vividcode/happyride/dispatchservice/api/events/TripAcceptanceSelectedEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.api.events; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @RequiredArgsConstructor 11 | public class TripAcceptanceSelectedEvent implements DispatchDomainEvent { 12 | 13 | @NonNull 14 | private String tripId; 15 | 16 | @NonNull 17 | private String driverId; 18 | } 19 | -------------------------------------------------------------------------------- /happyride/api/dispatch-service-api/src/main/java/io/vividcode/happyride/dispatchservice/api/events/TripDispatchFailedEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.api.events; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @RequiredArgsConstructor 11 | public class TripDispatchFailedEvent implements DispatchDomainEvent { 12 | 13 | @NonNull 14 | private String tripId; 15 | 16 | @NonNull 17 | private TripDispatchFailedReason reason; 18 | } 19 | -------------------------------------------------------------------------------- /happyride/api/dispatch-service-api/src/main/java/io/vividcode/happyride/dispatchservice/api/events/TripDispatchFailedReason.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.api.events; 2 | 3 | public enum TripDispatchFailedReason { 4 | NO_DRIVERS_AVAILABLE, 5 | NO_DRIVERS_ACCEPTED 6 | } 7 | -------------------------------------------------------------------------------- /happyride/api/dispatch-service-api/src/main/java/io/vividcode/happyride/dispatchservice/api/events/TripDispatchedEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.api.events; 2 | 3 | import io.vividcode.happyride.tripservice.api.events.TripDetails; 4 | import java.util.Set; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.NonNull; 8 | import lombok.RequiredArgsConstructor; 9 | 10 | @Data 11 | @NoArgsConstructor 12 | @RequiredArgsConstructor 13 | public class TripDispatchedEvent implements DispatchDomainEvent { 14 | 15 | @NonNull 16 | private String tripId; 17 | 18 | @NonNull 19 | private TripDetails tripDetails; 20 | 21 | @NonNull 22 | private Set drivers; 23 | } 24 | -------------------------------------------------------------------------------- /happyride/api/dispatch-service-api/src/main/java/io/vividcode/happyride/dispatchservice/api/events/VerifyDispatchCommand.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.api.events; 2 | 3 | import io.eventuate.tram.commands.common.Command; 4 | import io.vividcode.happyride.tripservice.api.events.TripDetails; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.NonNull; 8 | import lombok.RequiredArgsConstructor; 9 | 10 | @Data 11 | @NoArgsConstructor 12 | @RequiredArgsConstructor 13 | public class VerifyDispatchCommand implements Command { 14 | 15 | @NonNull 16 | private TripDetails tripDetails; 17 | } 18 | -------------------------------------------------------------------------------- /happyride/api/driver-service-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | happyride 7 | io.vividcode.happyride 8 | 3.0.0-SNAPSHOT 9 | ../../pom.xml 10 | 11 | 4.0.0 12 | 13 | driver-service-api 14 | API :: Driver Service 15 | 16 | 17 | 18 | lombok 19 | org.projectlombok 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /happyride/api/driver-service-api/src/main/java/io/vividcode/happyride/driverservice/api/web/CreateDriverRequest.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driverservice.api.web; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Set; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import lombok.NonNull; 9 | import lombok.RequiredArgsConstructor; 10 | 11 | @Data 12 | @RequiredArgsConstructor 13 | @NoArgsConstructor 14 | public class CreateDriverRequest { 15 | 16 | @NonNull 17 | private String name; 18 | 19 | private String email; 20 | 21 | @NonNull 22 | private String mobilePhoneNumber; 23 | 24 | private List vehicles = new ArrayList<>(); 25 | } 26 | -------------------------------------------------------------------------------- /happyride/api/driver-service-api/src/main/java/io/vividcode/happyride/driverservice/api/web/CreateVehicleRequest.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driverservice.api.web; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @RequiredArgsConstructor 10 | @NoArgsConstructor 11 | public class CreateVehicleRequest { 12 | @NonNull 13 | private String make; 14 | 15 | @NonNull 16 | private String mode; 17 | 18 | @NonNull 19 | private Integer year; 20 | 21 | @NonNull 22 | private String registration; 23 | } 24 | -------------------------------------------------------------------------------- /happyride/api/driver-service-api/src/main/java/io/vividcode/happyride/driverservice/api/web/DriverView.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driverservice.api.web; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import lombok.Data; 6 | 7 | @Data 8 | public class DriverView { 9 | private String id; 10 | 11 | private String name; 12 | 13 | private String email; 14 | 15 | private String mobilePhoneNumber; 16 | 17 | private String state; 18 | 19 | private List vehicles = new ArrayList<>(); 20 | } 21 | -------------------------------------------------------------------------------- /happyride/api/driver-service-api/src/main/java/io/vividcode/happyride/driverservice/api/web/VehicleView.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driverservice.api.web; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class VehicleView { 7 | private String id; 8 | 9 | private String make; 10 | 11 | private String mode; 12 | 13 | private Integer year; 14 | 15 | private String registration; 16 | } 17 | -------------------------------------------------------------------------------- /happyride/api/passenger-service-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | passenger-service-api 6 | API :: Passenger Service 7 | 8 | 4.0.0 9 | 10 | 11 | happyride 12 | io.vividcode.happyride 13 | 3.0.0-SNAPSHOT 14 | ../../pom.xml 15 | 16 | 17 | 18 | 19 | lombok 20 | org.projectlombok 21 | 22 | 23 | io.eventuate.tram.core 24 | eventuate-tram-spring-events 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /happyride/api/passenger-service-api/src/main/java/io/vividcode/happyride/passengerservice/api/events/PassengerDetails.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerservice.api.events; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @RequiredArgsConstructor 11 | public class PassengerDetails { 12 | 13 | @NonNull 14 | private String passengerName; 15 | } 16 | -------------------------------------------------------------------------------- /happyride/api/passenger-service-api/src/main/java/io/vividcode/happyride/passengerservice/api/events/PassengerDetailsUpdatedEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerservice.api.events; 2 | 3 | import io.eventuate.tram.events.common.DomainEvent; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.NonNull; 7 | import lombok.RequiredArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @RequiredArgsConstructor 12 | public class PassengerDetailsUpdatedEvent implements DomainEvent { 13 | 14 | @NonNull 15 | private PassengerDetails passengerDetails; 16 | } 17 | -------------------------------------------------------------------------------- /happyride/api/passenger-service-api/src/main/java/io/vividcode/happyride/passengerservice/api/web/CreatePassengerRequest.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerservice.api.web; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.NonNull; 8 | import lombok.RequiredArgsConstructor; 9 | 10 | @Data 11 | @RequiredArgsConstructor 12 | @NoArgsConstructor 13 | public class CreatePassengerRequest { 14 | 15 | @NonNull 16 | private String name; 17 | 18 | private String email; 19 | 20 | @NonNull 21 | private String mobilePhoneNumber; 22 | 23 | private List userAddresses = new ArrayList<>(); 24 | } 25 | -------------------------------------------------------------------------------- /happyride/api/passenger-service-api/src/main/java/io/vividcode/happyride/passengerservice/api/web/CreateUserAddressRequest.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerservice.api.web; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @RequiredArgsConstructor 10 | @NoArgsConstructor 11 | public class CreateUserAddressRequest { 12 | 13 | @NonNull 14 | private String name; 15 | 16 | @NonNull 17 | private String addressId; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /happyride/api/passenger-service-api/src/main/java/io/vividcode/happyride/passengerservice/api/web/PassengerVO.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerservice.api.web; 2 | 3 | import java.util.List; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.NonNull; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class PassengerVO { 13 | 14 | @NonNull 15 | private String id; 16 | 17 | @NonNull 18 | private String name; 19 | 20 | private String email; 21 | 22 | @NonNull 23 | private String mobilePhoneNumber; 24 | 25 | private List userAddresses; 26 | } 27 | -------------------------------------------------------------------------------- /happyride/api/passenger-service-api/src/main/java/io/vividcode/happyride/passengerservice/api/web/UserAddressVO.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerservice.api.web; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.NonNull; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | public class UserAddressVO { 12 | 13 | @NonNull 14 | private String id; 15 | 16 | @NonNull 17 | private String name; 18 | 19 | @NonNull 20 | private String addressId; 21 | } 22 | -------------------------------------------------------------------------------- /happyride/api/passenger-web-api/README.md: -------------------------------------------------------------------------------- 1 | # Passenger Web API 2 | 3 | To run locally, add following system properties: 4 | 5 | ``` 6 | -Dserver.port=8600 -Ddestination.address=http://localhost:8502 -Ddestination.passenger=http://localhost:8500 7 | ``` -------------------------------------------------------------------------------- /happyride/api/passenger-web-api/src/main/java/io/vividcode/happyride/passengerwebapi/ApplicationConfig.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerwebapi; 2 | 3 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | @Configuration 7 | @EnableConfigurationProperties(DestinationConfig.class) 8 | public class ApplicationConfig { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /happyride/api/passenger-web-api/src/main/java/io/vividcode/happyride/passengerwebapi/DestinationConfig.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerwebapi; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | 7 | @ConfigurationProperties(prefix = "destination") 8 | @Data 9 | @NoArgsConstructor 10 | public class DestinationConfig { 11 | 12 | private String passenger; 13 | 14 | private String address; 15 | } 16 | -------------------------------------------------------------------------------- /happyride/api/passenger-web-api/src/main/java/io/vividcode/happyride/passengerwebapi/PassengerWebApiApplication.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerwebapi; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class PassengerWebApiApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(PassengerWebApiApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /happyride/api/passenger-web-api/src/main/java/io/vividcode/happyride/passengerwebapi/UserAddressResponse.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerwebapi; 2 | 3 | import io.vividcode.happyride.addressservice.api.AreaVO; 4 | import java.math.BigDecimal; 5 | import java.util.List; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class UserAddressResponse { 12 | 13 | private String id; 14 | 15 | private String name; 16 | 17 | private String addressId; 18 | 19 | private Integer areaId; 20 | 21 | private String addressLine; 22 | 23 | private BigDecimal lng; 24 | 25 | private BigDecimal lat; 26 | 27 | private List areas; 28 | } 29 | -------------------------------------------------------------------------------- /happyride/api/passenger-web-api/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | level: 3 | org: 4 | springframework: 5 | cloud: 6 | gateway: TRACE 7 | spring: 8 | cloud: 9 | gateway: 10 | routes: 11 | - id: address_service 12 | uri: ${destination.address} 13 | predicates: 14 | - Path=/address/** 15 | filters: 16 | - StripPrefix=1 -------------------------------------------------------------------------------- /happyride/api/payment-service-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | happyride 7 | io.vividcode.happyride 8 | 3.0.0-SNAPSHOT 9 | ../../pom.xml 10 | 11 | 4.0.0 12 | 13 | payment-service-api 14 | API :: Payment Service 15 | 16 | 17 | 18 | io.eventuate.tram.core 19 | eventuate-tram-spring-commands 20 | 21 | 22 | org.projectlombok 23 | lombok 24 | 25 | 26 | -------------------------------------------------------------------------------- /happyride/api/payment-service-api/src/main/java/io/vividcode/happyride/paymentservice/api/PaymentServiceChannels.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice.api; 2 | 3 | public class PaymentServiceChannels { 4 | 5 | public static final String payment = "io.vividcode.happyride.paymentservice"; 6 | } 7 | -------------------------------------------------------------------------------- /happyride/api/payment-service-api/src/main/java/io/vividcode/happyride/paymentservice/api/events/CreatePaymentCommand.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice.api.events; 2 | 3 | import io.eventuate.tram.commands.common.Command; 4 | import java.math.BigDecimal; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.NonNull; 8 | import lombok.RequiredArgsConstructor; 9 | 10 | @Data 11 | @NoArgsConstructor 12 | @RequiredArgsConstructor 13 | public class CreatePaymentCommand implements Command { 14 | 15 | @NonNull 16 | private String tripId; 17 | 18 | @NonNull 19 | private BigDecimal amount; 20 | } 21 | -------------------------------------------------------------------------------- /happyride/api/payment-service-api/src/main/java/io/vividcode/happyride/paymentservice/api/events/MakePaymentCommand.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice.api.events; 2 | 3 | import io.eventuate.tram.commands.common.Command; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.NonNull; 7 | import lombok.RequiredArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @RequiredArgsConstructor 12 | public class MakePaymentCommand implements Command { 13 | 14 | @NonNull 15 | private String tripId; 16 | } 17 | -------------------------------------------------------------------------------- /happyride/api/payment-service-api/src/main/java/io/vividcode/happyride/paymentservice/api/events/PaymentFailedReply.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice.api.events; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @RequiredArgsConstructor 11 | public class PaymentFailedReply { 12 | 13 | @NonNull 14 | private String reason; 15 | } 16 | -------------------------------------------------------------------------------- /happyride/api/payment-service-api/src/main/java/io/vividcode/happyride/paymentservice/api/web/MakePaymentRequest.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice.api.web; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | public class MakePaymentRequest { 10 | 11 | @NonNull 12 | private String tripId; 13 | } 14 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | happyride 7 | io.vividcode.happyride 8 | 3.0.0-SNAPSHOT 9 | ../../pom.xml 10 | 11 | 4.0.0 12 | 13 | trip-service-api 14 | API :: Trip Service 15 | 16 | 17 | 18 | io.vividcode.happyride 19 | common 20 | ${project.version} 21 | 22 | 23 | org.projectlombok 24 | lombok 25 | 26 | 27 | io.eventuate.tram.core 28 | eventuate-tram-spring-events 29 | 30 | 31 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/TripServiceChannels.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api; 2 | 3 | public class TripServiceChannels { 4 | 5 | public static final String trip = "io.vividcode.happyride.tripservice"; 6 | } 7 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/TripState.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api; 2 | 3 | public enum TripState { 4 | CREATED, 5 | REJECTED, 6 | CONFIRMED, 7 | DISPATCHED, 8 | ACCEPTED, 9 | FAILED, 10 | CANCELLED_BY_PASSENGER, 11 | CANCELLED_BY_DRIVER, 12 | CANCELLATION_PENDING, 13 | CANCELLED, 14 | CANCELLATION_REJECTED_BY_PASSENGER, 15 | CANCELLATION_REJECTED_BY_DRIVER, 16 | STARTED, 17 | FINISHED, 18 | PAYMENT_PENDING, 19 | PAID 20 | } 21 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/events/CancellationParty.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.events; 2 | 3 | public enum CancellationParty { 4 | PASSENGER, 5 | DRIVER 6 | } 7 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/events/DriverAcceptTripDetails.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.events; 2 | 3 | import java.math.BigDecimal; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.NonNull; 7 | import lombok.RequiredArgsConstructor; 8 | 9 | @Data 10 | @RequiredArgsConstructor 11 | @NoArgsConstructor 12 | public class DriverAcceptTripDetails { 13 | 14 | @NonNull 15 | private String driverId; 16 | 17 | @NonNull 18 | private BigDecimal posLng; 19 | 20 | @NonNull 21 | private BigDecimal posLat; 22 | } 23 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/events/DriverAcceptTripEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.events; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @RequiredArgsConstructor 11 | public class DriverAcceptTripEvent implements TripDomainEvent { 12 | 13 | @NonNull 14 | private DriverAcceptTripDetails acceptTripDetails; 15 | } 16 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/events/TripCancellationResolutionRequiredEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.events; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @RequiredArgsConstructor 11 | public class TripCancellationResolutionRequiredEvent implements 12 | TripDomainEvent { 13 | 14 | @NonNull 15 | private CancellationParty rejectedParty; 16 | } 17 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/events/TripCancelledEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.events; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class TripCancelledEvent implements TripDomainEvent { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/events/TripConfirmedEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.events; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @RequiredArgsConstructor 11 | public class TripConfirmedEvent implements TripDomainEvent { 12 | 13 | @NonNull 14 | private TripDetails tripDetails; 15 | } 16 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/events/TripCreatedEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.events; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @RequiredArgsConstructor 11 | public class TripCreatedEvent implements TripDomainEvent { 12 | 13 | @NonNull 14 | private TripDetails tripDetails; 15 | } 16 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/events/TripDetails.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.events; 2 | 3 | 4 | import io.vividcode.happyride.common.PositionVO; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.NonNull; 8 | import lombok.RequiredArgsConstructor; 9 | 10 | @Data 11 | @NoArgsConstructor 12 | @RequiredArgsConstructor 13 | public class TripDetails { 14 | 15 | @NonNull 16 | private String passengerId; 17 | 18 | private String driverId; 19 | 20 | @NonNull 21 | private PositionVO startPos; 22 | 23 | @NonNull 24 | private PositionVO endPos; 25 | } 26 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/events/TripDispatchedEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.events; 2 | 3 | import java.util.Set; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.NonNull; 7 | import lombok.RequiredArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @RequiredArgsConstructor 12 | public class TripDispatchedEvent implements TripDomainEvent { 13 | 14 | @NonNull 15 | private String tripId; 16 | 17 | @NonNull 18 | private TripDetails tripDetails; 19 | 20 | @NonNull 21 | private Set drivers; 22 | } 23 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/events/TripDomainEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.events; 2 | 3 | import io.eventuate.tram.events.common.DomainEvent; 4 | 5 | public interface TripDomainEvent extends DomainEvent { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/events/TripFinishedEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.events; 2 | 3 | public class TripFinishedEvent implements TripDomainEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/events/TripRejectedEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.events; 2 | 3 | public class TripRejectedEvent implements TripDomainEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/events/TripStartedEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.events; 2 | 3 | public class TripStartedEvent implements TripDomainEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/web/AcceptTripRequest.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.web; 2 | 3 | import java.math.BigDecimal; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.NonNull; 7 | import lombok.RequiredArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @RequiredArgsConstructor 12 | public class AcceptTripRequest { 13 | 14 | @NonNull 15 | private String driverId; 16 | 17 | @NonNull 18 | private BigDecimal posLng; 19 | 20 | @NonNull 21 | private BigDecimal posLat; 22 | } 23 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/web/CreateTripRequest.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.web; 2 | 3 | 4 | import io.vividcode.happyride.common.PositionVO; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.NonNull; 8 | import lombok.RequiredArgsConstructor; 9 | 10 | @Data 11 | @NoArgsConstructor 12 | @RequiredArgsConstructor 13 | public class CreateTripRequest { 14 | 15 | @NonNull 16 | private String passengerId; 17 | 18 | @NonNull 19 | private PositionVO startPos; 20 | 21 | @NonNull 22 | private PositionVO endPos; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /happyride/api/trip-service-api/src/main/java/io/vividcode/happyride/tripservice/api/web/TripVO.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.api.web; 2 | 3 | import io.vividcode.happyride.common.PositionVO; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class TripVO { 8 | private String id; 9 | 10 | private String passengerId; 11 | 12 | private String driverId; 13 | 14 | private PositionVO startPos; 15 | 16 | private PositionVO endPos; 17 | 18 | private String state; 19 | } 20 | -------------------------------------------------------------------------------- /happyride/api/trip-validation-service-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | happyride 7 | io.vividcode.happyride 8 | 3.0.0-SNAPSHOT 9 | ../../pom.xml 10 | 11 | 4.0.0 12 | 13 | trip-validation-service-api 14 | API :: Trip Validation Service 15 | 16 | 17 | 18 | io.vividcode.happyride 19 | trip-service-api 20 | ${project.version} 21 | 22 | 23 | io.eventuate.tram.core 24 | eventuate-tram-spring-commands 25 | 26 | 27 | org.projectlombok 28 | lombok 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /happyride/api/trip-validation-service-api/src/main/java/io/vividcode/happyride/tripvalidationservice/api/InvalidTripReply.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripvalidationservice.api; 2 | 3 | public class InvalidTripReply { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /happyride/api/trip-validation-service-api/src/main/java/io/vividcode/happyride/tripvalidationservice/api/TripValidationServiceChannels.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripvalidationservice.api; 2 | 3 | public class TripValidationServiceChannels { 4 | 5 | public static final String tripValidation = "io.vividcode.happyride.tripvalidationservice"; 6 | } 7 | -------------------------------------------------------------------------------- /happyride/api/trip-validation-service-api/src/main/java/io/vividcode/happyride/tripvalidationservice/api/ValidateTripCommand.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripvalidationservice.api; 2 | 3 | import io.eventuate.tram.commands.common.Command; 4 | import io.vividcode.happyride.tripservice.api.events.TripDetails; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.NonNull; 8 | import lombok.RequiredArgsConstructor; 9 | 10 | @Data 11 | @RequiredArgsConstructor 12 | @NoArgsConstructor 13 | public class ValidateTripCommand implements Command { 14 | 15 | @NonNull 16 | private TripDetails tripDetails; 17 | } 18 | -------------------------------------------------------------------------------- /happyride/lib/common/src/main/java/io/vividcode/happyride/common/AbstractEntity.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.common; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import jakarta.persistence.MappedSuperclass; 5 | import jakarta.persistence.PostLoad; 6 | import jakarta.persistence.PrePersist; 7 | import jakarta.persistence.Transient; 8 | import org.springframework.data.domain.Persistable; 9 | 10 | @MappedSuperclass 11 | public abstract class AbstractEntity implements Persistable { 12 | 13 | @Transient 14 | private boolean isNew = true; 15 | 16 | @Override 17 | @JsonIgnore 18 | public boolean isNew() { 19 | return isNew; 20 | } 21 | 22 | @PrePersist 23 | @PostLoad 24 | void markNotNew() { 25 | this.isNew = false; 26 | } 27 | } -------------------------------------------------------------------------------- /happyride/lib/common/src/main/java/io/vividcode/happyride/common/BaseEntityWithGeneratedId.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.common; 2 | 3 | import jakarta.persistence.Column; 4 | import jakarta.persistence.MappedSuperclass; 5 | import jakarta.persistence.PrePersist; 6 | import jakarta.persistence.PreUpdate; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | @MappedSuperclass 11 | @Getter 12 | @Setter 13 | public abstract class BaseEntityWithGeneratedId extends EntityWithGeneratedId { 14 | 15 | @Column(name = "created_at") 16 | private Long createdAt; 17 | 18 | @Column(name = "updated_at") 19 | private Long updatedAt; 20 | 21 | @PrePersist 22 | void setInitialDate() { 23 | createdAt = updatedAt = System.currentTimeMillis(); 24 | } 25 | 26 | @PreUpdate 27 | void updateDate() { 28 | updatedAt = System.currentTimeMillis(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /happyride/lib/common/src/main/java/io/vividcode/happyride/common/DriverState.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.common; 2 | 3 | public enum DriverState { 4 | OFFLINE, 5 | AVAILABLE, 6 | NOT_AVAILABLE 7 | } 8 | -------------------------------------------------------------------------------- /happyride/lib/common/src/main/java/io/vividcode/happyride/common/EntityWithGeneratedId.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.common; 2 | 3 | import java.util.UUID; 4 | import jakarta.persistence.Column; 5 | import jakarta.persistence.Id; 6 | import jakarta.persistence.MappedSuperclass; 7 | import jakarta.persistence.PrePersist; 8 | import jakarta.validation.constraints.Size; 9 | import lombok.EqualsAndHashCode; 10 | import lombok.Getter; 11 | 12 | @MappedSuperclass 13 | @EqualsAndHashCode(of = "id", callSuper = false) 14 | @Getter 15 | public abstract class EntityWithGeneratedId extends AbstractEntity { 16 | 17 | @Id 18 | @Column(name = "id") 19 | @Size(max = 36) 20 | private String id; 21 | 22 | @PrePersist 23 | public void generateId() { 24 | if (id == null) { 25 | id = UUID.randomUUID().toString(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /happyride/lib/common/src/main/java/io/vividcode/happyride/common/Position.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.common; 2 | 3 | import java.math.BigDecimal; 4 | import jakarta.persistence.Column; 5 | import jakarta.persistence.Embeddable; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import lombok.NonNull; 10 | import lombok.RequiredArgsConstructor; 11 | 12 | @Embeddable 13 | @Data 14 | @NoArgsConstructor 15 | @RequiredArgsConstructor 16 | @AllArgsConstructor 17 | public class Position { 18 | 19 | @Column(name = "lng") 20 | @NonNull 21 | private BigDecimal lng; 22 | 23 | @Column(name = "lat") 24 | @NonNull 25 | private BigDecimal lat; 26 | 27 | @Column(name = "address_id", length = 36) 28 | private String addressId; 29 | 30 | public PositionVO serialize() { 31 | return new PositionVO(lng, lat, addressId); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /happyride/lib/common/src/main/java/io/vividcode/happyride/common/PositionVO.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.common; 2 | 3 | import java.math.BigDecimal; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.NonNull; 8 | import lombok.RequiredArgsConstructor; 9 | 10 | @Data 11 | @RequiredArgsConstructor 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class PositionVO { 15 | @NonNull 16 | private BigDecimal lng; 17 | 18 | @NonNull 19 | private BigDecimal lat; 20 | 21 | private String addressId; 22 | 23 | public Position deserialize() { 24 | return new Position(lng, lat, addressId); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /happyride/lib/common/src/main/java/io/vividcode/happyride/common/Utils.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.common; 2 | 3 | import static org.locationtech.spatial4j.distance.DistanceUtils.EARTH_MEAN_RADIUS_KM; 4 | 5 | import org.locationtech.spatial4j.distance.DistanceUtils; 6 | 7 | public class Utils { 8 | 9 | private Utils() { 10 | } 11 | 12 | public static double calculateDistance(final PositionVO startPos, 13 | final PositionVO endPos) { 14 | final double radians = DistanceUtils 15 | .distHaversineRAD(startPos.getLat().doubleValue(), 16 | startPos.getLng().doubleValue(), 17 | endPos.getLat().doubleValue(), endPos.getLng().doubleValue()); 18 | return DistanceUtils.radians2Dist(radians, EARTH_MEAN_RADIUS_KM); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /happyride/service/address-service/README.md: -------------------------------------------------------------------------------- 1 | # Address Management Service 2 | 3 | Use the `dev` profile to develop locally 4 | 5 | ``` 6 | -Dspring.profiles.active=dev 7 | ``` 8 | 9 | ``` -------------------------------------------------------------------------------- /happyride/service/address-service/src/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM adoptopenjdk/openjdk8:jre8u262-b10-alpine 2 | 3 | ADD target/happyride-address-service-1.0.0-SNAPSHOT.jar /opt/app.jar 4 | ENTRYPOINT [ "java", "-jar", "/opt/app.jar" ] -------------------------------------------------------------------------------- /happyride/service/address-service/src/k8s/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: address-config 6 | data: 7 | db_host: address-postgres 8 | db_port: '5432' 9 | db_name: happyride-address 10 | spring.yml: |- 11 | server: 12 | port: 8080 13 | app.yml: |- -------------------------------------------------------------------------------- /happyride/service/address-service/src/k8s/secret.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: address-postgres 5 | type: Opaque 6 | data: 7 | username: cG9zZ3Jlcw== 8 | password: cG9zZ3Jlcy1wYXNzd29yZA== -------------------------------------------------------------------------------- /happyride/service/address-service/src/k8s/service-monitor.yml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: ServiceMonitor 3 | metadata: 4 | name: address-service 5 | labels: 6 | release: prom-o 7 | spec: 8 | selector: 9 | matchLabels: 10 | app.kubernetes.io/name: address 11 | namespaceSelector: 12 | matchNames: 13 | - default 14 | endpoints: 15 | - port: api 16 | interval: 10s 17 | path: "/actuator/prometheus" 18 | honorLabels: true -------------------------------------------------------------------------------- /happyride/service/address-service/src/main/java/io/vividcode/happyride/addressservice/AddressServiceApplication.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.addressservice; 2 | 3 | import io.vividcode.happyride.common.DatabaseRuntimeHintsRegistrar; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.context.annotation.ImportRuntimeHints; 7 | 8 | @ImportRuntimeHints(DatabaseRuntimeHintsRegistrar.class) 9 | @SpringBootApplication 10 | public class AddressServiceApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(AddressServiceApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /happyride/service/address-service/src/main/java/io/vividcode/happyride/addressservice/ApplicationConfig.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.addressservice; 2 | 3 | import io.micrometer.core.aop.TimedAspect; 4 | import io.micrometer.core.instrument.MeterRegistry; 5 | import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.context.annotation.EnableAspectJAutoProxy; 9 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 10 | import org.springframework.transaction.annotation.EnableTransactionManagement; 11 | 12 | @Configuration 13 | @EnableJpaRepositories 14 | @EnableTransactionManagement 15 | @EnableAspectJAutoProxy 16 | public class ApplicationConfig { 17 | 18 | @Bean 19 | public TimedAspect timedAspect(final MeterRegistry meterRegistry) { 20 | return new TimedAspect(meterRegistry); 21 | } 22 | 23 | @Bean 24 | public MeterRegistryCustomizer meterRegistryCustomizer() { 25 | return registry -> registry.config().commonTags("service", "address"); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /happyride/service/address-service/src/main/java/io/vividcode/happyride/addressservice/dataaccess/AddressRepository.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.addressservice.dataaccess; 2 | 3 | import io.vividcode.happyride.addressservice.domain.Address; 4 | import java.util.List; 5 | import org.springframework.data.repository.CrudRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface AddressRepository extends CrudRepository { 10 | 11 | List
findByAreaAreaCodeAndAddressLineContains(Long areaCode, String query); 12 | } 13 | -------------------------------------------------------------------------------- /happyride/service/address-service/src/main/java/io/vividcode/happyride/addressservice/dataaccess/AreaRepository.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.addressservice.dataaccess; 2 | 3 | import io.vividcode.happyride.addressservice.domain.Area; 4 | import java.util.Optional; 5 | import org.springframework.data.repository.CrudRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface AreaRepository extends CrudRepository { 10 | 11 | Optional findByAreaCode(Long areaCode); 12 | } 13 | -------------------------------------------------------------------------------- /happyride/service/address-service/src/main/java/io/vividcode/happyride/addressservice/domain/Address.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.addressservice.domain; 2 | 3 | import io.vividcode.happyride.common.BaseEntityWithGeneratedId; 4 | import java.math.BigDecimal; 5 | import jakarta.persistence.Column; 6 | import jakarta.persistence.Entity; 7 | import jakarta.persistence.JoinColumn; 8 | import jakarta.persistence.ManyToOne; 9 | import jakarta.persistence.Table; 10 | import jakarta.validation.constraints.Size; 11 | import lombok.Getter; 12 | import lombok.NoArgsConstructor; 13 | import lombok.Setter; 14 | import lombok.ToString; 15 | 16 | @Entity 17 | @Table(name = "addresses") 18 | @Getter 19 | @Setter 20 | @NoArgsConstructor 21 | @ToString 22 | public class Address extends BaseEntityWithGeneratedId { 23 | 24 | @ManyToOne 25 | @JoinColumn(name = "area_id") 26 | private Area area; 27 | 28 | @Column(name = "address_line") 29 | @Size(max = 255) 30 | private String addressLine; 31 | 32 | @Column(name = "lng") 33 | private BigDecimal lng; 34 | 35 | @Column(name = "lat") 36 | private BigDecimal lat; 37 | } 38 | -------------------------------------------------------------------------------- /happyride/service/address-service/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8502 -------------------------------------------------------------------------------- /happyride/service/address-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | jpa: 3 | open-in-view: false 4 | hibernate: 5 | ddl-auto: validate 6 | properties: 7 | hibernate: 8 | dialect: org.hibernate.dialect.PostgreSQLDialect 9 | default_schema: happyride 10 | datasource: 11 | driver-class-name: org.postgresql.Driver 12 | url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:8430}/${DB_NAME:happyride-address} 13 | username: ${DB_USERNAME:postgres} 14 | password: ${DB_PASSWORD:postgres} 15 | flyway: 16 | schemas: 17 | - happyride 18 | grpc: 19 | server: 20 | port: ${GRPC_PORT:6565} 21 | management: 22 | health: 23 | livenessState: 24 | enabled: true 25 | readinessState: 26 | enabled: true 27 | endpoints: 28 | enabled-by-default: false 29 | web: 30 | exposure: 31 | include: prometheus, health 32 | endpoint: 33 | health: 34 | enabled: true 35 | show-components: always 36 | prometheus: 37 | enabled: true 38 | -------------------------------------------------------------------------------- /happyride/service/address-service/src/main/resources/db/migration/V1__init_schema.sql: -------------------------------------------------------------------------------- 1 | CREATE SCHEMA IF NOT EXISTS happyride; 2 | 3 | CREATE SEQUENCE hibernate_sequence START 1; 4 | 5 | CREATE TABLE happyride.areas ( 6 | id SERIAL PRIMARY KEY, 7 | level int NOT NULL, 8 | parent_code bigint NOT NULL DEFAULT '0', 9 | area_code bigint NOT NULL DEFAULT '0', 10 | zip_code varchar(6) NOT NULL DEFAULT '000000', 11 | city_code varchar(6) NOT NULL DEFAULT '', 12 | name varchar(50) NOT NULL DEFAULT '', 13 | short_name varchar(50) NOT NULL DEFAULT '', 14 | merger_name varchar(50) NOT NULL DEFAULT '', 15 | pinyin varchar(30) NOT NULL DEFAULT '', 16 | lng decimal(10,6) NOT NULL DEFAULT '0.000000', 17 | lat decimal(10,6) NOT NULL DEFAULT '0.000000' 18 | ); 19 | 20 | CREATE TABLE happyride.addresses ( 21 | id varchar(36) NOT NULL PRIMARY KEY, 22 | created_at bigint NOT NULL, 23 | updated_at bigint NOT NULL, 24 | area_id int NOT NULL, 25 | address_line varchar(255) NOT NULL, 26 | lng decimal(10,6) NOT NULL DEFAULT '0.000000', 27 | lat decimal(10,6) NOT NULL DEFAULT '0.000000', 28 | FOREIGN KEY (area_id) REFERENCES happyride.areas(id) 29 | ); -------------------------------------------------------------------------------- /happyride/service/address-service/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | jpa: 3 | hibernate: 4 | ddl-auto: validate 5 | properties: 6 | hibernate: 7 | dialect: org.hibernate.dialect.PostgreSQLDialect 8 | default_schema: happyride 9 | flyway: 10 | schemas: 11 | - happyride -------------------------------------------------------------------------------- /happyride/service/dispatch-service/src/main/java/io/vividcode/happyride/dispatchservice/AvailableDriver.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice; 2 | 3 | import java.math.BigDecimal; 4 | import lombok.Data; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @RequiredArgsConstructor 10 | public class AvailableDriver { 11 | 12 | @NonNull 13 | private String driverId; 14 | 15 | @NonNull 16 | private BigDecimal posLng; 17 | 18 | @NonNull 19 | private BigDecimal posLat; 20 | } 21 | -------------------------------------------------------------------------------- /happyride/service/dispatch-service/src/main/java/io/vividcode/happyride/dispatchservice/DispatchServiceApplication.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DispatchServiceApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DispatchServiceApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /happyride/service/dispatch-service/src/main/java/io/vividcode/happyride/dispatchservice/DispatchVerificationException.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice; 2 | 3 | public class DispatchVerificationException extends RuntimeException { 4 | 5 | public DispatchVerificationException() { 6 | } 7 | 8 | public DispatchVerificationException(String message) { 9 | super(message); 10 | } 11 | 12 | public DispatchVerificationException(String message, Throwable cause) { 13 | super(message, cause); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /happyride/service/dispatch-service/src/main/java/io/vividcode/happyride/dispatchservice/DriverLocationUpdater.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice; 2 | 3 | import io.vividcode.happyride.common.DriverState; 4 | import io.vividcode.happyride.dispatchservice.api.events.DriverLocation; 5 | import io.vividcode.happyride.dispatchservice.api.events.DriverLocationUpdatedEvent; 6 | import org.axonframework.eventhandling.EventHandler; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class DriverLocationUpdater { 12 | 13 | @Autowired 14 | DriverLocationService driverLocationService; 15 | 16 | @EventHandler 17 | public void handle(final DriverLocationUpdatedEvent event) { 18 | final DriverLocation location = event.getLocation(); 19 | if (event.getState() == DriverState.AVAILABLE) { 20 | this.driverLocationService.addAvailableDriver(location); 21 | } else { 22 | this.driverLocationService.removeAvailableDriver(location.getDriverId()); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /happyride/service/dispatch-service/src/main/java/io/vividcode/happyride/dispatchservice/commandhandlers/DispatchCommandHandlersConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.commandhandlers; 2 | 3 | import io.eventuate.tram.sagas.participant.SagaCommandDispatcher; 4 | import io.eventuate.tram.sagas.participant.SagaCommandDispatcherFactory; 5 | import io.eventuate.tram.sagas.spring.participant.SagaParticipantConfiguration; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.ComponentScan; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.context.annotation.Import; 10 | 11 | @Configuration 12 | @Import({SagaParticipantConfiguration.class}) 13 | @ComponentScan 14 | public class DispatchCommandHandlersConfiguration { 15 | 16 | @Bean 17 | public SagaCommandDispatcher dispatchCommandHandlersDispatcher( 18 | DispatchCommandHandlers dispatchCommandHandlers, 19 | SagaCommandDispatcherFactory sagaCommandDispatcherFactory) { 20 | return sagaCommandDispatcherFactory 21 | .make("dispatchService", dispatchCommandHandlers.commandHandlers()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /happyride/service/dispatch-service/src/main/java/io/vividcode/happyride/dispatchservice/dataaccess/DispatchRepository.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.dataaccess; 2 | 3 | import io.vividcode.happyride.dispatchservice.domain.Dispatch; 4 | import io.vividcode.happyride.dispatchservice.domain.DispatchState; 5 | import java.util.List; 6 | import java.util.Optional; 7 | import org.springframework.data.repository.CrudRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | @Repository 11 | public interface DispatchRepository extends CrudRepository { 12 | 13 | List findByTripIdAndState(String tripId, DispatchState state); 14 | 15 | default Optional findCurrentDispatch(String tripId) { 16 | return findByTripIdAndState(tripId, DispatchState.WAIT_FOR_ACCEPTANCE).stream().findFirst(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /happyride/service/dispatch-service/src/main/java/io/vividcode/happyride/dispatchservice/domain/DispatchDomainEventPublisher.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.domain; 2 | 3 | import io.eventuate.tram.events.aggregates.AbstractAggregateDomainEventPublisher; 4 | import io.eventuate.tram.events.publisher.DomainEventPublisher; 5 | import io.vividcode.happyride.dispatchservice.api.events.DispatchDomainEvent; 6 | 7 | public class DispatchDomainEventPublisher extends 8 | AbstractAggregateDomainEventPublisher { 9 | 10 | public DispatchDomainEventPublisher(DomainEventPublisher eventPublisher) { 11 | super(eventPublisher, Dispatch.class, Dispatch::getId); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /happyride/service/dispatch-service/src/main/java/io/vividcode/happyride/dispatchservice/domain/DispatchState.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.domain; 2 | 3 | public enum DispatchState { 4 | WAIT_FOR_ACCEPTANCE, 5 | ACCEPTANCE_SELECTED, 6 | FAILED, 7 | CANCELLED 8 | } 9 | -------------------------------------------------------------------------------- /happyride/service/dispatch-service/src/main/java/io/vividcode/happyride/dispatchservice/domain/TripAcceptanceState.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.dispatchservice.domain; 2 | 3 | public enum TripAcceptanceState { 4 | INVITED, 5 | SUBMITTED, 6 | SELECTED, 7 | DECLINED 8 | } 9 | -------------------------------------------------------------------------------- /happyride/service/dispatch-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | jpa: 3 | hibernate: 4 | ddl-auto: update 5 | properties: 6 | hibernate: 7 | dialect: org.hibernate.dialect.PostgreSQL10Dialect 8 | default_schema: happyride 9 | datasource: 10 | driver-class-name: org.postgresql.Driver 11 | url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:8433}/${DB_NAME:happyride-dispatch} 12 | username: ${DB_USERNAME:postgres} 13 | password: ${DB_PASSWORD:postgres} 14 | redis: 15 | url: redis://${REDIS_HOST:localhost}:${REDIS_PORT:6379} 16 | flyway: 17 | schemas: 18 | - happyride 19 | axon: 20 | axonserver: 21 | servers: ${AXON_HOST:localhost}:${AXON_PORT:8124} 22 | serializer: 23 | events: jackson 24 | eventuatelocal: 25 | kafka: 26 | bootstrap: 27 | servers: ${KAFKA_HOST:localhost}:${KAFKA_PORT:29092} 28 | zookeeper: 29 | connection: 30 | string: ${ZOOKEEPER_HOST:localhost}:${ZOOKEEPER_PORT:2181} 31 | -------------------------------------------------------------------------------- /happyride/service/dispatch-service/src/main/resources/db/migration/V1__init_schema.sql: -------------------------------------------------------------------------------- 1 | CREATE SCHEMA IF NOT EXISTS happyride; 2 | 3 | CREATE TABLE happyride.dispatches ( 4 | id varchar(36) NOT NULL PRIMARY KEY, 5 | trip_id varchar(36) NOT NULL, 6 | start_pos_lng decimal(10,6) NOT NULL DEFAULT '0.000000', 7 | start_pos_lat decimal(10,6) NOT NULL DEFAULT '0.000000', 8 | state varchar(30) NOT NULL, 9 | failed_reason varchar(30) 10 | ); 11 | 12 | CREATE TABLE happyride.trip_acceptances ( 13 | id varchar(36) NOT NULL PRIMARY KEY, 14 | dispatch_id varchar(36) NOT NULL, 15 | driver_id varchar(36) NOT NULL, 16 | timestamp bigint not null, 17 | current_pos_lng decimal(10,6) NOT NULL DEFAULT '0.000000', 18 | current_pos_lat decimal(10,6) NOT NULL DEFAULT '0.000000', 19 | state varchar(30) NOT NULL, 20 | declined_reason varchar(30), 21 | FOREIGN KEY (dispatch_id) REFERENCES happyride.dispatches(id) 22 | ); -------------------------------------------------------------------------------- /happyride/service/dispatch-service/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | jpa: 3 | hibernate: 4 | ddl-auto: validate 5 | properties: 6 | hibernate: 7 | dialect: org.hibernate.dialect.PostgreSQLDialect 8 | default_schema: happyride 9 | flyway: 10 | schemas: 11 | - happyride 12 | redis: 13 | url: redis://${embedded.redis.password}@${embedded.redis.host}:${embedded.redis.port} 14 | -------------------------------------------------------------------------------- /happyride/service/driver-service/src/main/java/io/vividcode/happyride/driverservice/ApplicationConfig.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driverservice; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 5 | import org.springframework.transaction.annotation.EnableTransactionManagement; 6 | 7 | @Configuration 8 | @EnableJpaRepositories 9 | @EnableTransactionManagement 10 | public class ApplicationConfig { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /happyride/service/driver-service/src/main/java/io/vividcode/happyride/driverservice/DriverServiceApplication.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driverservice; 2 | 3 | import io.vividcode.happyride.common.DatabaseRuntimeHintsRegistrar; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.context.annotation.ImportRuntimeHints; 7 | 8 | @ImportRuntimeHints(DatabaseRuntimeHintsRegistrar.class) 9 | @SpringBootApplication 10 | public class DriverServiceApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(DriverServiceApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /happyride/service/driver-service/src/main/java/io/vividcode/happyride/driverservice/dataaccess/DriverRepository.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driverservice.dataaccess; 2 | 3 | import io.vividcode.happyride.driverservice.model.Driver; 4 | import org.springframework.data.repository.CrudRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface DriverRepository extends CrudRepository { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /happyride/service/driver-service/src/main/java/io/vividcode/happyride/driverservice/model/Vehicle.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driverservice.model; 2 | 3 | import io.vividcode.happyride.common.BaseEntityWithGeneratedId; 4 | import jakarta.persistence.Column; 5 | import jakarta.persistence.Entity; 6 | import jakarta.persistence.Table; 7 | import jakarta.validation.constraints.Size; 8 | import lombok.Getter; 9 | import lombok.NoArgsConstructor; 10 | import lombok.Setter; 11 | import lombok.ToString; 12 | 13 | @Entity 14 | @Table(name = "vehicles") 15 | @Getter 16 | @Setter 17 | @NoArgsConstructor 18 | @ToString 19 | public class Vehicle extends BaseEntityWithGeneratedId { 20 | 21 | @Column(name = "make") 22 | @Size(max = 60) 23 | private String make; 24 | 25 | @Column(name = "mode") 26 | @Size(max = 60) 27 | private String mode; 28 | 29 | @Column(name = "year") 30 | private Integer year; 31 | 32 | @Column(name = "registration") 33 | @Size(max = 32) 34 | private String registration; 35 | } 36 | -------------------------------------------------------------------------------- /happyride/service/driver-service/src/main/java/io/vividcode/happyride/driverservice/service/DriverNotFoundException.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driverservice.service; 2 | 3 | public class DriverNotFoundException extends RuntimeException { 4 | 5 | private final String driverId; 6 | 7 | public DriverNotFoundException(String driverId) { 8 | this.driverId = driverId; 9 | } 10 | 11 | @Override 12 | public String getMessage() { 13 | return String.format("Driver %s not found", driverId); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /happyride/service/driver-service/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8503 -------------------------------------------------------------------------------- /happyride/service/driver-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | jpa: 3 | open-in-view: false 4 | hibernate: 5 | ddl-auto: validate 6 | properties: 7 | hibernate: 8 | dialect: org.hibernate.dialect.PostgreSQLDialect 9 | default_schema: happyride 10 | datasource: 11 | driver-class-name: org.postgresql.Driver 12 | url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:8437}/${DB_NAME:happyride-driver} 13 | username: ${DB_USERNAME:postgres} 14 | password: ${DB_PASSWORD:postgres} 15 | flyway: 16 | schemas: 17 | - happyride -------------------------------------------------------------------------------- /happyride/service/driver-service/src/main/resources/db/migration/V1__init_schema.sql: -------------------------------------------------------------------------------- 1 | CREATE SCHEMA IF NOT EXISTS happyride; 2 | 3 | CREATE TABLE happyride.drivers ( 4 | id varchar(36) NOT NULL PRIMARY KEY, 5 | created_at bigint NOT NULL, 6 | updated_at bigint NOT NULL, 7 | name varchar(255) NOT NULL, 8 | email varchar(255) NULL, 9 | mobile_phone_number varchar(255) NOT NULL, 10 | state varchar(30) NOT NULL 11 | ); 12 | 13 | CREATE TABLE happyride.vehicles ( 14 | id varchar(36) NOT NULL PRIMARY KEY, 15 | created_at bigint NOT NULL, 16 | updated_at bigint NOT NULL, 17 | driver_id varchar(36) NOT NULL, 18 | make varchar(60) NOT NULL, 19 | mode varchar(60) NOT NULL, 20 | year int NOT NULL, 21 | registration varchar(32) NOT NULL, 22 | FOREIGN KEY (driver_id) REFERENCES happyride.drivers(id) 23 | ); -------------------------------------------------------------------------------- /happyride/service/driver-service/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | jpa: 3 | hibernate: 4 | ddl-auto: validate 5 | properties: 6 | hibernate: 7 | dialect: org.hibernate.dialect.PostgreSQLDialect 8 | default_schema: happyride 9 | flyway: 10 | schemas: 11 | - happyride 12 | http: 13 | log-request-details: true 14 | logging: 15 | level: 16 | "org.springframework.web.reactive.function.client.ExchangeFunctions": TRACE -------------------------------------------------------------------------------- /happyride/service/passenger-service/README.md: -------------------------------------------------------------------------------- 1 | # Passenger Management Service 2 | 3 | Use the `dev` profile to develop locally 4 | 5 | ``` 6 | -Dspring.profiles.active=dev 7 | ``` -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/main/java/io/vividcode/happyride/passengerservice/ApplicationConfig.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerservice; 2 | 3 | import io.vividcode.happyride.passengerservice.messagehandlers.PassengerServiceMessageHandlersConfiguration; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.context.annotation.Import; 6 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 7 | import org.springframework.transaction.annotation.EnableTransactionManagement; 8 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 9 | 10 | @Configuration 11 | @EnableJpaRepositories 12 | @EnableTransactionManagement 13 | @Import(PassengerServiceMessageHandlersConfiguration.class) 14 | @EnableWebMvc 15 | public class ApplicationConfig { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/main/java/io/vividcode/happyride/passengerservice/PassengerServiceApplication.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerservice; 2 | 3 | import io.vividcode.happyride.common.DatabaseRuntimeHintsRegistrar; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.context.annotation.ImportRuntimeHints; 7 | 8 | @ImportRuntimeHints(DatabaseRuntimeHintsRegistrar.class) 9 | @SpringBootApplication 10 | public class PassengerServiceApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(PassengerServiceApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/main/java/io/vividcode/happyride/passengerservice/dataaccess/PassengerRepository.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerservice.dataaccess; 2 | 3 | import io.vividcode.happyride.passengerservice.domain.Passenger; 4 | import org.springframework.data.repository.CrudRepository; 5 | import org.springframework.data.repository.PagingAndSortingRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface PassengerRepository extends 10 | PagingAndSortingRepository, CrudRepository { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/main/java/io/vividcode/happyride/passengerservice/domain/PassengerNotFoundException.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerservice.domain; 2 | 3 | public class PassengerNotFoundException extends RuntimeException { 4 | 5 | private final String passengerId; 6 | 7 | public PassengerNotFoundException(String passengerId) { 8 | this.passengerId = passengerId; 9 | } 10 | 11 | @Override 12 | public String getMessage() { 13 | return String.format("Passenger %s not found", passengerId); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/main/java/io/vividcode/happyride/passengerservice/domain/TripServiceProxy.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerservice.domain; 2 | 3 | import io.vividcode.happyride.tripservice.api.web.CreateTripRequest; 4 | import io.vividcode.happyride.tripservice.client.ApiException; 5 | import io.vividcode.happyride.tripservice.client.api.TripApi; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | public class TripServiceProxy { 10 | 11 | private final TripApi tripApi = new TripApi(); 12 | 13 | public void createTrip(final CreateTripRequest request) throws ApiException { 14 | this.tripApi.createTrip(request); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/main/java/io/vividcode/happyride/passengerservice/domain/UserAddress.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerservice.domain; 2 | 3 | import io.vividcode.happyride.common.EntityWithGeneratedId; 4 | import jakarta.persistence.Column; 5 | import jakarta.persistence.Entity; 6 | import jakarta.persistence.Table; 7 | import jakarta.validation.constraints.Size; 8 | import lombok.Getter; 9 | import lombok.NoArgsConstructor; 10 | import lombok.NonNull; 11 | import lombok.Setter; 12 | 13 | @Entity 14 | @Table(name = "user_addresses") 15 | @Getter 16 | @Setter 17 | @NoArgsConstructor 18 | public class UserAddress extends EntityWithGeneratedId { 19 | 20 | @Column(name = "name") 21 | @Size(max = 255) 22 | @NonNull 23 | private String name; 24 | 25 | @Column(name = "address_id") 26 | @Size(max = 36) 27 | @NonNull 28 | private String addressId; 29 | } 30 | -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8500 -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | jpa: 3 | open-in-view: false 4 | hibernate: 5 | ddl-auto: validate 6 | properties: 7 | hibernate: 8 | dialect: org.hibernate.dialect.PostgreSQLDialect 9 | default_schema: happyride 10 | datasource: 11 | driver-class-name: org.postgresql.Driver 12 | url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:8431}/${DB_NAME:happyride-passenger} 13 | username: ${DB_USERNAME:postgres} 14 | password: ${DB_PASSWORD:postgres} 15 | flyway: 16 | schemas: 17 | - happyride 18 | eventuate: 19 | database: 20 | schema: eventuate 21 | eventuatelocal: 22 | kafka: 23 | bootstrap: 24 | servers: ${KAFKA_HOST:localhost}:${KAFKA_PORT:29092} 25 | zookeeper: 26 | connection: 27 | string: ${ZOOKEEPER_HOST:localhost}:${ZOOKEEPER_PORT:2181} -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/main/resources/db/migration/V1__init_schema.sql: -------------------------------------------------------------------------------- 1 | CREATE SCHEMA IF NOT EXISTS happyride; 2 | 3 | CREATE TABLE happyride.passengers ( 4 | id varchar(36) NOT NULL PRIMARY KEY, 5 | created_at bigint NOT NULL, 6 | updated_at bigint NOT NULL, 7 | name varchar(255) NOT NULL, 8 | email varchar(255) NULL, 9 | mobile_phone_number varchar(255) NOT NULL 10 | ); 11 | 12 | CREATE TABLE happyride.user_addresses ( 13 | id varchar(36) NOT NULL PRIMARY KEY, 14 | passenger_id varchar(36) NOT NULL, 15 | name varchar(255) NOT NULL, 16 | address_id varchar(36) NOT NULL, 17 | FOREIGN KEY (passenger_id) REFERENCES happyride.passengers(id) 18 | ); -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/test/java/io/vividcode/happyride/bdd/BddTestApplication.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.bdd; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | 5 | @SpringBootApplication 6 | public class BddTestApplication { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/test/java/io/vividcode/happyride/bdd/PassengerIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.bdd; 2 | 3 | 4 | import io.cucumber.junit.Cucumber; 5 | import io.cucumber.junit.CucumberOptions; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(Cucumber.class) 9 | @CucumberOptions( 10 | features = "src/test/resources/features", 11 | plugin = {"pretty", "html:target/cucumber"}) 12 | public class PassengerIntegrationTest { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/test/java/io/vividcode/happyride/mocktest/ActionService.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.mocktest; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | 6 | @Service 7 | public class ActionService { 8 | 9 | @Autowired 10 | ValueUpdater valueUpdater; 11 | 12 | @Autowired 13 | EventPublisher eventPublisher; 14 | 15 | public int performAction(Integer value) { 16 | Integer oldValue = valueUpdater.getValue(); 17 | if (valueUpdater.updateValue(value)) { 18 | ValueUpdatedEvent event = new ValueUpdatedEvent(oldValue, value); 19 | eventPublisher.publishEvent(event); 20 | return value * 10; 21 | } 22 | return 0; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/test/java/io/vividcode/happyride/mocktest/EventPublisher.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.mocktest; 2 | 3 | import org.springframework.stereotype.Service; 4 | 5 | @Service 6 | public class EventPublisher { 7 | 8 | public void publishEvent(ValueUpdatedEvent event) { 9 | System.out.println(event); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/test/java/io/vividcode/happyride/mocktest/TestConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.mocktest; 2 | 3 | import org.springframework.context.annotation.ComponentScan; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | @Configuration 7 | @ComponentScan 8 | public class TestConfiguration { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/test/java/io/vividcode/happyride/mocktest/ValueUpdatedEvent.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.mocktest; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | 6 | @Data 7 | @AllArgsConstructor 8 | public class ValueUpdatedEvent { 9 | 10 | private Integer previousValue; 11 | 12 | private Integer currentValue; 13 | } 14 | -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/test/java/io/vividcode/happyride/mocktest/ValueUpdater.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.mocktest; 2 | 3 | import org.springframework.stereotype.Service; 4 | 5 | @Service 6 | public class ValueUpdater { 7 | 8 | private Integer value; 9 | 10 | public boolean updateValue(Integer value) { 11 | if (value != null && value > 0) { 12 | this.value = value; 13 | return true; 14 | } 15 | return false; 16 | } 17 | 18 | public Integer getValue() { 19 | return value; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/test/java/io/vividcode/happyride/passengerservice/PassengerTestApplication.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.passengerservice; 2 | 3 | import io.vividcode.happyride.passengerservice.dataaccess.PassengerRepository; 4 | import io.vividcode.happyride.passengerservice.domain.PassengerService; 5 | import io.vividcode.happyride.passengerservice.web.PassengerController; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.annotation.ComponentScan; 8 | 9 | @SpringBootApplication 10 | @ComponentScan(basePackageClasses = {PassengerRepository.class, 11 | PassengerService.class, PassengerController.class}) 12 | public class PassengerTestApplication { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | jpa: 3 | open-in-view: false 4 | hibernate: 5 | ddl-auto: validate 6 | properties: 7 | hibernate: 8 | dialect: org.hibernate.dialect.PostgreSQLDialect 9 | default_schema: happyride 10 | flyway: 11 | schemas: 12 | - happyride 13 | http: 14 | log-request-details: true 15 | logging: 16 | level: 17 | "org.springframework.web.reactive.function.client.ExchangeFunctions": TRACE -------------------------------------------------------------------------------- /happyride/service/passenger-service/src/test/resources/features/address.feature: -------------------------------------------------------------------------------- 1 | Feature: Address management 2 | Manage a passenger's addresses 3 | 4 | Scenario: Add a new address 5 | Given a passenger with 1 addresses 6 | When the passenger adds a new address 7 | Then the passenger has 2 addresses 8 | 9 | Scenario: Delete an address 10 | Given a passenger with 3 addresses 11 | When the passenger deletes an address 12 | Then the passenger has 2 addresses -------------------------------------------------------------------------------- /happyride/service/payment-service/src/main/java/io/vividcode/happyride/paymentservice/ApplicationConfig.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice; 2 | 3 | import io.eventuate.tram.spring.jdbckafka.TramJdbcKafkaConfiguration; 4 | import io.vividcode.happyride.paymentservice.commandhandlers.PaymentCommandHandlersConfiguration; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.context.annotation.Import; 7 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 8 | import org.springframework.transaction.annotation.EnableTransactionManagement; 9 | 10 | @Configuration 11 | @EnableJpaRepositories 12 | @EnableTransactionManagement 13 | @Import({ 14 | TramJdbcKafkaConfiguration.class, 15 | PaymentCommandHandlersConfiguration.class}) 16 | public class ApplicationConfig { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /happyride/service/payment-service/src/main/java/io/vividcode/happyride/paymentservice/PaymentApplication.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class PaymentApplication { 8 | 9 | public static void main(final String[] args) { 10 | SpringApplication.run(PaymentApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /happyride/service/payment-service/src/main/java/io/vividcode/happyride/paymentservice/commandhandlers/PaymentCommandHandlersConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice.commandhandlers; 2 | 3 | import io.eventuate.tram.sagas.participant.SagaCommandDispatcher; 4 | import io.eventuate.tram.sagas.participant.SagaCommandDispatcherFactory; 5 | import io.eventuate.tram.sagas.spring.participant.SagaParticipantConfiguration; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.ComponentScan; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.context.annotation.Import; 10 | 11 | @Configuration 12 | @Import({SagaParticipantConfiguration.class}) 13 | @ComponentScan 14 | public class PaymentCommandHandlersConfiguration { 15 | 16 | @Bean 17 | public SagaCommandDispatcher paymentCommandHandlersDispatcher( 18 | final PaymentCommandHandlers paymentCommandHandlers, 19 | final SagaCommandDispatcherFactory sagaCommandDispatcherFactory) { 20 | return sagaCommandDispatcherFactory 21 | .make("paymentService", paymentCommandHandlers.commandHandlers()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /happyride/service/payment-service/src/main/java/io/vividcode/happyride/paymentservice/dataaccess/PaymentRepository.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice.dataaccess; 2 | 3 | import io.vividcode.happyride.paymentservice.domain.Payment; 4 | import java.util.Optional; 5 | import org.springframework.data.repository.CrudRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface PaymentRepository extends CrudRepository { 10 | 11 | Optional findByTripId(String tripId); 12 | } 13 | -------------------------------------------------------------------------------- /happyride/service/payment-service/src/main/java/io/vividcode/happyride/paymentservice/domain/Payment.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice.domain; 2 | 3 | import io.vividcode.happyride.common.BaseEntityWithGeneratedId; 4 | import java.math.BigDecimal; 5 | import jakarta.persistence.Column; 6 | import jakarta.persistence.Entity; 7 | import jakarta.persistence.EnumType; 8 | import jakarta.persistence.Enumerated; 9 | import jakarta.persistence.Table; 10 | import jakarta.validation.constraints.Size; 11 | import lombok.Getter; 12 | import lombok.NoArgsConstructor; 13 | import lombok.NonNull; 14 | import lombok.Setter; 15 | import lombok.ToString; 16 | 17 | @Entity 18 | @Table(name = "payments") 19 | @Getter 20 | @Setter 21 | @NoArgsConstructor 22 | @ToString 23 | public class Payment extends BaseEntityWithGeneratedId { 24 | 25 | @NonNull 26 | @Column(name = "trip_id") 27 | @Size(max = 36) 28 | private String tripId; 29 | 30 | @Column(name = "amount") 31 | @NonNull 32 | private BigDecimal amount; 33 | 34 | @Column(name = "state") 35 | @Enumerated(EnumType.STRING) 36 | private PaymentState state = PaymentState.PENDING; 37 | } 38 | -------------------------------------------------------------------------------- /happyride/service/payment-service/src/main/java/io/vividcode/happyride/paymentservice/domain/PaymentException.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice.domain; 2 | 3 | public class PaymentException extends RuntimeException { 4 | 5 | public PaymentException(final String message) { 6 | super(message); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /happyride/service/payment-service/src/main/java/io/vividcode/happyride/paymentservice/domain/PaymentGateway.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice.domain; 2 | 3 | import java.math.BigDecimal; 4 | import org.springframework.stereotype.Service; 5 | 6 | @Service 7 | public class PaymentGateway { 8 | 9 | private static final BigDecimal PAYMENT_LIMIT = BigDecimal.valueOf(200); 10 | 11 | public void makePayment(final BigDecimal amount) { 12 | if (PAYMENT_LIMIT.compareTo(amount) < 0) { 13 | throw new PaymentException(String 14 | .format("Amount too large, requested %s, limit %s", amount, 15 | PAYMENT_LIMIT)); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /happyride/service/payment-service/src/main/java/io/vividcode/happyride/paymentservice/domain/PaymentNotFoundException.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice.domain; 2 | 3 | public class PaymentNotFoundException extends RuntimeException { 4 | 5 | private final String tripId; 6 | 7 | public PaymentNotFoundException(final String tripId) { 8 | this.tripId = tripId; 9 | } 10 | 11 | @Override 12 | public String getMessage() { 13 | return String.format("Cannot find the payment for trip %s", this.tripId); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /happyride/service/payment-service/src/main/java/io/vividcode/happyride/paymentservice/domain/PaymentResult.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.NonNull; 7 | import lombok.RequiredArgsConstructor; 8 | 9 | @Data 10 | @RequiredArgsConstructor 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class PaymentResult { 14 | 15 | @NonNull 16 | private boolean success; 17 | 18 | private String errorMessage; 19 | 20 | public static PaymentResult SUCCESS = new PaymentResult(true); 21 | 22 | public static PaymentResult failure(final String errorMessage) { 23 | return new PaymentResult(false, errorMessage); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /happyride/service/payment-service/src/main/java/io/vividcode/happyride/paymentservice/domain/PaymentState.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice.domain; 2 | 3 | public enum PaymentState { 4 | PENDING, 5 | PAYED, 6 | FAILED 7 | } 8 | -------------------------------------------------------------------------------- /happyride/service/payment-service/src/main/java/io/vividcode/happyride/paymentservice/web/PaymentController.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.paymentservice.web; 2 | 3 | import io.vividcode.happyride.paymentservice.api.web.MakePaymentRequest; 4 | import io.vividcode.happyride.paymentservice.domain.PaymentService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.PostMapping; 7 | import org.springframework.web.bind.annotation.RequestBody; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | @RestController 11 | public class PaymentController { 12 | 13 | @Autowired 14 | PaymentService paymentService; 15 | 16 | @PostMapping("/") 17 | public void makePayment(@RequestBody final MakePaymentRequest request) { 18 | this.paymentService.makePayment(request.getTripId()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /happyride/service/payment-service/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8504 -------------------------------------------------------------------------------- /happyride/service/payment-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | jpa: 3 | open-in-view: false 4 | hibernate: 5 | ddl-auto: validate 6 | properties: 7 | hibernate: 8 | dialect: org.hibernate.dialect.PostgreSQL10Dialect 9 | default_schema: happyride 10 | datasource: 11 | driver-class-name: org.postgresql.Driver 12 | url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:8435}/${DB_NAME:happyride-payment} 13 | username: ${DB_USERNAME:postgres} 14 | password: ${DB_PASSWORD:postgres} 15 | flyway: 16 | schemas: 17 | - happyride 18 | eventuatelocal: 19 | kafka: 20 | bootstrap: 21 | servers: ${KAFKA_HOST:localhost}:${KAFKA_PORT:29092} 22 | zookeeper: 23 | connection: 24 | string: ${ZOOKEEPER_HOST:localhost}:${ZOOKEEPER_PORT:2181} -------------------------------------------------------------------------------- /happyride/service/payment-service/src/main/resources/db/migration/V1__init_schema.sql: -------------------------------------------------------------------------------- 1 | CREATE SCHEMA IF NOT EXISTS happyride; 2 | 3 | CREATE TABLE happyride.payments( 4 | id varchar(36) NOT NULL PRIMARY KEY, 5 | created_at bigint NOT NULL, 6 | updated_at bigint NOT NULL, 7 | trip_id varchar(36) NOT NULL, 8 | amount decimal(10,2) NOT NULL DEFAULT '0.00', 9 | state varchar(50) NOT NULL 10 | ); 11 | -------------------------------------------------------------------------------- /happyride/service/trip-history-service/src/main/java/io/vividcode/happyride/triphistoryservice/TripHistoryApplication.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.triphistoryservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class TripHistoryApplication { 8 | 9 | public static void main(final String[] args) { 10 | SpringApplication.run(TripHistoryApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /happyride/service/trip-history-service/src/main/java/io/vividcode/happyride/triphistoryservice/dataaccess/TripRepository.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.triphistoryservice.dataaccess; 2 | 3 | import io.vividcode.happyride.triphistoryservice.domain.Trip; 4 | import java.util.List; 5 | import org.springframework.data.jpa.repository.Modifying; 6 | import org.springframework.data.jpa.repository.Query; 7 | import org.springframework.data.repository.CrudRepository; 8 | import org.springframework.data.repository.query.Param; 9 | import org.springframework.stereotype.Repository; 10 | 11 | @Repository 12 | public interface TripRepository extends CrudRepository { 13 | 14 | List findByPassengerId(String passengerId); 15 | 16 | List findByDriverId(String driverId); 17 | 18 | @Modifying 19 | @Query("update Trip t set t.passengerName = :passengerName where t.passengerId = :passengerId") 20 | int updatePassengerDetails(@Param("passengerId") String passengerId, 21 | @Param("passengerName") String passengerName); 22 | } 23 | -------------------------------------------------------------------------------- /happyride/service/trip-history-service/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8506 -------------------------------------------------------------------------------- /happyride/service/trip-history-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | jpa: 3 | open-in-view: false 4 | hibernate: 5 | ddl-auto: validate 6 | properties: 7 | hibernate: 8 | dialect: org.hibernate.dialect.PostgreSQL10Dialect 9 | default_schema: happyride 10 | datasource: 11 | driver-class-name: org.postgresql.Driver 12 | url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:8436}/${DB_NAME:happyride-trip-history} 13 | username: ${DB_USERNAME:postgres} 14 | password: ${DB_PASSWORD:postgres} 15 | flyway: 16 | schemas: 17 | - happyride 18 | eventuate: 19 | database: 20 | schema: eventuate 21 | eventuatelocal: 22 | kafka: 23 | bootstrap: 24 | servers: ${KAFKA_HOST:localhost}:${KAFKA_PORT:29092} 25 | zookeeper: 26 | connection: 27 | string: ${ZOOKEEPER_HOST:localhost}:${ZOOKEEPER_PORT:2181} -------------------------------------------------------------------------------- /happyride/service/trip-history-service/src/main/resources/db/migration/V1__init_schema.sql: -------------------------------------------------------------------------------- 1 | CREATE SCHEMA IF NOT EXISTS happyride; 2 | 3 | CREATE TABLE happyride.trips( 4 | id varchar(36) NOT NULL PRIMARY KEY, 5 | passenger_id varchar(36) NOT NULL, 6 | passenger_name varchar(255), 7 | driver_id varchar(36), 8 | driver_name varchar(255), 9 | start_pos_lat decimal(10,6) NOT NULL DEFAULT '0.000000', 10 | start_pos_lng decimal(10,6) NOT NULL DEFAULT '0.000000', 11 | end_pos_lat decimal(10,6) NOT NULL DEFAULT '0.000000', 12 | end_pos_lng decimal(10,6) NOT NULL DEFAULT '0.000000', 13 | state varchar(50) NOT NULL 14 | ); 15 | -------------------------------------------------------------------------------- /happyride/service/trip-service/README.md: -------------------------------------------------------------------------------- 1 | # 行程管理服务 2 | 3 | 在IDE中运行时,需要添加如下的系统参数: 4 | 5 | ``` 6 | -Dserver.port=8501 -Dspring.datasource.username=postgres -Dspring.datasource.password=postgres 7 | ``` -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/TripApplication.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice; 2 | 3 | import io.vividcode.happyride.common.DatabaseRuntimeHintsRegistrar; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.context.annotation.ImportRuntimeHints; 7 | 8 | @ImportRuntimeHints(DatabaseRuntimeHintsRegistrar.class) 9 | @SpringBootApplication 10 | public class TripApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(TripApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/commandhandlers/TripCommandHandlersConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.commandhandlers; 2 | 3 | import io.eventuate.tram.sagas.participant.SagaCommandDispatcher; 4 | import io.eventuate.tram.sagas.participant.SagaCommandDispatcherFactory; 5 | import io.eventuate.tram.sagas.spring.participant.SagaParticipantConfiguration; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.ComponentScan; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.context.annotation.Import; 10 | 11 | @Configuration 12 | @Import({SagaParticipantConfiguration.class}) 13 | @ComponentScan 14 | public class TripCommandHandlersConfiguration { 15 | 16 | @Bean 17 | public SagaCommandDispatcher tripCommandHandlersDispatcher( 18 | TripCommandHandlers tripCommandHandlers, 19 | SagaCommandDispatcherFactory sagaCommandDispatcherFactory) { 20 | return sagaCommandDispatcherFactory.make("tripService", tripCommandHandlers.commandHandlers()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/commandsample/EchoCommand.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.commandsample; 2 | 3 | import io.eventuate.tram.commands.common.Command; 4 | 5 | public class EchoCommand implements Command { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/commandsample/EchoCommandHandlers.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.commandsample; 2 | 3 | import static io.eventuate.tram.commands.consumer.CommandHandlerReplyBuilder.withSuccess; 4 | 5 | import io.eventuate.tram.commands.consumer.CommandHandlers; 6 | import io.eventuate.tram.commands.consumer.CommandHandlersBuilder; 7 | import io.eventuate.tram.commands.consumer.CommandMessage; 8 | import io.eventuate.tram.commands.consumer.PathVariables; 9 | import io.eventuate.tram.messaging.common.Message; 10 | import org.springframework.stereotype.Component; 11 | 12 | @Component 13 | public class EchoCommandHandlers { 14 | 15 | public CommandHandlers commandHandlers() { 16 | return CommandHandlersBuilder.fromChannel("echo") 17 | .resource("/user/{username}") 18 | .onMessage(EchoCommand.class, this::echo) 19 | .build(); 20 | } 21 | 22 | private Message echo(CommandMessage cm, 23 | PathVariables pathVariables) { 24 | return withSuccess("echo -> " + pathVariables.getString("username")); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/commandsample/EchoConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.commandsample; 2 | 3 | import io.eventuate.tram.commands.consumer.CommandDispatcher; 4 | import io.eventuate.tram.commands.consumer.CommandDispatcherFactory; 5 | import io.eventuate.tram.spring.commands.consumer.TramCommandConsumerConfiguration; 6 | import io.eventuate.tram.spring.commands.producer.TramCommandProducerConfiguration; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.context.annotation.Import; 10 | 11 | @Configuration 12 | @Import({TramCommandProducerConfiguration.class, 13 | TramCommandConsumerConfiguration.class}) 14 | public class EchoConfiguration { 15 | 16 | @Bean 17 | public CommandDispatcher echoCommandDispatcher( 18 | CommandDispatcherFactory commandDispatcherFactory, 19 | EchoCommandHandlers echoCommandHandlers) { 20 | return commandDispatcherFactory 21 | .make("echoCommandDispatcher", 22 | echoCommandHandlers.commandHandlers()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/commandsample/QueryWeatherCommand.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.commandsample; 2 | 3 | import io.eventuate.tram.commands.common.Command; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.NonNull; 7 | import lombok.RequiredArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @RequiredArgsConstructor 12 | public class QueryWeatherCommand implements Command { 13 | 14 | @NonNull 15 | private String city; 16 | } 17 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/commandsample/QueryWeatherResult.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.commandsample; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @RequiredArgsConstructor 11 | public class QueryWeatherResult { 12 | 13 | @NonNull 14 | private String city; 15 | 16 | @NonNull 17 | private String result; 18 | } 19 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/commandsample/WeatherCommandHandlers.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.commandsample; 2 | 3 | import static io.eventuate.tram.commands.consumer.CommandHandlerReplyBuilder.withSuccess; 4 | 5 | import io.eventuate.tram.commands.consumer.CommandHandlers; 6 | import io.eventuate.tram.commands.consumer.CommandHandlersBuilder; 7 | import io.eventuate.tram.commands.consumer.CommandMessage; 8 | import io.eventuate.tram.commands.consumer.PathVariables; 9 | import io.eventuate.tram.messaging.common.Message; 10 | import org.springframework.stereotype.Component; 11 | 12 | @Component 13 | public class WeatherCommandHandlers { 14 | 15 | public CommandHandlers commandHandlers() { 16 | return CommandHandlersBuilder.fromChannel("weather") 17 | .onMessage(QueryWeatherCommand.class, this::queryWeather) 18 | .build(); 19 | } 20 | 21 | private Message queryWeather(CommandMessage cm, 22 | PathVariables pathVariables) { 23 | return withSuccess( 24 | new QueryWeatherResult(cm.getCommand().getCity(), "Rain")); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/commandsample/WeatherConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.commandsample; 2 | 3 | import io.eventuate.tram.commands.consumer.CommandDispatcher; 4 | import io.eventuate.tram.commands.consumer.CommandDispatcherFactory; 5 | import io.eventuate.tram.spring.commands.consumer.TramCommandConsumerConfiguration; 6 | import io.eventuate.tram.spring.commands.producer.TramCommandProducerConfiguration; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.context.annotation.Import; 10 | 11 | @Configuration 12 | @Import({TramCommandProducerConfiguration.class, 13 | TramCommandConsumerConfiguration.class}) 14 | public class WeatherConfiguration { 15 | 16 | @Bean 17 | public CommandDispatcher weatherCommandDispatcher( 18 | CommandDispatcherFactory commandDispatcherFactory, 19 | WeatherCommandHandlers weatherCommandHandlers) { 20 | return commandDispatcherFactory 21 | .make("weatherCommandDispatcher", 22 | weatherCommandHandlers.commandHandlers()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/dataaccess/TripRepository.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.dataaccess; 2 | 3 | import io.vividcode.happyride.tripservice.domain.Trip; 4 | import org.springframework.data.repository.CrudRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface TripRepository extends CrudRepository { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/domain/IllegalTripStateException.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.domain; 2 | 3 | import io.vividcode.happyride.tripservice.api.TripState; 4 | 5 | public class IllegalTripStateException extends RuntimeException { 6 | 7 | private final TripState requiredState; 8 | 9 | public IllegalTripStateException( 10 | TripState requiredState) { 11 | this.requiredState = requiredState; 12 | } 13 | 14 | @Override 15 | public String getMessage() { 16 | return String.format("Trip must be in %s state", requiredState); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/domain/TripDomainEventPublisher.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.domain; 2 | 3 | import io.eventuate.tram.events.aggregates.AbstractAggregateDomainEventPublisher; 4 | import io.eventuate.tram.events.publisher.DomainEventPublisher; 5 | import io.vividcode.happyride.tripservice.api.events.TripDomainEvent; 6 | 7 | public class TripDomainEventPublisher extends 8 | AbstractAggregateDomainEventPublisher { 9 | 10 | public TripDomainEventPublisher( 11 | DomainEventPublisher eventPublisher) { 12 | super(eventPublisher, Trip.class, Trip::getId); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/domain/TripFareService.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.domain; 2 | 3 | import io.vividcode.happyride.common.PositionVO; 4 | import io.vividcode.happyride.common.Utils; 5 | import java.math.BigDecimal; 6 | import org.springframework.stereotype.Service; 7 | 8 | @Service 9 | public class TripFareService { 10 | 11 | public BigDecimal calculate(final PositionVO startPos, 12 | final PositionVO endPos) { 13 | return BigDecimal.valueOf(3).multiply( 14 | BigDecimal.valueOf(Utils.calculateDistance(startPos, endPos))); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/messagehandlers/TripServiceMessageHandlersConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.messagehandlers; 2 | 3 | import io.eventuate.tram.events.subscriber.DomainEventDispatcher; 4 | import io.eventuate.tram.events.subscriber.DomainEventDispatcherFactory; 5 | import io.eventuate.tram.spring.events.subscriber.TramEventSubscriberConfiguration; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.context.annotation.Import; 9 | 10 | @Configuration 11 | @Import(TramEventSubscriberConfiguration.class) 12 | public class TripServiceMessageHandlersConfiguration { 13 | 14 | @Bean 15 | public TripServiceEventConsumer tripServiceEventConsumer() { 16 | return new TripServiceEventConsumer(); 17 | } 18 | 19 | @Bean 20 | public DomainEventDispatcher domainEventDispatcher( 21 | TripServiceEventConsumer tripServiceEventConsumer, 22 | DomainEventDispatcherFactory domainEventDispatcherFactory) { 23 | return domainEventDispatcherFactory 24 | .make("tripServiceEvents", tripServiceEventConsumer.domainEventHandlers()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/sagaparticipants/ConfirmTripCommand.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.sagaparticipants; 2 | 3 | public class ConfirmTripCommand extends TripCommand { 4 | 5 | public ConfirmTripCommand() { 6 | } 7 | 8 | public ConfirmTripCommand(String tripId) { 9 | super(tripId); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/sagaparticipants/RejectTripCommand.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.sagaparticipants; 2 | 3 | public class RejectTripCommand extends TripCommand { 4 | 5 | public RejectTripCommand() { 6 | 7 | } 8 | 9 | public RejectTripCommand(String tripId) { 10 | super(tripId); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/sagaparticipants/TripCommand.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.sagaparticipants; 2 | 3 | import io.eventuate.tram.commands.common.Command; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | import lombok.NonNull; 8 | import lombok.RequiredArgsConstructor; 9 | 10 | @NoArgsConstructor 11 | @RequiredArgsConstructor 12 | @EqualsAndHashCode 13 | @Getter 14 | public abstract class TripCommand implements Command { 15 | 16 | @NonNull 17 | private String tripId; 18 | } 19 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/sagaparticipants/TripServiceProxy.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.sagaparticipants; 2 | 3 | import io.eventuate.tram.commands.common.Success; 4 | import io.eventuate.tram.sagas.simpledsl.CommandEndpoint; 5 | import io.eventuate.tram.sagas.simpledsl.CommandEndpointBuilder; 6 | import io.vividcode.happyride.tripservice.api.TripServiceChannels; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Component 10 | public class TripServiceProxy { 11 | 12 | public final CommandEndpoint reject = CommandEndpointBuilder 13 | .forCommand(RejectTripCommand.class) 14 | .withChannel(TripServiceChannels.trip) 15 | .withReply(Success.class) 16 | .build(); 17 | 18 | public final CommandEndpoint confirm = CommandEndpointBuilder 19 | .forCommand(ConfirmTripCommand.class) 20 | .withChannel(TripServiceChannels.trip) 21 | .withReply(Success.class) 22 | .build(); 23 | } 24 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/java/io/vividcode/happyride/tripservice/sagaparticipants/TripValidationServiceProxy.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripservice.sagaparticipants; 2 | 3 | import io.eventuate.tram.commands.common.Success; 4 | import io.eventuate.tram.sagas.simpledsl.CommandEndpoint; 5 | import io.eventuate.tram.sagas.simpledsl.CommandEndpointBuilder; 6 | import io.vividcode.happyride.tripvalidationservice.api.InvalidTripReply; 7 | import io.vividcode.happyride.tripvalidationservice.api.TripValidationServiceChannels; 8 | import io.vividcode.happyride.tripvalidationservice.api.ValidateTripCommand; 9 | import org.springframework.stereotype.Component; 10 | 11 | @Component 12 | public class TripValidationServiceProxy { 13 | 14 | public final CommandEndpoint validateTrip = CommandEndpointBuilder 15 | .forCommand(ValidateTripCommand.class) 16 | .withChannel(TripValidationServiceChannels.tripValidation) 17 | .withReply(Success.class) 18 | .withReply(InvalidTripReply.class) 19 | .build(); 20 | } 21 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8501 -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | jpa: 3 | open-in-view: false 4 | hibernate: 5 | ddl-auto: validate 6 | properties: 7 | hibernate: 8 | dialect: org.hibernate.dialect.PostgreSQLDialect 9 | default_schema: happyride 10 | datasource: 11 | driver-class-name: org.postgresql.Driver 12 | url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:8432}/${DB_NAME:happyride-trip} 13 | username: ${DB_USERNAME:postgres} 14 | password: ${DB_PASSWORD:postgres} 15 | flyway: 16 | schemas: 17 | - happyride 18 | eventuate: 19 | database: 20 | schema: eventuate 21 | eventuatelocal: 22 | kafka: 23 | bootstrap: 24 | servers: ${KAFKA_HOST:localhost}:${KAFKA_PORT:29092} 25 | zookeeper: 26 | connection: 27 | string: ${ZOOKEEPER_HOST:localhost}:${ZOOKEEPER_PORT:2181} -------------------------------------------------------------------------------- /happyride/service/trip-service/src/main/resources/db/migration/V1__init_schema.sql: -------------------------------------------------------------------------------- 1 | CREATE SCHEMA IF NOT EXISTS happyride; 2 | 3 | CREATE TABLE happyride.trips( 4 | id varchar(36) NOT NULL PRIMARY KEY, 5 | created_at bigint NOT NULL, 6 | updated_at bigint NOT NULL, 7 | passenger_id varchar(36) NOT NULL, 8 | driver_id varchar(36), 9 | start_pos_lat decimal(10,6) NOT NULL DEFAULT '0.000000', 10 | start_pos_lng decimal(10,6) NOT NULL DEFAULT '0.000000', 11 | start_pos_address_id varchar(36), 12 | end_pos_lat decimal(10,6) NOT NULL DEFAULT '0.000000', 13 | end_pos_lng decimal(10,6) NOT NULL DEFAULT '0.000000', 14 | end_pos_address_id varchar(36), 15 | fare decimal(10, 2) NOT NULL DEFAULT '0.00', 16 | state varchar(50) NOT NULL 17 | ); 18 | -------------------------------------------------------------------------------- /happyride/service/trip-service/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | jpa: 3 | hibernate: 4 | ddl-auto: validate 5 | properties: 6 | hibernate: 7 | dialect: org.hibernate.dialect.PostgreSQLDialect 8 | default_schema: happyride 9 | flyway: 10 | schemas: 11 | - happyride -------------------------------------------------------------------------------- /happyride/service/trip-validation-service/src/main/java/io/vividcode/happyride/tripvalidationservice/AppConfig.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripvalidationservice; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import lombok.Data; 6 | import org.springframework.boot.context.properties.ConfigurationProperties; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Data 10 | @Component 11 | @ConfigurationProperties("app") 12 | public class AppConfig { 13 | 14 | private List blockedPassengers = new ArrayList<>(); 15 | 16 | private double tripDistanceLimit = 100; 17 | 18 | public boolean isPassengerBlocked(final String passengerId) { 19 | return this.blockedPassengers.contains(passengerId); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /happyride/service/trip-validation-service/src/main/java/io/vividcode/happyride/tripvalidationservice/TripValidationServiceApplication.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripvalidationservice; 2 | 3 | import io.eventuate.tram.spring.jdbckafka.TramJdbcKafkaConfiguration; 4 | import io.vividcode.happyride.tripvalidationservice.domain.TripValidationServiceConfiguration; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.annotation.Import; 8 | 9 | @SpringBootApplication 10 | @Import({TripValidationServiceConfiguration.class, TramJdbcKafkaConfiguration.class}) 11 | public class TripValidationServiceApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(TripValidationServiceApplication.class, args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /happyride/service/trip-validation-service/src/main/java/io/vividcode/happyride/tripvalidationservice/service/PassengerBlockedException.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripvalidationservice.service; 2 | 3 | public class PassengerBlockedException extends TripValidationException { 4 | 5 | private final String passengerId; 6 | 7 | public PassengerBlockedException(final String passengerId) { 8 | this.passengerId = passengerId; 9 | } 10 | 11 | @Override 12 | public String getMessage() { 13 | return String.format("Passenger [%s] is blocked", this.passengerId); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /happyride/service/trip-validation-service/src/main/java/io/vividcode/happyride/tripvalidationservice/service/TripDistanceTooLongException.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripvalidationservice.service; 2 | 3 | public class TripDistanceTooLongException extends TripValidationException { 4 | 5 | private final double value; 6 | private final double limit; 7 | 8 | public TripDistanceTooLongException(final double value, final double limit) { 9 | this.value = value; 10 | this.limit = limit; 11 | } 12 | 13 | @Override 14 | public String getMessage() { 15 | return String 16 | .format("Distance is too long, current value is [%s], limit is [%s]", 17 | this.value, this.limit); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /happyride/service/trip-validation-service/src/main/java/io/vividcode/happyride/tripvalidationservice/service/TripValidationException.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.tripvalidationservice.service; 2 | 3 | public class TripValidationException extends RuntimeException { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /happyride/service/trip-validation-service/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8505 3 | app: 4 | blockedPassengers: 5 | - bad_passenger1 6 | - bad_passenger2 -------------------------------------------------------------------------------- /happyride/service/trip-validation-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | driver-class-name: org.postgresql.Driver 4 | url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:8434}/${DB_NAME:happyride-trip-validation} 5 | username: ${DB_USERNAME:postgres} 6 | password: ${DB_PASSWORD:postgres} 7 | eventuatelocal: 8 | kafka: 9 | bootstrap: 10 | servers: ${KAFKA_HOST:localhost}:${KAFKA_PORT:29092} 11 | zookeeper: 12 | connection: 13 | string: ${ZOOKEEPER_HOST:localhost}:${ZOOKEEPER_PORT:2181} -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | speed-measure-plugin*.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # IDE - VSCode 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # misc 35 | /.angular/cache 36 | /.sass-cache 37 | /connect.lock 38 | /coverage 39 | /libpeerconnection.log 40 | npm-debug.log 41 | yarn-error.log 42 | testem.log 43 | /typings 44 | 45 | # System Files 46 | .DS_Store 47 | Thumbs.db 48 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": true 6 | } 7 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/README.md: -------------------------------------------------------------------------------- 1 | # Driver Simulator 2 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/browserslist: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # You can see what browsers were selected by your queries by running: 6 | # npx browserslist 7 | 8 | > 0.5% 9 | last 2 versions 10 | Firefox ESR 11 | not dead 12 | not IE 9-11 # For IE 9-11 support, remove 'not'. -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/e2e/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // Protractor configuration file, see link for more information 3 | // https://github.com/angular/protractor/blob/master/lib/config.ts 4 | 5 | const { SpecReporter } = require('jasmine-spec-reporter'); 6 | 7 | /** 8 | * @type { import("protractor").Config } 9 | */ 10 | exports.config = { 11 | allScriptsTimeout: 11000, 12 | specs: [ 13 | './src/**/*.e2e-spec.ts' 14 | ], 15 | capabilities: { 16 | browserName: 'chrome' 17 | }, 18 | directConnect: true, 19 | baseUrl: 'http://localhost:4200/', 20 | framework: 'jasmine', 21 | jasmineNodeOpts: { 22 | showColors: true, 23 | defaultTimeoutInterval: 30000, 24 | print: function() {} 25 | }, 26 | onPrepare() { 27 | require('ts-node').register({ 28 | project: require('path').join(__dirname, './tsconfig.json') 29 | }); 30 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 31 | } 32 | }; -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/e2e/src/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | import { browser, logging } from 'protractor'; 3 | 4 | describe('workspace-project App', () => { 5 | let page: AppPage; 6 | 7 | beforeEach(() => { 8 | page = new AppPage(); 9 | }); 10 | 11 | it('should display welcome message', () => { 12 | page.navigateTo(); 13 | expect(page.getTitleText()).toEqual('app app is running!'); 14 | }); 15 | 16 | afterEach(async () => { 17 | // Assert that there are no errors emitted from the browser 18 | const logs = await browser.manage().logs().get(logging.Type.BROWSER); 19 | expect(logs).not.toContain(jasmine.objectContaining({ 20 | level: logging.Level.SEVERE, 21 | } as logging.Entry)); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo(): Promise { 5 | return browser.get(browser.baseUrl) as Promise; 6 | } 7 | 8 | getTitleText(): Promise { 9 | return element(by.css('app-root .content span')).getText() as Promise; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types": [ 8 | "jasmine", 9 | "jasminewd2", 10 | "node" 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, './coverage/app'), 20 | reports: ['html', 'lcovonly', 'text-summary'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false, 30 | restartOnFileChange: true 31 | }); 32 | }; 33 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | const routes: Routes = []; 5 | 6 | @NgModule({ 7 | imports: [RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' })], 8 | exports: [RouterModule], 9 | }) 10 | export class AppRoutingModule {} 11 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | Driver Simulator 4 | 5 | 9 | 10 | 14 |
15 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | .spacer { 2 | flex: 1 1 auto; 3 | } 4 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, waitForAsync } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(waitForAsync(() => { 7 | TestBed.configureTestingModule({ 8 | imports: [RouterTestingModule], 9 | declarations: [AppComponent], 10 | }).compileComponents(); 11 | })); 12 | 13 | it('should create the app', () => { 14 | const fixture = TestBed.createComponent(AppComponent); 15 | const app = fixture.componentInstance; 16 | expect(app).toBeTruthy(); 17 | }); 18 | 19 | it(`should have as title 'app'`, () => { 20 | const fixture = TestBed.createComponent(AppComponent); 21 | const app = fixture.componentInstance; 22 | expect(app.title).toEqual('app'); 23 | }); 24 | 25 | it('should render title', () => { 26 | const fixture = TestBed.createComponent(AppComponent); 27 | fixture.detectChanges(); 28 | const compiled = fixture.nativeElement; 29 | expect(compiled.querySelector('.content span').textContent).toContain( 30 | 'app app is running!' 31 | ); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/app/components/drivers-list/drivers-list.component.scss: -------------------------------------------------------------------------------- 1 | table { 2 | width: 100%; 3 | } 4 | 5 | .button-row { 6 | display: table-cell; 7 | 8 | button { 9 | display: table-cell; 10 | margin-right: 8px; 11 | } 12 | } 13 | 14 | .mat-column-id { 15 | width: 20%; 16 | } 17 | 18 | .mat-column-state { 19 | width: 20%; 20 | } 21 | 22 | .mat-column-position { 23 | width: 30%; 24 | } 25 | 26 | .mat-column-actions { 27 | width: 30%; 28 | } 29 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/app/components/drivers-list/drivers-list.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; 2 | import { Driver, SimulatorAction } from '../../model'; 3 | 4 | @Component({ 5 | selector: 'app-drivers-list', 6 | templateUrl: './drivers-list.component.html', 7 | styleUrls: ['./drivers-list.component.scss'], 8 | }) 9 | export class DriversListComponent implements OnInit { 10 | @Input() drivers: Driver[]; 11 | @Output() actions = new EventEmitter(); 12 | 13 | displayedColumns: string[] = ['id', 'state', 'position', 'actions']; 14 | 15 | constructor() {} 16 | 17 | ngOnInit(): void {} 18 | 19 | sendAction(driver: Driver, action: string) { 20 | this.actions.emit({ 21 | simulatorId: driver.id, 22 | driverId: driver.driverId, 23 | action, 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/app/model.ts: -------------------------------------------------------------------------------- 1 | export interface Driver { 2 | id: string; 3 | driverId: string; 4 | state: string; 5 | posLat: number; 6 | posLng: number; 7 | isAvailable: boolean; 8 | isNotAvailable: boolean; 9 | isOffline: boolean; 10 | } 11 | 12 | export interface SimulatorAction { 13 | simulatorId: string; 14 | driverId: string; 15 | action: string; 16 | } 17 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexcheng1982/happyride/17a507fca213d87dab849b6cef6f1f469433b42e/happyride/tools/driver-simulator-ui/app/src/assets/.gitkeep -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexcheng1982/happyride/17a507fca213d87dab849b6cef6f1f469433b42e/happyride/tools/driver-simulator-ui/app/src/favicon.ico -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Driver Simulator 6 | 7 | 8 | 9 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch((err) => console.error(err)); 14 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/proxy.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "/api": { 3 | "target": "http://localhost:8509", 4 | "secure": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting, 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: { 11 | context( 12 | path: string, 13 | deep?: boolean, 14 | filter?: RegExp 15 | ): { 16 | keys(): string[]; 17 | (id: string): T; 18 | }; 19 | }; 20 | 21 | // First, initialize the Angular testing environment. 22 | getTestBed().initTestEnvironment( 23 | BrowserDynamicTestingModule, 24 | platformBrowserDynamicTesting(), { 25 | teardown: { destroyAfterEach: false } 26 | } 27 | ); 28 | // Then we find all the tests. 29 | const context = require.context('./', true, /\.spec\.ts$/); 30 | // And load the modules. 31 | context.keys().map(context); 32 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/app", 5 | "types": [] 6 | }, 7 | "files": [ 8 | "src/main.ts", 9 | "src/polyfills.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "downlevelIteration": true, 9 | "experimentalDecorators": true, 10 | "module": "esnext", 11 | "moduleResolution": "node", 12 | "importHelpers": true, 13 | "target": "es2015", 14 | "lib": [ 15 | "es2018", 16 | "dom" 17 | ] 18 | }, 19 | "angularCompilerOptions": { 20 | "fullTemplateTypeCheck": true, 21 | "strictInjectionParameters": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator-ui/app/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator/src/main/java/io/vividcode/happyride/driversimulator/ApplicationConfig.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driversimulator; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.reactive.config.EnableWebFlux; 5 | import org.springframework.web.reactive.config.ResourceHandlerRegistry; 6 | import org.springframework.web.reactive.config.ViewResolverRegistry; 7 | import org.springframework.web.reactive.config.WebFluxConfigurer; 8 | import org.springframework.web.reactive.result.view.UrlBasedViewResolver; 9 | 10 | @Configuration 11 | @EnableWebFlux 12 | public class ApplicationConfig implements WebFluxConfigurer { 13 | 14 | @Override 15 | public void addResourceHandlers(final ResourceHandlerRegistry registry) { 16 | registry.addResourceHandler("*.html", "/*.js", "/*.css") 17 | .addResourceLocations("classpath:/public/"); 18 | } 19 | 20 | @Override 21 | public void configureViewResolvers(final ViewResolverRegistry registry) { 22 | registry.viewResolver(new UrlBasedViewResolver()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator/src/main/java/io/vividcode/happyride/driversimulator/DriverSimulatorFactory.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driversimulator; 2 | 3 | import io.vividcode.happyride.dispatchservice.api.events.DriverLocation; 4 | import java.math.BigDecimal; 5 | import org.axonframework.eventhandling.gateway.EventGateway; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Component 10 | public class DriverSimulatorFactory { 11 | 12 | @Autowired 13 | EventGateway eventGateway; 14 | 15 | public DriverSimulator create(String driverId, String vehicleId, BigDecimal posLng, 16 | BigDecimal posLat) { 17 | return new DriverSimulator(driverId, vehicleId, eventGateway, 18 | new DriverLocation(driverId, vehicleId, posLng, posLat)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator/src/main/java/io/vividcode/happyride/driversimulator/DriverSimulatorMain.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driversimulator; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableScheduling; 6 | 7 | @SpringBootApplication 8 | @EnableScheduling 9 | public class DriverSimulatorMain { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(DriverSimulatorMain.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator/src/main/java/io/vividcode/happyride/driversimulator/DriverSimulatorNotFoundException.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driversimulator; 2 | 3 | public class DriverSimulatorNotFoundException extends RuntimeException { 4 | 5 | private final String driverSimulatorId; 6 | 7 | public DriverSimulatorNotFoundException(String driverSimulatorId) { 8 | this.driverSimulatorId = driverSimulatorId; 9 | } 10 | 11 | @Override 12 | public String getMessage() { 13 | return String.format("Driver simulator %s not found", driverSimulatorId); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator/src/main/java/io/vividcode/happyride/driversimulator/DriverSimulatorSnapshot.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driversimulator; 2 | 3 | import io.vividcode.happyride.common.DriverState; 4 | import java.math.BigDecimal; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | public class DriverSimulatorSnapshot { 11 | 12 | private String id; 13 | private String driverId; 14 | private String vehicleId; 15 | private DriverState state; 16 | private BigDecimal posLng; 17 | private BigDecimal posLat; 18 | } 19 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator/src/main/java/io/vividcode/happyride/driversimulator/web/AddDriverRequest.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driversimulator.web; 2 | 3 | import java.math.BigDecimal; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.NonNull; 7 | import lombok.RequiredArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @RequiredArgsConstructor 12 | public class AddDriverRequest { 13 | 14 | @NonNull 15 | private String driverId; 16 | 17 | @NonNull 18 | private BigDecimal posLng = BigDecimal.ZERO; 19 | 20 | @NonNull 21 | private BigDecimal posLat = BigDecimal.ZERO; 22 | 23 | private boolean startSimulation = true; 24 | } 25 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator/src/main/java/io/vividcode/happyride/driversimulator/web/IndexController.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driversimulator.web; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | 6 | @Controller 7 | public class IndexController { 8 | 9 | @RequestMapping("/") 10 | public String index() { 11 | return "redirect:/index.html"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator/src/main/java/io/vividcode/happyride/driversimulator/web/ResetPositionRequest.java: -------------------------------------------------------------------------------- 1 | package io.vividcode.happyride.driversimulator.web; 2 | 3 | import java.math.BigDecimal; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.NonNull; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | public class ResetPositionRequest { 11 | 12 | @NonNull 13 | private BigDecimal posLng = BigDecimal.ZERO; 14 | 15 | @NonNull 16 | private BigDecimal posLat = BigDecimal.ZERO; 17 | } 18 | -------------------------------------------------------------------------------- /happyride/tools/driver-simulator/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8509 -------------------------------------------------------------------------------- /happyride/tools/driver-simulator/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | axon: 2 | axonserver: 3 | servers: ${AXON_HOST:localhost}:${AXON_PORT:8124} 4 | serializer: 5 | events: jackson 6 | --------------------------------------------------------------------------------