chibenwa commented on code in PR #1849:
URL: https://github.com/apache/james-project/pull/1849#discussion_r1422325138
##########
server/data/data-postgres/src/main/java/org/apache/james/sieve/postgres/PostgresSieveRepository.java:
##########
@@ -100,166 +80,154 @@ private boolean overQuotaAfterModification(long
usedSpace, long size, QuotaSizeL
}
@Override
- public void putScript(Username username, ScriptName name, ScriptContent
content) {
-
transactionRunner.runAndHandleException(Throwing.<EntityManager>consumer(entityManager
-> {
- try {
- haveSpace(username, name, content.length());
- JPASieveScript jpaSieveScript = JPASieveScript.builder()
- .username(username.asString())
- .scriptName(name.getValue())
- .scriptContent(content)
- .build();
- entityManager.persist(jpaSieveScript);
- } catch (QuotaExceededException | StorageException e) {
- rollbackTransactionIfActive(entityManager.getTransaction());
- throw e;
- }
- }).sneakyThrow(), throwStorageExceptionConsumer("Unable to put script
for user " + username.asString()));
+ public void putScript(Username username, ScriptName name, ScriptContent
content) throws QuotaExceededException {
+ reThrowQuotaExceededException(() ->
spaceThatWillBeUsedByNewScript(username, name, content.length())
+ .flatMap(spaceToUse -> throwOnOverQuota(username, spaceToUse)
+ .thenEmpty(Flux.merge(
+ updateSpaceUsed(username, spaceToUse),
+
postgresSieveScriptDAO.upsertScript(PostgresSieveScript.builder()
+ .username(username.asString())
+ .scriptName(name.getValue())
+ .scriptContent(content.getValue())
+ .scriptSize(content.length())
+ .isActive(false)
+ .build()))
+ .then()))
+ .block());
+ }
+
+ private Mono<Void> updateSpaceUsed(Username username, long spaceToUse) {
+ if (spaceToUse == 0) {
+ return Mono.empty();
+ }
+ return postgresSieveQuotaDAO.updateSpaceUsed(username, spaceToUse);
+ }
+
+ private Mono<Long> spaceThatWillBeUsedByNewScript(Username username,
ScriptName name, long scriptSize) {
+ return postgresSieveScriptDAO.getScript(username, name)
+ .map(PostgresSieveScript::getScriptSize)
+ .defaultIfEmpty(0L)
+ .map(sizeOfStoredScript -> scriptSize - sizeOfStoredScript);
+ }
+
+ private Mono<Void> throwOnOverQuota(Username username, Long
sizeDifference) {
+ Mono<Long> spaceUsedMono = postgresSieveQuotaDAO.spaceUsedBy(username);
+
+ return limitToUser(username)
+ .zipWith(spaceUsedMono)
+ .flatMap(quotaToUsedSpacePair -> {
+ if (overQuotaAfterModification(quotaToUsedSpacePair.getT2(),
sizeDifference, quotaToUsedSpacePair.getT1())) {
+ return Mono.error(new QuotaExceededException());
+ }
+ return Mono.empty();
+ });
+ }
+
+ private Mono<QuotaSizeLimit> limitToUser(Username username) {
+ return postgresSieveQuotaDAO.getQuota(username)
+ .filter(Optional::isPresent)
+ .switchIfEmpty(postgresSieveQuotaDAO.getGlobalQuota())
+ .map(optional -> optional.orElse(QuotaSizeLimit.unlimited()));
}
@Override
public List<ScriptSummary> listScripts(Username username) {
- return findAllSieveScriptsForUser(username).stream()
- .map(JPASieveScript::toSummary)
- .collect(ImmutableList.toImmutableList());
+ return listScriptsReactive(username)
+ .collectList()
+ .block();
}
@Override
public Flux<ScriptSummary> listScriptsReactive(Username username) {
- return Mono.fromCallable(() ->
listScripts(username)).flatMapMany(Flux::fromIterable);
- }
-
- private List<JPASieveScript> findAllSieveScriptsForUser(Username username)
{
- return transactionRunner.runAndRetrieveResult(entityManager -> {
- List<JPASieveScript> sieveScripts =
entityManager.createNamedQuery("findAllByUsername", JPASieveScript.class)
- .setParameter("username",
username.asString()).getResultList();
- return
Optional.ofNullable(sieveScripts).orElse(ImmutableList.of());
- }, throwStorageException("Unable to list scripts for user " +
username.asString()));
+ return postgresSieveScriptDAO.getScripts(username)
+ .map(postgresSieveScript -> new ScriptSummary(
+ new ScriptName(postgresSieveScript.getScriptName()),
+ postgresSieveScript.isActive(),
+ postgresSieveScript.getScriptSize()));
}
@Override
public ZonedDateTime getActivationDateForActiveScript(Username username)
throws ScriptNotFoundException {
- Optional<JPASieveScript> script = findActiveSieveScript(username);
- JPASieveScript activeSieveScript = script.orElseThrow(() -> new
ScriptNotFoundException("Unable to find active script for user " +
username.asString()));
- return activeSieveScript.getActivationDateTime().toZonedDateTime();
+ return postgresSieveScriptDAO.getActiveScript(username)
+ .blockOptional()
+ .orElseThrow(ScriptNotFoundException::new)
+ .getActivationDateTime()
+ .toZonedDateTime();
}
@Override
public InputStream getActive(Username username) throws
ScriptNotFoundException {
- Optional<JPASieveScript> script = findActiveSieveScript(username);
- JPASieveScript activeSieveScript = script.orElseThrow(() -> new
ScriptNotFoundException("Unable to find active script for user " +
username.asString()));
- return IOUtils.toInputStream(activeSieveScript.getScriptContent(),
StandardCharsets.UTF_8);
- }
-
- private Optional<JPASieveScript> findActiveSieveScript(Username username) {
- return transactionRunner.runAndRetrieveResult(
- Throwing.<EntityManager,
Optional<JPASieveScript>>function(entityManager ->
findActiveSieveScript(username, entityManager)).sneakyThrow(),
- throwStorageException("Unable to find active script for user "
+ username.asString()));
+ return
IOUtils.toInputStream(postgresSieveScriptDAO.getActiveScript(username)
+ .blockOptional()
+ .orElseThrow(ScriptNotFoundException::new)
+ .getScriptContent(), StandardCharsets.UTF_8);
}
- private Optional<JPASieveScript> findActiveSieveScript(Username username,
EntityManager entityManager) {
- try {
- JPASieveScript activeSieveScript =
entityManager.createNamedQuery("findActiveByUsername", JPASieveScript.class)
- .setParameter("username",
username.asString()).getSingleResult();
- return Optional.ofNullable(activeSieveScript);
- } catch (NoResultException e) {
- LOGGER.debug("Sieve script not found for user {}",
username.asString());
- return Optional.empty();
+ @Override
+ public void setActive(Username username, ScriptName name) throws
ScriptNotFoundException {
+ if (SieveRepository.NO_SCRIPT_NAME.equals(name)) {
+ switchOffActiveScript(username);
+ } else {
+ switchOffActiveScript(username);
+ activateScript(username, name);
}
}
- @Override
- public void setActive(Username username, ScriptName name) {
-
transactionRunner.runAndHandleException(Throwing.<EntityManager>consumer(entityManager
-> {
- try {
- if (SieveRepository.NO_SCRIPT_NAME.equals(name)) {
- switchOffActiveScript(username, entityManager);
- } else {
- setActiveScript(username, name, entityManager);
- }
- } catch (StorageException | ScriptNotFoundException e) {
- rollbackTransactionIfActive(entityManager.getTransaction());
- throw e;
- }
- }).sneakyThrow(), throwStorageExceptionConsumer("Unable to set active
script " + name.getValue() + " for user " + username.asString()));
+ private void switchOffActiveScript(Username username) {
+ postgresSieveScriptDAO.deactivateCurrentActiveScript(username).block();
}
- private void switchOffActiveScript(Username username, EntityManager
entityManager) throws StorageException {
- Optional<JPASieveScript> activeSieveScript =
findActiveSieveScript(username, entityManager);
- activeSieveScript.ifPresent(JPASieveScript::deactivate);
+ private void activateScript(Username username, ScriptName scriptName)
throws ScriptNotFoundException {
+ if (noScriptUpdated(username, scriptName)) {
+ throw new ScriptNotFoundException();
+ }
}
- private void setActiveScript(Username username, ScriptName name,
EntityManager entityManager) throws StorageException, ScriptNotFoundException {
- JPASieveScript sieveScript = findSieveScript(username, name,
entityManager)
- .orElseThrow(() -> new ScriptNotFoundException("Unable to find
script " + name.getValue() + " for user " + username.asString()));
- findActiveSieveScript(username,
entityManager).ifPresent(JPASieveScript::deactivate);
- sieveScript.activate();
+ private boolean noScriptUpdated(Username username, ScriptName scriptName) {
+ return postgresSieveScriptDAO.activateScript(username, scriptName)
+ .blockOptional()
+ .map(updatedRows -> updatedRows == 0)
+ .orElse(false);
}
@Override
public InputStream getScript(Username username, ScriptName name) throws
ScriptNotFoundException {
- Optional<JPASieveScript> script = findSieveScript(username, name);
- JPASieveScript sieveScript = script.orElseThrow(() -> new
ScriptNotFoundException("Unable to find script " + name.getValue() + " for user
" + username.asString()));
- return IOUtils.toInputStream(sieveScript.getScriptContent(),
StandardCharsets.UTF_8);
+ return
IOUtils.toInputStream(postgresSieveScriptDAO.getScript(username, name)
+ .blockOptional()
+ .orElseThrow(ScriptNotFoundException::new)
+ .getScriptContent(), StandardCharsets.UTF_8);
}
- private Optional<JPASieveScript> findSieveScript(Username username,
ScriptName scriptName) {
- return transactionRunner.runAndRetrieveResult(entityManager ->
findSieveScript(username, scriptName, entityManager),
- throwStorageException("Unable to find script " +
scriptName.getValue() + " for user " + username.asString()));
- }
+ @Override
+ public void deleteScript(Username username, ScriptName name) throws
ScriptNotFoundException, IsActiveException {
+ PostgresSieveScript sieveScript =
postgresSieveScriptDAO.getScript(username, name)
+ .blockOptional()
+ .orElseThrow(ScriptNotFoundException::new);
- private Optional<JPASieveScript> findSieveScript(Username username,
ScriptName scriptName, EntityManager entityManager) {
- try {
- JPASieveScript sieveScript =
entityManager.createNamedQuery("findSieveScript", JPASieveScript.class)
- .setParameter("username", username.asString())
- .setParameter("scriptName",
scriptName.getValue()).getSingleResult();
- return Optional.ofNullable(sieveScript);
- } catch (NoResultException e) {
- LOGGER.debug("Sieve script not found for user {}",
username.asString());
- return Optional.empty();
+ if (sieveScript.isActive()) {
+ throw new IsActiveException();
}
- }
- @Override
- public void deleteScript(Username username, ScriptName name) {
-
transactionRunner.runAndHandleException(Throwing.<EntityManager>consumer(entityManager
-> {
- Optional<JPASieveScript> sieveScript = findSieveScript(username,
name, entityManager);
- if (!sieveScript.isPresent()) {
- rollbackTransactionIfActive(entityManager.getTransaction());
- throw new ScriptNotFoundException("Unable to find script " +
name.getValue() + " for user " + username.asString());
- }
- JPASieveScript sieveScriptToRemove = sieveScript.get();
- if (sieveScriptToRemove.isActive()) {
- rollbackTransactionIfActive(entityManager.getTransaction());
- throw new IsActiveException("Unable to delete active script "
+ name.getValue() + " for user " + username.asString());
- }
- entityManager.remove(sieveScriptToRemove);
- }).sneakyThrow(), throwStorageExceptionConsumer("Unable to delete
script " + name.getValue() + " for user " + username.asString()));
+ postgresSieveScriptDAO.deleteScript(username, name).block();
}
@Override
- public void renameScript(Username username, ScriptName oldName, ScriptName
newName) {
-
transactionRunner.runAndHandleException(Throwing.<EntityManager>consumer(entityManager
-> {
- Optional<JPASieveScript> sieveScript = findSieveScript(username,
oldName, entityManager);
- if (!sieveScript.isPresent()) {
- rollbackTransactionIfActive(entityManager.getTransaction());
- throw new ScriptNotFoundException("Unable to find script " +
oldName.getValue() + " for user " + username.asString());
- }
+ public void renameScript(Username username, ScriptName oldName, ScriptName
newName) throws DuplicateException, ScriptNotFoundException {
+ checkIfNewScriptNameDuplicated(username, newName);
Review Comment:
We should rather use a constraint on the DB and not check this ourselves.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]