namespace Dpz.Core.Service.RepositoryServiceImpl;
public class BlockService(
IRepository<Block> repository,
IHybridCachingProvider hybridCachingProvider,
IMapper mapper
) : IBlockService
{
public async Task SaveBlockAsync(Block block)
{
var entity = await repository
.SearchFor(x =>
x.RequestMethod == block.RequestMethod && x.RequestPath == block.RequestPath
)
.FirstOrDefaultAsync();
if (entity != null)
{
var updates = new List<UpdateDefinition<Block>>
{
Builders<Block>.Update.Inc(x => x.AccessCount, 1),
};
var pushIpAddresses = (block.IpAddresses ?? []).Except(entity.IpAddresses).ToList();
if (pushIpAddresses.Count > 0)
{
updates.Add(Builders<Block>.Update.PushEach(x => x.IpAddresses, pushIpAddresses));
}
var pushUserAgents = (block.UserAgents ?? []).Except(entity.UserAgents).ToList();
if (pushUserAgents.Count > 0)
{
updates.Add(Builders<Block>.Update.PushEach(x => x.UserAgents, pushUserAgents));
}
await repository.UpdateAsync(
x => x.Id == entity.Id,
Builders<Block>.Update.Combine(updates)
);
return;
}
if (block.AccessCount <= 0)
{
block.AccessCount = 1;
}
await repository.InsertAsync(block);
}
public async Task IncrementCountAsync(string method, string requestPath)
{
var block = await repository
.SearchFor(x => x.RequestMethod == method && x.RequestPath == requestPath)
.FirstOrDefaultAsync();
if (block == null)
{
await SaveBlockAsync(new Block { RequestMethod = method, RequestPath = requestPath });
return;
}
var update = Builders<Block>.Update.Inc(x => x.AccessCount, 1);
await repository.UpdateAsync(x => x.Id == block.Id, update);
}
public async Task PushIpAddressAsync(
string method,
string requestPath,
params string[] ipAddresses
)
{
if (string.IsNullOrEmpty(method))
throw new ArgumentNullException(nameof(method));
if (string.IsNullOrEmpty(requestPath))
throw new ArgumentNullException(nameof(requestPath));
var block = await repository
.SearchFor(x => x.RequestMethod == method && x.RequestPath == requestPath)
.FirstOrDefaultAsync();
if (block == null)
{
await SaveBlockAsync(
new Block
{
RequestMethod = method,
RequestPath = requestPath,
IpAddresses = ipAddresses,
}
);
return;
}
var pushIpAddresses = ipAddresses.Except(block.IpAddresses).ToList();
if (pushIpAddresses.Count == 0)
return;
var update = Builders<Block>
.Update.PushEach(x => x.IpAddresses, pushIpAddresses)
.Inc(x => x.AccessCount, 1);
await repository.UpdateAsync(x => x.Id == block.Id, update);
}
public async Task PushUserAgentAsync(
string method,
string requestPath,
params string[] userAgents
)
{
if (string.IsNullOrEmpty(method))
throw new ArgumentNullException(nameof(method));
if (string.IsNullOrEmpty(requestPath))
throw new ArgumentNullException(nameof(requestPath));
var block = await repository
.SearchFor(x => x.RequestMethod == method && x.RequestPath == requestPath)
.FirstOrDefaultAsync();
if (block == null)
{
await SaveBlockAsync(
new Block
{
RequestMethod = method,
RequestPath = requestPath,
UserAgents = userAgents,
}
);
return;
}
var pushUserAgents = userAgents.Except(block.UserAgents).ToList();
if (pushUserAgents.Count == 0)
return;
var update = Builders<Block>
.Update.PushEach(x => x.UserAgents, pushUserAgents)
.Inc(x => x.AccessCount, 1);
await repository.UpdateAsync(x => x.Id == block.Id, update);
}
public async Task<List<VmBlock>> GetBlocksAsync(int? minAccess = null)
{
var key = $"Block:List:{(minAccess is null or <= 0 ? "All" : minAccess)}";
var cache = await hybridCachingProvider.GetAsync<List<VmBlock>>(key);
if (!cache.IsNull && cache.HasValue)
return cache.Value;
var minAccessValue = minAccess ?? 0;
var list = await repository.SearchFor(x => x.AccessCount >= minAccessValue).ToListAsync();
var source = mapper.Map<List<VmBlock>>(list);
await hybridCachingProvider.SetAsync(key, source, TimeSpan.FromHours(3));
return source;
}
}