怪物奇妙物语

宇宙无敌超级美少男的怪物奇妙物语

首页 新随笔 联系 管理

dotnet_miniapi_quartz_ipaddress_check/Dtos.cs

using System.ComponentModel.DataAnnotations;
namespace GameStore.Api.Dtos;

public record IpAddressDto(
            Guid id,
            string ip,
            string name,
            string domain,
            string mac,
            string location,
            string cpe,
            bool? enable,
            bool? status,
            int? roundtripTime,
            int? ttl,
            string? url);



public record CreateIpaddressDto(
    [Required][StringLength(20)] string Ip,
    [Required][StringLength(20)] string Name,
    [Required][StringLength(20)] string Domain,
    [Required][StringLength(20)] string Mac,
    [Required][StringLength(20)] string Location,
    [Required][StringLength(20)] string Cpe,
    [Required] bool Enable);




public record UpdateIpaddressDto(
                            [Required][StringLength(20)] string Ip,
                            [Required][StringLength(20)] string Name,
                            [Required][StringLength(20)] string Domain,
                            [Required][StringLength(20)] string Mac,
                            [Required][StringLength(20)] string Location,
                            [Required][StringLength(20)] string Cpe,
                            [Required] bool Enable);






dotnet_miniapi_quartz_ipaddress_check/appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Trace",
      "Microsoft": "Warning",
      "Microsoft.AspNetCore": "Trace"
    },
    "Debug": {
      "LogLevel": {
        "Default": "Information",
        "Microsoft.Hosting": "Trace"
      }
    },
    "EventSource": {
      "LogLevel": {
        "Default": "Warning"
      }
    }
  },
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://0.0.0.0:8889"
      }
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=./Dbs/Games.db"
  },
  "Quartz": {

    "BatteryJob": {
      "Schedule": "0/5 * * * * ?"
    },

    "NetworkJob": {
      "Schedule": "0/30 * * * * ?"
    }
  }
}

dotnet_miniapi_quartz_ipaddress_check/global.json

{
  "sdk": {
    "version": "7.0.306"
  }
}

dotnet_miniapi_quartz_ipaddress_check/appsettings.Development.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  }
}


dotnet_miniapi_quartz_ipaddress_check/Program.cs

using GameStore.Api.Data;
using GameStore.Api.Endpoints;
using GameStore.Api.Repositoriesa;
using Job;
using NLog;
using NLog.Web;
using Quartz;

var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
var builder = WebApplication.CreateBuilder(args);

// config nlog
builder.Logging.ClearProviders();
builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
builder.Host.UseNLog();
// database
builder.Services.AddScoped<IIpAddressRepository, EntityFrameworkStatusRepository>();
builder.Services.AddRepositories(builder.Configuration);
// register swagger ui service
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// Add the required Quartz.NET services
builder.Services.AddQuartz(q =>
{
    q.AddJobAndTrigger<NetworkJob>(builder.Configuration);
});

// Add the Quartz.NET hosted service,When shutdown is requested, this setting ensures that Quartz.NET waits for the jobs to end gracefully before exiting.
builder.Services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);


// 配置cors请求
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowAll", builder =>
    {
        builder.AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader();
    });
});

var app = builder.Build();

// 配置cors请求
app.UseCors("AllowAll");

if (true)
{
    app.UseSwagger();
    app.UseSwaggerUI();
}


app.UseCors();
app.MapGet("/", (ILogger<Program> logger) =>
{
    return "hello world";
});

app.MapIpAddressEndpoints();
app.Run();




dotnet_miniapi_quartz_ipaddress_check/Endpoints/IpAddressEndpoints.cs

using GameStore.Api.Dtos;
using GameStore.Api.Entities;
using GameStore.Api.Repositoriesa;
using SQLitePCL;

namespace GameStore.Api.Endpoints;

public static class IpAddressEndpoints
{
    const string GetIpAddressEndpointName = "GetIpAddress";
    public static RouteGroupBuilder MapIpAddressEndpoints(this IEndpointRouteBuilder endpoints)
    {
        var group = endpoints.MapGroup("/ipaddress").WithParameterValidation();

        group.MapGet("/", async (IIpAddressRepository repository, IHttpContextAccessor httpContextAccessor) =>
        {

            var ipAddressArray = await repository.GetAllAsync();
            var totalCount = ipAddressArray.Count();
            var enableCount = ipAddressArray.Where(ip => ip.Enable == true).Count();
            var onlineCount = ipAddressArray.Where(ip => ip.Enable == true && ip.Status == true).Count();

            // Get the complete request path using HttpContext.Request.Path
            var host = httpContextAccessor.HttpContext?.Request.Host;
            var path = httpContextAccessor.HttpContext?.Request.Path;
            var url = $"http://{host}{path}";
            // 创建匿名类型包含三个属性
            var result = new
            {
                TotalCount = totalCount,
                EnableCount = enableCount,
                DisableCount = totalCount - enableCount,
                OnlineCount = onlineCount,
                OfflineCount = enableCount - onlineCount,
                IpAddressArray = ipAddressArray.Select(ipAddress => ipAddress.AsDto(url))
            };
            return result;
        });

        group.MapGet("/{id}", async (IIpAddressRepository repository, ILogger<Program> logger, Guid id,IHttpContextAccessor httpContextAccessor) =>
        {
            IpAddress? ipAddress = await repository.GetAsync(id);
            if (ipAddress is null)
            {
                return Results.NotFound();
            }
            // Get the complete request path using HttpContext.Request.Path
            var host = httpContextAccessor.HttpContext?.Request.Host;
            var path = httpContextAccessor.HttpContext?.Request.Path;
            var url = $"http://{host}{path}";
            return Results.Ok(ipAddress.AsDto(url));
        }).WithName(GetIpAddressEndpointName);

        group.MapPost("/", async (IIpAddressRepository repository, CreateIpaddressDto ipAddressDto) =>
        {
            IpAddress ipAddress = new()
            {
                Ip = ipAddressDto.Ip,
                Name = ipAddressDto.Name,
                Mac = ipAddressDto.Mac,
                Location = ipAddressDto.Location,
                Cpe = ipAddressDto.Cpe,
                Domain = ipAddressDto.Domain,
                Enable = ipAddressDto.Enable
            };
            await repository.CreateAsync(ipAddress);
            return Results.CreatedAtRoute(GetIpAddressEndpointName, new { id = ipAddress.Id }, ipAddress);
        });

        group.MapPut("/{id}", async (IIpAddressRepository repository, Guid id, UpdateIpaddressDto updatedIpAddressDto) =>
        {
            IpAddress? existingIp = await repository.GetAsync(id);
            if (existingIp is null)
            {
                return Results.NotFound();
            }

            existingIp.Ip = updatedIpAddressDto.Ip;
            existingIp.Name = updatedIpAddressDto.Name;
            existingIp.Domain = updatedIpAddressDto.Domain;
            existingIp.Mac = updatedIpAddressDto.Mac;
            existingIp.Location = updatedIpAddressDto.Location;
            existingIp.Cpe = updatedIpAddressDto.Cpe;
            existingIp.Enable = updatedIpAddressDto.Enable;

            await repository.UpdateAsync(existingIp);

            return Results.NoContent();
        });

        group.MapDelete("/{id}", async (IIpAddressRepository repository, Guid id) =>
        {
            IpAddress? ipAddress = await repository.GetAsync(id);
            if (ipAddress is not null)
            {
                await repository.DeleteAsync(id);
            }
            return Results.NoContent();
        });

        return group;
    }

}








dotnet_miniapi_quartz_ipaddress_check/Repositories/IPingRecordsRepository.cs


using GameStore.Api.Entities;

namespace GameStore.Api.Repositoriesa;


public interface IPingRecordsRepository
{

    Task<IEnumerable<IpAddress>> GetAllAsync();
    Task<IpAddress?> GetAsync(Guid id);
    Task CreateAsync(IpAddress ip);
    Task UpdateAsync(IpAddress updatedIpAddress);
    Task DeleteAsync(Guid id);
}



dotnet_miniapi_quartz_ipaddress_check/Repositories/EntityFrameworkIpAddressRepository.cs

using GameStore.Api.Data;
using GameStore.Api.Entities;
using Microsoft.EntityFrameworkCore;


namespace GameStore.Api.Repositoriesa;

public class EntityFrameworkStatusRepository : IIpAddressRepository
{
    private readonly StandardStoreContext dbContext;
    public EntityFrameworkStatusRepository(StandardStoreContext dbContext)
    {
        this.dbContext = dbContext;
    }

    public async Task CreateAsync(IpAddress ipAddress)
    {
        dbContext.IpAddresses.Add(ipAddress);
        await dbContext.SaveChangesAsync();
    }

    public async Task DeleteAsync(Guid id)
    {
        await dbContext.IpAddresses.Where(ipAddress => ipAddress.Id == id).ExecuteDeleteAsync();
    }

    public async Task<IpAddress?> GetAsync(Guid id)
    {

        return await dbContext.IpAddresses.FindAsync(id);
    }

    public async Task<IEnumerable<IpAddress>> GetAllAsync()
    {
        return await dbContext.IpAddresses.AsNoTracking().ToListAsync();
    }

    public async Task UpdateAsync(IpAddress updatedIpAddress)
    {
        dbContext.IpAddresses.Update(updatedIpAddress);
        await dbContext.SaveChangesAsync();
    }

}



dotnet_miniapi_quartz_ipaddress_check/Repositories/IIpAddressRepository.cs


using GameStore.Api.Entities;

namespace GameStore.Api.Repositoriesa;

public interface IIpAddressRepository
{

    Task<IEnumerable<IpAddress>> GetAllAsync();
    Task<IpAddress?> GetAsync(Guid id);
    Task CreateAsync(IpAddress ip);
    Task UpdateAsync(IpAddress updatedIpAddress);
    Task DeleteAsync(Guid id);
}



dotnet_miniapi_quartz_ipaddress_check/Jobs/NetworkJob.cs

using System.Net.NetworkInformation;
using System.Text;
using GameStore.Api.Data;
using GameStore.Api.Entities;
using Microsoft.EntityFrameworkCore;
using Quartz;

namespace Job;


[DisallowConcurrentExecution]
public class NetworkJob : IJob
{
    private readonly ILogger<NetworkJob> logger;
    private readonly StandardStoreContext dbContext;

    public NetworkJob(ILogger<NetworkJob> logger, StandardStoreContext dbContext)
    {
        this.dbContext = dbContext;
        this.logger = logger;
    }

    public async Task Execute(IJobExecutionContext context)
    {
        await DetectIpaddressJob();
    }
    private async Task DetectIpaddressJob()
    {
        return;
        await PingAll();
    }

    public async Task PingAll()
    {
        var ipAddresss = await dbContext.IpAddresses.Where(ipAddr => ipAddr.Enable == true).ToListAsync();
        foreach (var ipAddr in ipAddresss)
        {
            CheckIp(ipAddr);
            // 生成一个随机数,范围为 1 到 5 秒,延时指定的时间
            await Task.Delay(new Random().Next(1000, 15000));
        }

        await dbContext.SaveChangesAsync();
    }

    public void CheckIp(IpAddress ipAddr)
    {
        Ping pingSender = new Ping();
        byte[] buffer = Encoding.ASCII.GetBytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
        // 等待回复的时间为3秒。
        int timeout = 3000;
        // 设置传输选项: 数据在被销毁之前可以通过64个网关或路由器传输, 数据包不能被分片。
        PingOptions options = new PingOptions(64, true);
        PingReply reply = pingSender.Send(ipAddr.Ip, timeout, buffer, options);
        if (reply.Status == IPStatus.Success)
        {
            Console.WriteLine($"{DateTime.Now} : {ipAddr.Name} : {ipAddr.Ip} is online");
            ipAddr.Status = true;
            ipAddr.RoundtripTime = (int?)reply.RoundtripTime;
            ipAddr.Ttl = reply.Options?.Ttl;
        }
        else
        {
            Console.WriteLine($"{DateTime.Now} : {ipAddr.Name} : {ipAddr.Ip} is offline");
            ipAddr.Status = false;
        }
    }

}


dotnet_miniapi_quartz_ipaddress_check/Jobs/ServiceCollectionQuartzConfiguratorExtensions.cs

using Job;
using Quartz;


namespace Job;

/// <summary>
/// A base class for cron job options. 
/// </summary>
public class GenericCronJobOptions
{
    public string? Schedule { get; set; }
}


public static class ServiceCollectionQuartzConfiguratorExtensions
{
    public static void AddJobAndTrigger<T>(this IServiceCollectionQuartzConfigurator quartz, IConfiguration configuration) where T : IJob
    {

        // Use the name of the IJob as the appsettings.json key
        string jobName = typeof(T).Name;

        // Try and load the schedule from configuration
        var configKey = $"Quartz:{jobName}";
        var configurationSection = configuration.GetSection(configKey);
        var options = new GenericCronJobOptions();
        configurationSection.Bind(options);

        // Some minor validation
        if (string.IsNullOrEmpty(options.Schedule))
        {
            throw new Exception($"No Quartz.NET Cron schedule found for job in configuration at {configKey}");
        }

        // register the job 
        var jobKey = new JobKey(jobName);
        quartz.AddJob<T>(opts => opts.WithIdentity(jobKey));

        quartz.AddTrigger(opts => opts
            .ForJob(jobKey)
            .WithIdentity(jobName + "-trigger")
            .WithCronSchedule(options.Schedule)); // use the schedule from configuration

    }
}



dotnet_miniapi_quartz_ipaddress_check/Data/GameStoreContext.cs

using System.Reflection;
using GameStore.Api.Entities;
using Microsoft.EntityFrameworkCore;

namespace GameStore.Api.Data;
public class StandardStoreContext : DbContext
{
    public StandardStoreContext(DbContextOptions<StandardStoreContext> options) : base(options)
    {
    }

    public DbSet<IpAddress> IpAddresses => Set<IpAddress>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
    }

}




dotnet_miniapi_quartz_ipaddress_check/Data/DataExtensions.cs


using Microsoft.EntityFrameworkCore;

namespace GameStore.Api.Data;

public static class DataExtensions
{

    // 扩展 IServiceProvider接口的方法
    public static async Task InitalizeDb(this IServiceProvider provider)
    {
        using var scope = provider.CreateScope();
        var dbContext = scope.ServiceProvider.GetRequiredService<StandardStoreContext>();
        // dbContext.Database.Migrate();
        await dbContext.Database.MigrateAsync();
    }

    // 扩展IServiceCollection接口的方法
    public static IServiceCollection AddRepositories(this IServiceCollection services, IConfiguration configuration)
    {
        // config sqlite
        services.AddSqlite<StandardStoreContext>(configuration.GetConnectionString("DefaultConnection"));
        return services;
    }

}



dotnet_miniapi_quartz_ipaddress_check/Entities/IpAddress.cs

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace GameStore.Api.Entities;

public class IpAddress
{
    [Key]
    [Column("ID")]
    public Guid Id { get; set; } = new Guid();

    [Required]
    [Column("IP", TypeName = "varchar(20)")]
    public required string Ip { get; set; }

    [Column("NAME", TypeName = "varchar(20)")]
    public string? Name { get; set; }

    [Column("DOMAIN", TypeName = "varchar(20)")]
    public string? Domain { get; set; }


    [Column("MAC", TypeName = "varchar(20)")]
    public string? Mac { get; set; }

    [Column("LOCATION", TypeName = "varchar(20)")]
    public string? Location { get; set; }

    [Column("CPE", TypeName = "varchar(20)")]
    public string? Cpe { get; set; }


    [Column("ENABLE", TypeName = "boolean")]
    public bool? Enable { get; set; } = true;


    [Column("STATUS", TypeName = "boolean")]
    public bool? Status { get; set; }

    [Column("ROUNDTRIPTIME", TypeName = "NUMBER")]
    public int? RoundtripTime { get; set; }

    [Column("TTL", TypeName = "NUMBER")]
    public int? Ttl { get; set; }
}




dotnet_miniapi_quartz_ipaddress_check/Entities/EntityExtensions.cs

using GameStore.Api.Dtos;

namespace GameStore.Api.Entities;

public static class EntityExtensions
{

    public static IpAddressDto AsDto(this IpAddress ip,string url)
    {
        return new IpAddressDto(
            ip.Id,
            ip.Ip,
            ip.Name!,
            ip.Domain!,
            ip.Mac!,
            ip.Location!,
            ip.Cpe!,
            ip.Enable,
            ip.Status,
            ip.RoundtripTime,
            ip.Ttl,
            url
        );
    }

}

posted on 2024-02-27 18:46  超级无敌美少男战士  阅读(32)  评论(0编辑  收藏  举报