-
Notifications
You must be signed in to change notification settings - Fork 52
Ненашев Дмитрий 6513 Лаб. 1 #132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,5 +6,5 @@ | |
| } | ||
| }, | ||
| "AllowedHosts": "*", | ||
| "BaseAddress": "" | ||
| "BaseAddress": "https://localhost:7297/employee" | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFramework>net10.0</TargetFramework> | ||
| <Nullable>enable</Nullable> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="Aspire.StackExchange.Redis.DistributedCaching" Version="13.2.4" /> | ||
| <PackageReference Include="Bogus" Version="35.6.5" /> | ||
| <PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\Cloud.ServiceDefaults\Cloud.ServiceDefaults.csproj" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| using Cloud.API.Services; | ||
| using Cloud.API.Models; | ||
| using Microsoft.AspNetCore.Mvc; | ||
|
|
||
| namespace Cloud.API.Controllers; | ||
|
|
||
| /// <summary> | ||
| /// Контроллер для получения сотрудника компании по id | ||
| /// </summary> | ||
| /// <param name="employeeService">Сервис получения сотрудника компании</param> | ||
| /// <param name="logger">Логгер</param> | ||
| [ApiController] | ||
| [Route("employee")] | ||
| public class EmployeesController( | ||
| IEmployeeService employeeService, | ||
| ILogger<EmployeesController> logger | ||
| ) : ControllerBase | ||
| { | ||
| /// <summary> | ||
| /// Метод для получения сотрудника компании по id | ||
| /// </summary> | ||
| /// <param name="id">Идентификатор сотрудника</param> | ||
| /// <returns>Информация о сотруднике компании</returns> | ||
| /// <response code="200">Успешное получение сотрудника компании</response> | ||
| /// <response code="400">Некорректный id сотрудника</response> | ||
| [ProducesResponseType(typeof(Employee), StatusCodes.Status200OK)] | ||
| [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)] | ||
| [HttpGet] | ||
| public async Task<ActionResult<Employee>> GetEmployee([FromQuery] int id) | ||
| { | ||
| if (id <= 0) | ||
| return BadRequest(new { error = "Id must be a positive number" }); | ||
|
|
||
| logger.LogInformation("HTTP GET /employee, id: {employeeId}", id); | ||
|
|
||
| var employee = await employeeService.GetOrGenerateAsync(id); | ||
| return Ok(employee); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| namespace Cloud.API.Models; | ||
|
|
||
| /// <summary> | ||
| /// Информация о сотруднике компании | ||
| /// </summary> | ||
| public class Employee | ||
| { | ||
| /// <summary> | ||
| /// Идентификатор сотрудника в системе | ||
| /// </summary> | ||
| public required int Id { get; set; } | ||
| /// <summary> | ||
| /// ФИО | ||
| /// </summary> | ||
| public required string FullName { get; set; } | ||
| /// <summary> | ||
| /// Должность | ||
| /// </summary> | ||
| public required string Position { get; set; } | ||
| /// <summary> | ||
| /// Отдел | ||
| /// </summary> | ||
| public required string Department { get; set; } | ||
| /// <summary> | ||
| /// Дата приема | ||
| /// </summary> | ||
| public DateOnly HireDate { get; set; } | ||
| /// <summary> | ||
| /// Зарплата | ||
| /// </summary> | ||
| public required decimal Salary { get; set; } | ||
| /// <summary> | ||
| /// Электронная почта | ||
| /// </summary> | ||
| public required string Email { get; set; } | ||
| /// <summary> | ||
| /// Номер телефона | ||
| /// </summary> | ||
| public required string PhoneNumber { get; set; } | ||
| /// <summary> | ||
| /// Индикатор увольнения | ||
| /// </summary> | ||
| public required bool IsFired { get; set; } | ||
| /// <summary> | ||
| /// Дата увольнения | ||
| /// </summary> | ||
| public DateOnly? FiredDate { get; set; } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| using Cloud.Api.Services; | ||
| using Cloud.API.Services; | ||
|
|
||
| var builder = WebApplication.CreateBuilder(args); | ||
|
|
||
| builder.AddServiceDefaults(); | ||
| builder.AddRedisDistributedCache("redis"); | ||
|
|
||
| builder.Services.AddControllers(); | ||
| builder.Services.AddEndpointsApiExplorer(); | ||
| builder.Services.AddSwaggerGen(); | ||
|
|
||
| builder.Services.AddSingleton<IEmployeeGenerator, EmployeeGenerator>(); | ||
| builder.Services.AddScoped<IEmployeeService, EmployeeService>(); | ||
|
|
||
| builder.Services.AddCors(options => | ||
| { | ||
| options.AddPolicy("LocalPolicy", policy => | ||
| { | ||
| policy | ||
| .SetIsOriginAllowed(origin => origin.StartsWith("https://localhost")) | ||
| .WithHeaders("Content-Type") | ||
| .WithMethods("GET"); | ||
| }); | ||
| }); | ||
|
|
||
| var app = builder.Build(); | ||
|
|
||
| app.MapDefaultEndpoints(); | ||
|
|
||
| if (app.Environment.IsDevelopment()) | ||
| { | ||
| app.UseSwagger(); | ||
| app.UseSwaggerUI(); | ||
| } | ||
|
|
||
| app.UseHttpsRedirection(); | ||
| app.UseCors("LocalPolicy"); | ||
| app.MapControllers(); | ||
|
|
||
| app.Run(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| { | ||
| "$schema": "http://json.schemastore.org/launchsettings.json", | ||
| "iisSettings": { | ||
| "windowsAuthentication": false, | ||
| "anonymousAuthentication": true, | ||
| "iisExpress": { | ||
| "applicationUrl": "http://localhost:13373", | ||
| "sslPort": 44310 | ||
| } | ||
| }, | ||
| "profiles": { | ||
| "http": { | ||
| "commandName": "Project", | ||
| "dotnetRunMessages": true, | ||
| "launchBrowser": true, | ||
| "launchUrl": "swagger", | ||
| "applicationUrl": "http://localhost:5291", | ||
| "environmentVariables": { | ||
| "ASPNETCORE_ENVIRONMENT": "Development" | ||
| } | ||
| }, | ||
| "https": { | ||
| "commandName": "Project", | ||
| "dotnetRunMessages": true, | ||
| "launchBrowser": true, | ||
| "launchUrl": "swagger", | ||
| "applicationUrl": "https://localhost:7297;http://localhost:5291", | ||
| "environmentVariables": { | ||
| "ASPNETCORE_ENVIRONMENT": "Development" | ||
| } | ||
| }, | ||
| "IIS Express": { | ||
| "commandName": "IISExpress", | ||
| "launchBrowser": true, | ||
| "launchUrl": "swagger", | ||
| "environmentVariables": { | ||
| "ASPNETCORE_ENVIRONMENT": "Development" | ||
| } | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| using Bogus; | ||
| using Bogus.DataSets; | ||
| using Cloud.API.Models; | ||
| using Cloud.API.Services; | ||
|
|
||
| namespace Cloud.Api.Services; | ||
|
|
||
| /// <summary> | ||
| /// Генератор сотрудника по заданному id | ||
| /// </summary> | ||
| /// <param name="logger">Логгер</param> | ||
| public class EmployeeGenerator( | ||
| ILogger<EmployeeGenerator> logger | ||
| ) : IEmployeeGenerator | ||
| { | ||
| private static readonly string[] _professions = { "Developer", "Manager", "Analyst", "Designer", "QA" }; | ||
|
|
||
| private static readonly Dictionary<string, decimal> _baseSalaryBySuffix = new() | ||
| { | ||
| ["Junior"] = 50000, | ||
| ["Middle"] = 100000, | ||
| ["Senior"] = 150000, | ||
| ["Lead"] = 200000 | ||
| }; | ||
|
|
||
| private readonly Faker<Employee> _faker = new Faker<Employee>("ru") | ||
| .RuleFor(e => e.Id, _ => 0) | ||
| .RuleFor(e => e.FullName, f => | ||
| { | ||
| var gender = f.PickRandom<Name.Gender>(); | ||
| return $"{f.Name.LastName(gender)} {f.Name.FirstName(gender)} " + | ||
| $"{f.Name.FirstName(Name.Gender.Male)}{(gender == Name.Gender.Male ? "ович" : "овна")}"; | ||
|
|
||
| }) | ||
| .RuleFor(e => e.Position, f => $"{f.PickRandom(_baseSalaryBySuffix.Keys.ToArray())} {f.PickRandom(_professions)}") | ||
| .RuleFor(e => e.Department, f => f.Commerce.Department()) | ||
| .RuleFor(e => e.HireDate, f => DateOnly.FromDateTime(f.Date.Past(10))) | ||
| .RuleFor(e => e.Salary, (f, e) => | ||
| { | ||
| var suffix = e.Position.Split(' ')[0]; | ||
| var baseSalary = _baseSalaryBySuffix.GetValueOrDefault(suffix, 70000); | ||
| return Math.Round(baseSalary + f.Random.Decimal(-5000, 25000), 2); | ||
| }) | ||
| .RuleFor(e => e.Email, (f, e) => f.Internet.Email(e.FullName)) | ||
| .RuleFor(e => e.PhoneNumber, f => f.Phone.PhoneNumber("+7(###)###-##-##")) | ||
| .RuleFor(e => e.IsFired, f => f.Random.Bool(0.2f)) | ||
| .RuleFor(e => e.FiredDate, (f, e) => | ||
| e.IsFired ? DateOnly.FromDateTime(f.Date.Between(e.HireDate.ToDateTime(TimeOnly.MinValue), DateTime.Now)) : null); | ||
|
|
||
| /// <inheritdoc /> | ||
| public Employee Generate(int id) | ||
| { | ||
| var employee = _faker.Generate(); | ||
| employee.Id = id; | ||
| logger.LogInformation("Generated employee with id {employeeId}", id); | ||
| return employee; | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| using Cloud.API.Models; | ||
| using Cloud.API.Services; | ||
| using Microsoft.Extensions.Caching.Distributed; | ||
| using System.Text.Json; | ||
|
|
||
| namespace Cloud.Api.Services; | ||
|
|
||
| /// <summary> | ||
| /// Сервис для получения сотрудника компании по id с кэшированием | ||
| /// </summary> | ||
| /// <param name="generator">Генератор сотрудника</param> | ||
| /// <param name="cache">Сервис кэширования</param> | ||
| /// <param name="configuration">Конфигурация приложения</param> | ||
| /// <param name="logger">Логгер</param> | ||
| public class EmployeeService( | ||
| IEmployeeGenerator generator, | ||
| IDistributedCache cache, | ||
| IConfiguration configuration, | ||
| ILogger<EmployeeService> logger) : IEmployeeService | ||
| { | ||
| private readonly string _cacheKeyPrefix = configuration.GetValue("CacheKeyPrefix", "employee"); | ||
| private readonly TimeSpan _cacheTtl = TimeSpan.FromMinutes(configuration.GetValue("CacheTtlMinutes", 30)); | ||
|
|
||
| /// <inheritdoc /> | ||
| public async Task<Employee> GetOrGenerateAsync(int id) | ||
| { | ||
| var cacheKey = $"{_cacheKeyPrefix}:{id}"; | ||
|
|
||
| var cached = await GetFromCache(cacheKey); | ||
| if (cached is not null) | ||
| { | ||
| return cached; | ||
| } | ||
|
|
||
| logger.LogInformation("Cache miss for employee {Id}, generating new data", id); | ||
| var employee = generator.Generate(id); | ||
| await SetToCache(cacheKey, employee); | ||
| return employee; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Метод получения сотрудника из кэша | ||
| /// </summary> | ||
| /// <param name="cacheKey">Ключ кэша</param> | ||
| /// <returns> | ||
| /// Сотрудник, или null в случае ошибки или отсутствия данных в кэше | ||
| /// </returns> | ||
| private async Task<Employee?> GetFromCache(string cacheKey) | ||
| { | ||
| try | ||
| { | ||
| var cached = await cache.GetStringAsync(cacheKey); | ||
| if (cached is null) return null; | ||
|
|
||
| logger.LogInformation("Cache hit for key {CacheKey}", cacheKey); | ||
| return JsonSerializer.Deserialize<Employee>(cached); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| logger.LogWarning(ex, "Failed to read from cache for key {CacheKey}", cacheKey); | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Сохранение сотрудника в кэш с обработкой ошибок при записи | ||
| /// </summary> | ||
| /// <param name="cacheKey">Ключ кэша</param> | ||
| /// <param name="employee">Сотрудник компании</param> | ||
| private async Task SetToCache(string cacheKey, Employee employee) | ||
| { | ||
| try | ||
| { | ||
| var json = JsonSerializer.Serialize(employee); | ||
| await cache.SetStringAsync(cacheKey, json, new DistributedCacheEntryOptions | ||
| { | ||
| AbsoluteExpirationRelativeToNow = _cacheTtl | ||
| }); | ||
| logger.LogInformation("Cached employee {Id} with key {CacheKey}", employee.Id, cacheKey); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| logger.LogWarning(ex, "Failed to write to cache for key {CacheKey}", cacheKey); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| using Cloud.API.Models; | ||
|
|
||
| namespace Cloud.API.Services; | ||
|
|
||
| /// <summary> | ||
| /// Интерфейс генератора сотрудника компании по id | ||
| /// </summary> | ||
| public interface IEmployeeGenerator | ||
| { | ||
| /// <summary> | ||
| /// Генерирует сотрудника компании с указанным id | ||
| /// </summary> | ||
| /// <param name="id">Идентификатор сотрудника компании</param> | ||
| public Employee Generate(int id); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.