Skip to content

Commit

Permalink
implement a beer rating sample app to demonstrate distributed counter…
Browse files Browse the repository at this point in the history
…s in RavenDB
  • Loading branch information
aviv committed Jul 9, 2024
0 parents commit 823313e
Show file tree
Hide file tree
Showing 27 changed files with 4,936 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[Bb]in
[Oo]bj
.vs/
8 changes: 8 additions & 0 deletions BeerRatingApp.Server/Beer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
public class Beer
{
public string Id { get; set; }
public string Name { get; set; }
public string ImageUrl { get; set; }
public string Style { get; set; }

}
26 changes: 26 additions & 0 deletions BeerRatingApp.Server/BeerRatingApp.Server.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<SpaRoot>..\beerratingapp.client</SpaRoot>
<SpaProxyLaunchCommand>npm run dev</SpaProxyLaunchCommand>
<SpaProxyServerUrl>https://localhost:5173</SpaProxyServerUrl>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.SpaProxy">
<Version>8.*-*</Version>
</PackageReference>
<PackageReference Include="RavenDB.Client" Version="6.0.104" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\beerratingapp.client\BeerRatingApp.client.esproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>

</Project>
6 changes: 6 additions & 0 deletions BeerRatingApp.Server/BeerRatingApp.Server.csproj.user
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ActiveDebugProfile>https</ActiveDebugProfile>
</PropertyGroup>
</Project>
6 changes: 6 additions & 0 deletions BeerRatingApp.Server/BeerRatingApp.Server.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@BeerRatingApp.Server_HostAddress = http://localhost:5234

GET {{BeerRatingApp.Server_HostAddress}}/beers/
Accept: application/json

###
77 changes: 77 additions & 0 deletions BeerRatingApp.Server/Controllers/BeersController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using Microsoft.AspNetCore.Mvc;
using Raven.Client.Documents;

namespace BeerRatingApp.Server.Controllers
{
[ApiController]
[Route("[controller]")]
public class BeersController : ControllerBase
{
private readonly IDocumentStore _documentStore;

public BeersController(IDocumentStore documentStore)
{
_documentStore = documentStore;
}

[HttpGet]
public async Task<IEnumerable<Beer>> Get()
{
// return all beer documents
using var session = _documentStore.OpenAsyncSession();
var beers = await session.Query<Beer>().ToListAsync();

return beers;
}

[HttpPost("{id}/rate")]
public async Task<decimal?> Rate(string id, [FromBody] int rating)
{
if (rating is <= 0 or > 5)
throw new InvalidOperationException("rating must be a number between 1 and 5");

id = Uri.UnescapeDataString(id);

using var session = _documentStore.OpenAsyncSession();

// increment the counter corresponding to the rating
session.CountersFor(id).Increment(rating.ToString());
await session.SaveChangesAsync();

// return current rating
var currentRating = await GetRating(id);
return currentRating;
}

[HttpGet("{id}/rating")]
public async Task<decimal?> GetRating(string id)
{
id = Uri.UnescapeDataString(id);

// get all counters for this beer document
using var session = _documentStore.OpenAsyncSession();
var ratings = await session.CountersFor(id).GetAllAsync();

// if it has no counters, rating is 0
if (ratings.Count == 0)
return 0;

// sum the product of each score and its corresponding count,
// then divide by the total number of ratings
var numberOfVotes = ratings.Values.Sum();
long? sum = 0;
foreach (var kvp in ratings)
{
if (int.TryParse(kvp.Key, out var score) == false ||
score is <= 0 or > 5)
continue;


sum += kvp.Value * score;
}

var avg = (decimal)sum!/numberOfVotes;
return avg;
}
}
}
33 changes: 33 additions & 0 deletions BeerRatingApp.Server/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Raven.Client.Documents;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddSwaggerGen();

// Configure RavenDB
var store = new DocumentStore
{
Urls = new[] { "http://localhost:8080" },
Database = "BeerRatingApp"
};
store.Initialize();
builder.Services.AddSingleton<IDocumentStore>(store);

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();
app.UseAuthorization();
app.MapControllers();

app.Run();
45 changes: 45 additions & 0 deletions BeerRatingApp.Server/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:13550",
"sslPort": 44344
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5234",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7123;http://localhost:5234",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
}
}
}
}

8 changes: 8 additions & 0 deletions BeerRatingApp.Server/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
9 changes: 9 additions & 0 deletions BeerRatingApp.Server/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# samples-aspnet-distributed-counters
21 changes: 21 additions & 0 deletions beerratingapp.client/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react/jsx-runtime',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
settings: { react: { version: '18.2' } },
plugins: ['react-refresh'],
rules: {
'react/jsx-no-target-blank': 'off',
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
24 changes: 24 additions & 0 deletions beerratingapp.client/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
8 changes: 8 additions & 0 deletions beerratingapp.client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# React + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
11 changes: 11 additions & 0 deletions beerratingapp.client/beerratingapp.client.esproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.VisualStudio.JavaScript.Sdk/0.5.128-alpha">
<PropertyGroup>
<StartupCommand>npm run dev</StartupCommand>
<JavaScriptTestRoot>src\</JavaScriptTestRoot>
<JavaScriptTestFramework>Jest</JavaScriptTestFramework>
<!-- Allows the build (or compile) script located on package.json to run on Build -->
<ShouldRunBuildScript>false</ShouldRunBuildScript>
<!-- Folder where production build objects will be placed -->
<PublishAssetsDirectory>$(MSBuildProjectDirectory)\dist</PublishAssetsDirectory>
</PropertyGroup>
</Project>
13 changes: 13 additions & 0 deletions beerratingapp.client/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
10 changes: 10 additions & 0 deletions beerratingapp.client/nuget.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<disabledPackageSources>
<clear />
</disabledPackageSources>
</configuration>
Loading

0 comments on commit 823313e

Please sign in to comment.