├── .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 |
--------------------------------------------------------------------------------