{"id":17337866,"url":"https://github.com/edwinvw/inhouse-event-workshop","last_synced_at":"2025-03-27T08:12:50.796Z","repository":{"id":232898113,"uuid":"600979282","full_name":"EdwinVW/inhouse-event-workshop","owner":"EdwinVW","description":"Repository containing the code and instructions for the Info Support in-house day for students. ","archived":false,"fork":false,"pushed_at":"2023-03-03T14:33:54.000Z","size":3501,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-01T13:12:33.699Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EdwinVW.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-02-13T05:17:43.000Z","updated_at":"2023-08-14T20:56:16.000Z","dependencies_parsed_at":"2024-04-12T06:05:56.633Z","dependency_job_id":"c7838a4f-e5af-4268-9697-4c18692c2ce0","html_url":"https://github.com/EdwinVW/inhouse-event-workshop","commit_stats":null,"previous_names":["edwinvw/inhouse-event-workshop"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdwinVW%2Finhouse-event-workshop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdwinVW%2Finhouse-event-workshop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdwinVW%2Finhouse-event-workshop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdwinVW%2Finhouse-event-workshop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EdwinVW","download_url":"https://codeload.github.com/EdwinVW/inhouse-event-workshop/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245806458,"owners_count":20675298,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-15T15:36:27.155Z","updated_at":"2025-03-27T08:12:50.771Z","avatar_url":"https://github.com/EdwinVW.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Info Support in-house event workshop\n\nThis README contains instructions for the Dapr workshop. The goal of the workshop is to apply Dapr to a microservices application. This repository contains the source-code that forms the starting point of the workshop. \n\n## Case Setup\n\nThis is an overview of the fictitious setup I'm simulating in this sample:\n\n\u003cimg src=\"img/setup-overview.png\" alt=\"Setup overview\" style=\"zoom: 25%;\" /\u003e\n\nThere is a stretch of highway that is equipped with camera's. There's 1 entry-camera and 1 exit-camera per lane. When a vehicle passes an entry-camera, the license-number of the vehicle and the timestamp is registered.\n\nWhen the car passes an exit-camera, this timestamp is also registered and the average speed of the vehicle based on the entry- and exit-timestamp is calculated.\n\nNext to the highway, there is a CO2 sensor. This sensor will measure the amount of CO2 in the air surrounding the highway once every minute.\n\nUsing the overall average speed and CO2 levels over time, we can get investigate whether the average speed on a highway is correlated to the CO2 level  in the air. \n\n## Simulation\n\nIn order to simulate this in code, I created the following services:\n\n\u003cimg src=\"img/services.png\" style=\"zoom: 33%;\" /\u003e\n\n- The **Simulation** is a .NET console application that will simulate the 3 entry- and exit-camera's with cars passing under them and the CO2 level sensor.\n- The **Traffic Control Service** is an ASP.NET WebAPI application that offers 2 endpoints: `/entrycam` and `/exitcam`.\n- The **Measurements Service** is an ASP.NET Core WebAPI application that offers 3 endpoints: `/averageSpeed`, `/co2Level` and `/metrics`.\n\nThe way the simulation works is depicted in the sequence diagram below:\n\n\u003cimg src=\"./img/sequence.png\" alt=\"Sequence diagram\" style=\"zoom:25%;\" /\u003e\n\n1. The **Camera Simulation** generates a random license-number and sends a *VehicleRegistered* message (containing this license-number, a random entry-lane (1-3) and the timestamp) to the `/entrycam` endpoint of the **TrafficControl Service**.\n1. The **TrafficControl Service** stores the VehicleState (license-number and entry-timestamp).\n1. After some random interval, the **Camera Simulation** sends a *VehicleRegistered* message to the `/exitcam` endpoint of the **TrafficControl Service** (containing the license-number generated in step 1, a random exit-lane (1-3) and the exit timestamp).\n1. The **TrafficControl Service** retrieves the VehicleState that was stored at vehicle entry.\n1. The **TrafficControl Service** calculates the average speed of the vehicle using the entry- and exit-timestamp. It also stores the VehicleState with the exit timestamp for audit purposes, but this is left out of the sequence diagram for clarity.\n1. The average speed is sent to the `/averageSpeed` endpoint of the **Measurements Service**. The request payload will be an *AverageSpeedmeasured* message containing the average speed in KMh of a vehicle and the timestamp of the measurement.\n1. The **Measurements Service** calculates the overall average speed over time since the last sample point (see 9) and stores this.\n1. Every 15 seconds, the **CO2 Sensor Simulation** reads the current level of CO2 in the air and sends this to the `/co2Level` endpoint of the **Measurements Service**. The request payload will be a *CO2LevelMeasured* message containing the the amount of CO2 in the air expressed in parts per million (ppm) and the timestamp of the measurement. \n1. The **Measurements Service** generates a *sample point*. A sample point is a measurement at a point in time that contains a timestamp, the average speed over time since the last sample point and the CO2 level at that point in time.\n1. The **Dashboard\\*** gets all the sample points by calling the metrics endpoint of the of the **Measurements Service**. The **Measurements Service** returns the last 50 sample points. This data can be used to create a dashboard that will plot the average speed and CO2 level in a graph.\n\n**\\*** The Dashboard is not implemented in the sample solution. But it could look something like this:\n\n\u003cimg src=\"img/graphs.png\" style=\"zoom:25%\" /\u003e\n\nYou can check out the code of the sample solution by opening Visual Studio Code and opening the workspace file `inhouse-eventworkshop.code-workspace` in the repository. Go though the code and get familiar with how things are setup (with proxies and repositories).\n\n## Running the services\n\nYou can start the services using the `dotnet run` command. Follow the instructions below to get the sample application up \u0026 running:\n\n1. Open a terminal window. You could use the terminal window in Visual Studio Code.  \n\n1. Go into the `src/MeasurementsService` folder.\n\n1. Start the service by typing `dotnet run`. You should see output like this:\n   ```PowerShell\n   ❯ dotnet run\n   info: Microsoft.Hosting.Lifetime[14]\n         Now listening on: http://localhost:6003\n   info: Microsoft.Hosting.Lifetime[0]\n         Application started. Press Ctrl+C to shut down.\n   info: Microsoft.Hosting.Lifetime[0]\n         Hosting environment: Development\n   info: Microsoft.Hosting.Lifetime[0]\n         Content root path: D:\\dev\\inhouse-event-workshop\\MeasurementsService\n   ```\n\n1. Open a new terminal window.\n\n1. Go into the `src/TrafficControlService` folder.\n\n1. Start the service by typing `dotnet run`.\n\n1. Open a new terminal window.\n\n1. Go into the `src/Simulation` folder.\n\n1. Start the simulation by typing `dotnet run`.\n\nYou can see in the logging of the Measurements service what the average speed and CO2 level in the air is:\n\n![image-20230302131559093](img/measurementsservice-logging.png)\n\nYou can specify the maximum speed for the highway used by the Simulation on the command-line:\n\n```PowerShell\ndotnet run -- 80\n```\n\nThe allowed maximum speeds are: 80, 90, 100, 120 or 130. Now you can see whether the maximum speed impacts the level of CO2 in the air.\n\nNow that you have the application running, you will start adding Dapr to it in the workshop assignments.\n\n## Hands-on assignments\n\nYou've just heard about how Dapr can help with implementing microservices. In this hand-on part of the workshop, you will add Dapr building-blocks to the solution described above. The end result should look like this:\n\n![](img/services-dapr.png)\n\nThe workshop will not tell you exactly what to do. It's up to you to add the Dapr building-blocks. You can use the [Dapr Documentation](https://docs.dapr.io/) to get more information on how to implement the different Building Blocks. \n\nMake sure you've installed the prerequisites listed below, and you can dive right in!\n\n## Prerequisites\n\nIn order to get most value out of the workshop, make sure you have the prerequisites installed on your machine before the workshop starts. Install the General prerequisites first. Then, select the technology stack you are going to use for executing the workshop assignments and install the prerequisites for that technology stack.\n\n#### General\n\n- Git ([download](https://git-scm.com/))\n- Visual Studio Code ([download](https://code.visualstudio.com/download)) with at least the following extensions installed:\n  - [REST Client](https://marketplace.visualstudio.com/items?itemName=humao.rest-client)\n- Docker for desktop ([download](https://www.docker.com/products/docker-desktop))\n- [Install the Dapr CLI](https://docs.dapr.io/getting-started/install-dapr-cli/) and [initialize Dapr locally](https://docs.dapr.io/getting-started/install-dapr-selfhost/)\n\nAll scripts in the instructions are PowerShell scripts. If you're working on a Mac, it is recommended to install PowerShell for Mac:\n\n- PowerShell for Mac ([instructions](https://docs.microsoft.com/nl-nl/powershell/scripting/install/installing-powershell-core-on-macos?view=powershell-7.1))\n\n#### .NET\n\n- .NET 7 SDK ([download](https://dotnet.microsoft.com/download/dotnet/7.0))\n- [C# extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp)\n\n---\n\n### Assignment 1\n\n**Goal: make sure all communication between the Simulation and the TrafficControl service is done using Dapr service invocation.** \n\nReplace the default HTTP Proxy implementation and use the Dapr API to call the Traffic Control service using service invocation. Do this using the Dapr API directly and after that using the [Dapr SDK for .NET](https://docs.dapr.io/developing-applications/sdks/dotnet/).\n\n---\n\n### Assignment 2\n\n**Goal: make sure the TrafficControl service stores its state in Redis through the Dapr state-management building block.**\n\nCurrently, the state is stored in memory. Replace the current Repository implementation with one that uses Dapr state-management. Do this using the Dapr API directly and after that using the [Dapr SDK for .NET](https://docs.dapr.io/developing-applications/sdks/dotnet/).\n\n---\n\n### Assignment 3\n\n**Goal: make sure all communication with the Measurements service is done using asynchronous messaging.** \n\nYou will use the Redis server that is installed by default with Dapr as the message broker. Do this using the Dapr API directly and after that using the [Dapr SDK for .NET](https://docs.dapr.io/developing-applications/sdks/dotnet/).\n\n---\n\n### Stretch Goals\n\nThese stretch goals are for people that have finished all the other assignments within the timespan of te workshop. You can choose a stretch goal randomly. You don't have to do the in any particular order. \n\n#### Stretch goal 1\n\n**Goal: change the message-broker used in assignment 3 from Redis to RabbitMQ.** \n\nIn the `Infrastructure` folder in the repository you can find scripts to start and stop RabbitMQ as a Docker container on your local machine. Once started, you can access the RabbitMQ management console by browsing to [https://localhost:15672](https://localhost:15672). The default login credentials are: \n\n- Username:`guest`\n- Password: `guest`\n\nMake sure you create a new account and use this account and its password in the Dapr component-configuration file.\n\n#### Stretch Goal 2\n\n**Goal: use other Dapr building-blocks in the sample application.** \n\nYou may use any Dapr building-block and change / add services if you want.\n\n#### Stretch Goal 3 \n\n**Goal: create a cool Measurements DashBoard that shows the metrics.**  \n\nHow you create it is up to you. You could create a Blazor app, an Anguar website or a Mobile App. Whatever you like to do. And think of a creative way of presenting the metrics to the user.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedwinvw%2Finhouse-event-workshop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedwinvw%2Finhouse-event-workshop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedwinvw%2Finhouse-event-workshop/lists"}