Skip to content
This repository has been archived by the owner on Jun 7, 2024. It is now read-only.

Commit

Permalink
ARUHA-523 Use DB's uniqueness constraint to prevent duplicate storages
Browse files Browse the repository at this point in the history
  • Loading branch information
Lionel Montrieux committed Feb 1, 2017
1 parent 4a86309 commit cda190f
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.zalando.nakadi.domain.Storage;
import org.zalando.nakadi.domain.Timeline;
import org.zalando.nakadi.exceptions.DuplicatedEventTypeNameException;
import org.zalando.nakadi.exceptions.DuplicatedStorageIdException;
import org.zalando.nakadi.exceptions.InternalNakadiException;
import org.zalando.nakadi.utils.TestUtils;

Expand All @@ -36,7 +37,8 @@ public void setUp() {
}

@Test
public void testTimelineCreated() throws InternalNakadiException, DuplicatedEventTypeNameException {
public void testTimelineCreated()
throws InternalNakadiException, DuplicatedEventTypeNameException, DuplicatedStorageIdException {
final Storage storage = sRepository.createStorage(
StorageDbRepositoryTest.createStorage("default", "test", "path"));
final EventType testEt = eRepository.saveEventType(TestUtils.buildDefaultEventType());
Expand All @@ -54,7 +56,8 @@ public void testTimelineCreated() throws InternalNakadiException, DuplicatedEven
}

@Test
public void testTimelineUpdate() throws InternalNakadiException, DuplicatedEventTypeNameException {
public void testTimelineUpdate()
throws InternalNakadiException, DuplicatedEventTypeNameException, DuplicatedStorageIdException {
final Storage storage = sRepository.createStorage(
StorageDbRepositoryTest.createStorage("default", "test", "path"));
final EventType testEt = eRepository.saveEventType(TestUtils.buildDefaultEventType());
Expand All @@ -79,7 +82,8 @@ public void testTimelineUpdate() throws InternalNakadiException, DuplicatedEvent
}

@Test(expected = DuplicateKeyException.class)
public void testDuplicateOrderNotAllowed() throws InternalNakadiException, DuplicatedEventTypeNameException {
public void testDuplicateOrderNotAllowed()
throws InternalNakadiException, DuplicatedEventTypeNameException, DuplicatedStorageIdException {
final Storage storage = sRepository.createStorage(
StorageDbRepositoryTest.createStorage("default", "test", "path"));
final EventType testEt = eRepository.saveEventType(TestUtils.buildDefaultEventType());
Expand All @@ -93,7 +97,8 @@ public void testDuplicateOrderNotAllowed() throws InternalNakadiException, Dupli
}

@Test
public void testListTimelinesOrdered() throws InternalNakadiException, DuplicatedEventTypeNameException {
public void testListTimelinesOrdered()
throws InternalNakadiException, DuplicatedEventTypeNameException, DuplicatedStorageIdException {
final Storage storage = sRepository.createStorage(
StorageDbRepositoryTest.createStorage("default", "test", "path"));
final EventType testEt = eRepository.saveEventType(TestUtils.buildDefaultEventType());
Expand All @@ -111,7 +116,8 @@ public void testListTimelinesOrdered() throws InternalNakadiException, Duplicate
}

@Test
public void testTimelineDeleted() throws InternalNakadiException, DuplicatedEventTypeNameException {
public void testTimelineDeleted()
throws InternalNakadiException, DuplicatedEventTypeNameException, DuplicatedStorageIdException {
final Storage storage = sRepository.createStorage(
StorageDbRepositoryTest.createStorage("default", "test", "path"));
final EventType testEt = eRepository.saveEventType(TestUtils.buildDefaultEventType());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.zalando.nakadi.exceptions;

import javax.ws.rs.core.Response;

public class DuplicatedStorageIdException extends NakadiException {
public DuplicatedStorageIdException(final String message) {
super(message);
}

public DuplicatedStorageIdException(final String msg, final Exception cause) {
super(msg, cause);
}

public DuplicatedStorageIdException(final String msg, final String problemMessage, final Exception cause) {
super(msg, problemMessage, cause);
}

@Override
protected Response.StatusType getStatus() {
return Response.Status.CONFLICT;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.zalando.nakadi.annotations.DB;
import org.zalando.nakadi.domain.Storage;
import org.zalando.nakadi.exceptions.DuplicatedStorageIdException;
import org.zalando.nakadi.exceptions.InternalNakadiException;

@DB
Expand Down Expand Up @@ -48,7 +50,8 @@ public Optional<Storage> getStorage(final String id) throws InternalNakadiExcept
return Optional.ofNullable(storages.isEmpty() ? null : storages.get(0));
}

public Storage createStorage(final Storage storage) throws DataAccessException, InternalNakadiException {
public Storage createStorage(final Storage storage)
throws DataAccessException, DuplicatedStorageIdException, InternalNakadiException {
try {
jdbcTemplate.update(
"INSERT INTO zn_data.storage (st_id, st_type, st_configuration) VALUES (?, ?, ?::jsonb)",
Expand All @@ -59,6 +62,8 @@ public Storage createStorage(final Storage storage) throws DataAccessException,
} catch (final JsonProcessingException ex) {
throw new IllegalArgumentException("Storage configuration " + storage.getConfiguration(Object.class) +
" can't be mapped to json", ex);
} catch (DuplicateKeyException e) {
throw new DuplicatedStorageIdException("A storage with id '" + storage.getId() + "' already exists.", e);
} catch (DataAccessException e) {
throw new InternalNakadiException("Error occurred when creating Storage " + storage.getId(), e);
}
Expand Down
11 changes: 3 additions & 8 deletions src/main/java/org/zalando/nakadi/service/StorageService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.zalando.nakadi.domain.Storage;
import org.zalando.nakadi.exceptions.DuplicatedStorageIdException;
import org.zalando.nakadi.exceptions.InternalNakadiException;
import org.zalando.nakadi.repository.db.StorageDbRepository;
import org.zalando.problem.Problem;
Expand Down Expand Up @@ -75,14 +76,6 @@ public Result<Void> createStorage(final JSONObject json) {
return Result.problem(Problem.valueOf(UNPROCESSABLE_ENTITY, e.getMessage()));
}

try {
if (storageDbRepository.getStorage(id).isPresent()) {
return Result.conflict("Storage with ID " + id + " already exists.");
}
} catch (InternalNakadiException e) {
return Result.problem(Problem.valueOf(INTERNAL_SERVER_ERROR, e.getMessage()));
}

final Storage storage = new Storage();
storage.setId(id);
storage.setType(Storage.Type.valueOf(type.toUpperCase()));
Expand All @@ -94,6 +87,8 @@ public Result<Void> createStorage(final JSONObject json) {

try {
storageDbRepository.createStorage(storage);
} catch (DuplicatedStorageIdException e) {
return Result.problem(e.asProblem());
} catch (InternalNakadiException e) {
return Result.problem(Problem.valueOf(INTERNAL_SERVER_ERROR, e.getMessage()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ public void testCreateStorage() throws Exception {
final Storage dbReply = createTestStorage();

when(storageDbRepository.createStorage(any())).thenReturn(dbReply);
when(storageDbRepository.getStorage(any())).thenReturn(Optional.empty());

final JSONObject storage = createTestStorageJson("s1");
final Result<Void> result = storageService.createStorage(storage);
Expand Down

0 comments on commit cda190f

Please sign in to comment.