Search in sources :

Example 11 with DatabaseException

use of com.sanctionco.thunder.dao.DatabaseException in project thunder by RohanNagar.

the class DynamoDbUsersDao method update.

@Override
public CompletableFuture<User> update(@Nullable String existingEmail, User user) {
    Objects.requireNonNull(user);
    // Different email (primary key) means we need to delete and insert
    if (existingEmail != null && !existingEmail.equals(user.getEmail().getAddress())) {
        LOG.info("User to update has new email. The user will be deleted and then reinserted.");
        return updateEmail(existingEmail, user);
    }
    long now = Instant.now().toEpochMilli();
    // Get the old version
    GetItemRequest request = GetItemRequest.builder().tableName(tableName).key(Collections.singletonMap("email", AttributeValue.builder().s(user.getEmail().getAddress()).build())).build();
    return dynamoDbClient.getItem(request).thenApply(response -> {
        if (response.item().size() <= 0) {
            LOG.warn("The email {} was not found in the database.", user.getEmail().getAddress());
            throw new DatabaseException("User not found in the database.", DatabaseException.Error.USER_NOT_FOUND);
        }
        // Compute the new data
        String newVersion = UUID.randomUUID().toString();
        String document = UsersDao.toJson(mapper, user);
        // Build the new item
        Map<String, AttributeValue> newItem = new HashMap<>();
        // Fields that don't change
        newItem.put("email", response.item().get("email"));
        newItem.put("id", response.item().get("id"));
        newItem.put("creation_time", response.item().get("creation_time"));
        // Fields that do change
        newItem.put("version", AttributeValue.builder().s(newVersion).build());
        newItem.put("update_time", AttributeValue.builder().n(String.valueOf(now)).build());
        newItem.put("document", AttributeValue.builder().s(document).build());
        return PutItemRequest.builder().tableName(tableName).item(newItem).expected(Collections.singletonMap("version", ExpectedAttributeValue.builder().comparisonOperator(ComparisonOperator.EQ).value(response.item().get("version")).build())).returnValues(ReturnValue.ALL_OLD).build();
    }).thenCompose(dynamoDbClient::putItem).thenApply(response -> user.withTime(Long.parseLong(response.attributes().get("creation_time").n()), now)).exceptionally(throwable -> {
        throw convertToDatabaseException(throwable.getCause(), user.getEmail().getAddress());
    });
}
Also used : GetItemRequest(software.amazon.awssdk.services.dynamodb.model.GetItemRequest) LoggerFactory(org.slf4j.LoggerFactory) DynamoDbAsyncClient(software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient) SdkException(software.amazon.awssdk.core.exception.SdkException) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) ComparisonOperator(software.amazon.awssdk.services.dynamodb.model.ComparisonOperator) Map(java.util.Map) ExpectedAttributeValue(software.amazon.awssdk.services.dynamodb.model.ExpectedAttributeValue) ConditionalCheckFailedException(software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException) Nullable(javax.annotation.Nullable) AwsServiceException(software.amazon.awssdk.awscore.exception.AwsServiceException) Logger(org.slf4j.Logger) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) UUID(java.util.UUID) Instant(java.time.Instant) DatabaseException(com.sanctionco.thunder.dao.DatabaseException) Objects(java.util.Objects) PutItemRequest(software.amazon.awssdk.services.dynamodb.model.PutItemRequest) User(com.sanctionco.thunder.models.User) AttributeValue(software.amazon.awssdk.services.dynamodb.model.AttributeValue) DeleteItemRequest(software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest) Collections(java.util.Collections) UsersDao(com.sanctionco.thunder.dao.UsersDao) ReturnValue(software.amazon.awssdk.services.dynamodb.model.ReturnValue) DatabaseException(com.sanctionco.thunder.dao.DatabaseException) HashMap(java.util.HashMap) Map(java.util.Map) GetItemRequest(software.amazon.awssdk.services.dynamodb.model.GetItemRequest)

Example 12 with DatabaseException

use of com.sanctionco.thunder.dao.DatabaseException in project thunder by RohanNagar.

the class DynamoDbUsersDao method delete.

@Override
public CompletableFuture<User> delete(String email) {
    Objects.requireNonNull(email);
    DeleteItemRequest deleteItemRequest = DeleteItemRequest.builder().tableName(tableName).key(Collections.singletonMap("email", AttributeValue.builder().s(email).build())).expected(Collections.singletonMap("email", ExpectedAttributeValue.builder().value(AttributeValue.builder().s(email).build()).exists(true).build())).returnValues(ReturnValue.ALL_OLD).build();
    return dynamoDbClient.deleteItem(deleteItemRequest).thenApply(response -> UsersDao.fromJson(mapper, response.attributes().get("document").s()).withTime(Long.parseLong(response.attributes().get("creation_time").n()), Long.parseLong(response.attributes().get("update_time").n()))).exceptionally(throwable -> {
        // result than convertToDatabaseException() supplies
        if (throwable.getCause() instanceof ConditionalCheckFailedException) {
            LOG.warn("The email {} was not found in the database.", email, throwable);
            throw new DatabaseException("User not found in the database.", DatabaseException.Error.USER_NOT_FOUND);
        }
        throw convertToDatabaseException(throwable.getCause(), email);
    });
}
Also used : GetItemRequest(software.amazon.awssdk.services.dynamodb.model.GetItemRequest) LoggerFactory(org.slf4j.LoggerFactory) DynamoDbAsyncClient(software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient) SdkException(software.amazon.awssdk.core.exception.SdkException) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) ComparisonOperator(software.amazon.awssdk.services.dynamodb.model.ComparisonOperator) Map(java.util.Map) ExpectedAttributeValue(software.amazon.awssdk.services.dynamodb.model.ExpectedAttributeValue) ConditionalCheckFailedException(software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException) Nullable(javax.annotation.Nullable) AwsServiceException(software.amazon.awssdk.awscore.exception.AwsServiceException) Logger(org.slf4j.Logger) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) UUID(java.util.UUID) Instant(java.time.Instant) DatabaseException(com.sanctionco.thunder.dao.DatabaseException) Objects(java.util.Objects) PutItemRequest(software.amazon.awssdk.services.dynamodb.model.PutItemRequest) User(com.sanctionco.thunder.models.User) AttributeValue(software.amazon.awssdk.services.dynamodb.model.AttributeValue) DeleteItemRequest(software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest) Collections(java.util.Collections) UsersDao(com.sanctionco.thunder.dao.UsersDao) ReturnValue(software.amazon.awssdk.services.dynamodb.model.ReturnValue) DeleteItemRequest(software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest) ConditionalCheckFailedException(software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException) DatabaseException(com.sanctionco.thunder.dao.DatabaseException)

Example 13 with DatabaseException

use of com.sanctionco.thunder.dao.DatabaseException in project thunder by RohanNagar.

the class InMemoryDbUsersDao method insert.

@Override
public CompletableFuture<User> insert(User user) {
    if (!memoryAvailable()) {
        return CompletableFuture.failedFuture(new DatabaseException("There is no more memory available in the in-memory database.", DatabaseException.Error.DATABASE_DOWN));
    }
    Objects.requireNonNull(user);
    var now = Instant.now().toEpochMilli();
    var userWithTime = user.withTime(now, now);
    return database.putIfAbsent(userWithTime.getEmail().getAddress(), userWithTime) == null ? CompletableFuture.completedFuture(userWithTime) : CompletableFuture.failedFuture(new DatabaseException("A user with the same email address already exists.", DatabaseException.Error.CONFLICT));
}
Also used : DatabaseException(com.sanctionco.thunder.dao.DatabaseException)

Example 14 with DatabaseException

use of com.sanctionco.thunder.dao.DatabaseException in project thunder by RohanNagar.

the class UserResourceTest method create_withWrappedDatabaseException_shouldReturnCorrectResponse.

@Test
void create_withWrappedDatabaseException_shouldReturnCorrectResponse() {
    when(usersDao.insert(any(User.class))).thenReturn(CompletableFuture.failedFuture(new IllegalStateException(new DatabaseException("Malformed", DatabaseException.Error.REQUEST_REJECTED))));
    runCreateTest(Response.Status.INTERNAL_SERVER_ERROR);
}
Also used : User(com.sanctionco.thunder.models.User) DatabaseException(com.sanctionco.thunder.dao.DatabaseException) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 15 with DatabaseException

use of com.sanctionco.thunder.dao.DatabaseException in project thunder by RohanNagar.

the class MongoDbUsersDaoTest method testUpdateGetNotFound.

@Test
void testUpdateGetNotFound() {
    MongoCollection<Document> collection = mock(MongoCollection.class);
    FindIterable<Document> findIterable = mock(FindIterable.class);
    when(findIterable.first()).thenReturn(null);
    doReturn(findIterable).when(collection).find(any(Bson.class));
    MongoDbUsersDao usersDao = new MongoDbUsersDao(collection, MAPPER);
    CompletionException e = assertThrows(CompletionException.class, () -> usersDao.update(null, USER).join());
    assertTrue(e.getCause() instanceof DatabaseException);
    var exp = (DatabaseException) e.getCause();
    assertEquals(DatabaseException.Error.USER_NOT_FOUND, exp.getError());
    verify(collection, times(1)).find(eq(Filters.eq("_id", "test@test.com")));
}
Also used : CompletionException(java.util.concurrent.CompletionException) Document(org.bson.Document) BsonDocument(org.bson.BsonDocument) DatabaseException(com.sanctionco.thunder.dao.DatabaseException) Bson(org.bson.conversions.Bson) Test(org.junit.jupiter.api.Test)

Aggregations

DatabaseException (com.sanctionco.thunder.dao.DatabaseException)29 Test (org.junit.jupiter.api.Test)25 CompletionException (java.util.concurrent.CompletionException)24 BsonDocument (org.bson.BsonDocument)24 Document (org.bson.Document)24 Bson (org.bson.conversions.Bson)18 MongoCommandException (com.mongodb.MongoCommandException)5 User (com.sanctionco.thunder.models.User)4 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)3 UsersDao (com.sanctionco.thunder.dao.UsersDao)3 Instant (java.time.Instant)3 Collections (java.util.Collections)3 HashMap (java.util.HashMap)3 Map (java.util.Map)3 Objects (java.util.Objects)3 UUID (java.util.UUID)3 CompletableFuture (java.util.concurrent.CompletableFuture)3 Nullable (javax.annotation.Nullable)3 Logger (org.slf4j.Logger)3 LoggerFactory (org.slf4j.LoggerFactory)3