This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch postgresql
in repository https://gitbox.apache.org/repos/asf/james-project.git
The following commit(s) were added to refs/heads/postgresql by this push:
new 31d8ec6e77 JAMES-2586 Postgres Subscription mapper (#1775)
31d8ec6e77 is described below
commit 31d8ec6e7759ba487269eb3592f7f8dbfeb68c7a
Author: vttran <[email protected]>
AuthorDate: Wed Nov 8 09:56:20 2023 +0700
JAMES-2586 Postgres Subscription mapper (#1775)
---
backends-common/postgres/pom.xml | 1 -
.../james/backends/postgres/PostgresTable.java | 10 ++--
.../backends/postgres/utils/PostgresExecutor.java | 15 +++++
.../james/backends/postgres/PostgresExtension.java | 4 ++
.../postgres/PostgresTableManagerTest.java | 2 +-
mailbox/postgres/pom.xml | 11 ++++
.../mailbox/jpa/user/PostgresSubscriptionDAO.java | 57 ++++++++++++++++++
.../jpa/user/PostgresSubscriptionMapper.java | 70 ++++++++++++++++++++++
.../jpa/user/PostgresSubscriptionModule.java | 55 +++++++----------
.../jpa/user/PostgresSubscriptionTable.java | 42 +++----------
.../jpa/user/PostgresSubscriptionMapperTest.java | 45 ++++----------
pom.xml | 5 ++
12 files changed, 210 insertions(+), 107 deletions(-)
diff --git a/backends-common/postgres/pom.xml b/backends-common/postgres/pom.xml
index 3cf5b72327..b9d8923063 100644
--- a/backends-common/postgres/pom.xml
+++ b/backends-common/postgres/pom.xml
@@ -82,7 +82,6 @@
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
- <version>1.19.1</version>
<scope>test</scope>
</dependency>
<dependency>
diff --git
a/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/PostgresTable.java
b/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/PostgresTable.java
index 331f530ad7..1956d3c5e8 100644
---
a/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/PostgresTable.java
+++
b/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/PostgresTable.java
@@ -41,21 +41,21 @@ public class PostgresTable {
@FunctionalInterface
public interface RequireRowLevelSecurity {
- PostgresTable enableRLS(boolean enableRowLevelSecurity);
+ PostgresTable enableRowLevelSecurity(boolean enableRowLevelSecurity);
default PostgresTable noRLS() {
- return enableRLS(false);
+ return enableRowLevelSecurity(false);
}
- default PostgresTable enableRLS() {
- return enableRLS(true);
+ default PostgresTable enableRowLevelSecurity() {
+ return enableRowLevelSecurity(true);
}
}
public static RequireCreateTableStep name(String tableName) {
Preconditions.checkNotNull(tableName);
- return createTableFunction -> enableRLS -> new
PostgresTable(tableName, enableRLS, dsl -> createTableFunction.createTable(dsl,
tableName));
+ return createTableFunction -> enableRowLevelSecurity -> new
PostgresTable(tableName, enableRowLevelSecurity, dsl ->
createTableFunction.createTable(dsl, tableName));
}
private final String name;
diff --git
a/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresExecutor.java
b/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresExecutor.java
index 78636dc186..43b5efa4e1 100644
---
a/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresExecutor.java
+++
b/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresExecutor.java
@@ -19,9 +19,12 @@
package org.apache.james.backends.postgres.utils;
+import java.util.function.Function;
+
import javax.inject.Inject;
import org.jooq.DSLContext;
+import org.jooq.Record;
import org.jooq.SQLDialect;
import org.jooq.conf.Settings;
import org.jooq.impl.DSL;
@@ -29,6 +32,7 @@ import org.jooq.impl.DSL;
import com.google.common.annotations.VisibleForTesting;
import io.r2dbc.spi.Connection;
+import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public class PostgresExecutor {
@@ -47,6 +51,17 @@ public class PostgresExecutor {
return connection.map(con -> DSL.using(con, PGSQL_DIALECT, SETTINGS));
}
+ public Mono<Void> executeVoid(Function<DSLContext, Mono<?>> queryFunction)
{
+ return dslContext()
+ .flatMap(queryFunction)
+ .then();
+ }
+
+ public Flux<Record> executeRows(Function<DSLContext, Flux<Record>>
queryFunction) {
+ return dslContext()
+ .flatMapMany(queryFunction);
+ }
+
public Mono<Connection> connection() {
return connection;
}
diff --git
a/backends-common/postgres/src/test/java/org/apache/james/backends/postgres/PostgresExtension.java
b/backends-common/postgres/src/test/java/org/apache/james/backends/postgres/PostgresExtension.java
index 0e4ab28fa3..35606c4f8e 100644
---
a/backends-common/postgres/src/test/java/org/apache/james/backends/postgres/PostgresExtension.java
+++
b/backends-common/postgres/src/test/java/org/apache/james/backends/postgres/PostgresExtension.java
@@ -102,6 +102,10 @@ public class PostgresExtension implements
GuiceModuleTestExtension {
return postgresExecutor.connection();
}
+ public PostgresExecutor getPostgresExecutor() {
+ return postgresExecutor;
+ }
+
private void initTablesAndIndexes() {
PostgresTableManager postgresTableManager = new
PostgresTableManager(postgresExecutor, postgresModule);
postgresTableManager.initializeTables().block();
diff --git
a/backends-common/postgres/src/test/java/org/apache/james/backends/postgres/PostgresTableManagerTest.java
b/backends-common/postgres/src/test/java/org/apache/james/backends/postgres/PostgresTableManagerTest.java
index 007ff246a5..c08a070a48 100644
---
a/backends-common/postgres/src/test/java/org/apache/james/backends/postgres/PostgresTableManagerTest.java
+++
b/backends-common/postgres/src/test/java/org/apache/james/backends/postgres/PostgresTableManagerTest.java
@@ -286,7 +286,7 @@ class PostgresTableManagerTest {
.createTableStep((dsl, tbn) -> dsl.createTable(tbn)
.column("clm1", SQLDataType.UUID.notNull())
.column("clm2", SQLDataType.VARCHAR(255).notNull()))
- .enableRLS();
+ .enableRowLevelSecurity();
PostgresModule module = PostgresModule.table(table);
diff --git a/mailbox/postgres/pom.xml b/mailbox/postgres/pom.xml
index d63b431281..690389fab5 100644
--- a/mailbox/postgres/pom.xml
+++ b/mailbox/postgres/pom.xml
@@ -99,6 +99,12 @@
<artifactId>james-server-data-jpa</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>${james.groupId}</groupId>
+ <artifactId>james-server-guice-common</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>${james.groupId}</groupId>
<artifactId>james-server-testing</artifactId>
@@ -140,6 +146,11 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.testcontainers</groupId>
+ <artifactId>postgresql</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
diff --git
a/mailbox/postgres/src/main/java/org/apache/james/mailbox/jpa/user/PostgresSubscriptionDAO.java
b/mailbox/postgres/src/main/java/org/apache/james/mailbox/jpa/user/PostgresSubscriptionDAO.java
new file mode 100644
index 0000000000..a1a903e90d
--- /dev/null
+++
b/mailbox/postgres/src/main/java/org/apache/james/mailbox/jpa/user/PostgresSubscriptionDAO.java
@@ -0,0 +1,57 @@
+/****************************************************************
+ * 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.jpa.user;
+
+import static
org.apache.james.mailbox.jpa.user.PostgresSubscriptionTable.MAILBOX;
+import static
org.apache.james.mailbox.jpa.user.PostgresSubscriptionTable.TABLE_NAME;
+import static org.apache.james.mailbox.jpa.user.PostgresSubscriptionTable.USER;
+
+import org.apache.james.backends.postgres.utils.PostgresExecutor;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class PostgresSubscriptionDAO {
+ protected final PostgresExecutor executor;
+
+ public PostgresSubscriptionDAO(PostgresExecutor executor) {
+ this.executor = executor;
+ }
+
+ public Mono<Void> save(String username, String mailbox) {
+ return executor.executeVoid(dsl ->
Mono.from(dsl.insertInto(TABLE_NAME, USER, MAILBOX)
+ .values(username, mailbox)
+ .onConflict(USER, MAILBOX)
+ .doNothing()
+ .returningResult(MAILBOX)));
+ }
+
+ public Mono<Void> delete(String username, String mailbox) {
+ return executor.executeVoid(dsl -> Mono.from(dsl.deleteFrom(TABLE_NAME)
+ .where(USER.eq(username))
+ .and(MAILBOX.eq(mailbox))));
+ }
+
+ public Flux<String> findMailboxByUser(String username) {
+ return executor.executeRows(dsl -> Flux.from(dsl.selectFrom(TABLE_NAME)
+ .where(USER.eq(username))))
+ .map(record -> record.get(MAILBOX));
+ }
+}
diff --git
a/mailbox/postgres/src/main/java/org/apache/james/mailbox/jpa/user/PostgresSubscriptionMapper.java
b/mailbox/postgres/src/main/java/org/apache/james/mailbox/jpa/user/PostgresSubscriptionMapper.java
new file mode 100644
index 0000000000..02514fef6a
--- /dev/null
+++
b/mailbox/postgres/src/main/java/org/apache/james/mailbox/jpa/user/PostgresSubscriptionMapper.java
@@ -0,0 +1,70 @@
+/****************************************************************
+ * 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.jpa.user;
+
+import java.util.List;
+
+import org.apache.james.core.Username;
+import org.apache.james.mailbox.exception.SubscriptionException;
+import org.apache.james.mailbox.store.user.SubscriptionMapper;
+import org.apache.james.mailbox.store.user.model.Subscription;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class PostgresSubscriptionMapper implements SubscriptionMapper {
+
+ private final PostgresSubscriptionDAO subscriptionDAO;
+
+ public PostgresSubscriptionMapper(PostgresSubscriptionDAO subscriptionDAO)
{
+ this.subscriptionDAO = subscriptionDAO;
+ }
+
+ @Override
+ public void save(Subscription subscription) throws SubscriptionException {
+ saveReactive(subscription).block();
+ }
+
+ @Override
+ public List<Subscription> findSubscriptionsForUser(Username user) throws
SubscriptionException {
+ return findSubscriptionsForUserReactive(user).collectList().block();
+ }
+
+ @Override
+ public void delete(Subscription subscription) throws SubscriptionException
{
+ deleteReactive(subscription).block();
+ }
+
+ @Override
+ public Mono<Void> saveReactive(Subscription subscription) {
+ return subscriptionDAO.save(subscription.getUser().asString(),
subscription.getMailbox());
+ }
+
+ @Override
+ public Flux<Subscription> findSubscriptionsForUserReactive(Username user) {
+ return subscriptionDAO.findMailboxByUser(user.asString())
+ .map(mailbox -> new Subscription(user, mailbox));
+ }
+
+ @Override
+ public Mono<Void> deleteReactive(Subscription subscription) {
+ return subscriptionDAO.delete(subscription.getUser().asString(),
subscription.getMailbox());
+ }
+}
diff --git
a/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresExecutor.java
b/mailbox/postgres/src/main/java/org/apache/james/mailbox/jpa/user/PostgresSubscriptionModule.java
similarity index 52%
copy from
backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresExecutor.java
copy to
mailbox/postgres/src/main/java/org/apache/james/mailbox/jpa/user/PostgresSubscriptionModule.java
index 78636dc186..66d5372eeb 100644
---
a/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresExecutor.java
+++
b/mailbox/postgres/src/main/java/org/apache/james/mailbox/jpa/user/PostgresSubscriptionModule.java
@@ -17,42 +17,29 @@
* under the License. *
****************************************************************/
-package org.apache.james.backends.postgres.utils;
+package org.apache.james.mailbox.jpa.user;
-import javax.inject.Inject;
+import static
org.apache.james.mailbox.jpa.user.PostgresSubscriptionTable.MAILBOX;
+import static
org.apache.james.mailbox.jpa.user.PostgresSubscriptionTable.TABLE_NAME;
+import static org.apache.james.mailbox.jpa.user.PostgresSubscriptionTable.USER;
-import org.jooq.DSLContext;
-import org.jooq.SQLDialect;
-import org.jooq.conf.Settings;
+import org.apache.james.backends.postgres.PostgresIndex;
+import org.apache.james.backends.postgres.PostgresModule;
+import org.apache.james.backends.postgres.PostgresTable;
import org.jooq.impl.DSL;
-import com.google.common.annotations.VisibleForTesting;
-
-import io.r2dbc.spi.Connection;
-import reactor.core.publisher.Mono;
-
-public class PostgresExecutor {
-
- private static final SQLDialect PGSQL_DIALECT = SQLDialect.POSTGRES;
- private static final Settings SETTINGS = new Settings()
- .withRenderFormatted(true);
- private final Mono<Connection> connection;
-
- @Inject
- public PostgresExecutor(Mono<Connection> connection) {
- this.connection = connection;
- }
-
- public Mono<DSLContext> dslContext() {
- return connection.map(con -> DSL.using(con, PGSQL_DIALECT, SETTINGS));
- }
-
- public Mono<Connection> connection() {
- return connection;
- }
-
- @VisibleForTesting
- public Mono<Void> dispose() {
- return connection.flatMap(con -> Mono.from(con.close()));
- }
+public interface PostgresSubscriptionModule {
+ PostgresTable TABLE = PostgresTable.name(TABLE_NAME.getName())
+ .createTableStep(((dsl, tableName) -> dsl.createTable(tableName)
+ .column(MAILBOX)
+ .column(USER)
+ .constraint(DSL.unique(MAILBOX, USER))))
+ .enableRowLevelSecurity();
+ PostgresIndex INDEX = PostgresIndex.name("subscription_user_index")
+ .createIndexStep((dsl, indexName) -> dsl.createIndex(indexName)
+ .on(TABLE_NAME, USER));
+ PostgresModule MODULE = PostgresModule.builder()
+ .addTable(TABLE)
+ .addIndex(INDEX)
+ .build();
}
diff --git
a/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresExecutor.java
b/mailbox/postgres/src/main/java/org/apache/james/mailbox/jpa/user/PostgresSubscriptionTable.java
similarity index 55%
copy from
backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresExecutor.java
copy to
mailbox/postgres/src/main/java/org/apache/james/mailbox/jpa/user/PostgresSubscriptionTable.java
index 78636dc186..3cdc2cf1e8 100644
---
a/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresExecutor.java
+++
b/mailbox/postgres/src/main/java/org/apache/james/mailbox/jpa/user/PostgresSubscriptionTable.java
@@ -17,42 +17,18 @@
* under the License. *
****************************************************************/
-package org.apache.james.backends.postgres.utils;
+package org.apache.james.mailbox.jpa.user;
-import javax.inject.Inject;
-
-import org.jooq.DSLContext;
-import org.jooq.SQLDialect;
-import org.jooq.conf.Settings;
+import org.jooq.Field;
+import org.jooq.Record;
+import org.jooq.Table;
import org.jooq.impl.DSL;
+import org.jooq.impl.SQLDataType;
-import com.google.common.annotations.VisibleForTesting;
-
-import io.r2dbc.spi.Connection;
-import reactor.core.publisher.Mono;
-
-public class PostgresExecutor {
-
- private static final SQLDialect PGSQL_DIALECT = SQLDialect.POSTGRES;
- private static final Settings SETTINGS = new Settings()
- .withRenderFormatted(true);
- private final Mono<Connection> connection;
-
- @Inject
- public PostgresExecutor(Mono<Connection> connection) {
- this.connection = connection;
- }
-
- public Mono<DSLContext> dslContext() {
- return connection.map(con -> DSL.using(con, PGSQL_DIALECT, SETTINGS));
- }
+public interface PostgresSubscriptionTable {
- public Mono<Connection> connection() {
- return connection;
- }
+ Field<String> MAILBOX = DSL.field("mailbox",
SQLDataType.VARCHAR(255).notNull());
+ Field<String> USER = DSL.field("user_name",
SQLDataType.VARCHAR(255).notNull());
+ Table<Record> TABLE_NAME = DSL.table("subscription");
- @VisibleForTesting
- public Mono<Void> dispose() {
- return connection.flatMap(con -> Mono.from(con.close()));
- }
}
diff --git
a/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresExecutor.java
b/mailbox/postgres/src/test/java/org/apache/james/mailbox/jpa/user/PostgresSubscriptionMapperTest.java
similarity index 54%
copy from
backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresExecutor.java
copy to
mailbox/postgres/src/test/java/org/apache/james/mailbox/jpa/user/PostgresSubscriptionMapperTest.java
index 78636dc186..009a900c35 100644
---
a/backends-common/postgres/src/main/java/org/apache/james/backends/postgres/utils/PostgresExecutor.java
+++
b/mailbox/postgres/src/test/java/org/apache/james/mailbox/jpa/user/PostgresSubscriptionMapperTest.java
@@ -17,42 +17,21 @@
* under the License. *
****************************************************************/
-package org.apache.james.backends.postgres.utils;
+package org.apache.james.mailbox.jpa.user;
-import javax.inject.Inject;
+import org.apache.james.backends.postgres.PostgresExtension;
+import org.apache.james.mailbox.store.user.SubscriptionMapper;
+import org.apache.james.mailbox.store.user.SubscriptionMapperTest;
+import org.junit.jupiter.api.extension.RegisterExtension;
-import org.jooq.DSLContext;
-import org.jooq.SQLDialect;
-import org.jooq.conf.Settings;
-import org.jooq.impl.DSL;
+public class PostgresSubscriptionMapperTest extends SubscriptionMapperTest {
-import com.google.common.annotations.VisibleForTesting;
+ @RegisterExtension
+ static PostgresExtension postgresExtension = new
PostgresExtension(PostgresSubscriptionModule.MODULE);
-import io.r2dbc.spi.Connection;
-import reactor.core.publisher.Mono;
-
-public class PostgresExecutor {
-
- private static final SQLDialect PGSQL_DIALECT = SQLDialect.POSTGRES;
- private static final Settings SETTINGS = new Settings()
- .withRenderFormatted(true);
- private final Mono<Connection> connection;
-
- @Inject
- public PostgresExecutor(Mono<Connection> connection) {
- this.connection = connection;
- }
-
- public Mono<DSLContext> dslContext() {
- return connection.map(con -> DSL.using(con, PGSQL_DIALECT, SETTINGS));
- }
-
- public Mono<Connection> connection() {
- return connection;
- }
-
- @VisibleForTesting
- public Mono<Void> dispose() {
- return connection.flatMap(con -> Mono.from(con.close()));
+ @Override
+ protected SubscriptionMapper createSubscriptionMapper() {
+ PostgresSubscriptionDAO dao = new
PostgresSubscriptionDAO(postgresExtension.getPostgresExecutor());
+ return new PostgresSubscriptionMapper(dao);
}
}
diff --git a/pom.xml b/pom.xml
index f2de37f723..cec1d1216c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2956,6 +2956,11 @@
<artifactId>junit-jupiter</artifactId>
<version>${testcontainers.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.testcontainers</groupId>
+ <artifactId>postgresql</artifactId>
+ <version>1.19.1</version>
+ </dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>pulsar</artifactId>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]