quantranhong1999 commented on code in PR #1673:
URL: https://github.com/apache/james-project/pull/1673#discussion_r1294260475


##########
mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/quota/CassandraQuotaLimitDaoTest.java:
##########
@@ -0,0 +1,94 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.quota;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.james.backends.cassandra.CassandraClusterExtension;
+import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
+import org.apache.james.core.quota.QuotaComponent;
+import org.apache.james.core.quota.QuotaLimit;
+import org.apache.james.core.quota.QuotaScope;
+import org.apache.james.core.quota.QuotaType;
+import org.apache.james.mailbox.cassandra.mail.utils.GuiceUtils;
+import org.apache.james.mailbox.cassandra.modules.CassandraQuotaModule;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class CassandraQuotaLimitDaoTest {
+
+    private CassandraQuotaLimitDao cassandraQuotaLimitDao;
+
+    @RegisterExtension
+    static CassandraClusterExtension cassandraCluster = new 
CassandraClusterExtension(CassandraModule.aggregateModules(
+        CassandraBlobModule.MODULE,
+        CassandraQuotaModule.MODULE));
+
+    @BeforeEach
+    private void setup() {
+        cassandraQuotaLimitDao = 
GuiceUtils.testInjector(cassandraCluster.getCassandraCluster()).getInstance(CassandraQuotaLimitDao.class);
+    }
+
+    @Test
+    void getQuotaLimitsShouldGetSomeQuotaLimitsSuccessfully() {
+        QuotaLimit expectedOne = 
QuotaLimit.of(QuotaLimit.QuotaKey.of(QuotaComponent.MAILBOX, QuotaScope.DOMAIN, 
"A", QuotaType.COUNT),200l);
+        QuotaLimit expectedTwo = 
QuotaLimit.of(QuotaLimit.QuotaKey.of(QuotaComponent.MAILBOX, QuotaScope.DOMAIN, 
"A", QuotaType.SIZE),100l);

Review Comment:
   ```suggestion
           QuotaLimit expectedOne = 
QuotaLimit.of(QuotaLimit.QuotaKey.of(QuotaComponent.MAILBOX, QuotaScope.DOMAIN, 
"A", QuotaType.COUNT), 200l);
           QuotaLimit expectedTwo = 
QuotaLimit.of(QuotaLimit.QuotaKey.of(QuotaComponent.MAILBOX, QuotaScope.DOMAIN, 
"A", QuotaType.SIZE), 100l);
   ```
   
   space at other places also please



##########
mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/quota/CassandraQuotaLimitDaoTest.java:
##########
@@ -0,0 +1,94 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.quota;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.james.backends.cassandra.CassandraClusterExtension;
+import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
+import org.apache.james.core.quota.QuotaComponent;
+import org.apache.james.core.quota.QuotaLimit;
+import org.apache.james.core.quota.QuotaScope;
+import org.apache.james.core.quota.QuotaType;
+import org.apache.james.mailbox.cassandra.mail.utils.GuiceUtils;
+import org.apache.james.mailbox.cassandra.modules.CassandraQuotaModule;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class CassandraQuotaLimitDaoTest {
+
+    private CassandraQuotaLimitDao cassandraQuotaLimitDao;
+
+    @RegisterExtension
+    static CassandraClusterExtension cassandraCluster = new 
CassandraClusterExtension(CassandraModule.aggregateModules(
+        CassandraBlobModule.MODULE,

Review Comment:
   no need `CassandraBlobModule.MODULE` ?



##########
server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java:
##########
@@ -31,6 +31,7 @@
 import org.apache.james.webadmin.routes.EventDeadLettersRoutes;
 import org.apache.james.webadmin.routes.GlobalQuotaRoutes;
 import org.apache.james.webadmin.routes.MailboxesRoutes;
+import org.apache.james.webadmin.routes.QuotaLimitRoutes;

Review Comment:
   ```suggestion
   ```



##########
mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraQuotaCurrentValue.java:
##########
@@ -0,0 +1,31 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.table;
+
+import com.datastax.oss.driver.api.core.CqlIdentifier;
+
+public interface CassandraQuotaCurrentValue {

Review Comment:
   ```suggestion
   public interface CassandraQuotaCurrentValueTable {
   ```



##########
mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/quota/CassandraQuotaLimitDaoTest.java:
##########
@@ -0,0 +1,94 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.quota;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.james.backends.cassandra.CassandraClusterExtension;
+import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.blob.cassandra.CassandraBlobModule;
+import org.apache.james.core.quota.QuotaComponent;
+import org.apache.james.core.quota.QuotaLimit;
+import org.apache.james.core.quota.QuotaScope;
+import org.apache.james.core.quota.QuotaType;
+import org.apache.james.mailbox.cassandra.mail.utils.GuiceUtils;
+import org.apache.james.mailbox.cassandra.modules.CassandraQuotaModule;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class CassandraQuotaLimitDaoTest {
+
+    private CassandraQuotaLimitDao cassandraQuotaLimitDao;
+
+    @RegisterExtension
+    static CassandraClusterExtension cassandraCluster = new 
CassandraClusterExtension(CassandraModule.aggregateModules(
+        CassandraBlobModule.MODULE,
+        CassandraQuotaModule.MODULE));
+
+    @BeforeEach
+    private void setup() {
+        cassandraQuotaLimitDao = 
GuiceUtils.testInjector(cassandraCluster.getCassandraCluster()).getInstance(CassandraQuotaLimitDao.class);
+    }
+
+    @Test
+    void getQuotaLimitsShouldGetSomeQuotaLimitsSuccessfully() {
+        QuotaLimit expectedOne = 
QuotaLimit.of(QuotaLimit.QuotaKey.of(QuotaComponent.MAILBOX, QuotaScope.DOMAIN, 
"A", QuotaType.COUNT),200l);
+        QuotaLimit expectedTwo = 
QuotaLimit.of(QuotaLimit.QuotaKey.of(QuotaComponent.MAILBOX, QuotaScope.DOMAIN, 
"A", QuotaType.SIZE),100l);
+        cassandraQuotaLimitDao.setQuotaLimit(expectedOne).block();
+        cassandraQuotaLimitDao.setQuotaLimit(expectedTwo).block();
+        List<QuotaLimit> expected = Arrays.asList(expectedOne, expectedTwo);
+
+        List<QuotaLimit> actual = 
cassandraQuotaLimitDao.getQuotaLimits(QuotaLimit.QuotaKey.of(QuotaComponent.MAILBOX,
 QuotaScope.DOMAIN, "A", null)).collectList().block();
+        assertThat(actual).isEqualTo(expected);

Review Comment:
   ``` suggestion
           
assertThat(cassandraQuotaLimitDao.getQuotaLimits(QuotaLimit.QuotaKey.of(QuotaComponent.MAILBOX,
 QuotaScope.DOMAIN, "A", null)).collectList().block())
              .containsExactlyInAnyOrder(expectedOne, expectedTwo)
   ```
   
   shorter



##########
mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/quota/CassandraQuotaLimitDao.java:
##########
@@ -0,0 +1,145 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.quota;
+
+import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.bindMarker;
+import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.deleteFrom;
+import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.insertInto;
+import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.selectFrom;
+import static 
com.datastax.oss.driver.api.querybuilder.relation.Relation.column;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.IDENTIFIER;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.QUOTA_COMPONENT;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.QUOTA_LIMIT;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.QUOTA_SCOPE;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.QUOTA_TYPE;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.TABLE_NAME;
+
+import javax.inject.Inject;
+
+import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
+import org.apache.james.core.quota.QuotaComponent;
+import org.apache.james.core.quota.QuotaLimit;
+import org.apache.james.core.quota.QuotaScope;
+import org.apache.james.core.quota.QuotaType;
+
+import com.datastax.oss.driver.api.core.CqlSession;
+import com.datastax.oss.driver.api.core.cql.PreparedStatement;
+import com.datastax.oss.driver.api.core.cql.Row;
+import com.datastax.oss.driver.api.querybuilder.delete.Delete;
+import com.datastax.oss.driver.api.querybuilder.insert.Insert;
+import com.datastax.oss.driver.api.querybuilder.select.Select;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class CassandraQuotaLimitDao {
+
+    private final CassandraAsyncExecutor queryExecutor;
+    private final PreparedStatement getQuotaLimitStatement;
+    private final PreparedStatement getQuotaLimitsStatement;
+    private final PreparedStatement setQuotaLimitStatement;
+    private final PreparedStatement deleteQuotaLimitStatement;
+
+    @Inject
+    public CassandraQuotaLimitDao(CqlSession session) {
+        this.queryExecutor = new CassandraAsyncExecutor(session);
+        this.getQuotaLimitStatement = 
session.prepare(getQuotaLimitStatement().build());
+        this.getQuotaLimitsStatement = 
session.prepare(getQuotaLimitsStatement().build());
+        this.setQuotaLimitStatement = 
session.prepare(setQuotaLimitStatement().build());
+        this.deleteQuotaLimitStatement = 
session.prepare((deleteQuotaLimitStatement().build()));
+    }
+
+    public Mono<QuotaLimit> getQuotaLimit(QuotaLimit.QuotaKey quotaKey) {
+        return queryExecutor.executeSingleRow(getQuotaLimitStatement.bind()
+            .setString(QUOTA_COMPONENT, 
quotaKey.getQuotaComponent().getValue())
+            .setString(QUOTA_SCOPE, quotaKey.getQuotaScope().getValue())
+            .setString(IDENTIFIER, quotaKey.getIdentifier())
+            .setString(QUOTA_TYPE, quotaKey.getQuotaType().getValue()))
+            .map(row -> convertRowToModel(row));
+    }
+
+    public Flux<QuotaLimit> getQuotaLimits(QuotaLimit.QuotaKey quotaKey) {
+        return queryExecutor.executeRows(getQuotaLimitsStatement.bind()
+            .setString(QUOTA_COMPONENT, 
quotaKey.getQuotaComponent().getValue())
+            .setString(QUOTA_SCOPE, quotaKey.getQuotaScope().getValue())
+            .setString(IDENTIFIER, quotaKey.getIdentifier()))
+            .map(row -> convertRowToModel(row));
+    }

Review Comment:
   IMO at this low-level DAO layer, we can accept lower abstraction here (just 
listing the method params instead of reusing QuotaLimit.QuotaKey).
   
   Especially in this case: the same `QuotaLimit.QuotaKey` param is used for 
`getQuotaLimit` and `getQuotaLimits` methods seems easily to make higher caller 
confused. (The caller needs to check the code to see if it can put a `null` 
`QUOTA_TYPE` or not).
   
   Again we do not tend to use `null` like that. If you want to put a potential 
null in a method params, use Optional and let the DAO handles the null logic.



##########
mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/quota/CassandraQuotaLimitDao.java:
##########
@@ -0,0 +1,145 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.quota;
+
+import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.bindMarker;
+import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.deleteFrom;
+import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.insertInto;
+import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.selectFrom;
+import static 
com.datastax.oss.driver.api.querybuilder.relation.Relation.column;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.IDENTIFIER;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.QUOTA_COMPONENT;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.QUOTA_LIMIT;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.QUOTA_SCOPE;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.QUOTA_TYPE;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.TABLE_NAME;
+
+import javax.inject.Inject;
+
+import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
+import org.apache.james.core.quota.QuotaComponent;
+import org.apache.james.core.quota.QuotaLimit;
+import org.apache.james.core.quota.QuotaScope;
+import org.apache.james.core.quota.QuotaType;
+
+import com.datastax.oss.driver.api.core.CqlSession;
+import com.datastax.oss.driver.api.core.cql.PreparedStatement;
+import com.datastax.oss.driver.api.core.cql.Row;
+import com.datastax.oss.driver.api.querybuilder.delete.Delete;
+import com.datastax.oss.driver.api.querybuilder.insert.Insert;
+import com.datastax.oss.driver.api.querybuilder.select.Select;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class CassandraQuotaLimitDao {
+
+    private final CassandraAsyncExecutor queryExecutor;
+    private final PreparedStatement getQuotaLimitStatement;
+    private final PreparedStatement getQuotaLimitsStatement;
+    private final PreparedStatement setQuotaLimitStatement;
+    private final PreparedStatement deleteQuotaLimitStatement;
+
+    @Inject
+    public CassandraQuotaLimitDao(CqlSession session) {
+        this.queryExecutor = new CassandraAsyncExecutor(session);
+        this.getQuotaLimitStatement = 
session.prepare(getQuotaLimitStatement().build());
+        this.getQuotaLimitsStatement = 
session.prepare(getQuotaLimitsStatement().build());
+        this.setQuotaLimitStatement = 
session.prepare(setQuotaLimitStatement().build());
+        this.deleteQuotaLimitStatement = 
session.prepare((deleteQuotaLimitStatement().build()));
+    }
+
+    public Mono<QuotaLimit> getQuotaLimit(QuotaLimit.QuotaKey quotaKey) {
+        return queryExecutor.executeSingleRow(getQuotaLimitStatement.bind()
+            .setString(QUOTA_COMPONENT, 
quotaKey.getQuotaComponent().getValue())
+            .setString(QUOTA_SCOPE, quotaKey.getQuotaScope().getValue())
+            .setString(IDENTIFIER, quotaKey.getIdentifier())
+            .setString(QUOTA_TYPE, quotaKey.getQuotaType().getValue()))
+            .map(row -> convertRowToModel(row));
+    }
+
+    public Flux<QuotaLimit> getQuotaLimits(QuotaLimit.QuotaKey quotaKey) {
+        return queryExecutor.executeRows(getQuotaLimitsStatement.bind()
+            .setString(QUOTA_COMPONENT, 
quotaKey.getQuotaComponent().getValue())
+            .setString(QUOTA_SCOPE, quotaKey.getQuotaScope().getValue())
+            .setString(IDENTIFIER, quotaKey.getIdentifier()))
+            .map(row -> convertRowToModel(row));
+    }

Review Comment:
   Also would not it be weird if e.g we call `.getQuotaLimits` with a 
`QuotaKey` containing a `count` `QuotaType` object and then we receive a size 
`QuotaType` record?



##########
mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/modules/CassandraQuotaModule.java:
##########
@@ -68,5 +70,26 @@ public interface CassandraQuotaModule {
             .withPartitionKey(CassandraGlobalMaxQuota.KEY, TEXT)
             .withColumn(CassandraGlobalMaxQuota.STORAGE, BIGINT)
             .withColumn(CassandraGlobalMaxQuota.MESSAGE, BIGINT))
+
+        .table(CassandraQuotaLimit.TABLE_NAME)
+        .comment("Holds quota limits.")
+        .options(options -> options
+            .withCaching(true, 
rows(CassandraConstants.DEFAULT_CACHED_ROW_PER_PARTITION)))
+        .statement(statement -> types -> statement
+            .withPartitionKey(CassandraQuotaLimit.QUOTA_COMPONENT, TEXT)
+            .withPartitionKey(CassandraQuotaLimit.QUOTA_SCOPE, TEXT)
+            .withPartitionKey(CassandraQuotaLimit.IDENTIFIER, TEXT)
+            .withClusteringColumn(CassandraQuotaLimit.QUOTA_TYPE, TEXT)

Review Comment:
   Do you think we should open the door for a (future) potential API to get all 
quotas of a user (all of the Quota Components: jmap upload, mailbox... + Quota 
scopes...)?
   
   The same case is an admin who would want to get all quotas of a domain in a 
single request.
   
   With the current table design, I am afraid we would be closed to that usage. 
(always need QUOTA_COMPONENT + QUOTA_SCOPE + IDENTIFIER in `WHERE` condition).
   
   I think Primary key = Partition Key (IDENTIFIER) + Clustering Key 
(QUOTA_COMPONENT + QUOTA_SCOPE + QUOTA_TYPE) would be more flexible.
   
   WDYT?
   



##########
mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraQuotaLimit.java:
##########
@@ -0,0 +1,32 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.table;
+
+import com.datastax.oss.driver.api.core.CqlIdentifier;
+
+public interface CassandraQuotaLimit {

Review Comment:
   ```suggestion
   public interface CassandraQuotaLimitTable {
   ```



##########
mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/quota/CassandraQuotaLimitDao.java:
##########
@@ -0,0 +1,145 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.quota;
+
+import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.bindMarker;
+import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.deleteFrom;
+import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.insertInto;
+import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.selectFrom;
+import static 
com.datastax.oss.driver.api.querybuilder.relation.Relation.column;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.IDENTIFIER;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.QUOTA_COMPONENT;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.QUOTA_LIMIT;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.QUOTA_SCOPE;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.QUOTA_TYPE;
+import static 
org.apache.james.mailbox.cassandra.table.CassandraQuotaLimit.TABLE_NAME;
+
+import javax.inject.Inject;
+
+import org.apache.james.backends.cassandra.utils.CassandraAsyncExecutor;
+import org.apache.james.core.quota.QuotaComponent;
+import org.apache.james.core.quota.QuotaLimit;
+import org.apache.james.core.quota.QuotaScope;
+import org.apache.james.core.quota.QuotaType;
+
+import com.datastax.oss.driver.api.core.CqlSession;
+import com.datastax.oss.driver.api.core.cql.PreparedStatement;
+import com.datastax.oss.driver.api.core.cql.Row;
+import com.datastax.oss.driver.api.querybuilder.delete.Delete;
+import com.datastax.oss.driver.api.querybuilder.insert.Insert;
+import com.datastax.oss.driver.api.querybuilder.select.Select;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class CassandraQuotaLimitDao {
+
+    private final CassandraAsyncExecutor queryExecutor;
+    private final PreparedStatement getQuotaLimitStatement;
+    private final PreparedStatement getQuotaLimitsStatement;
+    private final PreparedStatement setQuotaLimitStatement;
+    private final PreparedStatement deleteQuotaLimitStatement;
+
+    @Inject
+    public CassandraQuotaLimitDao(CqlSession session) {
+        this.queryExecutor = new CassandraAsyncExecutor(session);
+        this.getQuotaLimitStatement = 
session.prepare(getQuotaLimitStatement().build());
+        this.getQuotaLimitsStatement = 
session.prepare(getQuotaLimitsStatement().build());
+        this.setQuotaLimitStatement = 
session.prepare(setQuotaLimitStatement().build());
+        this.deleteQuotaLimitStatement = 
session.prepare((deleteQuotaLimitStatement().build()));
+    }
+
+    public Mono<QuotaLimit> getQuotaLimit(QuotaLimit.QuotaKey quotaKey) {
+        return queryExecutor.executeSingleRow(getQuotaLimitStatement.bind()
+            .setString(QUOTA_COMPONENT, 
quotaKey.getQuotaComponent().getValue())
+            .setString(QUOTA_SCOPE, quotaKey.getQuotaScope().getValue())
+            .setString(IDENTIFIER, quotaKey.getIdentifier())
+            .setString(QUOTA_TYPE, quotaKey.getQuotaType().getValue()))
+            .map(row -> convertRowToModel(row));
+    }
+
+    public Flux<QuotaLimit> getQuotaLimits(QuotaLimit.QuotaKey quotaKey) {
+        return queryExecutor.executeRows(getQuotaLimitsStatement.bind()
+            .setString(QUOTA_COMPONENT, 
quotaKey.getQuotaComponent().getValue())
+            .setString(QUOTA_SCOPE, quotaKey.getQuotaScope().getValue())
+            .setString(IDENTIFIER, quotaKey.getIdentifier()))
+            .map(row -> convertRowToModel(row));
+    }
+
+    public Mono<Void> setQuotaLimit(QuotaLimit quotaLimit) {
+        return queryExecutor.executeVoid(setQuotaLimitStatement.bind()
+            .setString(QUOTA_COMPONENT, 
quotaLimit.getQuotaKey().getQuotaComponent().getValue())
+            .setString(QUOTA_SCOPE, 
quotaLimit.getQuotaKey().getQuotaScope().getValue())
+            .setString(IDENTIFIER, quotaLimit.getQuotaKey().getIdentifier())
+            .setString(QUOTA_TYPE, 
quotaLimit.getQuotaKey().getQuotaType().getValue())
+            .setLong(QUOTA_LIMIT, quotaLimit.getQuotaLimit().orElse(null)));

Review Comment:
   Question: In which case do we accept `null` as input for a Quota Limit value?



-- 
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