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]

Reply via email to