public void GivenHttpIdempotencySerializerShouldDeserializeIdempotencyRegister() { var expectedRegister = HttpIdempotencyRegister.Of("key", HttpStatusCode.OK, new MemoryStream(Encoding.UTF8.GetBytes("body"))); var serializedObject = _serializer.Serialize(expectedRegister); var register = _serializer.Deserialize <HttpIdempotencyRegister>(serializedObject); register.Key.Should().Be(expectedRegister.Key); register.IsCompleted.Should().Be(expectedRegister.IsCompleted); register.StatusCode.Should().Be(HttpStatusCode.OK); register.Value.Should().Be(expectedRegister.Value); }
public async Task <TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate <TResponse> next) { var idempotencyKey = _keyReader?.Read(request); if (string.IsNullOrWhiteSpace(idempotencyKey)) { return(await next()); } TResponse response; _logger?.WriteInformation(idempotencyKey, "Idempotency: Key detected."); if (await _repository.TryAddAsync(idempotencyKey)) { _logger?.WriteRequest(idempotencyKey, "Idempotency: First request.", request); try { response = await next(); } catch (Exception ex) { await _repository.RemoveAsync(idempotencyKey); _logger?.WriteException(idempotencyKey, ex); throw; } if (response is IResult result && result.Failure) { await _repository.RemoveAsync(idempotencyKey); _logger?.WriteInformation(idempotencyKey, "Idempotency: First request failed."); return(response); } var updatedRegister = IdempotencyRegister.Of(idempotencyKey, _idempotencySerializer.Serialize(response)); await _repository.UpdateAsync(idempotencyKey, updatedRegister); _logger?.WriteInformation(idempotencyKey, "Idempotency: First request completed."); return(response); } var register = await _repository.GetAsync <IdempotencyRegister>(idempotencyKey); if (!register.IsCompleted) { _logger?.WriteResponse(idempotencyKey, "Idempotency: Conflict detected.", default); throw new ConflictDetectedException(idempotencyKey); } response = _idempotencySerializer.Deserialize <TResponse>(register.Value); _logger?.WriteResponse(idempotencyKey, "Idempotency: Conflict detected.", response); return(response); }
public async Task <bool> TryAddAsync(string key) { if (await _database.KeyExistsAsync((RedisKey)key)) { return(false); } using (var factory = RedLockFactory.Create(new[] { new RedLockMultiplexer(_database.Multiplexer) })) using (var redLock = factory.CreateLock(key, TimeSpan.FromMinutes(1))) { if (!redLock.IsAcquired || await _database.KeyExistsAsync((RedisKey)key)) { return(false); } var value = _serializer.Serialize(IdempotencyRegister.Of(key)); return(await _database.StringSetAsync(key, value, TimeSpan.FromMinutes(1), When.NotExists)); } }