Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions Client.Wasm/Components/StudentCard.razor
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>№1 "Кеширование"</Strong></UnorderedListItem>
<UnorderedListItem>Вариант <Strong>№14 "Медицинский пациeнт"</Strong></UnorderedListItem>
<UnorderedListItem>Выполнена <Strong>Степановым Дмитрием 6511</Strong> </UnorderedListItem>
<UnorderedListItem><Link To="https://github.com/negniy/cloud-development.git">Ссылка на форк</Link></UnorderedListItem>
</UnorderedList>
</CardBody>
</Card>
12 changes: 6 additions & 6 deletions Client.Wasm/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,30 @@
"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",
"applicationUrl": "http://localhost:5128",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"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",
"applicationUrl": "https://localhost:7283;http://localhost:5128",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchBrowser": false,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
}
4 changes: 2 additions & 2 deletions Client.Wasm/wwwroot/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
}
},
"AllowedHosts": "*",
"BaseAddress": ""
}
"BaseAddress": "http://localhost:5171/patient"
}
20 changes: 19 additions & 1 deletion CloudDevelopment.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ 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}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client.Wasm", "Client.Wasm\Client.Wasm.csproj", "{AE7EEA74-2FE0-136F-D797-854FD87E022A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PatientApp.Generator", "GeneratorService\PatientApp.Generator.csproj", "{DB627DDE-E411-4B5B-9FE3-15F9A8EC1491}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PatientApp.AppHost", "Patient\Patient.AppHost\PatientApp.AppHost.csproj", "{03605D0F-0E69-461D-9417-32DD06B53E23}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PatientApp.ServiceDefaults", "Patient\Patient.ServiceDefaults\PatientApp.ServiceDefaults.csproj", "{DA24CCA7-7B4A-871C-985C-DBE0FA1F7524}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -15,6 +21,18 @@ Global
{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
{DB627DDE-E411-4B5B-9FE3-15F9A8EC1491}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DB627DDE-E411-4B5B-9FE3-15F9A8EC1491}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB627DDE-E411-4B5B-9FE3-15F9A8EC1491}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DB627DDE-E411-4B5B-9FE3-15F9A8EC1491}.Release|Any CPU.Build.0 = Release|Any CPU
{03605D0F-0E69-461D-9417-32DD06B53E23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{03605D0F-0E69-461D-9417-32DD06B53E23}.Debug|Any CPU.Build.0 = Debug|Any CPU
{03605D0F-0E69-461D-9417-32DD06B53E23}.Release|Any CPU.ActiveCfg = Release|Any CPU
{03605D0F-0E69-461D-9417-32DD06B53E23}.Release|Any CPU.Build.0 = Release|Any CPU
{DA24CCA7-7B4A-871C-985C-DBE0FA1F7524}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DA24CCA7-7B4A-871C-985C-DBE0FA1F7524}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA24CCA7-7B4A-871C-985C-DBE0FA1F7524}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DA24CCA7-7B4A-871C-985C-DBE0FA1F7524}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
6 changes: 6 additions & 0 deletions GeneratorService/GeneratorService.http
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Этот файл не нужен

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@GeneratorService_HostAddress = http://localhost:5104

GET {{GeneratorService_HostAddress}}/weatherforecast/
Accept: application/json

###
21 changes: 21 additions & 0 deletions GeneratorService/Models/Patient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace PatientApp.Generator.Models;

public class Patient
{
public int Id { get; set; }
public string FullName { get; set; }
public DateOnly Birthday { get; set; }
public string Address { get; set; }

public double Height { get; set; }
public double Weight { get; set; }

public int BloodType { get; set; }

public bool Resus { get; set; }

public DateOnly LastVisit { get; set; }

public bool Vactination { get; set; }
Comment on lines +5 to +19
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нужно добавить summary

А также сделать свойства либо nullable, либо required, а то сейчас все свойства строки подсвечиваются с:

Non-nullable property '...' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.


}
22 changes: 22 additions & 0 deletions GeneratorService/PatientApp.Generator.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<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="13.1.2" />
<PackageReference Include="Bogus" Version="35.6.5" />
<PackageReference Include="Serilog" Version="4.3.2-dev-02419" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="StackExchange.Redis" Version="2.12.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>

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

</Project>
58 changes: 58 additions & 0 deletions GeneratorService/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using PatientApp.Generator.Services;
using PatientApp.ServiceDefaults;
using Serilog;

var builder = WebApplication.CreateBuilder(args);

builder.AddServiceDefaults();

builder.AddRedisDistributedCache("redis");

builder.Services.AddSingleton<PatientGenerator>();
builder.Services.AddScoped<PatientService>();

builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
Comment on lines +14 to +22
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нужно настроить cors так, чтобы делать запрос мог только клиент

Для этого лучше задать явный список origins в appsettings.json


var app = builder.Build();

app.UseCors();
app.UseSerilogRequestLogging();

app.MapDefaultEndpoints();

app.MapGet("/patient", async (
int id,
PatientService service,
ILogger<Program> logger,
CancellationToken cancellationToken) =>
{
logger.LogInformation($"Received request for patient with ID: {id}");

if (id <= 0)
{
logger.LogWarning($"Received invalid ID: {id}");
return Results.BadRequest(new { error = "ID must be a positive number" });
}

try
{
var application = await service.GetByIdAsync(id, cancellationToken);
return Results.Ok(application);
}
catch (Exception ex)
{
logger.LogError(ex, $"Error while getting patient {id}");
return Results.Problem("An error occurred while processing the request");
}
})
.WithName("GetPatient");

app.Run();
23 changes: 23 additions & 0 deletions GeneratorService/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5171",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7171;http://localhost:5171",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
37 changes: 37 additions & 0 deletions GeneratorService/Services/Generator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Bogus;
using Bogus.DataSets;
using static System.Math;
using PatientApp.Generator.Models;

namespace PatientApp.Generator.Services;

public class PatientGenerator(ILogger<PatientGenerator> logger)
{
private readonly Faker<Patient> _faker = new Faker<Patient>("ru")
.RuleFor(x => x.FullName, GeneratePatientFullName)
.RuleFor(x => x.Birthday, f => f.Date.PastDateOnly())
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

По дефолту первый параметр у этого метода равен 1, то есть день рождения будет браться за последний год

.RuleFor(x => x.Address, f => f.Address.FullAddress())
.RuleFor(x => x.Weight, f => Round(f.Random.Double(5, 120), 2))
.RuleFor(x => x.Height, f => Round(f.Random.Double(50, 200), 2))
Comment on lines +14 to +15
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Что вероятно неправильно, потому что в 1 год быть 120кг 200см тяжело

Но и 5кг и 50см тоже кстати тяжело, если там 1 месяц например
Нужно либо еще ограничить минимальную дату рождения, либо сделать вес и рост зависимыми от возраста

.RuleFor(x => x.BloodType, f => f.Random.Int(1, 4))
.RuleFor(x => x.Resus, f => f.Random.Bool())
.RuleFor(x => x.Vactination, f => f.Random.Bool())
.RuleFor(x => x.LastVisit, (f, patient) => f.Date.BetweenDateOnly(patient.Birthday, DateOnly.FromDateTime(DateTime.UtcNow))
);

public Patient Generate(int id)
{
logger.LogInformation($"Generating Patient with ID: {id}");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Во всех операциях логирования убрать интерполяцию строк, нужно вот так:

logger.LogInformation("Generating Patient with ID: {id}", id);

return _faker.UseSeed(id).RuleFor(x => x.Id, _ => id).Generate();
}

private static string GeneratePatientFullName(Faker faker)
{
var gender = faker.Person.Gender;
var firstName = faker.Name.FirstName(gender);
var lastName = faker.Name.LastName(gender);
var patronymic = faker.Name.FirstName(Name.Gender.Male) + (gender == Name.Gender.Male ? "еевич" : "еевна");

return string.Join(' ', firstName, lastName, patronymic);
}
}
47 changes: 47 additions & 0 deletions GeneratorService/Services/PatientService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Microsoft.Extensions.Caching.Distributed;
using System.Text.Json;
using PatientApp.Generator.Services;
using PatientApp.Generator.Models;

public class PatientService(
PatientGenerator generator,
IDistributedCache cache,
ILogger<PatientService> logger,
IConfiguration config
)
{
private readonly TimeSpan _cacheExpiration = TimeSpan.FromMinutes(config.GetSection("CacheSetting").GetValue("CacheExpirationMinutes", 5));
private const string CacheKeyPrefix = "patient:";

public async Task<Patient> GetByIdAsync(int id, CancellationToken cancellationToken = default)
{
var cacheKey = $"{CacheKeyPrefix}{id}";

logger.LogInformation($"Patient with Id: {id} was requested");

var cachedData = await cache.GetStringAsync(cacheKey, cancellationToken);

if (!string.IsNullOrEmpty(cachedData))
{
logger.LogInformation($"Patient with {id} was found in cache");
var cachedPatient = JsonSerializer.Deserialize<Patient>(cachedData);
if (cachedPatient != null) return cachedPatient;
}

logger.LogInformation($"Patient with {id} was found in cache, start generating");

var patient = generator.Generate(id);

var serializedData = JsonSerializer.Serialize(patient);
var cacheOptions = new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = _cacheExpiration
};

await cache.SetStringAsync(cacheKey, serializedData, cacheOptions, cancellationToken);

logger.LogInformation($"Patint with Id: {id} was saved to cache with TTL {_cacheExpiration.TotalMinutes} minutes");

return patient;
}
}
8 changes: 8 additions & 0 deletions GeneratorService/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 GeneratorService/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
13 changes: 13 additions & 0 deletions Patient/Patient.AppHost/AppHost.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var builder = DistributedApplication.CreateBuilder(args);

var redis = builder.AddRedis("redis")
.WithRedisCommander();

var generator = builder.AddProject<Projects.PatientApp_Generator>("generator")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Генератору стоит подождать редис

.WithReference(redis)
.WithExternalHttpEndpoints();

builder.AddProject<Projects.Client_Wasm>("client")
.WithReference(generator);
Comment on lines +10 to +11
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А клиенту подождать генератор


builder.Build().Run();
25 changes: 25 additions & 0 deletions Patient/Patient.AppHost/PatientApp.AppHost.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">

<Sdk Name="Aspire.AppHost.Sdk" Version="9.5.2" />

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>9850a275-b1ed-4763-b4e3-9c0fbc45d25f</UserSecretsId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Aspire.Hosting" Version="9.5.2" />
<PackageReference Include="Aspire.Hosting.AppHost" Version="9.5.2" />
<PackageReference Include="Aspire.Hosting.Redis" Version="9.5.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Client.Wasm\Client.Wasm.csproj" />
<ProjectReference Include="..\..\GeneratorService\PatientApp.Generator.csproj" />
<ProjectReference Include="..\Patient.ServiceDefaults\PatientApp.ServiceDefaults.csproj" />
</ItemGroup>

</Project>
Loading
Loading