Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
7cec63d
Ignores macOS .DS_Store files
the80hz Mar 11, 2026
1ef5a12
Лаб 1: добавлен сервис генерации учебных курсов на Bogus
the80hz Mar 11, 2026
bb86231
Лаб 1: добавлено кэширование генерации через Redis
the80hz Mar 11, 2026
e568e91
Лаб 1: добавлено структурное логирование генератора и кэша
the80hz Mar 11, 2026
b0910cf
Лаб 1: настроена оркестрация через .NET Aspire и Redis
the80hz Mar 11, 2026
c280b1f
Лаб 1: зависимости приведены к .NET 8 и backend запущен
the80hz Mar 11, 2026
b8261c4
Лаб 1: исправлен запуск оркестрации Aspire AppHost
the80hz Mar 11, 2026
34c232f
Лаб 1: добавлена поддержка внешних HTTP-эндпоинтов для генератора курсов
the80hz Mar 11, 2026
58a6d82
Лаб 1: добавлен Makefile для управления проектом и контейнером Redis
the80hz Mar 11, 2026
946e793
Лаб 1: добавлено использование патронимиков для генерации полных имен…
the80hz Mar 11, 2026
b74aa51
Лаб 1: обновлены данные в компоненте StudentCard и настроен BaseAddre…
the80hz Mar 11, 2026
5457b0f
Лаб 1: переименован словарь патронимов и добавлена поддержка женских …
the80hz Mar 11, 2026
d526502
Лаб 1: добавлена настройка окружения для проекта course-generator-api
the80hz Mar 11, 2026
22e1d0d
Лаб 1: подключены ServiceDefaults и health-эндпоинты в CourseGenerato…
the80hz Mar 11, 2026
084a517
Лаб 1: расширены ServiceDefaults (telemetry, discovery, resilience)
the80hz Mar 11, 2026
e0020ea
Лаб 1: обновлен AppHost до Aspire 9.5 с WaitFor и RedisInsight
the80hz Mar 11, 2026
9e1a396
Лаб 1: добавлен Client.Wasm в оркестрацию AppHost
the80hz Mar 11, 2026
6df7844
Лаб 1: добавлены контроллер, DTO и интерфейсы для генератора курсов
the80hz Mar 11, 2026
80b42cc
Лаб 1: добавлены ссылки на проекты Client.Wasm и CourseGenerator.Api …
the80hz Mar 12, 2026
4276483
Лаб 1: убран бесполезный для браузерного клиента вызов
the80hz Mar 12, 2026
f88c6d8
Лаб 1: убран вызов WithHttpEndpoint для courseGeneratorApi
the80hz Mar 12, 2026
9d8256a
Лаб1: добавил саммари из замечаний pr
the80hz Mar 12, 2026
1f9789b
Лаб 1: дополнительные саммари
the80hz Mar 12, 2026
dab62d2
Лаб 1: обновлен параметр генерации контрактов и удалён класс CourseGe…
the80hz Mar 12, 2026
e82b1a3
Лаб 1: добавлено ограничение на параметр count в методе GenerateAsync
the80hz Mar 12, 2026
0339ec7
Лаб 1: переделал генерацию под RuleFor()
the80hz Mar 12, 2026
ffda91f
Лаб 1: обновлён способ подключения к Redis, заменён на AddRedisDistri…
the80hz Mar 12, 2026
495593c
Лаб 1: фейкер вынесен в статическое поле
the80hz Mar 12, 2026
192f34b
Лаб 1: удалены настройки подключения к Redis из appsettings.json
the80hz Mar 12, 2026
c5b3106
Лаб1: добавлен метод получения контракта по идентификатору
the80hz Mar 12, 2026
14b1a6d
Лаб 1: указан порт для апи
the80hz Mar 12, 2026
67bf219
Лаб 1: поправлен генератор объектов
the80hz Mar 12, 2026
e431d3d
Обновлены настройки проекта: изменен номер лабораторной работы, отклю…
the80hz Apr 10, 2026
27c9c1f
Лаба 2 сделять
the80hz Apr 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -416,3 +416,6 @@ FodyWeavers.xsd
*.msix
*.msm
*.msp

# User-specific
.DS_Store
17 changes: 17 additions & 0 deletions Api.Gateway/Api.Gateway.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Ocelot" Version="24.1.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CourseApp\CourseApp.ServiceDefaults\CourseApp.ServiceDefaults.csproj" />
</ItemGroup>

</Project>
38 changes: 38 additions & 0 deletions Api.Gateway/LoadBalancing/WeightedRandomLoadBalancer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Ocelot.LoadBalancer.Interfaces;
using Ocelot.Responses;
using Ocelot.Values;

namespace Api.Gateway.LoadBalancing;

/// <summary>
/// Балансировка случайным образом с весами
/// </summary>
/// <param name="services">Функция получения списка сервисов</param>
/// <param name="configuration">Конфигурация приложения</param>
public class WeightedRandomLoadBalancer(
Func<Task<List<Service>>> services,
IConfiguration configuration) : ILoadBalancer
{
private readonly int[] _frequencies = configuration.GetSection("LoadBalancing:Weights").Get<int[]>() ?? [5, 4, 3, 2, 1];

public string Type => nameof(WeightedRandomLoadBalancer);

public async Task<Response<ServiceHostAndPort>> LeaseAsync(HttpContext httpContext)
{
var availableServices = await services();

if (availableServices.Count == 0)
throw new InvalidOperationException("No available downstream services");

var values = Enumerable.Range(1, availableServices.Count)
.Zip(_frequencies, (val, freq) => Enumerable.Repeat(val, freq))
.SelectMany(x => x)
.ToArray();

Random.Shared.Shuffle(values);

return new OkResponse<ServiceHostAndPort>(availableServices[values.First() - 1].HostAndPort);
}

public void Release(ServiceHostAndPort hostAndPort) { }
}
34 changes: 34 additions & 0 deletions Api.Gateway/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using Api.Gateway.LoadBalancing;

var builder = WebApplication.CreateBuilder(args);

builder.AddServiceDefaults();

builder.Configuration.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
builder.Services.AddOcelot()
.AddCustomLoadBalancer((sp, _, provider) =>
new WeightedRandomLoadBalancer(provider.GetAsync, sp.GetRequiredService<IConfiguration>()));

var allowedOrigins = builder.Configuration.GetSection("Cors:AllowedOrigins").Get<string[]>() ?? [];

builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.WithOrigins(allowedOrigins)
.AllowAnyHeader()
.WithMethods("GET");
});
});

var app = builder.Build();

app.UseCors();

app.MapDefaultEndpoints();

await app.UseOcelot();

app.Run();
38 changes: 38 additions & 0 deletions Api.Gateway/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:51762",
"sslPort": 44308
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5297",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7297;http://localhost:5297",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
8 changes: 8 additions & 0 deletions Api.Gateway/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
18 changes: 18 additions & 0 deletions Api.Gateway/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Cors": {
"AllowedOrigins": [
"http://localhost:5127",
"https://localhost:7282"
]
},
"LoadBalancing": {
"Weights": [ 5, 4, 3, 2, 1 ]
}
}
35 changes: 35 additions & 0 deletions Api.Gateway/ocelot.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"Routes": [
{
"DownstreamPathTemplate": "/api/courses",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5213
},
{
"Host": "localhost",
"Port": 5214
},
{
"Host": "localhost",
"Port": 5215
},
{
"Host": "localhost",
"Port": 5216
},
{
"Host": "localhost",
"Port": 5217
}
],
"UpstreamPathTemplate": "/courses",
"UpstreamHttpMethod": [ "GET" ],
"LoadBalancerOptions": {
"Type": "WeightedRandomLoadBalancer"
}
}
]
}
8 changes: 4 additions & 4 deletions Client.Wasm/Components/StudentCard.razor
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
</CardHeader>
<CardBody>
<UnorderedList Unstyled>
<UnorderedListItem>Номер <Strong>№X "Название лабораторной"</Strong></UnorderedListItem>
<UnorderedListItem>Вариант <Strong>№Х "Название варианта"</Strong></UnorderedListItem>
<UnorderedListItem>Выполнена <Strong>Фамилией Именем 65ХХ</Strong> </UnorderedListItem>
<UnorderedListItem><Link To="https://puginarug.com/">Ссылка на форк</Link></UnorderedListItem>
<UnorderedListItem>Номер <Strong>№2 "Кэширование"</Strong></UnorderedListItem>
<UnorderedListItem>Вариант <Strong>№37 "Учебный курс"</Strong></UnorderedListItem>
<UnorderedListItem>Выполнена <Strong>Вольговым Даниилом 6513</Strong> </UnorderedListItem>
<UnorderedListItem><Link To="https://github.com/the80hz/cloud-development">Ссылка на форк</Link></UnorderedListItem>
</UnorderedList>
</CardBody>
</Card>
6 changes: 3 additions & 3 deletions Client.Wasm/Properties/launchSettings.json
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchBrowser": false,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "http://localhost:5127",
"environmentVariables": {
Expand All @@ -22,7 +22,7 @@
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchBrowser": false,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "https://localhost:7282;http://localhost:5127",
"environmentVariables": {
Expand All @@ -31,7 +31,7 @@
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchBrowser": false,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
Expand Down
2 changes: 1 addition & 1 deletion Client.Wasm/wwwroot/appsettings.json
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
}
},
"AllowedHosts": "*",
"BaseAddress": ""
"BaseAddress": "https://localhost:7297/courses"
}
74 changes: 49 additions & 25 deletions CloudDevelopment.sln
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,25 +1,49 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36811.4
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client.Wasm", "Client.Wasm\Client.Wasm.csproj", "{AE7EEA74-2FE0-136F-D797-854FD87E022A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AE7EEA74-2FE0-136F-D797-854FD87E022A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE7EEA74-2FE0-136F-D797-854FD87E022A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE7EEA74-2FE0-136F-D797-854FD87E022A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE7EEA74-2FE0-136F-D797-854FD87E022A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {90FE6B04-8381-437E-893A-FEBA1DA10AEE}
EndGlobalSection
EndGlobal

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36811.4
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client.Wasm", "Client.Wasm\Client.Wasm.csproj", "{AE7EEA74-2FE0-136F-D797-854FD87E022A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CourseApp.AppHost", "CourseApp\CourseApp.AppHost\CourseApp.AppHost.csproj", "{B51DE59B-BAF5-434D-B2AB-05002DF1BA24}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CourseApp.ServiceDefaults", "CourseApp\CourseApp.ServiceDefaults\CourseApp.ServiceDefaults.csproj", "{064D02F8-AA28-8AA3-C1DB-6440761E6CB3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CourseApp.Api", "CourseApp.Api\CourseApp.Api.csproj", "{2077B3EC-232D-D44F-72B9-3B84AA8AE54F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Api.Gateway", "Api.Gateway\Api.Gateway.csproj", "{C99E72F4-9BA7-7D56-C88E-FB28534EFCB6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AE7EEA74-2FE0-136F-D797-854FD87E022A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE7EEA74-2FE0-136F-D797-854FD87E022A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE7EEA74-2FE0-136F-D797-854FD87E022A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE7EEA74-2FE0-136F-D797-854FD87E022A}.Release|Any CPU.Build.0 = Release|Any CPU
{B51DE59B-BAF5-434D-B2AB-05002DF1BA24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B51DE59B-BAF5-434D-B2AB-05002DF1BA24}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B51DE59B-BAF5-434D-B2AB-05002DF1BA24}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B51DE59B-BAF5-434D-B2AB-05002DF1BA24}.Release|Any CPU.Build.0 = Release|Any CPU
{064D02F8-AA28-8AA3-C1DB-6440761E6CB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{064D02F8-AA28-8AA3-C1DB-6440761E6CB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{064D02F8-AA28-8AA3-C1DB-6440761E6CB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{064D02F8-AA28-8AA3-C1DB-6440761E6CB3}.Release|Any CPU.Build.0 = Release|Any CPU
{2077B3EC-232D-D44F-72B9-3B84AA8AE54F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2077B3EC-232D-D44F-72B9-3B84AA8AE54F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2077B3EC-232D-D44F-72B9-3B84AA8AE54F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2077B3EC-232D-D44F-72B9-3B84AA8AE54F}.Release|Any CPU.Build.0 = Release|Any CPU
{C99E72F4-9BA7-7D56-C88E-FB28534EFCB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C99E72F4-9BA7-7D56-C88E-FB28534EFCB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C99E72F4-9BA7-7D56-C88E-FB28534EFCB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C99E72F4-9BA7-7D56-C88E-FB28534EFCB6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {90FE6B04-8381-437E-893A-FEBA1DA10AEE}
EndGlobalSection
EndGlobal
18 changes: 18 additions & 0 deletions CourseApp.Api/CourseApp.Api.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Aspire.StackExchange.Redis.DistributedCaching" Version="9.5.2" />
<PackageReference Include="Bogus" Version="35.6.5" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CourseApp\CourseApp.ServiceDefaults\CourseApp.ServiceDefaults.csproj" />
</ItemGroup>

</Project>
Loading
Loading