diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 01314585c..8c7c3d0bd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,7 +2,7 @@ name: Java CI with Maven on: push: - branches: "*" + branches: "main" pull_request: branches: "*" @@ -74,6 +74,30 @@ jobs: - name: Run tests with postgres run: mvn test -pl core -am -Dspring.profiles.active=postgres + test-mariadb: + runs-on: ubuntu-latest + needs: build + services: + postgres: + image: mariadb:latest + env: + MYSQL_USER: sa + MYSQL_ROOT_PASSWORD: veryStrong123 + MYSQL_PASSWORD: veryStrong123 + MYSQL_DATABASE: testdb + ports: + - 3306:3306 + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + cache: maven + - name: Run tests with mariadb + run: mvn test -pl core -am -Dspring.profiles.active=mariadb + java-doc: runs-on: ubuntu-latest needs: [build] @@ -105,7 +129,7 @@ jobs: maven-deploy: runs-on: ubuntu-latest - needs: [build, test-mssql, test-postgres] + needs: [build, test-mssql, test-postgres, test-mariadb] if: ${{ github.ref == 'refs/heads/main' }} steps: - uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fb57d070..bf1398d8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## v1.3.0 - (2025-01-01) + +- MariaDB support +- PostgreSQL support + ## v1.2.0 - (2024-12-31) - Run now button in the UI diff --git a/README.md b/README.md index ec8a4c1e9..33fda7ecb 100644 --- a/README.md +++ b/README.md @@ -12,15 +12,20 @@ Secondary goal is to support [Poor mans Workflow](https://github.com/sterlp/pmw) ## Tested in the pipeline -- H2 -- azure-sql-edge (MSSQL) +- H2 +- azure-sql-edge (MSSQL) +- PostgreSQL +- MariaDB + +![History](screenshots/supported-dbs.png) ## Supported in theory -- MSSQL -- PostgreSQL -- mySQL -- MariaDB +- MSSQL, as azure-sql-edge is tested + +## Not supported + +- mySQL: sequences are not supported # Setup and Run a Task diff --git a/RUN_AND_BUILD.md b/RUN_AND_BUILD.md index 23c0b6a05..209cdd5c5 100644 --- a/RUN_AND_BUILD.md +++ b/RUN_AND_BUILD.md @@ -1,7 +1,15 @@ mvn versions:display-dependency-updates -mvn versions:set -DnewVersion=1.2.1 -DgenerateBackupPoms=false -mvn versions:set -DnewVersion=1.2.2-SNAPSHOT -DgenerateBackupPoms=false +mvn versions:set -DnewVersion=1.3.0 -DgenerateBackupPoms=false +mvn versions:set -DnewVersion=1.3.1-SNAPSHOT -DgenerateBackupPoms=false +## postgres docker run --name pg-container -e POSTGRES_USER=sa -e POSTGRES_PASSWORD=veryStrong123 -p 5432:5432 -d postgres +## azure-sql-edge docker run --cap-add SYS_PTRACE -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=veryStrong123' -p 1433:1433 --name azuresqledge -d mcr.microsoft.com/azure-sql-edge + +## MariaDB +docker run -e MYSQL_ROOT_PASSWORD=veryStrong123 -e MYSQL_DATABASE=testdb -e MYSQL_USER=sa -e MYSQL_PASSWORD=veryStrong123 -p 3306:3306 -d mariadb:latest + +## MySQL +docker run -e MYSQL_ROOT_PASSWORD=veryStrong123 -e MYSQL_DATABASE=testdb -e MYSQL_USER=sa -e MYSQL_PASSWORD=veryStrong123 -p 3306:3306 -d mysql diff --git a/core/pom.xml b/core/pom.xml index fc9fd2187..9eae2c4d1 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -6,7 +6,7 @@ org.sterl.spring spring-persistent-tasks-root - 1.2.2-SNAPSHOT + 1.3.1-SNAPSHOT ../pom.xml @@ -89,6 +89,16 @@ postgresql test + + com.mysql + mysql-connector-j + test + + + org.mariadb.jdbc + mariadb-java-client + test + diff --git a/core/src/main/java/org/sterl/spring/persistent_tasks/history/model/TriggerHistoryDetailEntity.java b/core/src/main/java/org/sterl/spring/persistent_tasks/history/model/TriggerHistoryDetailEntity.java index 5334dd236..9c46fc0c9 100644 --- a/core/src/main/java/org/sterl/spring/persistent_tasks/history/model/TriggerHistoryDetailEntity.java +++ b/core/src/main/java/org/sterl/spring/persistent_tasks/history/model/TriggerHistoryDetailEntity.java @@ -25,12 +25,12 @@ * Just a copy of the trigger status but without any data/state. */ @Entity -@Table(name = "PT_TRIGGER_HISTORY_DETAILS", indexes = { - @Index(name = "IDX_PT_TRIGGERS_HISTORY_INSTANCE_ID", columnList = "instance_id"), - @Index(name = "IDX_PT_TRIGGERS_HISTORY_TASK_NAME", columnList = "task_name"), - @Index(name = "IDX_PT_TRIGGERS_HISTORY_TRIGGER_ID", columnList = "trigger_id"), - @Index(name = "IDX_PT_TRIGGERS_HISTORY_STATUS", columnList = "status"), - @Index(name = "IDX_PT_TRIGGERS_HISTORY_CREATED_TIME", columnList = "created_time"), +@Table(name = "pt_trigger_history_details", indexes = { + @Index(name = "idx_pt_triggers_history_instance_id", columnList = "instance_id"), + @Index(name = "idx_pt_triggers_history_task_name", columnList = "task_name"), + @Index(name = "idx_pt_triggers_history_trigger_id", columnList = "trigger_id"), + @Index(name = "idx_pt_triggers_history_status", columnList = "status"), + @Index(name = "idx_pt_triggers_history_created_time", columnList = "created_time"), }) @Data @NoArgsConstructor @@ -39,7 +39,7 @@ @EqualsAndHashCode(of = "id") public class TriggerHistoryDetailEntity implements HasTriggerData { - @GeneratedValue(generator = "SEQ_PT_TRIGGER_HISTORY_DETAILS", strategy = GenerationType.SEQUENCE) + @GeneratedValue(generator = "seq_pt_trigger_history_details", strategy = GenerationType.SEQUENCE) @Column(updatable = false) @Id private Long id; diff --git a/core/src/main/java/org/sterl/spring/persistent_tasks/history/model/TriggerHistoryLastStateEntity.java b/core/src/main/java/org/sterl/spring/persistent_tasks/history/model/TriggerHistoryLastStateEntity.java index e6b9504d0..fbb09a362 100644 --- a/core/src/main/java/org/sterl/spring/persistent_tasks/history/model/TriggerHistoryLastStateEntity.java +++ b/core/src/main/java/org/sterl/spring/persistent_tasks/history/model/TriggerHistoryLastStateEntity.java @@ -20,11 +20,11 @@ import lombok.NoArgsConstructor; @Entity -@Table(name = "PT_TRIGGER_HISTORY_LAST_STATES", indexes = { - @Index(name = "IDX_PT_TRIGGER_HISTORY_LAST_STATES_TASK_NAME", columnList = "task_name"), - @Index(name = "IDX_PT_TRIGGER_HISTORY_LAST_STATES_TRIGGER_ID", columnList = "trigger_id"), - @Index(name = "IDX_PT_TRIGGER_HISTORY_LAST_STATES_STATUS", columnList = "status"), - @Index(name = "IDX_PT_TRIGGER_HISTORY_LAST_STATES_CREATED_TIME", columnList = "created_time"), +@Table(name = "pt_trigger_history_last_states", indexes = { + @Index(name = "idx_pt_trigger_history_last_states_task_name", columnList = "task_name"), + @Index(name = "idx_pt_trigger_history_last_states_trigger_id", columnList = "trigger_id"), + @Index(name = "idx_pt_trigger_history_last_states_status", columnList = "status"), + @Index(name = "idx_pt_trigger_history_last_states_created_time", columnList = "created_time"), }) @Data @NoArgsConstructor diff --git a/core/src/main/java/org/sterl/spring/persistent_tasks/scheduler/SchedulerService.java b/core/src/main/java/org/sterl/spring/persistent_tasks/scheduler/SchedulerService.java index f1d004652..d3582742a 100644 --- a/core/src/main/java/org/sterl/spring/persistent_tasks/scheduler/SchedulerService.java +++ b/core/src/main/java/org/sterl/spring/persistent_tasks/scheduler/SchedulerService.java @@ -70,11 +70,14 @@ public void shutdownNow() { } public SchedulerEntity pingRegistry() { - var result = editSchedulerStatus.checkinToRegistry(name); - result.setRunnungTasks(taskExecutor.getRunningTasks()); - result.setTasksSlotCount(taskExecutor.getMaxThreads()); - log.debug("Ping {}", result); - return result; + // using trx template to ensure the TRX is started if we use this method internally + return trx.execute(t -> { + var result = editSchedulerStatus.checkinToRegistry(name); + result.setRunnungTasks(taskExecutor.getRunningTasks()); + result.setTasksSlotCount(taskExecutor.getMaxThreads()); + log.debug("Ping {}", result); + return result; + }); } public SchedulerEntity getScheduler() { @@ -100,21 +103,16 @@ public List> triggerNextTasks() { */ @NonNull public List> triggerNextTasks(OffsetDateTime timeDue) { - var triggers = trx.execute(t -> { - List result; - // in any case we say hello - final var runningOn = pingRegistry(); - if (taskExecutor.getFreeThreads() > 0) { - result = triggerService.lockNextTrigger( - name, taskExecutor.getFreeThreads(), timeDue); - runningOn.setRunnungTasks(taskExecutor.getRunningTasks() + result.size()); - } else { - result = Collections.emptyList(); - log.debug("triggerNextTasks({}) skipped as no free threads are available.", timeDue); - } - return result; - }); - return taskExecutor.submit(triggers); + List triggers; + if (taskExecutor.getFreeThreads() > 0) { + triggers = triggerService.lockNextTrigger( + name, taskExecutor.getFreeThreads(), timeDue); + } else { + triggers = Collections.emptyList(); + } + var result = taskExecutor.submit(triggers); + pingRegistry(); + return result; } /** diff --git a/core/src/main/java/org/sterl/spring/persistent_tasks/scheduler/entity/SchedulerEntity.java b/core/src/main/java/org/sterl/spring/persistent_tasks/scheduler/entity/SchedulerEntity.java index ce9d802d2..dd4043780 100644 --- a/core/src/main/java/org/sterl/spring/persistent_tasks/scheduler/entity/SchedulerEntity.java +++ b/core/src/main/java/org/sterl/spring/persistent_tasks/scheduler/entity/SchedulerEntity.java @@ -13,7 +13,7 @@ import lombok.ToString; @Entity -@Table(name = "PT_SCHEDULER", indexes = @Index(name = "IDX_TASK_SCHEDULER_STATUS", columnList = "last_ping")) +@Table(name = "pt_scheduler", indexes = @Index(name = "idx_task_scheduler_status", columnList = "last_ping")) @Data @ToString(of = { "id", "lastPing", "runnungTasks", "tasksSlotCount" }) @EqualsAndHashCode(of = "id") diff --git a/core/src/main/java/org/sterl/spring/persistent_tasks/trigger/model/TriggerEntity.java b/core/src/main/java/org/sterl/spring/persistent_tasks/trigger/model/TriggerEntity.java index 89c16be0a..87899e0b9 100644 --- a/core/src/main/java/org/sterl/spring/persistent_tasks/trigger/model/TriggerEntity.java +++ b/core/src/main/java/org/sterl/spring/persistent_tasks/trigger/model/TriggerEntity.java @@ -25,12 +25,12 @@ import lombok.NoArgsConstructor; @Entity -@Table(name = "PT_TASK_TRIGGERS", indexes = { - @Index(name = "UNQ_PT_TRIGGERS_KEY", columnList = "trigger_id, task_name", unique = true), - @Index(name = "IDX_PT_TRIGGERS_PRIORITY", columnList = "priority"), - @Index(name = "IDX_PT_TRIGGERS_RUN_AT", columnList = "run_at"), - @Index(name = "IDX_PT_TRIGGERS_STATUS", columnList = "status"), - @Index(name = "IDX_PT_TRIGGERS_PING", columnList = "last_ping"), +@Table(name = "pt_task_triggers", indexes = { + @Index(name = "unq_pt_triggers_key", columnList = "trigger_id, task_name", unique = true), + @Index(name = "idx_pt_triggers_priority", columnList = "priority"), + @Index(name = "idx_pt_triggers_run_at", columnList = "run_at"), + @Index(name = "idx_pt_triggers_status", columnList = "status"), + @Index(name = "idx_pt_triggers_ping", columnList = "last_ping"), }) @Data @NoArgsConstructor @@ -39,7 +39,7 @@ @Builder public class TriggerEntity implements HasTriggerData { - @GeneratedValue(generator = "SEQ_PT_TASK_TRIGGERS", strategy = GenerationType.SEQUENCE) + @GeneratedValue(generator = "seq_pt_task_triggers", strategy = GenerationType.SEQUENCE) @Column(updatable = false) @Id private Long id; diff --git a/core/src/test/java/org/sterl/spring/persistent_tasks/AbstractSpringTest.java b/core/src/test/java/org/sterl/spring/persistent_tasks/AbstractSpringTest.java index ccf810d8a..db53e9dba 100644 --- a/core/src/test/java/org/sterl/spring/persistent_tasks/AbstractSpringTest.java +++ b/core/src/test/java/org/sterl/spring/persistent_tasks/AbstractSpringTest.java @@ -34,7 +34,7 @@ import uk.co.jemos.podam.api.PodamFactory; import uk.co.jemos.podam.api.PodamFactoryImpl; -//@ActiveProfiles("postgres") // postgres mssql +// @ActiveProfiles("mssql") // postgres mssql mariadb mysql @SpringBootTest(classes = SampleApp.class, webEnvironment = WebEnvironment.RANDOM_PORT) public class AbstractSpringTest { diff --git a/core/src/test/java/org/sterl/spring/persistent_tasks/TaskSchedulerServiceTest.java b/core/src/test/java/org/sterl/spring/persistent_tasks/TaskSchedulerServiceTest.java index 3d6787792..fb4fd2332 100644 --- a/core/src/test/java/org/sterl/spring/persistent_tasks/TaskSchedulerServiceTest.java +++ b/core/src/test/java/org/sterl/spring/persistent_tasks/TaskSchedulerServiceTest.java @@ -59,11 +59,7 @@ void testLockTriggerInSchedulers() throws Exception { lockInvocations.add(() -> runNextTrigger()); } - while (triggerService.hasPendingTriggers()) { - schedulerService.triggerNextTasks(); - schedulerB.triggerNextTasks(); - Thread.sleep(10); - } + persistentTaskService.executeTriggersAndWait(); // THEN for (int i = 1; i <= 100; ++i) { diff --git a/core/src/test/java/org/sterl/spring/persistent_tasks/scheduler/SchedulerServiceTest.java b/core/src/test/java/org/sterl/spring/persistent_tasks/scheduler/SchedulerServiceTest.java index 77570383e..2f6d91816 100644 --- a/core/src/test/java/org/sterl/spring/persistent_tasks/scheduler/SchedulerServiceTest.java +++ b/core/src/test/java/org/sterl/spring/persistent_tasks/scheduler/SchedulerServiceTest.java @@ -44,7 +44,7 @@ void testWillTriggerOnlyFreeThreadSize() throws Exception { for (int i = 0; i < 15; i++) { triggerService.queue(TaskTriggerBuilder .newTrigger("slowTask") - .state(50L) + .state(200L) .build() ); } @@ -53,9 +53,9 @@ void testWillTriggerOnlyFreeThreadSize() throws Exception { subject.triggerNextTasks(); // THEN - Thread.sleep(15); assertThat(triggerService.countTriggers(TriggerStatus.RUNNING)).isEqualTo(10); assertThat(triggerService.countTriggers(TriggerStatus.WAITING)).isEqualTo(5); + // AND final SchedulerEntity scheduler = subject.getScheduler(); assertThat(scheduler.getRunnungTasks()).isEqualTo(10); diff --git a/core/src/test/resources/application-mariadb.yml b/core/src/test/resources/application-mariadb.yml new file mode 100644 index 000000000..a3d1adf99 --- /dev/null +++ b/core/src/test/resources/application-mariadb.yml @@ -0,0 +1,11 @@ +spring: + datasource: + username: root + password: veryStrong123 + url: jdbc:mariadb://localhost:3306/testdb + driver-class-name: org.mariadb.jdbc.Driver + hikari: + maximum-pool-size: 100 + jpa: + hibernate: + ddl-auto: none \ No newline at end of file diff --git a/core/src/test/resources/application-mysql.yml b/core/src/test/resources/application-mysql.yml new file mode 100644 index 000000000..6416497f7 --- /dev/null +++ b/core/src/test/resources/application-mysql.yml @@ -0,0 +1,14 @@ +spring: + datasource: + username: root + password: veryStrong123 + url: jdbc:mysql://localhost:3306/testdb + driver-class-name: com.mysql.jdbc.Driver + hikari: + maximum-pool-size: 100 + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.MySQLDialect + hibernate: + ddl-auto: create diff --git a/core/src/test/resources/db/changelog/db.changelog-master.xml b/core/src/test/resources/db/changelog/db.changelog-master.xml index b43fc3dc9..c72d6eeed 100644 --- a/core/src/test/resources/db/changelog/db.changelog-master.xml +++ b/core/src/test/resources/db/changelog/db.changelog-master.xml @@ -8,10 +8,10 @@ http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd"> - + + primaryKeyName="pk_personbe_id" /> diff --git a/db/pom.xml b/db/pom.xml index 8082322c2..2eca93acb 100644 --- a/db/pom.xml +++ b/db/pom.xml @@ -6,7 +6,7 @@ org.sterl.spring spring-persistent-tasks-root - 1.2.2-SNAPSHOT + 1.3.1-SNAPSHOT ../pom.xml diff --git a/db/src/main/resources/spring-persistent-tasks/db/pt-changelog-v1.xml b/db/src/main/resources/spring-persistent-tasks/db/pt-changelog-v1.xml index f1ab91ea1..6b72da0fe 100644 --- a/db/src/main/resources/spring-persistent-tasks/db/pt-changelog-v1.xml +++ b/db/src/main/resources/spring-persistent-tasks/db/pt-changelog-v1.xml @@ -20,10 +20,10 @@ - + + primaryKeyName="PK_pt_task_triggers_ID" /> @@ -54,10 +54,10 @@ - + + primaryKeyName="pk_pt_trigger_history_details_id" /> @@ -85,10 +85,10 @@ - + + primaryKeyName="pk_pt_trigger_history_last_states_id" /> @@ -117,10 +117,10 @@ - + + primaryKeyName="pk_pt_scheduler_id" /> @@ -140,69 +140,69 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + minValue="-9223372036854775808" sequenceName="seq_pt_task_triggers" startValue="1" /> \ No newline at end of file diff --git a/example/pom.xml b/example/pom.xml index 482ecb536..fd8453e70 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -6,7 +6,7 @@ org.sterl.spring spring-persistent-tasks-root - 1.2.2-SNAPSHOT + 1.3.1-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index aa245564d..4e3455ce8 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.sterl.spring spring-persistent-tasks-root - 1.2.2-SNAPSHOT + 1.3.1-SNAPSHOT pom 2024 diff --git a/screenshots/supported-dbs.png b/screenshots/supported-dbs.png new file mode 100644 index 000000000..6c2b72c01 Binary files /dev/null and b/screenshots/supported-dbs.png differ diff --git a/ui/pom.xml b/ui/pom.xml index 5b533a38f..415d6f25b 100644 --- a/ui/pom.xml +++ b/ui/pom.xml @@ -6,7 +6,7 @@ org.sterl.spring spring-persistent-tasks-root - 1.2.2-SNAPSHOT + 1.3.1-SNAPSHOT ../pom.xml