using IM_API.Interface.Services; using IM_API.Models; using IM_API.Tools; using Microsoft.EntityFrameworkCore; using RedLockNet; using StackExchange.Redis; namespace IM_API.Services { public class SequenceIdService : ISequenceIdService { private IDatabase _database; private IDistributedLockFactory _lockFactory; private ImContext _context; public SequenceIdService(IConnectionMultiplexer connectionMultiplexer, IDistributedLockFactory distributedLockFactory, ImContext imContext) { _database = connectionMultiplexer.GetDatabase(); _lockFactory = distributedLockFactory; _context = imContext; } public async Task GetNextSquenceIdAsync(string streamKey) { string key = RedisKeys.GetSequenceIdKey(streamKey); string lockKey = RedisKeys.GetSequenceIdLockKey(streamKey); var exists = await _database.KeyExistsAsync(key); if (!exists) { using (var _lock = await _lockFactory.CreateLockAsync(lockKey, TimeSpan.FromSeconds(5))) { if (_lock.IsAcquired) { if(!await _database.KeyExistsAsync(key)) { var max = await _context.Messages .Where(x => x.StreamKey == streamKey) .MaxAsync(m => (long?)m.SequenceId) ?? 0; await _database.StringSetAsync(key, max, TimeSpan.FromDays(7)); } } } } return await _database.StringIncrementAsync(key); } } }