diff --git a/deploy/k8s/local/dashboard-adminuser.yaml b/deploy/k8s/local/dashboard-adminuser.yaml new file mode 100644 index 0000000..0485553 --- /dev/null +++ b/deploy/k8s/local/dashboard-adminuser.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: admin-user + namespace: kubernetes-dashboard +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: admin-user +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: admin-user + namespace: kubernetes-dashboard \ No newline at end of file diff --git a/deploy/k8s/local/external-system/payment-deployment.yaml b/deploy/k8s/local/external-system/payment-deployment.yaml new file mode 100644 index 0000000..4843dfc --- /dev/null +++ b/deploy/k8s/local/external-system/payment-deployment.yaml @@ -0,0 +1,23 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: payment +spec: + selector: + matchLabels: + app: payment + replicas: 1 + template: + metadata: + labels: + app: payment + spec: + containers: + - name: payment + image: vany0114/externalsystem.paymentservice + imagePullPolicy: Always + env: + - name: ASPNETCORE_ENVIRONMENT + value: "Development" + ports: + - containerPort: 80 \ No newline at end of file diff --git a/deploy/k8s/local/external-system/payment-service.yaml b/deploy/k8s/local/external-system/payment-service.yaml new file mode 100644 index 0000000..2e5d1e7 --- /dev/null +++ b/deploy/k8s/local/external-system/payment-service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: payment +spec: + selector: + app: payment + ports: + - name: http + protocol: TCP + port: 80 + targetPort: 80 \ No newline at end of file diff --git a/deploy/k8s/local/invoice/invoice-deployment.yaml b/deploy/k8s/local/invoice/invoice-deployment.yaml new file mode 100644 index 0000000..82117bf --- /dev/null +++ b/deploy/k8s/local/invoice/invoice-deployment.yaml @@ -0,0 +1,38 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: invoice +spec: + selector: + matchLabels: + app: invoice + replicas: 3 + template: + metadata: + labels: + app: invoice + spec: + containers: + - name: invoice + image: vany0114/duber.invoice.api + imagePullPolicy: Always + resources: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "256Mi" + cpu: "500m" + env: + - name: ASPNETCORE_ENVIRONMENT + value: "Development" + - name: ConnectionStrings__InvoiceDB + value: "Server=sql-data;Database=Duber.InvoiceDb;User Id=sa;Password=Pass@word" + - name: EventBusConnection + value: "rabbitmq" + - name: PaymentServiceBaseUrl + value: "http://payment" + - name: AzureServiceBusEnabled + value: "False" + ports: + - containerPort: 80 \ No newline at end of file diff --git a/deploy/k8s/local/invoice/invoice-ingress.yaml b/deploy/k8s/local/invoice/invoice-ingress.yaml new file mode 100644 index 0000000..28ec57a --- /dev/null +++ b/deploy/k8s/local/invoice/invoice-ingress.yaml @@ -0,0 +1,13 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: invoice +spec: + rules: + - host: invoice.local.com + http: + paths: + - path: / + backend: + serviceName: invoice + servicePort: 80 \ No newline at end of file diff --git a/deploy/k8s/local/invoice/invoice-service.yaml b/deploy/k8s/local/invoice/invoice-service.yaml new file mode 100644 index 0000000..4c41e3b --- /dev/null +++ b/deploy/k8s/local/invoice/invoice-service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: invoice +spec: + selector: + app: invoice + ports: + - name: http + protocol: TCP + port: 80 + targetPort: 80 \ No newline at end of file diff --git a/deploy/k8s/local/mongo/mongo-admin.yaml b/deploy/k8s/local/mongo/mongo-admin.yaml new file mode 100644 index 0000000..cbba348 --- /dev/null +++ b/deploy/k8s/local/mongo/mongo-admin.yaml @@ -0,0 +1,14 @@ +# to expose the port in order to connect with an IDE such as Studio 3T, etc + +kind: Service +apiVersion: v1 +metadata: + name: mongo-service +spec: + type: NodePort + selector: + app: nosql-data + ports: + - port: 27017 + nodePort: 31434 + name: mongo-port \ No newline at end of file diff --git a/deploy/k8s/local/mongo/mongo-deployment.yaml b/deploy/k8s/local/mongo/mongo-deployment.yaml new file mode 100644 index 0000000..e61df82 --- /dev/null +++ b/deploy/k8s/local/mongo/mongo-deployment.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nosql-data +spec: + selector: + matchLabels: + app: nosql-data + replicas: 1 + template: + metadata: + labels: + app: nosql-data + spec: + containers: + - name: nosql-data + image: mongo + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 27017 + protocol: TCP \ No newline at end of file diff --git a/deploy/k8s/local/mongo/mongo-service.yaml b/deploy/k8s/local/mongo/mongo-service.yaml new file mode 100644 index 0000000..b85acd6 --- /dev/null +++ b/deploy/k8s/local/mongo/mongo-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: nosql-data +spec: + selector: + app: nosql-data + ports: + - port: 27017 + targetPort: http + protocol: TCP + name: http + type: ClusterIP \ No newline at end of file diff --git a/deploy/k8s/local/nginx-ingress/custom-service.yaml b/deploy/k8s/local/nginx-ingress/custom-service.yaml new file mode 100644 index 0000000..ebf1b78 --- /dev/null +++ b/deploy/k8s/local/nginx-ingress/custom-service.yaml @@ -0,0 +1,23 @@ +kind: Service +apiVersion: v1 +metadata: + name: ingress-nginx + namespace: ingress-nginx + labels: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx +spec: + externalTrafficPolicy: Local + type: LoadBalancer + selector: + app.kubernetes.io/name: ingress-nginx + app.kubernetes.io/part-of: ingress-nginx + ports: + - name: http + port: 81 + protocol: TCP + targetPort: http + - name: https + port: 444 + protocol: TCP + targetPort: https \ No newline at end of file diff --git a/deploy/k8s/local/rabbit/rabbit-admin.yaml b/deploy/k8s/local/rabbit/rabbit-admin.yaml new file mode 100644 index 0000000..dfe9f27 --- /dev/null +++ b/deploy/k8s/local/rabbit/rabbit-admin.yaml @@ -0,0 +1,14 @@ +# to expose the port in order to connect to the admin dashboard. + +kind: Service +apiVersion: v1 +metadata: + name: rabbitmq-admin +spec: + type: NodePort + selector: + app: rabbitmq + ports: + - port: 15672 + nodePort: 31672 + name: rabbitmq-port \ No newline at end of file diff --git a/deploy/k8s/local/rabbit/rabbit-deployment.yaml b/deploy/k8s/local/rabbit/rabbit-deployment.yaml new file mode 100644 index 0000000..31a3b0d --- /dev/null +++ b/deploy/k8s/local/rabbit/rabbit-deployment.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: rabbitmq +spec: + selector: + matchLabels: + app: rabbitmq + replicas: 1 + template: + metadata: + labels: + app: rabbitmq + spec: + containers: + - name: rabbitmq + image: rabbitmq:3-management + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 5672 + protocol: TCP \ No newline at end of file diff --git a/deploy/k8s/local/rabbit/rabbit-service.yaml b/deploy/k8s/local/rabbit/rabbit-service.yaml new file mode 100644 index 0000000..34fea70 --- /dev/null +++ b/deploy/k8s/local/rabbit/rabbit-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: rabbitmq +spec: + selector: + app: rabbitmq + ports: + - port: 5672 + targetPort: http + protocol: TCP + name: http + type: ClusterIP \ No newline at end of file diff --git a/deploy/k8s/local/sql-server/sql-admin.yaml b/deploy/k8s/local/sql-server/sql-admin.yaml new file mode 100644 index 0000000..a7d920b --- /dev/null +++ b/deploy/k8s/local/sql-server/sql-admin.yaml @@ -0,0 +1,14 @@ +# to expose the port in order to connect with an IDE such as SQL MS, etc + +kind: Service +apiVersion: v1 +metadata: + name: sql-service +spec: + type: NodePort + selector: + app: sql-data + ports: + - port: 1433 + nodePort: 31433 + name: sql-port \ No newline at end of file diff --git a/deploy/k8s/local/sql-server/sql-deployment.yaml b/deploy/k8s/local/sql-server/sql-deployment.yaml new file mode 100644 index 0000000..7ab9139 --- /dev/null +++ b/deploy/k8s/local/sql-server/sql-deployment.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: sql-data +spec: + selector: + matchLabels: + app: sql-data + replicas: 1 + template: + metadata: + labels: + app: sql-data + spec: + containers: + - name: sql-data + image: microsoft/mssql-server-linux:2017-latest + imagePullPolicy: IfNotPresent + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Developer + - name: MSSQL_SA_PASSWORD + value: Pass@word + ports: + - name: http + containerPort: 1433 + protocol: TCP \ No newline at end of file diff --git a/deploy/k8s/local/sql-server/sql-service.yaml b/deploy/k8s/local/sql-server/sql-service.yaml new file mode 100644 index 0000000..d54ed55 --- /dev/null +++ b/deploy/k8s/local/sql-server/sql-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: sql-data +spec: + selector: + app: sql-data + ports: + - port: 1433 + targetPort: http + protocol: TCP + name: http + type: ClusterIP \ No newline at end of file diff --git a/deploy/k8s/local/trip/trip-deployment.yaml b/deploy/k8s/local/trip/trip-deployment.yaml new file mode 100644 index 0000000..a72a1a2 --- /dev/null +++ b/deploy/k8s/local/trip/trip-deployment.yaml @@ -0,0 +1,36 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: trip +spec: + selector: + matchLabels: + app: trip + replicas: 1 + template: + metadata: + labels: + app: trip + spec: + containers: + - name: trip + image: vany0114/duber.trip.api + imagePullPolicy: Always + resources: + requests: + memory: "128Mi" + cpu: "200m" + limits: + memory: "256Mi" + cpu: "600m" + env: + - name: ASPNETCORE_ENVIRONMENT + value: "Development" + - name: EventStoreConfiguration__ConnectionString + value: "mongodb://nosql-data" + - name: EventBusConnection + value: "rabbitmq" + - name: AzureServiceBusEnabled + value: "False" + ports: + - containerPort: 80 \ No newline at end of file diff --git a/deploy/k8s/local/trip/trip-hpa.yaml b/deploy/k8s/local/trip/trip-hpa.yaml new file mode 100644 index 0000000..7349202 --- /dev/null +++ b/deploy/k8s/local/trip/trip-hpa.yaml @@ -0,0 +1,12 @@ +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: trip +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: trip + minReplicas: 5 + maxReplicas: 10 + targetCPUUtilizationPercentage: 50 \ No newline at end of file diff --git a/deploy/k8s/local/trip/trip-ingress.yaml b/deploy/k8s/local/trip/trip-ingress.yaml new file mode 100644 index 0000000..bfc0b6e --- /dev/null +++ b/deploy/k8s/local/trip/trip-ingress.yaml @@ -0,0 +1,13 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: trip-ingress +spec: + rules: + - host: trip.local.com + http: + paths: + - path: / + backend: + serviceName: trip + servicePort: 80 \ No newline at end of file diff --git a/deploy/k8s/local/trip/trip-service.yaml b/deploy/k8s/local/trip/trip-service.yaml new file mode 100644 index 0000000..44960b8 --- /dev/null +++ b/deploy/k8s/local/trip/trip-service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: trip +spec: + selector: + app: trip + ports: + - name: http + protocol: TCP + port: 80 + targetPort: 80 \ No newline at end of file diff --git a/deploy/k8s/local/website/website-deployment.yaml b/deploy/k8s/local/website/website-deployment.yaml new file mode 100644 index 0000000..d1f7b25 --- /dev/null +++ b/deploy/k8s/local/website/website-deployment.yaml @@ -0,0 +1,38 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: frontend +spec: + selector: + matchLabels: + app: frontend + replicas: 1 + template: + metadata: + labels: + app: frontend + spec: + containers: + - name: frontend + image: vany0114/duber.website + imagePullPolicy: Always + resources: + requests: + memory: "128Mi" + cpu: "200m" + limits: + memory: "256Mi" + cpu: "600m" + env: + - name: ASPNETCORE_ENVIRONMENT + value: "Development" + - name: ConnectionStrings__WebsiteDB + value: "Server=sql-data;Database=Duber.WebSiteDb;User Id=sa;Password=Pass@word" + - name: EventBusConnection + value: "rabbitmq" + - name: TripApiSettings__BaseUrl + value: "http://trip" + - name: AzureServiceBusEnabled + value: "False" + ports: + - containerPort: 80 \ No newline at end of file diff --git a/deploy/k8s/local/website/website-hpa.yaml b/deploy/k8s/local/website/website-hpa.yaml new file mode 100644 index 0000000..f5cdef0 --- /dev/null +++ b/deploy/k8s/local/website/website-hpa.yaml @@ -0,0 +1,12 @@ +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: frontend +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: frontend + minReplicas: 3 + maxReplicas: 5 + targetCPUUtilizationPercentage: 50 \ No newline at end of file diff --git a/deploy/k8s/local/website/website-ingress.yaml b/deploy/k8s/local/website/website-ingress.yaml new file mode 100644 index 0000000..8bd4cf2 --- /dev/null +++ b/deploy/k8s/local/website/website-ingress.yaml @@ -0,0 +1,15 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: frontend + annotations: + nginx.ingress.kubernetes.io/affinity: cookie +spec: + rules: + - host: duber.local.com + http: + paths: + - path: / + backend: + serviceName: frontend + servicePort: 80 \ No newline at end of file diff --git a/deploy/k8s/local/website/website-service.yaml b/deploy/k8s/local/website/website-service.yaml new file mode 100644 index 0000000..9f7074c --- /dev/null +++ b/deploy/k8s/local/website/website-service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: frontend +spec: + selector: + app: frontend + ports: + - name: http + protocol: TCP + port: 80 + targetPort: 80 \ No newline at end of file diff --git a/src/Application/Duber.Invoice.API/Application/IntegrationEvents/Hnadlers/TripCancelledIntegrationEventHandler.cs b/src/Application/Duber.Invoice.API/Application/IntegrationEvents/Hnadlers/TripCancelledIntegrationEventHandler.cs index 183bdb0..c47fa50 100644 --- a/src/Application/Duber.Invoice.API/Application/IntegrationEvents/Hnadlers/TripCancelledIntegrationEventHandler.cs +++ b/src/Application/Duber.Invoice.API/Application/IntegrationEvents/Hnadlers/TripCancelledIntegrationEventHandler.cs @@ -5,6 +5,7 @@ using Duber.Domain.SharedKernel.Model; using Duber.Infrastructure.EventBus.Abstractions; using Duber.Invoice.API.Application.IntegrationEvents.Events; +using Microsoft.Extensions.Logging; namespace Duber.Invoice.API.Application.IntegrationEvents.Hnadlers { @@ -12,15 +13,19 @@ public class TripCancelledIntegrationEventHandler : IIntegrationEventHandler _logger; - public TripCancelledIntegrationEventHandler(IInvoiceRepository invoiceRepository, IPaymentService paymentService) + public TripCancelledIntegrationEventHandler(IInvoiceRepository invoiceRepository, IPaymentService paymentService, ILogger logger) { _invoiceRepository = invoiceRepository ?? throw new ArgumentNullException(nameof(invoiceRepository)); _paymentService = paymentService ?? throw new ArgumentNullException(nameof(paymentService)); + _logger = logger; } public async Task Handle(TripCancelledIntegrationEvent @event) { + _logger.LogInformation($"Trip {@event.TripId} has been cancelled."); + var invoice = await _invoiceRepository.GetInvoiceByTripAsync(@event.TripId); if (invoice != null) return; @@ -34,16 +39,18 @@ public async Task Handle(TripCancelledIntegrationEvent @event) TripStatus.Cancelled.Id); await _invoiceRepository.AddInvoiceAsync(invoice); + _logger.LogInformation($"Invoice {invoice.InvoiceId} created."); // integration with external payment system. if (Equals(invoice.PaymentMethod, PaymentMethod.CreditCard) && invoice.Total > 0) { await _paymentService.PerformPayment(invoice, @event.UserId); + _logger.LogInformation($"Payment for invoice {invoice.InvoiceId} has been processed."); } } catch (Exception ex) { - throw new InvalidOperationException($"Error trying to perform tge payment the Trip: {@event.TripId}", ex); + throw new InvalidOperationException($"Error trying to perform the paymen. Trip: {@event.TripId}", ex); } finally { diff --git a/src/Application/Duber.Invoice.API/Application/IntegrationEvents/Hnadlers/TripFinishedIntegrationEventHandler.cs b/src/Application/Duber.Invoice.API/Application/IntegrationEvents/Hnadlers/TripFinishedIntegrationEventHandler.cs index f6b25e3..723d647 100644 --- a/src/Application/Duber.Invoice.API/Application/IntegrationEvents/Hnadlers/TripFinishedIntegrationEventHandler.cs +++ b/src/Application/Duber.Invoice.API/Application/IntegrationEvents/Hnadlers/TripFinishedIntegrationEventHandler.cs @@ -5,6 +5,7 @@ using Duber.Domain.SharedKernel.Model; using Duber.Infrastructure.EventBus.Abstractions; using Duber.Invoice.API.Application.IntegrationEvents.Events; +using Microsoft.Extensions.Logging; namespace Duber.Invoice.API.Application.IntegrationEvents.Hnadlers { @@ -12,15 +13,19 @@ public class TripFinishedIntegrationEventHandler : IIntegrationEventHandler _logger; - public TripFinishedIntegrationEventHandler(IInvoiceRepository invoiceRepository, IPaymentService paymentService) + public TripFinishedIntegrationEventHandler(IInvoiceRepository invoiceRepository, IPaymentService paymentService, ILogger logger) { _invoiceRepository = invoiceRepository ?? throw new ArgumentNullException(nameof(invoiceRepository)); _paymentService = paymentService ?? throw new ArgumentNullException(nameof(paymentService)); + _logger = logger; } public async Task Handle(TripFinishedIntegrationEvent @event) { + _logger.LogInformation($"Trip {@event.TripId} has finished."); + var invoice = await _invoiceRepository.GetInvoiceByTripAsync(@event.TripId); if (invoice != null) return; @@ -34,16 +39,18 @@ public async Task Handle(TripFinishedIntegrationEvent @event) TripStatus.Finished.Id); await _invoiceRepository.AddInvoiceAsync(invoice); + _logger.LogInformation($"Invoice {invoice.InvoiceId} created."); // integration with external payment system. if (Equals(invoice.PaymentMethod, PaymentMethod.CreditCard) && invoice.Total > 0) { await _paymentService.PerformPayment(invoice, @event.UserId); + _logger.LogInformation($"Payment for invoice {invoice.InvoiceId} has been processed."); } } catch (Exception ex) { - throw new InvalidOperationException($"Error trying to perform the payment the Trip: {@event.TripId}", ex); + throw new InvalidOperationException($"Error trying to perform the payment. Trip: {@event.TripId}", ex); } finally { diff --git a/src/Application/Duber.Invoice.API/appsettings.json b/src/Application/Duber.Invoice.API/appsettings.json index dd7061a..c39420b 100644 --- a/src/Application/Duber.Invoice.API/appsettings.json +++ b/src/Application/Duber.Invoice.API/appsettings.json @@ -8,7 +8,7 @@ }, "Console": { "LogLevel": { - "Default": "Warning" + "Default": "Information" } } }, diff --git a/src/Application/Duber.Trip.API/Application/DomainEventHandlers/TripCreatedDomainEventHandlerAsync.cs b/src/Application/Duber.Trip.API/Application/DomainEventHandlers/TripCreatedDomainEventHandlerAsync.cs index e8da31a..6f5ec9f 100644 --- a/src/Application/Duber.Trip.API/Application/DomainEventHandlers/TripCreatedDomainEventHandlerAsync.cs +++ b/src/Application/Duber.Trip.API/Application/DomainEventHandlers/TripCreatedDomainEventHandlerAsync.cs @@ -5,6 +5,7 @@ using Duber.Infrastructure.EventBus.Abstractions; using Duber.Trip.API.Application.IntegrationEvents; using Kledex.Events; +using Microsoft.Extensions.Logging; namespace Duber.Trip.API.Application.DomainEventHandlers { @@ -12,15 +13,18 @@ public class TripCreatedDomainEventHandlerAsync : IEventHandlerAsync _logger; - public TripCreatedDomainEventHandlerAsync(IEventBus eventBus, IMapper mapper) + public TripCreatedDomainEventHandlerAsync(IEventBus eventBus, IMapper mapper, ILogger logger) { _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper)); + _logger = logger; } public async Task HandleAsync(TripCreatedDomainEvent @event) { + _logger.LogInformation($"Trip {@event.AggregateRootId} has been created."); var integrationEvent = _mapper.Map(@event); // to update the query side (materialized view) diff --git a/src/Application/Duber.Trip.API/Application/DomainEventHandlers/TripUpdatedDomainEventHandlerAsync.cs b/src/Application/Duber.Trip.API/Application/DomainEventHandlers/TripUpdatedDomainEventHandlerAsync.cs index cb1b806..dd8381c 100644 --- a/src/Application/Duber.Trip.API/Application/DomainEventHandlers/TripUpdatedDomainEventHandlerAsync.cs +++ b/src/Application/Duber.Trip.API/Application/DomainEventHandlers/TripUpdatedDomainEventHandlerAsync.cs @@ -6,6 +6,7 @@ using Duber.Trip.API.Application.IntegrationEvents; using Duber.Trip.API.Application.Model; using Kledex.Events; +using Microsoft.Extensions.Logging; using TripStatus = Duber.Domain.SharedKernel.Model.TripStatus; namespace Duber.Trip.API.Application.DomainEventHandlers @@ -14,11 +15,13 @@ public class TripUpdatedDomainEventHandlerAsync : IEventHandlerAsync _logger; - public TripUpdatedDomainEventHandlerAsync(IEventBus eventBus, IMapper mapper) + public TripUpdatedDomainEventHandlerAsync(IEventBus eventBus, IMapper mapper, ILogger logger) { _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper)); + _logger = logger; } public async Task HandleAsync(TripUpdatedDomainEvent @event) @@ -26,6 +29,7 @@ public async Task HandleAsync(TripUpdatedDomainEvent @event) var integrationEvent = _mapper.Map(@event); // to update the query side (materialized view) + _logger.LogInformation($"Trip {@event.AggregateRootId} has been updated."); _eventBus.Publish(integrationEvent); // TODO: make an async Publish method. // events for invoice microservice @@ -34,6 +38,7 @@ public async Task HandleAsync(TripUpdatedDomainEvent @event) if (!@event.Distance.HasValue || !@event.Duration.HasValue || !@event.UserTripId.HasValue) throw new ArgumentException("Distance, duration and user id are required to trigger a TripFinishedIntegrationEvent"); + _logger.LogInformation($"Trip {@event.AggregateRootId} has finished."); _eventBus.Publish(new TripFinishedIntegrationEvent( @event.AggregateRootId, @event.Distance.Value, @@ -46,6 +51,7 @@ public async Task HandleAsync(TripUpdatedDomainEvent @event) if (!@event.Duration.HasValue || !@event.UserTripId.HasValue) throw new ArgumentException("Duration and user id are required to trigger a TripCancelledIntegrationEvent"); + _logger.LogInformation($"Trip {@event.AggregateRootId} has been canceled."); _eventBus.Publish(new TripCancelledIntegrationEvent( @event.AggregateRootId, @event.Duration.Value, diff --git a/src/Application/Duber.Trip.API/appsettings.json b/src/Application/Duber.Trip.API/appsettings.json index ec2ad91..0ae0e43 100644 --- a/src/Application/Duber.Trip.API/appsettings.json +++ b/src/Application/Duber.Trip.API/appsettings.json @@ -8,7 +8,7 @@ }, "Console": { "LogLevel": { - "Default": "Warning" + "Default": "Information" } } }, diff --git a/src/Infrastructure/EventBus/Duber.Infrastructure.EventBus.RabbitMQ/EventBusRabbitMQ.cs b/src/Infrastructure/EventBus/Duber.Infrastructure.EventBus.RabbitMQ/EventBusRabbitMQ.cs index 58c2dd3..4c6be2c 100644 --- a/src/Infrastructure/EventBus/Duber.Infrastructure.EventBus.RabbitMQ/EventBusRabbitMQ.cs +++ b/src/Infrastructure/EventBus/Duber.Infrastructure.EventBus.RabbitMQ/EventBusRabbitMQ.cs @@ -29,11 +29,12 @@ public class EventBusRabbitMQ : IEventBus, IDisposable private string _queueName; public EventBusRabbitMQ(IRabbitMQPersistentConnection persistentConnection, ILogger logger, - ILifetimeScope autofac, IEventBusSubscriptionsManager subsManager, int retryCount = 5) + ILifetimeScope autofac, IEventBusSubscriptionsManager subsManager, string queueName = null, int retryCount = 5) { _persistentConnection = persistentConnection ?? throw new ArgumentNullException(nameof(persistentConnection)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _subsManager = subsManager ?? new InMemoryEventBusSubscriptionsManager(); + _queueName = queueName; _consumerChannel = CreateConsumerChannel(); _autofac = autofac; _retryCount = retryCount; @@ -85,15 +86,17 @@ public void Publish(IntegrationEvent @event) // to avoid lossing messages var properties = channel.CreateBasicProperties(); - properties.Persistent = true; + properties.DeliveryMode = 2; // persistent properties.Expiration = "60000"; policy.Execute(() => { - channel.BasicPublish(exchange: BROKER_NAME, - routingKey: eventName, - basicProperties: properties, - body: body); + channel.BasicPublish( + exchange: BROKER_NAME, + routingKey: eventName, + mandatory: true, + basicProperties: properties, + body: body); }); } } @@ -103,6 +106,7 @@ public void SubscribeDynamic(string eventName) { DoInternalSubscription(eventName); _subsManager.AddDynamicSubscription(eventName); + StartBasicConsume(); } public void Subscribe() @@ -112,6 +116,7 @@ public void Subscribe() var eventName = _subsManager.GetEventKey(); DoInternalSubscription(eventName); _subsManager.AddSubscription(); + StartBasicConsume(); } private void DoInternalSubscription(string eventName) @@ -152,23 +157,34 @@ public void Dispose() _subsManager.Clear(); } - private IModel CreateConsumerChannel() + private void StartBasicConsume() { - if (!_persistentConnection.IsConnected) + _logger.LogTrace("Starting RabbitMQ basic consume"); + + if (_consumerChannel != null) { - _persistentConnection.TryConnect(); - } + var consumer = new AsyncEventingBasicConsumer(_consumerChannel); - var channel = _persistentConnection.CreateModel(); - channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct"); - _queueName = channel.QueueDeclare().QueueName; + consumer.Received += Consumer_Received; - var consumer = new EventingBasicConsumer(channel); - consumer.Received += async (model, ea) => + _consumerChannel.BasicConsume( + queue: _queueName, + autoAck: false, + consumer: consumer); + } + else { - var eventName = ea.RoutingKey; - var message = Encoding.UTF8.GetString(ea.Body); + _logger.LogError("StartBasicConsume can't call on _consumerChannel == null"); + } + } + private async Task Consumer_Received(object sender, BasicDeliverEventArgs eventArgs) + { + var eventName = eventArgs.RoutingKey; + var message = Encoding.UTF8.GetString(eventArgs.Body); + + try + { var policy = Policy.Handle() .Or() .WaitAndRetryAsync(_retryCount, retryAttempt => TimeSpan.FromSeconds(1), @@ -177,14 +193,42 @@ private IModel CreateConsumerChannel() await policy.ExecuteAsync(async () => await ProcessEvent(eventName, message)); // to avoid losing messages - channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false); - }; + _consumerChannel.BasicAck(deliveryTag: eventArgs.DeliveryTag, multiple: false); + } + catch (Exception ex) + { + // consider using a Dead Letter Exchange for undelivered messages. + _logger.LogWarning(ex, "----- ERROR Processing message \"{Message}\"", message); + } + } + + private IModel CreateConsumerChannel() + { + if (!_persistentConnection.IsConnected) + { + _persistentConnection.TryConnect(); + } + + _logger.LogTrace("Creating RabbitMQ consumer channel"); + + var channel = _persistentConnection.CreateModel(); + + channel.ExchangeDeclare(exchange: BROKER_NAME, + type: "direct"); + + channel.QueueDeclare(queue: _queueName, + durable: true, + exclusive: false, + autoDelete: false, + arguments: null); - channel.BasicConsume(queue: _queueName, autoAck: false, consumer: consumer); channel.CallbackException += (sender, ea) => { + _logger.LogWarning(ea.Exception, "Recreating RabbitMQ consumer channel"); + _consumerChannel.Dispose(); _consumerChannel = CreateConsumerChannel(); + StartBasicConsume(); }; return channel; @@ -192,6 +236,8 @@ private IModel CreateConsumerChannel() private async Task ProcessEvent(string eventName, string message) { + _logger.LogTrace("Processing RabbitMQ event: {EventName}", eventName); + if (_subsManager.HasSubscriptionsForEvent(eventName)) { using (var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME)) @@ -200,22 +246,32 @@ private async Task ProcessEvent(string eventName, string message) foreach (var subscription in subscriptions) { if (subscription.IsDynamic) - { + { var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler; + if (handler == null) continue; dynamic eventData = JObject.Parse(message); + + await Task.Yield(); await handler.Handle(eventData); } else { + var handler = scope.ResolveOptional(subscription.HandlerType); + if (handler == null) continue; var eventType = _subsManager.GetEventTypeByName(eventName); var integrationEvent = JsonConvert.DeserializeObject(message, eventType); - var handler = scope.ResolveOptional(subscription.HandlerType); var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType); + + await Task.Yield(); await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent }); } } } } + else + { + _logger.LogWarning("No subscription for RabbitMQ event: {EventName}", eventName); + } } } } diff --git a/src/Infrastructure/EventBus/Duber.Infrastructure.EventBus.RabbitMQ/IoC/ServiceCollectionExtensions.cs b/src/Infrastructure/EventBus/Duber.Infrastructure.EventBus.RabbitMQ/IoC/ServiceCollectionExtensions.cs index 7a6b09b..8912653 100644 --- a/src/Infrastructure/EventBus/Duber.Infrastructure.EventBus.RabbitMQ/IoC/ServiceCollectionExtensions.cs +++ b/src/Infrastructure/EventBus/Duber.Infrastructure.EventBus.RabbitMQ/IoC/ServiceCollectionExtensions.cs @@ -22,7 +22,8 @@ public static IServiceCollection AddRabbitMQ(this IServiceCollection services, I var logger = sp.GetRequiredService>(); var factory = new ConnectionFactory() { - HostName = configuration["EventBusConnection"] + HostName = configuration["EventBusConnection"], + DispatchConsumersAsync = true }; return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); @@ -34,8 +35,9 @@ public static IServiceCollection AddRabbitMQ(this IServiceCollection services, I var iLifetimeScope = sp.GetRequiredService(); var logger = sp.GetRequiredService>(); var eventBusSubcriptionsManager = sp.GetRequiredService(); + var subscriptionClientName = configuration["SubscriptionClientName"]; - return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, retryCount); + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); }); services.AddSingleton(); diff --git a/src/Infrastructure/EventBus/Duber.Infrastructure.EventBus/InMemoryEventBusSubscriptionsManager.cs b/src/Infrastructure/EventBus/Duber.Infrastructure.EventBus/InMemoryEventBusSubscriptionsManager.cs index fa0a418..400888e 100644 --- a/src/Infrastructure/EventBus/Duber.Infrastructure.EventBus/InMemoryEventBusSubscriptionsManager.cs +++ b/src/Infrastructure/EventBus/Duber.Infrastructure.EventBus/InMemoryEventBusSubscriptionsManager.cs @@ -35,8 +35,13 @@ public void AddSubscription() where TH : IIntegrationEventHandler { var eventName = GetEventKey(); + DoAddSubscription(typeof(TH), eventName, isDynamic: false); - _eventTypes.Add(typeof(T)); + + if (!_eventTypes.Contains(typeof(T))) + { + _eventTypes.Add(typeof(T)); + } } private void DoAddSubscription(Type handlerType, string eventName, bool isDynamic) @@ -110,10 +115,7 @@ public IEnumerable GetHandlersForEvent() where T : Integrat private void RaiseOnEventRemoved(string eventName) { var handler = OnEventRemoved; - if (handler != null) - { - OnEventRemoved(this, eventName); - } + handler?.Invoke(this, eventName); } diff --git a/src/Web/Duber.WebSite/.bowerrc b/src/Web/Duber.WebSite/.bowerrc deleted file mode 100644 index 6406626..0000000 --- a/src/Web/Duber.WebSite/.bowerrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "directory": "wwwroot/lib" -} diff --git a/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/InvoiceCreatedIntegrationEventHandler.cs b/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/InvoiceCreatedIntegrationEventHandler.cs index 381c2a9..221b12e 100644 --- a/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/InvoiceCreatedIntegrationEventHandler.cs +++ b/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/InvoiceCreatedIntegrationEventHandler.cs @@ -3,20 +3,24 @@ using Duber.Infrastructure.EventBus.Abstractions; using Duber.WebSite.Application.IntegrationEvents.Events; using Duber.WebSite.Infrastructure.Repository; +using Microsoft.Extensions.Logging; namespace Duber.WebSite.Application.IntegrationEvents.Handlers { public class InvoiceCreatedIntegrationEventHandler: IIntegrationEventHandler { private readonly IReportingRepository _reportingRepository; + private readonly ILogger _logger; - public InvoiceCreatedIntegrationEventHandler(IReportingRepository reportingRepository) + public InvoiceCreatedIntegrationEventHandler(IReportingRepository reportingRepository, ILogger logger) { _reportingRepository = reportingRepository ?? throw new ArgumentNullException(nameof(reportingRepository)); + _logger = logger; } public async Task Handle(InvoiceCreatedIntegrationEvent @event) { + _logger.LogInformation("InvoiceCreatedIntegrationEvent handled"); var trip = await _reportingRepository.GetTripAsync(@event.TripId); // we throw an exception in order to don't send the Acknowledgement to the service bus, probably the consumer read @@ -24,6 +28,8 @@ public async Task Handle(InvoiceCreatedIntegrationEvent @event) if (trip == null) throw new InvalidOperationException($"The trip {@event.TripId} doesn't exist. Error trying to update the materialized view."); + _logger.LogInformation($"Invoice {@event.InvoiceId} for Trip {@event.TripId} has been created."); + trip.InvoiceId = @event.InvoiceId; trip.Fee = @event.Fee; trip.Fare = @event.Total - @event.Fee; diff --git a/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/InvoicePaidIntegrationEventHandler.cs b/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/InvoicePaidIntegrationEventHandler.cs index 4c2057e..28f5881 100644 --- a/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/InvoicePaidIntegrationEventHandler.cs +++ b/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/InvoicePaidIntegrationEventHandler.cs @@ -3,20 +3,24 @@ using Duber.Infrastructure.EventBus.Abstractions; using Duber.WebSite.Application.IntegrationEvents.Events; using Duber.WebSite.Infrastructure.Repository; +using Microsoft.Extensions.Logging; namespace Duber.WebSite.Application.IntegrationEvents.Handlers { public class InvoicePaidIntegrationEventHandler : IIntegrationEventHandler { private readonly IReportingRepository _reportingRepository; + private readonly ILogger _logger; - public InvoicePaidIntegrationEventHandler(IReportingRepository reportingRepository) + public InvoicePaidIntegrationEventHandler(IReportingRepository reportingRepository, ILogger logger) { _reportingRepository = reportingRepository ?? throw new ArgumentNullException(nameof(reportingRepository)); + _logger = logger; } public async Task Handle(InvoicePaidIntegrationEvent @event) { + _logger.LogInformation("InvoicePaidIntegrationEvent handled"); var trip = await _reportingRepository.GetTripAsync(@event.TripId); // we throw an exception in order to don't send the Acknowledgement to the service bus, probably the consumer read @@ -24,6 +28,8 @@ public async Task Handle(InvoicePaidIntegrationEvent @event) if (trip == null) throw new InvalidOperationException($"The trip {@event.TripId} doesn't exist. Error trying to update the materialized view."); + _logger.LogInformation($"Invoice {@event.InvoiceId} for Trip {@event.TripId} has been paid."); + trip.CardNumber = @event.CardNumber; trip.CardType = @event.CardType; trip.PaymentStatus = @event.Status == PaymentStatus.Accepted ? nameof(PaymentStatus.Accepted) : nameof(PaymentStatus.Rejected); diff --git a/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/TripCreatedIntegrationEventHandler.cs b/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/TripCreatedIntegrationEventHandler.cs index 91bca08..6e25135 100644 --- a/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/TripCreatedIntegrationEventHandler.cs +++ b/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/TripCreatedIntegrationEventHandler.cs @@ -6,6 +6,7 @@ using Duber.WebSite.Application.IntegrationEvents.Events; using Duber.WebSite.Infrastructure.Repository; using Duber.WebSite.Models; +using Microsoft.Extensions.Logging; namespace Duber.WebSite.Application.IntegrationEvents.Handlers { @@ -14,25 +15,25 @@ public class TripCreatedIntegrationEventHandler : IIntegrationEventHandler _logger; - public TripCreatedIntegrationEventHandler(IReportingRepository reportingRepository, IDriverRepository driverRepository, IUserRepository userRepository) + public TripCreatedIntegrationEventHandler(IReportingRepository reportingRepository, IDriverRepository driverRepository, IUserRepository userRepository, ILogger logger) { _reportingRepository = reportingRepository ?? throw new ArgumentNullException(nameof(reportingRepository)); _driverRepository = driverRepository ?? throw new ArgumentNullException(nameof(driverRepository)); _userRepository = userRepository ?? throw new ArgumentNullException(nameof(userRepository)); + _logger = logger; } public async Task Handle(TripCreatedIntegrationEvent @event) { + _logger.LogInformation("TripCreatedIntegrationEvent handled"); var existingTrip = await _reportingRepository.GetTripAsync(@event.TripId); if (existingTrip != null) return; - var driverTask = _driverRepository.GetDriverAsync(@event.DriverId); - var userTask = _userRepository.GetUserAsync(@event.UserTripId); - await Task.WhenAll(driverTask, userTask); - - var driver = await driverTask; - var user = await userTask; + _logger.LogInformation($"Trip {@event.TripId} has been created."); + var driver = await _driverRepository.GetDriverAsync(@event.DriverId); + var user = await _userRepository.GetUserAsync(@event.UserTripId); var newTrip = new Trip { diff --git a/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/TripUpdatedIntegrationEventHandler.cs b/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/TripUpdatedIntegrationEventHandler.cs index b3b28c2..d8a782c 100644 --- a/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/TripUpdatedIntegrationEventHandler.cs +++ b/src/Web/Duber.WebSite/Application/IntegrationEvents/Handlers/TripUpdatedIntegrationEventHandler.cs @@ -3,20 +3,24 @@ using Duber.Infrastructure.EventBus.Abstractions; using Duber.WebSite.Application.IntegrationEvents.Events; using Duber.WebSite.Infrastructure.Repository; +using Microsoft.Extensions.Logging; namespace Duber.WebSite.Application.IntegrationEvents.Handlers { public class TripUpdatedIntegrationEventHandler : IIntegrationEventHandler { private readonly IReportingRepository _reportingRepository; + private readonly ILogger _logger; - public TripUpdatedIntegrationEventHandler(IReportingRepository reportingRepository) + public TripUpdatedIntegrationEventHandler(IReportingRepository reportingRepository, ILogger logger) { _reportingRepository = reportingRepository ?? throw new ArgumentNullException(nameof(reportingRepository)); + _logger = logger; } public async Task Handle(TripUpdatedIntegrationEvent @event) { + _logger.LogInformation("TripUpdatedIntegrationEvent handled"); var trip = await _reportingRepository.GetTripAsync(@event.TripId); // we throw an exception in order to don't send the Acknowledgement to the service bus, probably the consumer read the @@ -24,6 +28,7 @@ public async Task Handle(TripUpdatedIntegrationEvent @event) if (trip == null) throw new InvalidOperationException($"The trip {@event.TripId} doesn't exist. Error trying to update the materialized view."); + _logger.LogInformation($"Trip {@event.TripId} has been updated. Status: {@event.Status}"); if (trip.Status == "Finished") return; trip.Distance = @event.Distance; diff --git a/src/Web/Duber.WebSite/Controllers/TripController.cs b/src/Web/Duber.WebSite/Controllers/TripController.cs index 5ee0107..c1a1994 100644 --- a/src/Web/Duber.WebSite/Controllers/TripController.cs +++ b/src/Web/Duber.WebSite/Controllers/TripController.cs @@ -98,15 +98,15 @@ public async Task SimulateTrip(TripRequestModel model) { if (!ModelState.IsValid) return BadRequest(ModelState.AllErrors()); - + var tripID = await CreateTrip(model); - await _hubContext.Clients.All.SendAsync("NotifyTrip", "Created"); - + await _hubContext.Clients.Client(model.ConnectionId).SendAsync("NotifyTrip", "Created"); + await AcceptOrStartTrip(_tripApiSettings.Value.AcceptUrl, tripID); - await _hubContext.Clients.All.SendAsync("NotifyTrip", "Accepted"); + await _hubContext.Clients.Client(model.ConnectionId).SendAsync("NotifyTrip", "Accepted"); await AcceptOrStartTrip(_tripApiSettings.Value.StartUrl, tripID); - await _hubContext.Clients.All.SendAsync("NotifyTrip", "Started"); + await _hubContext.Clients.Client(model.ConnectionId).SendAsync("NotifyTrip", "Started"); for (var index = 0; index < model.Directions.Count; index += 5) { @@ -115,10 +115,10 @@ public async Task SimulateTrip(TripRequestModel model) direction = _originsAndDestinations.Values.SingleOrDefault(x => x.Description == model.To); await UpdateTripLocation(tripID, direction); - await _hubContext.Clients.All.SendAsync("UpdateCurrentPosition", direction); + await _hubContext.Clients.Client(model.ConnectionId).SendAsync("UpdateCurrentPosition", direction); } - await _hubContext.Clients.All.SendAsync("NotifyTrip", "Finished"); + await _hubContext.Clients.Client(model.ConnectionId).SendAsync("NotifyTrip", "Finished"); return Ok(); } diff --git a/src/Web/Duber.WebSite/Duber.WebSite.csproj b/src/Web/Duber.WebSite/Duber.WebSite.csproj index 9ab8627..0343214 100644 --- a/src/Web/Duber.WebSite/Duber.WebSite.csproj +++ b/src/Web/Duber.WebSite/Duber.WebSite.csproj @@ -47,4 +47,15 @@ + + + + + + + + + + + diff --git a/src/Web/Duber.WebSite/Hubs/TripHub.cs b/src/Web/Duber.WebSite/Hubs/TripHub.cs index 14bf67b..990782a 100644 --- a/src/Web/Duber.WebSite/Hubs/TripHub.cs +++ b/src/Web/Duber.WebSite/Hubs/TripHub.cs @@ -1,19 +1,12 @@ -using System.Threading.Tasks; -using Duber.WebSite.Models; -using Microsoft.AspNetCore.SignalR; +using Microsoft.AspNetCore.SignalR; namespace Duber.WebSite.Hubs { public class TripHub : Hub { - public Task UpdateCurrentPosition(LocationModel position) + public string GetConnectionId() { - return Clients.All.SendAsync("UpdateCurrentPosition", position); - } - - public Task NotifyTrip(string message) - { - return Clients.All.SendAsync("NotifyTrip", message); + return Context.ConnectionId; } } } diff --git a/src/Web/Duber.WebSite/Models/TripRequestModel.cs b/src/Web/Duber.WebSite/Models/TripRequestModel.cs index 60be3ad..724fb08 100644 --- a/src/Web/Duber.WebSite/Models/TripRequestModel.cs +++ b/src/Web/Duber.WebSite/Models/TripRequestModel.cs @@ -30,6 +30,9 @@ public class TripRequestModel : IValidatableObject [Required] public string To { get; set; } + [Required] + public string ConnectionId { get; set; } + public IEnumerable Validate(ValidationContext validationContext) { if (From == To) diff --git a/src/Web/Duber.WebSite/Views/Shared/_Layout.cshtml b/src/Web/Duber.WebSite/Views/Shared/_Layout.cshtml index 2e48289..e814dc9 100644 --- a/src/Web/Duber.WebSite/Views/Shared/_Layout.cshtml +++ b/src/Web/Duber.WebSite/Views/Shared/_Layout.cshtml @@ -46,12 +46,12 @@ - + - + @@ -70,7 +70,7 @@ - + diff --git a/src/Web/Duber.WebSite/Views/Trip/Index.cshtml b/src/Web/Duber.WebSite/Views/Trip/Index.cshtml index 09d2ee8..c2d834b 100644 --- a/src/Web/Duber.WebSite/Views/Trip/Index.cshtml +++ b/src/Web/Duber.WebSite/Views/Trip/Index.cshtml @@ -86,25 +86,32 @@ DuberWebSite.init(@placesJson, '@Url.Action("SimulateTrip")', "@Url.Content("~/images/car-icon4.png")"); }; - let logger = new signalR.ConsoleLogger(signalR.LogLevel.Information); - let connection = new signalR.HubConnection(`http://${document.location.host}/triphub`, { transport: signalR.HttpTransportType.WebSockets, logger: logger }); + let connection = new signalR.HubConnectionBuilder() + .withUrl("/triphub", signalR.HttpTransportType.WebSockets) + .configureLogging(signalR.LogLevel.Information) + .build(); let startConnection = () => { - connection.start() - .then(e => { - console.log("Connection opened"); - }) - .catch(err => console.log(err)); + connection.start().then(function() { + console.log("Connection opened"); + + connection.invoke('getConnectionId') + .then(function(connectionId) { + sessionStorage.setItem('conectionId', connectionId); + }).catch(err => console.error(err.toString())); + }); }; startConnection(); connection.on('UpdateCurrentPosition', location => { DuberWebSite.updateTripPosition(location); + console.log("Current position", location); }); connection.on('NotifyTrip', (message) => { DuberWebSite.notifyTripStatus(message); + console.log("Trip status", message); }); } \ No newline at end of file diff --git a/src/Web/Duber.WebSite/bower.json b/src/Web/Duber.WebSite/bower.json deleted file mode 100644 index 3faa108..0000000 --- a/src/Web/Duber.WebSite/bower.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "asp.net", - "private": true, - "dependencies": { - "bootstrap": "3.3.7", - "jquery": "2.2.0", - "jquery-validation": "1.14.0", - "jquery-validation-unobtrusive": "3.2.6", - "lodash": "4.17.5" - } -} diff --git a/src/Web/Duber.WebSite/libman.json b/src/Web/Duber.WebSite/libman.json new file mode 100644 index 0000000..190c8e5 --- /dev/null +++ b/src/Web/Duber.WebSite/libman.json @@ -0,0 +1,33 @@ +{ + "version": "1.0", + "defaultProvider": "cdnjs", + "libraries": [ + { + "library": "jquery@2.2.0", + "destination": "wwwroot/lib/jquery/" + }, + { + "provider": "jsdelivr", + "library": "jquery-validation@1.14.0", + "destination": "wwwroot/lib/jquery-validation/" + }, + { + "library": "jquery-validation-unobtrusive@3.2.6", + "destination": "wwwroot/lib/jquery-validation-unobtrusive/" + }, + { + "library": "lodash.js@4.17.5", + "destination": "wwwroot/lib/lodash.js/" + }, + { + "provider": "jsdelivr", + "library": "bootstrap@3.3.7", + "destination": "wwwroot/lib/bootstrap/" + }, + { + "provider": "unpkg", + "library": "@microsoft/signalr@3.1.2", + "destination": "wwwroot/lib/signalr" + } + ] +} \ No newline at end of file diff --git a/src/Web/Duber.WebSite/wwwroot/js/site.js b/src/Web/Duber.WebSite/wwwroot/js/site.js index ec3f668..30a3a94 100644 --- a/src/Web/Duber.WebSite/wwwroot/js/site.js +++ b/src/Web/Duber.WebSite/wwwroot/js/site.js @@ -74,7 +74,8 @@ var DuberWebSite = (function () { Driver: $("#Driver").val(), From: $("#From").val(), To: $("#To").val(), - Directions: _directions + Directions: _directions, + ConnectionId: sessionStorage.getItem('conectionId') }, () => { console.log("Simulation request sent succesfully."); diff --git a/src/Web/Duber.WebSite/wwwroot/lib/signalr/README.md b/src/Web/Duber.WebSite/wwwroot/lib/signalr/README.md deleted file mode 100644 index adde540..0000000 --- a/src/Web/Duber.WebSite/wwwroot/lib/signalr/README.md +++ /dev/null @@ -1,49 +0,0 @@ -JavaScript and TypeScript clients for SignalR for ASP.NET Core - -## Installation - -```bash -npm install @aspnet/signalr -``` - -## Usage - -### Browser - -To use the client in a browser, copy `*.js` files from the `dist/browser` folder to your script folder include on your page using the `