diff --git a/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/enums/IteratorNextMapperEnum.java b/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/enums/IteratorNextMapperEnum.java index b72c2f38..948e9a24 100644 --- a/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/enums/IteratorNextMapperEnum.java +++ b/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/enums/IteratorNextMapperEnum.java @@ -1,5 +1,5 @@ /* - * This file was last modified at 2024-05-14 21:36 by Victor N. Skurikhin. + * This file was last modified at 2024-05-22 23:14 by Victor N. Skurikhin. * This is free and unencumbered software released into the public domain. * For more information, please refer to * IteratorNextMapperEnum.java @@ -17,7 +17,7 @@ import java.util.function.Function; public enum IteratorNextMapperEnum { - Null(it -> Optional.empty()), + Null(null), LongIdIterator(it -> it.hasNext() ? Optional.of(it.next().getLong(Constants.ID)) : Optional.empty()), StringIdIterator(it -> it.hasNext() ? Optional.of(it.next().getString(Constants.ID)) : Optional.empty()), UUIDIdIterator(it -> it.hasNext() ? Optional.of(it.next().getUUID(Constants.ID)) : Optional.empty()); diff --git a/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/transact/StanzaTransactionalJob.java b/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/transact/StanzaTransactionalJob.java index feb199db..94e32ebf 100644 --- a/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/transact/StanzaTransactionalJob.java +++ b/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/transact/StanzaTransactionalJob.java @@ -1,5 +1,5 @@ /* - * This file was last modified at 2024-05-14 21:36 by Victor N. Skurikhin. + * This file was last modified at 2024-05-23 18:35 by Victor N. Skurikhin. * This is free and unencumbered software released into the public domain. * For more information, please refer to * StanzaTransactionalJob.java @@ -41,15 +41,14 @@ public StanzaTransactionalJob() { @TransactionAction( value = """ INSERT INTO dictionary.stanza - (id, name, description, parent_id, user_name, visible, flags) - VALUES(%s, $2, $3, $4, $5, $7, $8) - ON CONFLICT (name) DO + (id, name, description, parent_id, user_name, enabled, visible, flags) + VALUES($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (id) DO UPDATE SET name = $2, description = $3, parent_id = $4, - user_name = $5, - enabled = true, + enabled = $6, visible = $7, flags = $8 RETURNING id; @@ -80,9 +79,9 @@ public Uni> upsert(Collection> delete(@Nonnull StanzaTable table) { @@ -97,7 +96,7 @@ protected Function, Optional> iteratorNextMapper(String acti Constants.UPSERT_MAIN_TABLE, Constants.DELETE_MAIN -> iterator -> iterator.hasNext() - ? Optional.of(iterator.next().getUUID(StanzaTable.ID)) + ? Optional.of(iterator.next().getLong(StanzaTable.ID)) : Optional.empty(); default -> throw new IllegalStateException("Unexpected value: " + actionName); }; diff --git a/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/transact/one_to_many/AbstractListHelper.java b/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/transact/one_to_many/AbstractListHelper.java index 29f28eef..18ae9c81 100644 --- a/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/transact/one_to_many/AbstractListHelper.java +++ b/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/transact/one_to_many/AbstractListHelper.java @@ -1,5 +1,5 @@ /* - * This file was last modified at 2024-05-14 21:36 by Victor N. Skurikhin. + * This file was last modified at 2024-05-22 23:15 by Victor N. Skurikhin. * This is free and unencumbered software released into the public domain. * For more information, please refer to * AbstractListHelper.java @@ -48,7 +48,7 @@ protected void setConnection(@Nonnull final SqlConnection connection) { } protected Function, ? extends Optional> iteratorNextMapper(Action action, String aName) { - return (action.iteratorNextMapper() == null) + return action.iteratorNextMapper() == null ? job.iteratorNextMapper(aName) : action.iteratorNextMapper(); } diff --git a/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/transact/one_to_many/UpsertHelper.java b/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/transact/one_to_many/UpsertHelper.java index 4a8e7a90..f8ad8d5c 100644 --- a/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/transact/one_to_many/UpsertHelper.java +++ b/api-gateway/src/main/java/su/svn/daybook3/api/gateway/domain/transact/one_to_many/UpsertHelper.java @@ -1,5 +1,5 @@ /* - * This file was last modified at 2024-05-14 21:36 by Victor N. Skurikhin. + * This file was last modified at 2024-05-23 18:39 by Victor N. Skurikhin. * This is free and unencumbered software released into the public domain. * For more information, please refer to * UpsertHelper.java @@ -9,6 +9,7 @@ package su.svn.daybook3.api.gateway.domain.transact.one_to_many; import io.smallrye.mutiny.Uni; +import io.vertx.mutiny.sqlclient.Row; import io.vertx.mutiny.sqlclient.RowSet; import io.vertx.mutiny.sqlclient.SqlConnection; import io.vertx.mutiny.sqlclient.Tuple; @@ -55,11 +56,21 @@ public Uni> apply(@Nonnull final SqlConnection sqlConnection) { private Uni> checkCountInJoinTableAndThenInsert() { LOG.tracef("checkCountInJoinTableAndThenInsert"); - return Uni - .join() - .all(this.doEachMainTable()) - .andCollectFailures() - .map(this::listOfOptionalToList); + return Uni.combine() + .all() + .unis(this.doEachMainTable()) + .with(objects -> { + System.out.println("objects = " + objects); + return objects.stream().map(o -> { + if (o instanceof Optional opt) { + return job.castOptionalMainId().apply(opt); + } else { + return Optional.empty(); + } + }).filter(Optional::isPresent) + .map(Optional::get) + .toList(); + }); } @Nonnull @@ -70,58 +81,8 @@ private List>> doEachMainTable() { .toList(); } - @Nonnull - private List listOfOptionalToList(List> list) { - return list - .stream() - .map(o -> o.orElse(null)) - .filter(Objects::nonNull) - .toList(); - } - - private Uni> upsertMain(Pair> pair) { - var table = pair.getKey(); - var subsidiaries = pair.getValue(); - var helper = new UpsertMainHelper<>(super.job, super.map, table, subsidiaries); - helper.setConnection(super.connection); - return null; - } - - static class UpsertMainHelper< - MainId extends Comparable, - MainTable extends CasesOfId, - SubId extends Comparable, - Subsidiary extends CasesOfId> - extends AbstractHelper { - - private final Action action; - private final MainTable table; - private final Collection subsidiaries; - - UpsertMainHelper( - AbstractOneToManyJob job, - Map map, - MainTable table, - Collection subsidiaries) { - super(job, map); - this.action = super.map.get(Constants.UPSERT_MAIN_TABLE); - this.table = table; - this.subsidiaries = subsidiaries; - } - - @Override - public Uni> apply(@Nonnull final SqlConnection sqlConnection) { - return connection - .preparedQuery(this.action.sql()) - .execute(Helper.updateTuple(action, table)) - .map(RowSet::iterator) - .map(iteratorNextMapper(action, Constants.UPSERT_MAIN_TABLE)) - .map(job.castOptionalMainId()); - } - } - private Uni> updateRelation(Pair> pair) { - var action = super.map.get(Constants.UPDATE_RELATION); + var action = super.map.get(Constants.UPSERT_MAIN_TABLE); var table = pair.getKey(); var subsidiaries = pair.getValue(); var array = subsidiaries @@ -130,27 +91,35 @@ private Uni> updateRelation(PairtoArray(); return connection .preparedQuery(action.sql()) - .execute(Tuple.of(table.id(), array)) + .execute(Helper.updateTuple(action, table)) .map(RowSet::iterator) - .flatMap(r -> rowIteratorUniFunction1(table, array)); + .map(iteratorNextMapper(action, Constants.UPSERT_MAIN_TABLE)) + .map(job.castOptionalMainId()) + .flatMap( + mainId -> rowIteratorUniFunction1(table, array) + .replaceWith(Uni.createFrom().item(mainId)) + ) + .flatMap( + mainId -> rowIteratorUniFunction2(table, array) + .replaceWith(Uni.createFrom().item(mainId)) + ); } - private Uni> rowIteratorUniFunction1(MainTable table, Object[] array) { + private Uni> rowIteratorUniFunction1(MainTable table, Object[] array) { var action = super.map.get(Constants.CLEAR_RELATION); return connection .preparedQuery(action.sql()) .execute(Tuple.of(table.id(), array)) .map(RowSet::iterator) - .flatMap(r -> rowIteratorUniFunction2(table)); + .map(r -> r.hasNext() ? Optional.of(r.next()) : Optional.empty()); } - private Uni> rowIteratorUniFunction2(MainTable table) { - var action = super.map.get(Constants.UPDATE_MAIN_TABLE); + private Uni> rowIteratorUniFunction2(MainTable table, Object[] array) { + var action = super.map.get(Constants.UPDATE_RELATION); return connection .preparedQuery(action.sql()) - .execute(Helper.updateTuple(action, table)) + .execute(Tuple.of(table.id(), array)) .map(RowSet::iterator) - .map(iteratorNextMapper(action, Constants.UPDATE_MAIN_TABLE)) - .map(job.castOptionalMainId()); + .map(r -> r.hasNext() ? Optional.of(r.next()) : Optional.empty()); } } diff --git a/api-gateway/src/test/java/su/svn/daybook3/api/gateway/DataBaseIT.java b/api-gateway/src/test/java/su/svn/daybook3/api/gateway/DataBaseIT.java index 4abd7228..a1793da3 100644 --- a/api-gateway/src/test/java/su/svn/daybook3/api/gateway/DataBaseIT.java +++ b/api-gateway/src/test/java/su/svn/daybook3/api/gateway/DataBaseIT.java @@ -13,15 +13,54 @@ import io.smallrye.mutiny.Multi; import io.vertx.core.json.JsonObject; import jakarta.inject.Inject; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; -import org.junit.jupiter.api.*; -import su.svn.daybook3.api.gateway.domain.dao.*; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import su.svn.daybook3.api.gateway.domain.dao.CodifierDao; +import su.svn.daybook3.api.gateway.domain.dao.I18nDao; +import su.svn.daybook3.api.gateway.domain.dao.I18nViewDao; +import su.svn.daybook3.api.gateway.domain.dao.KeyValueDao; +import su.svn.daybook3.api.gateway.domain.dao.LanguageDao; +import su.svn.daybook3.api.gateway.domain.dao.RoleDao; +import su.svn.daybook3.api.gateway.domain.dao.SessionDao; +import su.svn.daybook3.api.gateway.domain.dao.SettingDao; +import su.svn.daybook3.api.gateway.domain.dao.SettingViewDao; +import su.svn.daybook3.api.gateway.domain.dao.StanzaDao; +import su.svn.daybook3.api.gateway.domain.dao.StanzaViewDao; +import su.svn.daybook3.api.gateway.domain.dao.TagLabelDao; +import su.svn.daybook3.api.gateway.domain.dao.UserNameDao; +import su.svn.daybook3.api.gateway.domain.dao.UserViewDao; +import su.svn.daybook3.api.gateway.domain.dao.ValueTypeDao; +import su.svn.daybook3.api.gateway.domain.dao.VocabularyDao; +import su.svn.daybook3.api.gateway.domain.dao.WordDao; import su.svn.daybook3.api.gateway.domain.messages.Answer; import su.svn.daybook3.api.gateway.domain.messages.ApiResponse; import su.svn.daybook3.api.gateway.domain.messages.Request; -import su.svn.daybook3.api.gateway.domain.model.*; +import su.svn.daybook3.api.gateway.domain.model.CodifierTable; +import su.svn.daybook3.api.gateway.domain.model.I18nTable; +import su.svn.daybook3.api.gateway.domain.model.I18nView; +import su.svn.daybook3.api.gateway.domain.model.KeyValueTable; +import su.svn.daybook3.api.gateway.domain.model.LanguageTable; +import su.svn.daybook3.api.gateway.domain.model.RoleTable; +import su.svn.daybook3.api.gateway.domain.model.SessionTable; +import su.svn.daybook3.api.gateway.domain.model.SettingTable; +import su.svn.daybook3.api.gateway.domain.model.SettingView; +import su.svn.daybook3.api.gateway.domain.model.StanzaTable; +import su.svn.daybook3.api.gateway.domain.model.StanzaView; +import su.svn.daybook3.api.gateway.domain.model.TagLabelTable; +import su.svn.daybook3.api.gateway.domain.model.UserNameTable; +import su.svn.daybook3.api.gateway.domain.model.UserView; +import su.svn.daybook3.api.gateway.domain.model.ValueTypeTable; +import su.svn.daybook3.api.gateway.domain.model.VocabularyTable; +import su.svn.daybook3.api.gateway.domain.model.WordTable; import su.svn.daybook3.api.gateway.domain.transact.I18nTransactionalJob; import su.svn.daybook3.api.gateway.domain.transact.SettingTransactionalJob; +import su.svn.daybook3.api.gateway.domain.transact.StanzaTransactionalJob; import su.svn.daybook3.api.gateway.domain.transact.UserTransactionalJob; import su.svn.daybook3.api.gateway.models.TimeUpdated; import su.svn.daybook3.api.gateway.models.domain.User; @@ -31,6 +70,7 @@ import java.math.BigInteger; import java.security.Principal; import java.time.LocalDateTime; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; @@ -38,7 +78,10 @@ import java.util.function.Function; import java.util.function.Supplier; -import static su.svn.daybook3.api.gateway.TestUtils.*; +import static su.svn.daybook3.api.gateway.TestUtils.multiAsListHelper; +import static su.svn.daybook3.api.gateway.TestUtils.uniListHelper; +import static su.svn.daybook3.api.gateway.TestUtils.uniOptionalHelper; +import static su.svn.daybook3.api.gateway.TestUtils.uniToAnswerHelper; @SuppressWarnings({"SameParameterValue"}) @QuarkusTest @@ -71,6 +114,8 @@ public class DataBaseIT { @Inject StanzaViewDao stanzaViewDao; @Inject + StanzaTransactionalJob stanzaTransactionalJob; + @Inject TagLabelDao tagLabelDao; @Inject UserNameDao userNameDao; @@ -1452,6 +1497,85 @@ void test() { } } + @SuppressWarnings("UnusedReturnValue") + @Nested + @DisplayName("StanzaTransactionalJob") + class StanzaTransactionalJobTest { + + long valueTypeId; + UUID userNameId; + SettingTable setting; + + @BeforeEach + void setUp() { + userNameId = UUID.randomUUID(); + var userName = UserNameTable.builder() + .id(userNameId) + .userName("user") + .password("password") + .enabled(true) + .build(); + Assertions.assertDoesNotThrow(() -> { + uniOptionalHelper(userNameDao.insert(userName)); + }); + var valueType = ValueTypeTable.builder() + .valueType(ValueTypeTable.NONE) + .enabled(true) + .build(); + Assertions.assertDoesNotThrow(() -> { + valueTypeId = uniOptionalHelper(valueTypeDao.insert(valueType)); + }); + setting = SettingTable.builder() + .id(13L) + .variable("variable1") + .value(SettingTable.NONE) + .valueTypeId(valueTypeId) + .stanzaId(0L) + .build(); + Assertions.assertDoesNotThrow(() -> { + uniOptionalHelper(settingDao.insert(setting)); + }); + } + + @AfterEach + void tearDown() { + Assertions.assertDoesNotThrow(() -> { + uniOptionalHelper(settingDao.delete(13L)); + }); + Assertions.assertDoesNotThrow(() -> { + uniOptionalHelper(valueTypeDao.delete(valueTypeId)); + }); + Assertions.assertDoesNotThrow(() -> { + uniOptionalHelper(userNameDao.delete(userNameId)); + }); + } + + @Test + void test() { + var stanza1 = StanzaTable.builder() + .id(13L) + .name("name1") + .description("description1") + .parentId(0L) + .userName("user") + .createTime(LocalDateTime.now()) + .updateTime(LocalDateTime.now()) + .build(); + var setting1 = setting.toBuilder().stanzaId(13L).build(); + + Collection settings = Collections.singleton(setting1); + Pair> pair = Pair.of(stanza1, settings); + Collection>> stanzas = Collections.singleton(pair); + + Assertions.assertDoesNotThrow(() -> { + uniListHelper(stanzaTransactionalJob.upsert(stanzas)); + }); + Assertions.assertDoesNotThrow(() -> { + uniOptionalHelper(stanzaTransactionalJob.delete(stanza1)); + }); + } + } + @Nested @DisplayName("TagLabelDao") class TagLabelDaoTest extends AbstractDaoTest { diff --git a/api-gateway/src/test/java/su/svn/daybook3/api/gateway/TestUtils.java b/api-gateway/src/test/java/su/svn/daybook3/api/gateway/TestUtils.java index e96a4847..f452f374 100644 --- a/api-gateway/src/test/java/su/svn/daybook3/api/gateway/TestUtils.java +++ b/api-gateway/src/test/java/su/svn/daybook3/api/gateway/TestUtils.java @@ -17,6 +17,7 @@ import java.time.LocalTime; import java.util.List; import java.util.Optional; +import java.util.concurrent.CompletableFuture; public class TestUtils { @@ -43,6 +44,12 @@ public static List multiAsListHelper(Multi multi) throws Exception { return multi.collect().asList().subscribeAsCompletionStage().get(); } + public static List uniListHelper(Uni> uni) throws Exception { + var result = uni.subscribeAsCompletionStage(); + Assertions.assertNotNull(result); + return result.get(); + } + public static T uniOptionalHelper(Uni> uni) throws Exception { var result = uni.subscribeAsCompletionStage(); Assertions.assertNotNull(result);