From 747168949c5d0cf12adacc723f9868d931806d38 Mon Sep 17 00:00:00 2001 From: Matthieu Jacquet Date: Mon, 6 Nov 2023 23:24:42 +0100 Subject: [PATCH] bump to java 17, kotlin 1.9.10 and libraries (#191) - Bump to gradle 8.4 and jvm toolchain 17 - Change ci and code to jvm 17 and kotlin to 1.9.20 - Bump several libraries. - Plugin replace ktfmt with Spotless (with ktfmt) - Bumped Infinitic version to 0.11.7 - Separate build and test and lint Co-authored-by: @Ouriel and @geomagilles --- .addlicense.yml | 60 +- .github/stale.yml | 2 +- .github/workflows/engine-ci.yml | 24 +- .github/workflows/release.yml | 4 +- .github/workflows/repository.yml | 18 +- README.md | 10 +- build.gradle.kts | 12 +- buildSrc/build.gradle.kts | 31 +- buildSrc/src/main/kotlin/Ci.kt | 2 +- buildSrc/src/main/kotlin/Libs.kt | 24 +- buildSrc/src/main/kotlin/Plugins.kt | 14 +- gradle/wrapper/gradle-wrapper.jar | Bin 59821 -> 62076 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 25 +- gradlew.bat | 15 +- infinitic-cache/build.gradle.kts | 27 +- .../io/infinitic/cache/keySet/CachedKeySet.kt | 3 + .../cache/keyValue/CachedKeyValue.kt | 2 + infinitic-client-base/build.gradle.kts | 29 +- .../infinitic/clients/ClientWorkflowTests.kt | 2 +- .../io/infinitic/clients/samples/FakeTask.kt | 7 + .../infinitic/clients/samples/FakeWorkflow.kt | 14 + infinitic-client/build.gradle.kts | 33 +- infinitic-common/build.gradle.kts | 20 +- .../infinitic/common/data/MillisDuration.kt | 2 + .../io/infinitic/common/data/MillisInstant.kt | 2 + .../kotlin/io/infinitic/common/data/Name.kt | 2 + .../io/infinitic/common/data/ReturnValue.kt | 2 + .../data/methods/MethodParameterTypes.kt | 2 + .../common/data/methods/MethodParameters.kt | 2 + .../io/infinitic/common/parser/Parser.kt | 12 +- .../serDe/kserializer/DurationSerializer.kt | 1 + .../serDe/kserializer/UUIDSerializer.kt | 2 + .../common/tasks/data/ServiceName.kt | 1 + .../infinitic/common/tasks/data/TaskMeta.kt | 2 + .../common/tasks/data/TaskRetryIndex.kt | 2 + .../common/tasks/data/TaskRetrySequence.kt | 1 + .../io/infinitic/common/tasks/data/TaskTag.kt | 2 + .../workers/registry/RegisteredWorkflow.kt | 1 + .../workflows/data/channels/ChannelFilter.kt | 2 + .../workflows/data/channels/ChannelName.kt | 1 + .../workflows/data/channels/ChannelType.kt | 3 + .../workflows/data/channels/SignalData.kt | 2 + .../workflows/data/commands/CommandHash.kt | 2 + .../workflows/data/commands/CommandId.kt | 3 + .../workflows/data/commands/CommandStatus.kt | 1 + .../workflows/data/properties/PropertyHash.kt | 2 + .../workflows/data/properties/PropertyName.kt | 2 + .../data/properties/PropertyValue.kt | 2 + .../common/workflows/data/steps/Step.kt | 5 +- .../common/workflows/data/steps/StepHash.kt | 2 + .../data/workflowTasks/WorkflowTaskIndex.kt | 2 + .../workflows/data/workflows/WorkflowMeta.kt | 2 + .../workflows/data/workflows/WorkflowName.kt | 2 + .../workflows/data/workflows/WorkflowTag.kt | 2 + .../engine/messages/WorkflowEngineMessage.kt | 4 + .../workflows/engine/state/WorkflowState.kt | 4 +- .../engine/storage/WorkflowStateStorage.kt | 2 + .../kotlin/io/infinitic/workflows/Deferred.kt | 2 + .../schemas/clientEnvelope-0.11.7.avsc | 431 +++++ .../schemas/taskExecutorEnvelope-0.11.7.avsc | 124 ++ .../schemas/taskTagEnvelope-0.11.7.avsc | 117 ++ .../workflowEngineEnvelope-0.11.7.avsc | 716 ++++++++ .../schemas/workflowState-0.11.7.avsc | 1352 +++++++++++++++ .../schemas/workflowTagEnvelope-0.11.7.avsc | 353 ++++ .../workflowTaskParameters-0.11.7.avsc | 817 +++++++++ .../workflowTaskReturnValue-0.11.7.avsc | 660 ++++++++ infinitic-common/src/main/resources/version | 2 +- infinitic-common/src/main/resources/versions | 1 + .../io/infinitic/common/tasks/DataTests.kt | 1 - .../infinitic/common/workflows/DataTests.kt | 1 - .../io/infinitic/workflows/DataTests.kt | 1 - .../io/infinitic/workflows/samples/TaskA.kt | 2 + .../infinitic/workflows/samples/WorkflowA.kt | 9 + infinitic-dashboard/README.md | 1 - infinitic-dashboard/build.gradle.kts | 41 +- infinitic-dashboard/postcss.config.js | 10 +- .../panels/infrastructure/AllJobsPanel.kt | 6 +- .../panels/infrastructure/AllJobsState.kt | 4 +- .../panels/infrastructure/AllTasksState.kt | 2 +- .../infrastructure/AllWorkflowsState.kt | 2 +- .../panels/infrastructure/jobs/JobState.kt | 3 +- .../jobs/displayJobSectionHeader.kt | 2 +- .../panels/infrastructure/requests/Request.kt | 4 +- .../panels/infrastructure/task/TaskPanel.kt | 2 +- .../infrastructure/workflow/WorkflowPanel.kt | 4 +- .../src/main/resources/css/compiled.css | 1486 ++++++++++------- .../main/resources/simplelogger.properties | 9 - infinitic-dashboard/tailwind.config.js | 18 +- infinitic-inMemory/build.gradle.kts | 47 +- .../test/resources/simplelogger.properties | 6 - infinitic-pulsar/build.gradle.kts | 61 +- .../infinitic/pulsar/PulsarInfiniticAdmin.kt | 5 +- .../infinitic/pulsar/PulsarInfiniticWorker.kt | 4 +- .../io/infinitic/pulsar/getProducerName.kt | 2 +- .../io/infinitic/pulsar/samples/TaskA.kt | 4 + .../io/infinitic/pulsar/samples/WorkflowA.kt | 21 + .../io/infinitic/pulsar/samples/WorkflowB.kt | 1 + infinitic-storage/build.gradle.kts | 4 +- .../infinitic/storage/keySet/KeySetStorage.kt | 2 + .../storage/keyValue/KeyValueStorage.kt | 2 + .../infinitic/storage/config/StorageTests.kt | 81 +- infinitic-task-executor/build.gradle.kts | 33 +- .../infinitic/tasks/executor/TaskExecutor.kt | 20 +- .../tasks/executor/samples/SimpleService.kt | 5 + infinitic-task-tag/build.gradle.kts | 33 +- infinitic-tests/build.gradle.kts | 45 +- .../tests/branches/BranchesWorkflow.kt | 7 + .../tests/channels/ChannelWorkflowTests.kt | 2 +- .../tests/channels/ChannelsWorkflow.kt | 13 + .../tests/children/ChildrenWorkflow.kt | 3 + .../tests/context/ContextWorkflow.kt | 8 + .../tests/deferred/DeferredWorkflow.kt | 11 + .../infinitic/tests/errors/ErrorsWorkflow.kt | 18 + .../infinitic/tests/inline/InlineWorkflow.kt | 2 + .../tests/properties/PropertiesWorkflow.kt | 16 + .../io/infinitic/tests/scaffolds/engine.kt | 2 +- .../infinitic/tests/syntax/SyntaxWorkflow.kt | 2 + .../tests/timers/TimerWorkflowTests.kt | 174 +- .../io/infinitic/tests/utils/TestService.kt | 1 + .../io/infinitic/tests/utils/UtilService.kt | 9 + .../io/infinitic/tests/utils/UtilWorkflow.kt | 7 + .../test/resources/simplelogger.properties | 9 - infinitic-transport-inmemory/build.gradle.kts | 43 +- .../transport/inMemory/InMemoryStarter.kt | 4 +- .../test/resources/simplelogger.properties | 6 - infinitic-transport-pulsar/build.gradle.kts | 49 +- .../transport/pulsar/topics/TopicNames.kt | 3 + infinitic-transport/build.gradle.kts | 27 +- infinitic-worker-base/build.gradle.kts | 45 +- .../io/infinitic/workers/WorkerAbstract.kt | 2 +- infinitic-worker/build.gradle.kts | 59 +- .../io/infinitic/workers/config/Workflow.kt | 2 +- infinitic-workflow-engine/build.gradle.kts | 33 +- .../workflows/engine/WorkflowEngine.kt | 2 +- .../workflows/engine/handlers/SendSignal.kt | 3 +- .../workflows/engine/WorkflowEngineTests.kt | 2 +- infinitic-workflow-tag/build.gradle.kts | 33 +- infinitic-workflow-task/build.gradle.kts | 33 +- .../workflowTask/workflows/WorkflowA.kt | 2 +- pulsar/README.md | 11 +- 141 files changed, 6321 insertions(+), 1343 deletions(-) create mode 100644 infinitic-common/src/main/resources/schemas/clientEnvelope-0.11.7.avsc create mode 100644 infinitic-common/src/main/resources/schemas/taskExecutorEnvelope-0.11.7.avsc create mode 100644 infinitic-common/src/main/resources/schemas/taskTagEnvelope-0.11.7.avsc create mode 100644 infinitic-common/src/main/resources/schemas/workflowEngineEnvelope-0.11.7.avsc create mode 100644 infinitic-common/src/main/resources/schemas/workflowState-0.11.7.avsc create mode 100644 infinitic-common/src/main/resources/schemas/workflowTagEnvelope-0.11.7.avsc create mode 100644 infinitic-common/src/main/resources/schemas/workflowTaskParameters-0.11.7.avsc create mode 100644 infinitic-common/src/main/resources/schemas/workflowTaskReturnValue-0.11.7.avsc diff --git a/.addlicense.yml b/.addlicense.yml index 9f20b798e..4cfe46249 100644 --- a/.addlicense.yml +++ b/.addlicense.yml @@ -10,66 +10,66 @@ hasLicensePatterns: # File extension commenting format configuration fileExtensions: - - extensions: [".c", ".h"] + - extensions: [ ".c", ".h" ] top: "/*" mid: " * " bot: "*/" - - extensions: [".js", ".mjs", ".cjs", ".jsx", ".tsx", ".css", ".tf", ".ts", ".java", ".kt", ".kts"] + - extensions: [ ".js", ".mjs", ".cjs", ".jsx", ".tsx", ".css", ".tf", ".ts", ".java", ".kt", ".kts" ] top: "/**" mid: " * " bot: " */" - extensions: [ - ".cc", - ".cpp", - ".cs", - ".go", - ".hh", - ".hpp", - ".m", - ".mm", - ".proto", - ".rs", - ".scala", - ".swift", - ".dart", - ".groovy", - ".php", + ".cc", + ".cpp", + ".cs", + ".go", + ".hh", + ".hpp", + ".m", + ".mm", + ".proto", + ".rs", + ".scala", + ".swift", + ".dart", + ".groovy", + ".php", ] top: "" mid: "// " bot: "" - extensions: [ - ".py", - ".sh", - ".yaml", - ".yml", - ".dockerfile", - "dockerfile", - ".rb", - "gemfile", + ".py", + ".sh", + ".yaml", + ".yml", + ".dockerfile", + "dockerfile", + ".rb", + "gemfile", ] top: "" mid: "# " bot: "" - - extensions: [".el", ".lisp"] + - extensions: [ ".el", ".lisp" ] top: "" mid: ";; " bot: "" - - extensions: [".erl"] + - extensions: [ ".erl" ] top: "" mid: "% " bot: "" - - extensions: [".hs", ".sql"] + - extensions: [ ".hs", ".sql" ] top: "" mid: "-- " bot: "" - - extensions: [".html", ".xml", ".vue"] + - extensions: [ ".html", ".xml", ".vue" ] top: "" - - extensions: [".ml", ".mli", ".mll", ".mly"] + - extensions: [ ".ml", ".mli", ".mll", ".mly" ] top: "(**" mid: " " bot: "*)" diff --git a/.github/stale.yml b/.github/stale.yml index 80c6ce7ee..d434e0d6e 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -31,7 +31,7 @@ daysUntilStale: 60 daysUntilClose: 7 # Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled) -onlyLabels: [] +onlyLabels: [ ] # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable exemptLabels: diff --git a/.github/workflows/engine-ci.yml b/.github/workflows/engine-ci.yml index 420ec7e69..daa4d8a3a 100644 --- a/.github/workflows/engine-ci.yml +++ b/.github/workflows/engine-ci.yml @@ -38,11 +38,27 @@ jobs: - name: Checkout Repository uses: actions/checkout@v2 - - name: Setup Java 11 + - name: Setup Java 17 uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - name: Build with Gradle - run: ./gradlew build # <= -d used to debug if needed - timeout-minutes: 15 # max time allocated (useful if some tests hang) + run: ./gradlew build --no-daemon -x test -x spotlessCheck --parallel --max-workers=8 # <= -d used to debug if needed + timeout-minutes: 5 # max time allocated (useful if some tests hang) + + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Setup Java 17 + uses: actions/setup-java@v1 + with: + java-version: 17 + + - name: Test with Gradle + run: ./gradlew test --no-daemon --parallel --max-workers=8 # <= -d used to debug if needed + timeout-minutes: 20 # max time allocated (useful if some tests hang) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bd7e72f60..8457ec68d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,10 +35,10 @@ jobs: - name: Checkout Repository uses: actions/checkout@v2 - - name: Setup Java 11 + - name: Setup Java 17 uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 # - name: Run gradle build # uses: eskatos/gradle-command-action@v1 diff --git a/.github/workflows/repository.yml b/.github/workflows/repository.yml index 902e8a9ba..d6261c0e5 100644 --- a/.github/workflows/repository.yml +++ b/.github/workflows/repository.yml @@ -28,7 +28,7 @@ on: - main jobs: - lint: + license: runs-on: ubuntu-latest steps: @@ -39,3 +39,19 @@ jobs: uses: ./.github/actions/addlicense-action env: OPTIONS: "-s -c infinitic.io -f .license-header -config .addlicense.yml -check" + + linter: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Setup Java 17 + uses: actions/setup-java@v1 + with: + java-version: 17 + + - name: Check lint with Gradle Spotless + run: ./gradlew spotlessCheck --no-daemon --parallel --max-workers=8 # <= -d used to debug if needed + timeout-minutes: 5 # max time allocated (useful if some tests hang) diff --git a/README.md b/README.md index a3458e81c..9507ac746 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,15 @@ Infinitic is still in active development. Subscribe [here](https://infinitic.sub ## What is it? -Infinitic is a framework based on [Apache Pulsar](https://pulsar.apache.org/) that considerably eases building asynchronous distributed apps. +Infinitic is a framework based on [Apache Pulsar](https://pulsar.apache.org/) that considerably eases building +asynchronous distributed apps. -Many issues arise when we build and scale a distributed system - issues we don’t have in a single-process one. Infinitic provides simple but powerful libraries that let developers build distributed applications as if they were run on an infallible single-process system. It does this on top of Pulsar to benefit from its scalability and reliability. +Many issues arise when we build and scale a distributed system - issues we don’t have in a single-process one. Infinitic +provides simple but powerful libraries that let developers build distributed applications as if they were run on an +infallible single-process system. It does this on top of Pulsar to benefit from its scalability and reliability. -Infinitic is very good at orchestrating workflows, ie. at managing the execution of tasks on distributed servers according to any complex scenario. Moreover, Infinitic ensures that a failure somewhere will never break your workflows. +Infinitic is very good at orchestrating workflows, ie. at managing the execution of tasks on distributed servers +according to any complex scenario. Moreover, Infinitic ensures that a failure somewhere will never break your workflows. At last, Infinitic lets us monitor everything occurring inside your app through dashboards. diff --git a/build.gradle.kts b/build.gradle.kts index 9b1ddbc74..6b4fc9d0d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,16 +32,24 @@ buildscript { plugins { id(Plugins.Kotlin.id) version Plugins.Kotlin.version id(Plugins.Serialization.id) version Plugins.Serialization.version apply false - id(Plugins.Ktfmt.id) version Plugins.Ktfmt.version apply true id(Plugins.TestLogger.id) version Plugins.TestLogger.version apply true + id(Plugins.Spotless.id) version Plugins.Spotless.version apply true } +// code quality +spotless { + kotlin { ktfmt() } + kotlinGradle { ktfmt() } +} + +kotlin { jvmToolchain(17) } + repositories { mavenCentral() } subprojects { apply(plugin = Plugins.Kotlin.id) apply(plugin = Plugins.Serialization.id) - apply(plugin = Plugins.Ktfmt.id) + apply(plugin = Plugins.Spotless.id) apply(plugin = Plugins.TestLogger.id) group = Libs.org diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index c25716826..a9d1b4535 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,11 +20,6 @@ * * Licensor: infinitic.io */ +repositories { mavenCentral() } -repositories { - mavenCentral() -} - -plugins { - `kotlin-dsl` -} +plugins { `kotlin-dsl` } diff --git a/buildSrc/src/main/kotlin/Ci.kt b/buildSrc/src/main/kotlin/Ci.kt index ff25eef24..2e12fe2e5 100644 --- a/buildSrc/src/main/kotlin/Ci.kt +++ b/buildSrc/src/main/kotlin/Ci.kt @@ -24,7 +24,7 @@ object Ci { // this is the version used for building snapshots // .GITHUB_RUN_NUMBER-snapshot will be appended - const val base = "0.11.6" + const val base = "0.11.7" private val githubRunNumber = System.getenv("GITHUB_RUN_NUMBER") diff --git a/buildSrc/src/main/kotlin/Libs.kt b/buildSrc/src/main/kotlin/Libs.kt index ebd637e75..9b000155a 100644 --- a/buildSrc/src/main/kotlin/Libs.kt +++ b/buildSrc/src/main/kotlin/Libs.kt @@ -29,17 +29,17 @@ object Libs { } object Coroutines { - private const val version = "1.7.1" + private const val version = "1.7.3" const val core = "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version" const val jdk8 = "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$version" } object Caffeine { - const val caffeine = "com.github.ben-manes.caffeine:caffeine:3.1.6" + const val caffeine = "com.github.ben-manes.caffeine:caffeine:3.1.8" } object Serialization { - const val json = "org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1" + const val json = "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0" } object JsonPath { @@ -47,7 +47,7 @@ object Libs { } object Jackson { - private const val version = "2.15.2" + private const val version = "2.15.3" const val core = "com.fasterxml.jackson.core:jackson-core:$version" const val databind = "com.fasterxml.jackson.core:jackson-databind:$version" const val kotlin = "com.fasterxml.jackson.module:jackson-module-kotlin:$version" @@ -55,27 +55,27 @@ object Libs { } object Kotest { - private const val version = "5.6.2" + private const val version = "5.7.2" const val property = "io.kotest:kotest-property-jvm:$version" const val junit5 = "io.kotest:kotest-runner-junit5-jvm:$version" } object Mockk { - const val mockk = "io.mockk:mockk:1.13.5" + const val mockk = "io.mockk:mockk:1.13.8" } object Avro4k { - const val core = "com.github.avro-kotlin.avro4k:avro4k-core:1.7.0" + const val core = "com.github.avro-kotlin.avro4k:avro4k-core:1.10.0" } object Hoplite { - private const val version = "2.7.4" + private const val version = "2.7.5" const val core = "com.sksamuel.hoplite:hoplite-core:$version" const val yaml = "com.sksamuel.hoplite:hoplite-yaml:$version" } object Pulsar { - private const val version = "2.11.1" + private const val version = "3.1.0" const val client = "org.apache.pulsar:pulsar-client:$version" const val clientAdmin = "org.apache.pulsar:pulsar-client-admin:$version" const val functions = "org.apache.pulsar:pulsar-functions-api:$version" @@ -84,7 +84,7 @@ object Libs { } object Kweb { - const val core = "io.kweb:kweb-core:1.4.0" + const val core = "io.kweb:kweb-core:1.4.8" } object EasyRandom { @@ -92,7 +92,7 @@ object Libs { } object Slf4j { - private const val version = "2.0.7" + private const val version = "2.0.9" const val simple = "org.slf4j:slf4j-simple:$version" const val api = "org.slf4j:slf4j-api:$version" } @@ -102,6 +102,6 @@ object Libs { } object Compress { - const val commons = "org.apache.commons:commons-compress:1.23.0" + const val commons = "org.apache.commons:commons-compress:1.24.0" } } diff --git a/buildSrc/src/main/kotlin/Plugins.kt b/buildSrc/src/main/kotlin/Plugins.kt index f106d6a45..70c2d1343 100644 --- a/buildSrc/src/main/kotlin/Plugins.kt +++ b/buildSrc/src/main/kotlin/Plugins.kt @@ -20,7 +20,7 @@ * * Licensor: infinitic.io */ -const val kotlinVersion = "1.8.10" +const val kotlinVersion = "1.9.20" object Plugins { object Kotlin { @@ -33,13 +33,13 @@ object Plugins { const val version = kotlinVersion } - object Ktfmt { - const val id = "com.ncorti.ktfmt.gradle" - const val version = "0.12.0" - } - object TestLogger { const val id = "com.adarshr.test-logger" - const val version = "3.2.0" + const val version = "4.0.0" + } + + object Spotless { + const val id = "com.diffplug.spotless" + const val version = "6.22.0" } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 41d9927a4d4fb3f96a785543079b8df6723c946b..c1962a79e29d3e0ab67b14947c167a862655af9b 100644 GIT binary patch delta 40199 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 delta 37942 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/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index 107acd32c..93e3f59f1 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/infinitic-cache/build.gradle.kts b/infinitic-cache/build.gradle.kts index 80fab34a6..bf6a3f5ba 100644 --- a/infinitic-cache/build.gradle.kts +++ b/infinitic-cache/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,11 +20,10 @@ * * Licensor: infinitic.io */ - dependencies { - implementation(Libs.Caffeine.caffeine) + implementation(Libs.Caffeine.caffeine) - testImplementation(Libs.Hoplite.yaml) + testImplementation(Libs.Hoplite.yaml) } apply("../publish.gradle.kts") diff --git a/infinitic-cache/src/main/kotlin/io/infinitic/cache/keySet/CachedKeySet.kt b/infinitic-cache/src/main/kotlin/io/infinitic/cache/keySet/CachedKeySet.kt index 39441f1cb..21cd2e5e7 100644 --- a/infinitic-cache/src/main/kotlin/io/infinitic/cache/keySet/CachedKeySet.kt +++ b/infinitic-cache/src/main/kotlin/io/infinitic/cache/keySet/CachedKeySet.kt @@ -26,7 +26,10 @@ import io.infinitic.cache.Flushable interface CachedKeySet : Flushable { fun get(key: String): Set? + fun set(key: String, value: Set) + fun add(key: String, value: T) + fun remove(key: String, value: T) } diff --git a/infinitic-cache/src/main/kotlin/io/infinitic/cache/keyValue/CachedKeyValue.kt b/infinitic-cache/src/main/kotlin/io/infinitic/cache/keyValue/CachedKeyValue.kt index c2544309e..e7b7e1cf2 100644 --- a/infinitic-cache/src/main/kotlin/io/infinitic/cache/keyValue/CachedKeyValue.kt +++ b/infinitic-cache/src/main/kotlin/io/infinitic/cache/keyValue/CachedKeyValue.kt @@ -26,6 +26,8 @@ import io.infinitic.cache.Flushable interface CachedKeyValue : Flushable { fun getValue(key: String): T? + fun putValue(key: String, value: T) + fun delValue(key: String) } diff --git a/infinitic-client-base/build.gradle.kts b/infinitic-client-base/build.gradle.kts index c853aa88a..cd4f9ef9c 100644 --- a/infinitic-client-base/build.gradle.kts +++ b/infinitic-client-base/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,12 +20,11 @@ * * Licensor: infinitic.io */ - dependencies { - implementation(Libs.Coroutines.jdk8) - implementation(Libs.Kotlin.reflect) + implementation(Libs.Coroutines.jdk8) + implementation(Libs.Kotlin.reflect) - api(project(":infinitic-common")) + api(project(":infinitic-common")) } apply("../publish.gradle.kts") diff --git a/infinitic-client-base/src/test/kotlin/io/infinitic/clients/ClientWorkflowTests.kt b/infinitic-client-base/src/test/kotlin/io/infinitic/clients/ClientWorkflowTests.kt index f8690050f..51d2ed790 100644 --- a/infinitic-client-base/src/test/kotlin/io/infinitic/clients/ClientWorkflowTests.kt +++ b/infinitic-client-base/src/test/kotlin/io/infinitic/clients/ClientWorkflowTests.kt @@ -70,7 +70,7 @@ import io.kotest.matchers.shouldBe import io.mockk.every import io.mockk.mockk import io.mockk.slot -import java.util.UUID +import java.util.* import java.util.concurrent.CopyOnWriteArrayList private val taskTagSlots = CopyOnWriteArrayList() // multithreading update diff --git a/infinitic-client-base/src/test/kotlin/io/infinitic/clients/samples/FakeTask.kt b/infinitic-client-base/src/test/kotlin/io/infinitic/clients/samples/FakeTask.kt index bdf7d3b08..8cfaf9250 100644 --- a/infinitic-client-base/src/test/kotlin/io/infinitic/clients/samples/FakeTask.kt +++ b/infinitic-client-base/src/test/kotlin/io/infinitic/clients/samples/FakeTask.kt @@ -32,12 +32,19 @@ internal interface FakeTaskParent { internal interface FakeTask : FakeTaskParent { fun m0() + fun m0String(): String + fun m1(i: Int): String + fun m2(str: String?): Any? + fun m3(p1: Int, p2: String): String + fun m4(id: FakeInterface): FooTask + fun m5(): Boolean + suspend fun suspendedMethod() } diff --git a/infinitic-client-base/src/test/kotlin/io/infinitic/clients/samples/FakeWorkflow.kt b/infinitic-client-base/src/test/kotlin/io/infinitic/clients/samples/FakeWorkflow.kt index 960fbe99e..c35c0abee 100644 --- a/infinitic-client-base/src/test/kotlin/io/infinitic/clients/samples/FakeWorkflow.kt +++ b/infinitic-client-base/src/test/kotlin/io/infinitic/clients/samples/FakeWorkflow.kt @@ -34,11 +34,17 @@ internal interface FakeWorkflowParent { internal interface FakeWorkflow : FakeWorkflowParent { fun m0() + fun m1(i: Int?): String + fun m2(str: String): Any? + fun m3(p1: Int, p2: String): String + fun m4(id: FakeInterface): String + suspend fun suspendedMethod() + val channelString: SendChannel val channelFakeTask: SendChannel val channelFakeTaskParent: SendChannel @@ -46,15 +52,23 @@ internal interface FakeWorkflow : FakeWorkflowParent { internal class FakeWorkflowImpl : Workflow(), FakeWorkflow { override fun m0() {} + override fun m1(i: Int?): String = "$i" + override fun m2(str: String): Any? = str + override fun m3(p1: Int, p2: String): String = "$p1$p2" + override fun m4(id: FakeInterface): String = "$id" + override suspend fun suspendedMethod() {} + override val channelString = channel() override val channelFakeTask = channel() override val channelFakeTaskParent = channel() + override fun parent(): String = "foo" + override fun annotated(): String = "foo" } diff --git a/infinitic-client/build.gradle.kts b/infinitic-client/build.gradle.kts index 738cd29de..2e2e20ec7 100644 --- a/infinitic-client/build.gradle.kts +++ b/infinitic-client/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,13 +20,12 @@ * * Licensor: infinitic.io */ - dependencies { - api(project(":infinitic-inMemory")) - api(project(":infinitic-pulsar")) - api(project(":infinitic-client-base")) - api(project(":infinitic-worker-base")) - api(project(":infinitic-worker")) + api(project(":infinitic-inMemory")) + api(project(":infinitic-pulsar")) + api(project(":infinitic-client-base")) + api(project(":infinitic-worker-base")) + api(project(":infinitic-worker")) } apply("../publish.gradle.kts") diff --git a/infinitic-common/build.gradle.kts b/infinitic-common/build.gradle.kts index 564fabd79..a7bf28182 100644 --- a/infinitic-common/build.gradle.kts +++ b/infinitic-common/build.gradle.kts @@ -46,17 +46,17 @@ dependencies { } tasks.withType { - doFirst { - // all versions - val file = File(project.projectDir.absolutePath, "/src/main/resources/versions") - // append current version if not yet present - if (!file.useLines { lines -> lines.any { it == Ci.base } }) { - file.appendText(Ci.base + "\n") - } - - // current version - File(project.projectDir.absolutePath, "/src/main/resources/version").writeText(Ci.base) + doFirst { + // all versions + val file = File(project.projectDir.absolutePath, "/src/main/resources/versions") + // append current version if not yet present + if (!file.useLines { lines -> lines.any { it == Ci.base } }) { + file.appendText(Ci.base + "\n") } + + // current version + File(project.projectDir.absolutePath, "/src/main/resources/version").writeText(Ci.base) } +} apply("../publish.gradle.kts") diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/data/MillisDuration.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/data/MillisDuration.kt index 33f969648..b8e73c7f6 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/data/MillisDuration.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/data/MillisDuration.kt @@ -50,8 +50,10 @@ data class MillisDuration(val long: Long) : Comparable { object MillisDurationSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("MillisDuration", PrimitiveKind.LONG) + override fun serialize(encoder: Encoder, value: MillisDuration) { encoder.encodeLong(value.long) } + override fun deserialize(decoder: Decoder) = MillisDuration(decoder.decodeLong()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/data/MillisInstant.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/data/MillisInstant.kt index 71258d599..09510eac4 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/data/MillisInstant.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/data/MillisInstant.kt @@ -51,8 +51,10 @@ data class MillisInstant(val long: Long = 0) : Comparable { object MillisInstantSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("MillisInstant", PrimitiveKind.LONG) + override fun serialize(encoder: Encoder, value: MillisInstant) { encoder.encodeLong(value.long) } + override fun deserialize(decoder: Decoder) = MillisInstant(decoder.decodeLong()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/data/Name.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/data/Name.kt index 6484fd9f5..8624be484 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/data/Name.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/data/Name.kt @@ -53,8 +53,10 @@ open class Name(open val name: String) : CharSequence by name, Comparable { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Name", PrimitiveKind.STRING) + override fun serialize(encoder: Encoder, value: Name) { encoder.encodeString(value.name) } + override fun deserialize(decoder: Decoder) = Name(decoder.decodeString()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/data/ReturnValue.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/data/ReturnValue.kt index be524199f..59a0494e0 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/data/ReturnValue.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/data/ReturnValue.kt @@ -42,9 +42,11 @@ data class ReturnValue(val serializedData: SerializedData) { object ReturnValueSerializer : KSerializer { override val descriptor: SerialDescriptor = SerializedData.serializer().descriptor + override fun serialize(encoder: Encoder, value: ReturnValue) { SerializedData.serializer().serialize(encoder, value.serializedData) } + override fun deserialize(decoder: Decoder) = ReturnValue(SerializedData.serializer().deserialize(decoder)) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/data/methods/MethodParameterTypes.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/data/methods/MethodParameterTypes.kt index 4919e5342..5435136a0 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/data/methods/MethodParameterTypes.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/data/methods/MethodParameterTypes.kt @@ -40,9 +40,11 @@ data class MethodParameterTypes(val types: List) { object MethodParameterTypesSerializer : KSerializer { override val descriptor: SerialDescriptor = ListSerializer(String.serializer()).descriptor + override fun serialize(encoder: Encoder, value: MethodParameterTypes) { ListSerializer(String.serializer()).serialize(encoder, value.types) } + override fun deserialize(decoder: Decoder) = MethodParameterTypes(ListSerializer(String.serializer()).deserialize(decoder)) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/data/methods/MethodParameters.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/data/methods/MethodParameters.kt index b02d3a547..d9d200b7e 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/data/methods/MethodParameters.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/data/methods/MethodParameters.kt @@ -61,9 +61,11 @@ data class MethodParameters(val parameters: List = listOf()) : object MethodParametersSerializer : KSerializer { override val descriptor: SerialDescriptor = ListSerializer(SerializedData.serializer()).descriptor + override fun serialize(encoder: Encoder, value: MethodParameters) { ListSerializer(SerializedData.serializer()).serialize(encoder, value.parameters.toList()) } + override fun deserialize(decoder: Decoder) = MethodParameters(ListSerializer(SerializedData.serializer()).deserialize(decoder).toList()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/parser/Parser.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/parser/Parser.kt index 2e9fefa32..875c6ad15 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/parser/Parser.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/parser/Parser.kt @@ -37,14 +37,14 @@ fun getMethodPerNameAndParameters( parametersCount: Int ): Method = when (parameterTypes) { - null -> getMethodPerAnnotationAndParametersCount(klass, name, parametersCount) + null -> + getMethodPerAnnotationAndParametersCount(klass, name, parametersCount) ?: getMethodPerNameAndParameterCount(klass, name, parametersCount) - ?: throw NoMethodFoundWithParameterCountException( - klass.name, name, parametersCount) - else -> getMethodPerAnnotationAndParameterTypes(klass, name, parameterTypes) + ?: throw NoMethodFoundWithParameterCountException(klass.name, name, parametersCount) + else -> + getMethodPerAnnotationAndParameterTypes(klass, name, parameterTypes) ?: getMethodPerNameAndParameterTypes(klass, name, parameterTypes) - ?: throw NoMethodFoundWithParameterTypesException( - klass.name, name, parameterTypes) + ?: throw NoMethodFoundWithParameterTypesException(klass.name, name, parameterTypes) } fun classForName(name: String): Class = diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/serDe/kserializer/DurationSerializer.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/serDe/kserializer/DurationSerializer.kt index c0fec8e2d..abdb8c1cb 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/serDe/kserializer/DurationSerializer.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/serDe/kserializer/DurationSerializer.kt @@ -33,6 +33,7 @@ import kotlinx.serialization.encoding.Encoder object DurationSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("DurationLong", PrimitiveKind.LONG) + override fun serialize(encoder: Encoder, value: Duration) { encoder.encodeLong(value.toMillis()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/serDe/kserializer/UUIDSerializer.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/serDe/kserializer/UUIDSerializer.kt index 5d5b15e05..93c647cea 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/serDe/kserializer/UUIDSerializer.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/serDe/kserializer/UUIDSerializer.kt @@ -33,8 +33,10 @@ import kotlinx.serialization.encoding.Encoder object UUIDSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("UUID", PrimitiveKind.STRING) + override fun serialize(encoder: Encoder, value: UUID) { encoder.encodeString(value.toString()) } + override fun deserialize(decoder: Decoder) = UUID.fromString(decoder.decodeString()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/ServiceName.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/ServiceName.kt index 45ffcf426..4715cd837 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/ServiceName.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/ServiceName.kt @@ -37,6 +37,7 @@ data class ServiceName(override val name: String) : Name(name) object ServiceNameSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ServiceName", PrimitiveKind.STRING) + override fun serialize(encoder: Encoder, value: ServiceName) { encoder.encodeString(value.name) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskMeta.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskMeta.kt index d9ed6f29d..b96c49661 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskMeta.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskMeta.kt @@ -47,8 +47,10 @@ data class TaskMeta(val map: Map = mapOf()) : Map { val ser = MapSerializer(String.serializer(), ByteArraySerializer()) override val descriptor: SerialDescriptor = ser.descriptor + override fun serialize(encoder: Encoder, value: TaskMeta) { ser.serialize(encoder, value.map) } + override fun deserialize(decoder: Decoder) = TaskMeta(ser.deserialize(decoder)) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskRetryIndex.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskRetryIndex.kt index 1d4175fa8..32a67996e 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskRetryIndex.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskRetryIndex.kt @@ -35,6 +35,7 @@ data class TaskRetryIndex(private val int: Int = 0) : Comparable override fun toString() = "$int" fun toInt() = int + override operator fun compareTo(other: TaskRetryIndex): Int = this.int.compareTo(other.int) operator fun plus(increment: Int) = TaskRetryIndex(this.int + increment) @@ -43,6 +44,7 @@ data class TaskRetryIndex(private val int: Int = 0) : Comparable object TaskRetryIndexSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("TaskRetryIndex", PrimitiveKind.INT) + override fun serialize(encoder: Encoder, value: TaskRetryIndex) { encoder.encodeInt(value.toInt()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskRetrySequence.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskRetrySequence.kt index 6352c2d06..c96a5d539 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskRetrySequence.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskRetrySequence.kt @@ -44,6 +44,7 @@ data class TaskRetrySequence(private val int: Int = 0) : Comparable { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("TaskRetrySequence", PrimitiveKind.INT) + override fun serialize(encoder: Encoder, value: TaskRetrySequence) { encoder.encodeInt(value.toInt()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskTag.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskTag.kt index 757e19e1e..2663b20a9 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskTag.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/tasks/data/TaskTag.kt @@ -38,8 +38,10 @@ data class TaskTag(val tag: String) { object TaskTagSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("TaskTag", PrimitiveKind.STRING) + override fun serialize(encoder: Encoder, value: TaskTag) { encoder.encodeString(value.tag) } + override fun deserialize(decoder: Decoder) = TaskTag(decoder.decodeString()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workers/registry/RegisteredWorkflow.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workers/registry/RegisteredWorkflow.kt index 451a2f8a5..8b506ec84 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workers/registry/RegisteredWorkflow.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workers/registry/RegisteredWorkflow.kt @@ -63,6 +63,7 @@ data class RegisteredWorkflow( private val classByVersion by lazy { classes.associateBy { WorkflowVersion.from(it) } } private val lastVersion by lazy { classByVersion.keys.maxOrNull() ?: thisShouldNotHappen() } + fun getInstance(workflowVersion: WorkflowVersion?): Workflow = getClass(workflowVersion).getDeclaredConstructor().newInstance() diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/ChannelFilter.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/ChannelFilter.kt index 8be70c5cf..c814ea3b1 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/ChannelFilter.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/ChannelFilter.kt @@ -51,7 +51,9 @@ data class ChannelFilter(val jsonPath: String, val filter: String? = null) { Configuration.setDefaults( object : Configuration.Defaults { override fun jsonProvider() = JacksonJsonProvider() + override fun mappingProvider() = JacksonMappingProvider() + override fun options() = setOf(Option.ALWAYS_RETURN_LIST) }) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/ChannelName.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/ChannelName.kt index 33615621a..264f89c6d 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/ChannelName.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/ChannelName.kt @@ -31,6 +31,7 @@ import kotlinx.serialization.Serializable value class ChannelName(private val name: String) { companion object { fun from(method: Method) = ChannelName(method.name) + fun from(methodName: MethodName) = ChannelName(methodName.toString()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/ChannelType.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/ChannelType.kt index 6c56210e7..f6ecf308e 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/ChannelType.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/ChannelType.kt @@ -35,6 +35,7 @@ import kotlinx.serialization.encoding.Encoder data class ChannelType(override val name: String) : Name(name) { companion object { fun from(klass: Class) = ChannelType(klass.name) + fun allFrom(klass: Class) = getAllExtendedOrImplementedTypes(klass) } } @@ -42,8 +43,10 @@ data class ChannelType(override val name: String) : Name(name) { object ChannelTypeSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ChannelType", PrimitiveKind.STRING) + override fun serialize(encoder: Encoder, value: ChannelType) { encoder.encodeString(value.name) } + override fun deserialize(decoder: Decoder) = ChannelType(decoder.decodeString()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/SignalData.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/SignalData.kt index b4a1bf035..3502703fb 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/SignalData.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/channels/SignalData.kt @@ -40,9 +40,11 @@ data class SignalData(val serializedData: SerializedData) { object ChannelSignalSerializer : KSerializer { override val descriptor: SerialDescriptor = SerializedData.serializer().descriptor + override fun serialize(encoder: Encoder, value: SignalData) { SerializedData.serializer().serialize(encoder, value.serializedData) } + override fun deserialize(decoder: Decoder) = SignalData(SerializedData.serializer().deserialize(decoder)) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/commands/CommandHash.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/commands/CommandHash.kt index 08bdb43cc..93d0e976d 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/commands/CommandHash.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/commands/CommandHash.kt @@ -37,8 +37,10 @@ data class CommandHash(override val hash: String) : Hash(hash) object CommandHashSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("CommandHash", PrimitiveKind.STRING) + override fun serialize(encoder: Encoder, value: CommandHash) { encoder.encodeString(value.hash) } + override fun deserialize(decoder: Decoder) = CommandHash(decoder.decodeString()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/commands/CommandId.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/commands/CommandId.kt index 41bf19bc9..fffacb166 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/commands/CommandId.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/commands/CommandId.kt @@ -34,8 +34,11 @@ import kotlinx.serialization.Serializable value class CommandId(private val id: String = UUID.randomUUID().toString()) { companion object { fun from(taskId: TaskId) = CommandId(taskId.toString()) + fun from(workflowId: WorkflowId) = CommandId(workflowId.toString()) + fun from(methodRunId: MethodRunId) = CommandId(methodRunId.toString()) + fun from(timerId: TimerId) = CommandId(timerId.toString()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/commands/CommandStatus.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/commands/CommandStatus.kt index cdbb50984..2d9214db3 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/commands/CommandStatus.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/commands/CommandStatus.kt @@ -45,6 +45,7 @@ sealed class CommandStatus { @SerialName("CommandStatus.Ongoing") object Ongoing : CommandStatus() { override fun equals(other: Any?) = javaClass == other?.javaClass + override fun toString(): String = Ongoing::class.java.name } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/properties/PropertyHash.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/properties/PropertyHash.kt index 5d1ffe259..02011e8a6 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/properties/PropertyHash.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/properties/PropertyHash.kt @@ -37,8 +37,10 @@ data class PropertyHash(override val hash: String) : Hash(hash) object PropertyHashSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("PropertyHash", PrimitiveKind.STRING) + override fun serialize(encoder: Encoder, value: PropertyHash) { encoder.encodeString(value.hash) } + override fun deserialize(decoder: Decoder) = PropertyHash(decoder.decodeString()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/properties/PropertyName.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/properties/PropertyName.kt index 1b988aebe..cb6b23e65 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/properties/PropertyName.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/properties/PropertyName.kt @@ -37,8 +37,10 @@ data class PropertyName(override val name: String) : Name(name) object PropertyNameSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("PropertyName", PrimitiveKind.STRING) + override fun serialize(encoder: Encoder, value: PropertyName) { encoder.encodeString(value.name) } + override fun deserialize(decoder: Decoder) = PropertyName(decoder.decodeString()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/properties/PropertyValue.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/properties/PropertyValue.kt index e6086c739..1a0138658 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/properties/PropertyValue.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/properties/PropertyValue.kt @@ -44,9 +44,11 @@ data class PropertyValue(val serializedData: SerializedData) { object PropertyValueSerializer : KSerializer { override val descriptor: SerialDescriptor = SerializedData.serializer().descriptor + override fun serialize(encoder: Encoder, value: PropertyValue) { SerializedData.serializer().serialize(encoder, value.serializedData) } + override fun deserialize(decoder: Decoder) = PropertyValue(SerializedData.serializer().deserialize(decoder)) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/steps/Step.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/steps/Step.kt index 78158d3c3..ba279206a 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/steps/Step.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/steps/Step.kt @@ -122,6 +122,7 @@ sealed class Step { throw OutOfBoundAwaitException } } + override fun nextAwaitIndex() { awaitIndex++ @@ -237,6 +238,7 @@ sealed class Step { override fun checkAwaitIndex() { steps.map { it.checkAwaitIndex() } } + override fun nextAwaitIndex() { steps.map { it.nextAwaitIndex() } } @@ -290,8 +292,7 @@ sealed class Step { else -> commandStatuses.firstOrNull { it is Completed && it.returnIndex == awaitIndex - } - ?: thisShouldNotHappen() + } ?: thisShouldNotHappen() } } is And -> steps = steps.map { it.updateWith(commandId, commandStatus, commandStatuses) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/steps/StepHash.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/steps/StepHash.kt index 39e07f307..adb928459 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/steps/StepHash.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/steps/StepHash.kt @@ -37,8 +37,10 @@ data class StepHash(override val hash: String) : Hash(hash) object StepHashSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("StepHash", PrimitiveKind.STRING) + override fun serialize(encoder: Encoder, value: StepHash) { encoder.encodeString(value.hash) } + override fun deserialize(decoder: Decoder) = StepHash(decoder.decodeString()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflowTasks/WorkflowTaskIndex.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflowTasks/WorkflowTaskIndex.kt index 2e937e427..492a890e0 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflowTasks/WorkflowTaskIndex.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflowTasks/WorkflowTaskIndex.kt @@ -42,8 +42,10 @@ data class WorkflowTaskIndex(val int: Int = 0) : Comparable { object WorkflowTaskIndexSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("WorkflowTaskIndex", PrimitiveKind.INT) + override fun serialize(encoder: Encoder, value: WorkflowTaskIndex) { encoder.encodeInt(value.int) } + override fun deserialize(decoder: Decoder) = WorkflowTaskIndex(decoder.decodeInt()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflows/WorkflowMeta.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflows/WorkflowMeta.kt index f245645b3..e5d92dfa7 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflows/WorkflowMeta.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflows/WorkflowMeta.kt @@ -51,8 +51,10 @@ data class WorkflowMeta(val map: Map = mapOf()) : Map { val ser = MapSerializer(String.serializer(), ByteArraySerializer()) override val descriptor: SerialDescriptor = ser.descriptor + override fun serialize(encoder: Encoder, value: WorkflowMeta) { ser.serialize(encoder, value.map) } + override fun deserialize(decoder: Decoder) = WorkflowMeta(ser.deserialize(decoder)) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflows/WorkflowName.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflows/WorkflowName.kt index e5d219414..0e2faeed8 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflows/WorkflowName.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflows/WorkflowName.kt @@ -42,8 +42,10 @@ data class WorkflowName(override val name: String) : Name(name) { object WorkflowNameSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("WorkflowName", PrimitiveKind.STRING) + override fun serialize(encoder: Encoder, value: WorkflowName) { encoder.encodeString(value.name) } + override fun deserialize(decoder: Decoder) = WorkflowName(decoder.decodeString()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflows/WorkflowTag.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflows/WorkflowTag.kt index 855c7d463..473aa4e26 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflows/WorkflowTag.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/data/workflows/WorkflowTag.kt @@ -44,8 +44,10 @@ data class WorkflowTag(val tag: String) { object WorkflowTagSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("WorkflowTag", PrimitiveKind.STRING) + override fun serialize(encoder: Encoder, value: WorkflowTag) { encoder.encodeString(value.tag) } + override fun deserialize(decoder: Decoder) = WorkflowTag(decoder.decodeString()) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/engine/messages/WorkflowEngineMessage.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/engine/messages/WorkflowEngineMessage.kt index 46f0ead9c..f31ce9825 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/engine/messages/WorkflowEngineMessage.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/engine/messages/WorkflowEngineMessage.kt @@ -65,6 +65,7 @@ interface MethodEvent : WorkflowEvent { interface TaskEvent : MethodEvent { fun taskId(): TaskId + fun serviceName(): ServiceName } @@ -242,6 +243,7 @@ data class TaskCanceled( override val emitterName: ClientName ) : WorkflowEngineMessage(), TaskEvent { override fun taskId() = canceledTaskError.taskId + override fun serviceName() = canceledTaskError.serviceName } @@ -256,6 +258,7 @@ data class TaskFailed( override val emitterName: ClientName ) : WorkflowEngineMessage(), TaskEvent { override fun taskId() = failedTaskError.taskId + override fun serviceName() = failedTaskError.serviceName } @@ -269,5 +272,6 @@ data class TaskCompleted( override val emitterName: ClientName ) : WorkflowEngineMessage(), TaskEvent { override fun taskId() = taskReturnValue.taskId + override fun serviceName() = taskReturnValue.serviceName } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/engine/state/WorkflowState.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/engine/state/WorkflowState.kt index d0a0408eb..d5fdfe381 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/engine/state/WorkflowState.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/engine/state/WorkflowState.kt @@ -136,8 +136,8 @@ data class WorkflowState( fun getPastCommand(commandId: CommandId, methodRun: MethodRun): PastCommand = methodRun.getPastCommand(commandId) - // if we do not find in this methodRun, then search within others - ?: methodRuns.map { it.getPastCommand(commandId) }.firstOrNull { it != null } + // if we do not find in this methodRun, then search within others + ?: methodRuns.map { it.getPastCommand(commandId) }.firstOrNull { it != null } // methodRun should not be deleted if a step is still running ?: thisShouldNotHappen() diff --git a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/engine/storage/WorkflowStateStorage.kt b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/engine/storage/WorkflowStateStorage.kt index ae86ecb80..b90a55f33 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/engine/storage/WorkflowStateStorage.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/common/workflows/engine/storage/WorkflowStateStorage.kt @@ -28,6 +28,8 @@ import io.infinitic.common.workflows.engine.state.WorkflowState interface WorkflowStateStorage : Flushable { suspend fun getState(workflowId: WorkflowId): WorkflowState? + suspend fun putState(workflowId: WorkflowId, workflowState: WorkflowState) + suspend fun delState(workflowId: WorkflowId) } diff --git a/infinitic-common/src/main/kotlin/io/infinitic/workflows/Deferred.kt b/infinitic-common/src/main/kotlin/io/infinitic/workflows/Deferred.kt index e2335bb22..9e0513a52 100644 --- a/infinitic-common/src/main/kotlin/io/infinitic/workflows/Deferred.kt +++ b/infinitic-common/src/main/kotlin/io/infinitic/workflows/Deferred.kt @@ -84,9 +84,11 @@ data class Deferred(val step: Step) { object DeferredSerializer : KSerializer> { override val descriptor: SerialDescriptor = Step.serializer().descriptor + override fun serialize(encoder: Encoder, value: Deferred<*>) { encoder.encodeSerializableValue(Step.serializer(), value.step) } + override fun deserialize(decoder: Decoder): Deferred<*> = Deferred(decoder.decodeSerializableValue(Step.serializer())) } diff --git a/infinitic-common/src/main/resources/schemas/clientEnvelope-0.11.7.avsc b/infinitic-common/src/main/resources/schemas/clientEnvelope-0.11.7.avsc new file mode 100644 index 000000000..2aa7af107 --- /dev/null +++ b/infinitic-common/src/main/resources/schemas/clientEnvelope-0.11.7.avsc @@ -0,0 +1,431 @@ +{ + "type" : "record", + "name" : "ClientEnvelope", + "namespace" : "io.infinitic.common.clients.messages", + "fields" : [ { + "name" : "clientName", + "type" : "string" + }, { + "name" : "type", + "type" : { + "type" : "enum", + "name" : "ClientMessageType", + "symbols" : [ "TASK_COMPLETED", "TASK_CANCELED", "TASK_FAILED", "TASK_IDS_PER_TAG", "UNKNOWN_WORKFLOW", "WORKFLOW_COMPLETED", "WORKFLOW_CANCELED", "WORKFLOW_FAILED", "WORKFLOW_ALREADY_COMPLETED", "WORKFLOW_IDS_PER_TAG" ] + } + }, { + "name" : "taskCompleted", + "type" : [ "null", { + "type" : "record", + "name" : "TaskCompleted", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + }, { + "name" : "recipientName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "taskReturnValue", + "type" : { + "type" : "record", + "name" : "SerializedData", + "namespace" : "io.infinitic.data", + "fields" : [ { + "name" : "bytes", + "type" : "bytes" + }, { + "name" : "type", + "type" : { + "type" : "enum", + "name" : "SerializedDataType", + "symbols" : [ "NULL", "JSON_JACKSON", "JSON_KOTLIN" ] + } + }, { + "name" : "meta", + "type" : { + "type" : "map", + "values" : "bytes" + } + } ] + } + }, { + "name" : "taskMeta", + "type" : { + "type" : "map", + "values" : "bytes" + } + } ] + } ] + }, { + "name" : "taskCanceled", + "type" : [ "null", { + "type" : "record", + "name" : "TaskCanceled", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "recipientName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "taskFailed", + "type" : [ "null", { + "type" : "record", + "name" : "TaskFailed", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "recipientName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "cause", + "type" : { + "type" : "record", + "name" : "WorkerError", + "namespace" : "io.infinitic.tasks.executor", + "fields" : [ { + "name" : "workerName", + "type" : "string" + }, { + "name" : "name", + "type" : "string" + }, { + "name" : "message", + "type" : [ "null", "string" ] + }, { + "name" : "stackTraceToString", + "type" : "string" + }, { + "name" : "cause", + "type" : [ "null", "WorkerError" ] + } ] + } + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "taskIdsByTag", + "type" : [ "null", { + "type" : "record", + "name" : "TaskIdsByTag", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "recipientName", + "type" : "string" + }, { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskTag", + "type" : "string" + }, { + "name" : "taskIds", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "workflowCompleted", + "type" : [ "null", { + "type" : "record", + "name" : "MethodCompleted", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "recipientName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "methodReturnValue", + "type" : "io.infinitic.data.SerializedData" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "workflowCanceled", + "type" : [ "null", { + "type" : "record", + "name" : "MethodCanceled", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "recipientName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "workflowFailed", + "type" : [ "null", { + "type" : "record", + "name" : "MethodFailed", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "recipientName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "cause", + "type" : [ { + "type" : "record", + "name" : "CanceledTaskError", + "namespace" : "", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "CanceledWorkflowError", + "namespace" : "", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + } ] + }, { + "type" : "record", + "name" : "FailedTaskError", + "namespace" : "", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "cause", + "type" : "io.infinitic.tasks.executor.WorkerError" + } ] + }, { + "type" : "record", + "name" : "FailedWorkflowError", + "namespace" : "", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "deferredError", + "type" : [ "CanceledTaskError", "CanceledWorkflowError", "FailedTaskError", "FailedWorkflowError", { + "type" : "record", + "name" : "FailedWorkflowTaskError", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "workflowTaskId", + "type" : "string" + }, { + "name" : "cause", + "type" : "io.infinitic.tasks.executor.WorkerError" + } ] + }, { + "type" : "record", + "name" : "TimedOutTaskError", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "TimedOutWorkflowError", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + } ] + }, { + "type" : "record", + "name" : "UnknownTaskError", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "UnknownWorkflowError", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + } ] + } ] + } ] + }, "FailedWorkflowTaskError", "TimedOutTaskError", "TimedOutWorkflowError", "UnknownTaskError", "UnknownWorkflowError" ] + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "unknownWorkflow", + "type" : [ "null", { + "type" : "record", + "name" : "MethodRunUnknown", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "recipientName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "methodAlreadyCompleted", + "type" : [ "null", { + "type" : "record", + "name" : "MethodAlreadyCompleted", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "recipientName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "workflowIdsByTag", + "type" : [ "null", { + "type" : "record", + "name" : "WorkflowIdsByTag", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "recipientName", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowTag", + "type" : "string" + }, { + "name" : "workflowIds", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + } ] +} \ No newline at end of file diff --git a/infinitic-common/src/main/resources/schemas/taskExecutorEnvelope-0.11.7.avsc b/infinitic-common/src/main/resources/schemas/taskExecutorEnvelope-0.11.7.avsc new file mode 100644 index 000000000..fd990b954 --- /dev/null +++ b/infinitic-common/src/main/resources/schemas/taskExecutorEnvelope-0.11.7.avsc @@ -0,0 +1,124 @@ +{ + "type" : "record", + "name" : "TaskExecutorEnvelope", + "namespace" : "io.infinitic.tasks.executor", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "type", + "type" : { + "type" : "enum", + "name" : "TaskExecutorMessageType", + "symbols" : [ "EXECUTE_TASK" ] + } + }, { + "name" : "executeTask", + "type" : [ "null", { + "type" : "record", + "name" : "ExecuteTask", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + }, { + "name" : "clientWaiting", + "type" : "boolean" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameterTypes", + "type" : [ "null", { + "type" : "array", + "items" : "string" + } ] + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : { + "type" : "record", + "name" : "SerializedData", + "namespace" : "io.infinitic.data", + "fields" : [ { + "name" : "bytes", + "type" : "bytes" + }, { + "name" : "type", + "type" : { + "type" : "enum", + "name" : "SerializedDataType", + "symbols" : [ "NULL", "JSON_JACKSON", "JSON_KOTLIN" ] + } + }, { + "name" : "meta", + "type" : { + "type" : "map", + "values" : "bytes" + } + } ] + } + } + }, { + "name" : "taskRetrySequence", + "type" : "int" + }, { + "name" : "taskRetryIndex", + "type" : "int" + }, { + "name" : "lastError", + "type" : [ "null", { + "type" : "record", + "name" : "WorkerError", + "fields" : [ { + "name" : "workerName", + "type" : "string" + }, { + "name" : "name", + "type" : "string" + }, { + "name" : "message", + "type" : [ "null", "string" ] + }, { + "name" : "stackTraceToString", + "type" : "string" + }, { + "name" : "cause", + "type" : [ "null", "WorkerError" ] + } ] + } ] + }, { + "name" : "workflowId", + "type" : [ "null", "string" ] + }, { + "name" : "workflowName", + "type" : [ "null", "string" ] + }, { + "name" : "workflowVersion", + "type" : [ "null", "int" ], + "default" : null + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "taskTags", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "taskMeta", + "type" : { + "type" : "map", + "values" : "bytes" + } + } ] + } ] + } ] +} \ No newline at end of file diff --git a/infinitic-common/src/main/resources/schemas/taskTagEnvelope-0.11.7.avsc b/infinitic-common/src/main/resources/schemas/taskTagEnvelope-0.11.7.avsc new file mode 100644 index 000000000..a410b4ab9 --- /dev/null +++ b/infinitic-common/src/main/resources/schemas/taskTagEnvelope-0.11.7.avsc @@ -0,0 +1,117 @@ +{ + "type" : "record", + "name" : "TaskTagEnvelope", + "namespace" : "io.infinitic.tasks.tag", + "fields" : [ { + "name" : "name", + "type" : "string" + }, { + "name" : "type", + "type" : { + "type" : "enum", + "name" : "TaskTagMessageType", + "symbols" : [ "ADD_TAG_TO_TASK", "REMOVE_TAG_FROM_TASK", "CANCEL_TASK_BY_TAG", "RETRY_TASK_BY_TAG", "GET_TASK_IDS_BY_TAG" ] + } + }, { + "name" : "addTagToTask", + "type" : [ "null", { + "type" : "record", + "name" : "AddTagToTask", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskTag", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "removeTagFromTask", + "type" : [ "null", { + "type" : "record", + "name" : "RemoveTagFromTask", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskTag", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "cancelTaskByTag", + "type" : [ "null", { + "type" : "record", + "name" : "CancelTaskByTag", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskTag", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "retryTaskByTag", + "type" : [ "null", { + "type" : "record", + "name" : "RetryTaskByTag", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskTag", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "getTaskIdsByTag", + "type" : [ "null", { + "type" : "record", + "name" : "GetTaskIdsByTag", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskTag", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + } ] +} \ No newline at end of file diff --git a/infinitic-common/src/main/resources/schemas/workflowEngineEnvelope-0.11.7.avsc b/infinitic-common/src/main/resources/schemas/workflowEngineEnvelope-0.11.7.avsc new file mode 100644 index 000000000..792689cee --- /dev/null +++ b/infinitic-common/src/main/resources/schemas/workflowEngineEnvelope-0.11.7.avsc @@ -0,0 +1,716 @@ +{ + "type" : "record", + "name" : "WorkflowEngineEnvelope", + "namespace" : "io.infinitic.workflows.engine", + "fields" : [ { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "type", + "type" : { + "type" : "enum", + "name" : "WorkflowEngineMessageType", + "symbols" : [ "WAIT_WORKFLOW", "CANCEL_WORKFLOW", "RETRY_WORKFLOW_TASK", "RETRY_TASKS", "COMPLETE_TIMERS", "COMPLETE_WORKFLOW", "SEND_SIGNAL", "DISPATCH_WORKFLOW", "DISPATCH_METHOD", "TIMER_COMPLETED", "CHILD_WORKFLOW_UNKNOWN", "CHILD_WORKFLOW_CANCELED", "CHILD_WORKFLOW_FAILED", "CHILD_WORKFLOW_COMPLETED", "TASK_CANCELED", "TASK_FAILED", "TASK_COMPLETED" ] + } + }, { + "name" : "dispatchWorkflow", + "type" : [ "null", { + "type" : "record", + "name" : "DispatchWorkflow", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : { + "type" : "record", + "name" : "SerializedData", + "namespace" : "io.infinitic.data", + "fields" : [ { + "name" : "bytes", + "type" : "bytes" + }, { + "name" : "type", + "type" : { + "type" : "enum", + "name" : "SerializedDataType", + "symbols" : [ "NULL", "JSON_JACKSON", "JSON_KOTLIN" ] + } + }, { + "name" : "meta", + "type" : { + "type" : "map", + "values" : "bytes" + } + } ] + } + } + }, { + "name" : "methodParameterTypes", + "type" : [ "null", { + "type" : "array", + "items" : "string" + } ] + }, { + "name" : "workflowTags", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "workflowMeta", + "type" : { + "type" : "map", + "values" : "bytes" + } + }, { + "name" : "parentWorkflowName", + "type" : [ "null", "string" ] + }, { + "name" : "parentWorkflowId", + "type" : [ "null", "string" ] + }, { + "name" : "parentMethodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "clientWaiting", + "type" : "boolean" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "dispatchMethod", + "type" : [ "null", { + "type" : "record", + "name" : "DispatchMethod", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : "io.infinitic.data.SerializedData" + } + }, { + "name" : "methodParameterTypes", + "type" : [ "null", { + "type" : "array", + "items" : "string" + } ] + }, { + "name" : "parentWorkflowId", + "type" : [ "null", "string" ] + }, { + "name" : "parentWorkflowName", + "type" : [ "null", "string" ] + }, { + "name" : "parentMethodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "clientWaiting", + "type" : "boolean" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "waitWorkflow", + "type" : [ "null", { + "type" : "record", + "name" : "WaitWorkflow", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "cancelWorkflow", + "type" : [ "null", { + "type" : "record", + "name" : "CancelWorkflow", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "reason", + "type" : { + "type" : "enum", + "name" : "WorkflowCancellationReason", + "namespace" : "io.infinitic.workflows.data", + "symbols" : [ "CANCELED_BY_CLIENT", "CANCELED_BY_PARENT" ] + } + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "retryWorkflowTask", + "type" : [ "null", { + "type" : "record", + "name" : "RetryWorkflowTask", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "retryTasks", + "type" : [ "null", { + "type" : "record", + "name" : "RetryTasks", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "taskId", + "type" : [ "null", "string" ] + }, { + "name" : "taskStatus", + "type" : [ "null", { + "type" : "enum", + "name" : "DeferredStatus", + "namespace" : "io.infinitic.workflows", + "symbols" : [ "ONGOING", "UNKNOWN", "CANCELED", "FAILED", "COMPLETED" ] + } ] + }, { + "name" : "taskName", + "type" : [ "null", "string" ] + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "completeTimers", + "type" : [ "null", { + "type" : "record", + "name" : "CompleteTimers", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ], + "default" : null + }, { + "name" : "completeWorkflow", + "type" : [ "null", { + "type" : "record", + "name" : "CompleteWorkflow", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "workflowReturnValue", + "type" : "io.infinitic.data.SerializedData" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "sendSignal", + "type" : [ "null", { + "type" : "record", + "name" : "SendSignal", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "channelName", + "type" : "string" + }, { + "name" : "channelSignalId", + "type" : "string" + }, { + "name" : "channelSignal", + "type" : "io.infinitic.data.SerializedData" + }, { + "name" : "channelSignalTypes", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "timerCompleted", + "type" : [ "null", { + "type" : "record", + "name" : "TimerCompleted", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "timerId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "childMethodUnknown", + "type" : [ "null", { + "type" : "record", + "name" : "ChildMethodUnknown", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "childUnknownWorkflowError", + "type" : { + "type" : "record", + "name" : "UnknownWorkflowError", + "namespace" : "", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + } ] + } + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "childMethodCanceled", + "type" : [ "null", { + "type" : "record", + "name" : "ChildMethodCanceled", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "childCanceledWorkflowError", + "type" : { + "type" : "record", + "name" : "CanceledWorkflowError", + "namespace" : "", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + } ] + } + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "childMethodFailed", + "type" : [ "null", { + "type" : "record", + "name" : "ChildMethodFailed", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "childFailedWorkflowError", + "type" : { + "type" : "record", + "name" : "FailedWorkflowError", + "namespace" : "", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "deferredError", + "type" : [ { + "type" : "record", + "name" : "CanceledTaskError", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + } ] + }, "CanceledWorkflowError", { + "type" : "record", + "name" : "FailedTaskError", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "cause", + "type" : { + "type" : "record", + "name" : "WorkerError", + "namespace" : "io.infinitic.tasks.executor", + "fields" : [ { + "name" : "workerName", + "type" : "string" + }, { + "name" : "name", + "type" : "string" + }, { + "name" : "message", + "type" : [ "null", "string" ] + }, { + "name" : "stackTraceToString", + "type" : "string" + }, { + "name" : "cause", + "type" : [ "null", "WorkerError" ] + } ] + } + } ] + }, "FailedWorkflowError", { + "type" : "record", + "name" : "FailedWorkflowTaskError", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "workflowTaskId", + "type" : "string" + }, { + "name" : "cause", + "type" : "io.infinitic.tasks.executor.WorkerError" + } ] + }, { + "type" : "record", + "name" : "TimedOutTaskError", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "TimedOutWorkflowError", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + } ] + }, { + "type" : "record", + "name" : "UnknownTaskError", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + } ] + }, "UnknownWorkflowError" ] + } ] + } + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "childMethodCompleted", + "type" : [ "null", { + "type" : "record", + "name" : "ChildMethodCompleted", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "childWorkflowReturnValue", + "type" : { + "type" : "record", + "name" : "WorkflowReturnValue", + "namespace" : "io.infinitic.workflows.data", + "fields" : [ { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "returnValue", + "type" : "io.infinitic.data.SerializedData" + } ] + } + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "taskCanceled", + "type" : [ "null", { + "type" : "record", + "name" : "TaskCanceled", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "canceledTaskError", + "type" : "CanceledTaskError" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "taskFailed", + "type" : [ "null", { + "type" : "record", + "name" : "TaskFailed", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "failedTaskError", + "type" : "FailedTaskError" + }, { + "name" : "deferredError", + "type" : [ "null", "CanceledTaskError", "CanceledWorkflowError", "FailedTaskError", "FailedWorkflowError", "FailedWorkflowTaskError", "TimedOutTaskError", "TimedOutWorkflowError", "UnknownTaskError", "UnknownWorkflowError" ] + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "taskCompleted", + "type" : [ "null", { + "type" : "record", + "name" : "TaskCompleted", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "taskReturnValue", + "type" : { + "type" : "record", + "name" : "TaskReturnValue", + "namespace" : "io.infinitic.tasks.data", + "fields" : [ { + "name" : "taskId", + "type" : "string" + }, { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskMeta", + "type" : { + "type" : "map", + "values" : "bytes" + } + }, { + "name" : "returnValue", + "type" : "io.infinitic.data.SerializedData" + } ] + } + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + } ] +} \ No newline at end of file diff --git a/infinitic-common/src/main/resources/schemas/workflowState-0.11.7.avsc b/infinitic-common/src/main/resources/schemas/workflowState-0.11.7.avsc new file mode 100644 index 000000000..a1d0003a2 --- /dev/null +++ b/infinitic-common/src/main/resources/schemas/workflowState-0.11.7.avsc @@ -0,0 +1,1352 @@ +{ + "type" : "record", + "name" : "WorkflowState", + "namespace" : "io.infinitic.workflows.engine", + "fields" : [ { + "name" : "lastMessageId", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowVersion", + "type" : [ "null", "int" ], + "default" : null + }, { + "name" : "workflowTags", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "workflowMeta", + "type" : { + "type" : "map", + "values" : "bytes" + } + }, { + "name" : "runningWorkflowTaskId", + "type" : [ "null", "string" ] + }, { + "name" : "runningMethodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "runningMethodRunPosition", + "type" : [ "null", "int" ] + }, { + "name" : "runningTerminatedCommands", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "runningWorkflowTaskInstant", + "type" : [ "null", "long" ] + }, { + "name" : "workflowTaskIndex", + "type" : "int" + }, { + "name" : "methodRuns", + "type" : { + "type" : "array", + "items" : { + "type" : "record", + "name" : "MethodRun", + "namespace" : "io.infinitic.workflows.data", + "fields" : [ { + "name" : "waitingClients", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "parentWorkflowId", + "type" : [ "null", "string" ] + }, { + "name" : "parentWorkflowName", + "type" : [ "null", "string" ] + }, { + "name" : "parentMethodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameterTypes", + "type" : [ "null", { + "type" : "array", + "items" : "string" + } ] + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : { + "type" : "record", + "name" : "SerializedData", + "namespace" : "io.infinitic.data", + "fields" : [ { + "name" : "bytes", + "type" : "bytes" + }, { + "name" : "type", + "type" : { + "type" : "enum", + "name" : "SerializedDataType", + "symbols" : [ "NULL", "JSON_JACKSON", "JSON_KOTLIN" ] + } + }, { + "name" : "meta", + "type" : { + "type" : "map", + "values" : "bytes" + } + } ] + } + } + }, { + "name" : "methodReturnValue", + "type" : [ "null", "io.infinitic.data.SerializedData" ] + }, { + "name" : "workflowTaskIndexAtStart", + "type" : "int" + }, { + "name" : "propertiesNameHashAtStart", + "type" : { + "type" : "map", + "values" : "string" + } + }, { + "name" : "pastCommands", + "type" : { + "type" : "array", + "items" : [ { + "type" : "record", + "name" : "DispatchMethod", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "DispatchMethod", + "namespace" : "Command", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : [ "null", "string" ] + }, { + "name" : "workflowTag", + "type" : [ "null", "string" ] + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameterTypes", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : "io.infinitic.data.SerializedData" + } + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ { + "type" : "record", + "name" : "Canceled", + "namespace" : "CommandStatus", + "fields" : [ { + "name" : "canceledDeferredError", + "type" : [ { + "type" : "record", + "name" : "CanceledTaskError", + "namespace" : "", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "CanceledWorkflowError", + "namespace" : "", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + } ] + } ] + }, { + "name" : "cancellationWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "Completed", + "namespace" : "CommandStatus", + "fields" : [ { + "name" : "returnIndex", + "type" : "int", + "default" : 0 + }, { + "name" : "returnValue", + "type" : "io.infinitic.data.SerializedData" + }, { + "name" : "completionWorkflowTaskIndex", + "type" : "int" + }, { + "name" : "signalId", + "type" : [ "null", "string" ], + "default" : null + } ] + }, { + "type" : "record", + "name" : "Failed", + "namespace" : "CommandStatus", + "fields" : [ { + "name" : "failedDeferredError", + "type" : [ { + "type" : "record", + "name" : "FailedTaskError", + "namespace" : "", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "cause", + "type" : { + "type" : "record", + "name" : "WorkerError", + "namespace" : "io.infinitic.tasks.executor", + "fields" : [ { + "name" : "workerName", + "type" : "string" + }, { + "name" : "name", + "type" : "string" + }, { + "name" : "message", + "type" : [ "null", "string" ] + }, { + "name" : "stackTraceToString", + "type" : "string" + }, { + "name" : "cause", + "type" : [ "null", "WorkerError" ] + } ] + } + } ] + }, { + "type" : "record", + "name" : "FailedWorkflowError", + "namespace" : "", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "deferredError", + "type" : [ "CanceledTaskError", "CanceledWorkflowError", "FailedTaskError", "FailedWorkflowError", { + "type" : "record", + "name" : "FailedWorkflowTaskError", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "workflowTaskId", + "type" : "string" + }, { + "name" : "cause", + "type" : "io.infinitic.tasks.executor.WorkerError" + } ] + }, { + "type" : "record", + "name" : "TimedOutTaskError", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "TimedOutWorkflowError", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + } ] + }, { + "type" : "record", + "name" : "UnknownTaskError", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "UnknownWorkflowError", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + } ] + } ] + } ] + }, "FailedWorkflowTaskError" ] + }, { + "name" : "failureWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "Ongoing", + "namespace" : "CommandStatus", + "fields" : [ ] + }, { + "type" : "record", + "name" : "Unknown", + "namespace" : "CommandStatus", + "fields" : [ { + "name" : "unknownDeferredError", + "type" : [ "UnknownTaskError", "UnknownWorkflowError" ] + }, { + "name" : "unknowingWorkflowTaskIndex", + "type" : "int" + } ] + } ] + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "DispatchTask", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "DispatchTask", + "namespace" : "Command", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameterTypes", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : "io.infinitic.data.SerializedData" + } + }, { + "name" : "taskTags", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "taskMeta", + "type" : { + "type" : "map", + "values" : "bytes" + } + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "taskRetrySequence", + "type" : "int" + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "DispatchWorkflow", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "DispatchWorkflow", + "namespace" : "Command", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameterTypes", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : "io.infinitic.data.SerializedData" + } + }, { + "name" : "workflowTags", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "workflowMeta", + "type" : { + "type" : "map", + "values" : "bytes" + } + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "InlineTask", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "InlineTask", + "namespace" : "Command", + "fields" : [ { + "name" : "task", + "type" : "string" + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "ReceiveSignal", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "ReceiveSignal", + "namespace" : "Command", + "fields" : [ { + "name" : "channelName", + "type" : "string" + }, { + "name" : "channelSignalType", + "type" : [ "null", "string" ] + }, { + "name" : "channelEventFilter", + "type" : [ "null", { + "type" : "record", + "name" : "ChannelEventFilter", + "namespace" : "io.infinitic.workflows.data", + "fields" : [ { + "name" : "jsonPath", + "type" : "string" + }, { + "name" : "filter", + "type" : [ "null", "string" ] + } ] + } ] + }, { + "name" : "receivedSignalLimit", + "type" : [ "int", "null" ], + "default" : 1 + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + }, { + "name" : "commandStatuses", + "type" : { + "type" : "array", + "items" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, + "default" : [ ] + } ] + }, { + "type" : "record", + "name" : "SendSignal", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "SendSignal", + "namespace" : "Command", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : [ "null", "string" ] + }, { + "name" : "workflowTag", + "type" : [ "null", "string" ] + }, { + "name" : "channelName", + "type" : "string" + }, { + "name" : "channelSignal", + "type" : "io.infinitic.data.SerializedData" + }, { + "name" : "channelSignalTypes", + "type" : { + "type" : "array", + "items" : "string" + } + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "StartDurationTimer", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "StartDurationTimer", + "namespace" : "Command", + "fields" : [ { + "name" : "duration", + "type" : "long" + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "StartInstantTimer", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "StartInstantTimer", + "namespace" : "Command", + "fields" : [ { + "name" : "instant", + "type" : "long" + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + } ] + } ] + } + }, { + "name" : "pastSteps", + "type" : { + "type" : "array", + "items" : { + "type" : "record", + "name" : "PastStep", + "fields" : [ { + "name" : "stepPosition", + "type" : "int" + }, { + "name" : "step", + "type" : [ { + "type" : "record", + "name" : "And", + "namespace" : "Step", + "fields" : [ { + "name" : "steps", + "type" : { + "type" : "array", + "items" : [ "And", { + "type" : "record", + "name" : "Id", + "fields" : [ { + "name" : "commandId", + "type" : "string" + }, { + "name" : "awaitIndex", + "type" : "int", + "default" : 0 + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + } ] + }, { + "type" : "record", + "name" : "Or", + "fields" : [ { + "name" : "steps", + "type" : { + "type" : "array", + "items" : [ "And", "Id", "Or" ] + } + } ] + } ] + } + } ] + }, "Step.Id", "Step.Or" ] + }, { + "name" : "stepHash", + "type" : "string" + }, { + "name" : "workflowTaskIndexAtStart", + "type" : "int" + }, { + "name" : "stepStatus", + "type" : [ { + "type" : "record", + "name" : "Canceled", + "namespace" : "StepStatus", + "fields" : [ { + "name" : "canceledDeferredError", + "type" : [ "CanceledTaskError", "CanceledWorkflowError" ] + }, { + "name" : "cancellationWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "Completed", + "namespace" : "StepStatus", + "fields" : [ { + "name" : "returnValue", + "type" : "io.infinitic.data.SerializedData" + }, { + "name" : "completionWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "CurrentlyFailed", + "namespace" : "StepStatus", + "fields" : [ { + "name" : "failedDeferredError", + "type" : [ "FailedTaskError", "FailedWorkflowError", "FailedWorkflowTaskError" ] + }, { + "name" : "failureWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "Failed", + "namespace" : "StepStatus", + "fields" : [ { + "name" : "failedDeferredError", + "type" : [ "FailedTaskError", "FailedWorkflowError", "FailedWorkflowTaskError" ] + }, { + "name" : "failureWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "Unknown", + "namespace" : "StepStatus", + "fields" : [ { + "name" : "unknownDeferredError", + "type" : [ "UnknownTaskError", "UnknownWorkflowError" ] + }, { + "name" : "unknowingWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "Waiting", + "namespace" : "StepStatus", + "fields" : [ ] + } ] + }, { + "name" : "propertiesNameHashAtTermination", + "type" : [ "null", { + "type" : "map", + "values" : "string" + } ] + }, { + "name" : "workflowTaskIndexAtTermination", + "type" : [ "null", "int" ] + } ] + } + } + }, { + "name" : "currentStep", + "type" : [ "null", "PastStep" ] + } ] + } + } + }, { + "name" : "receivingChannels", + "type" : { + "type" : "array", + "items" : { + "type" : "record", + "name" : "ReceivingChannel", + "namespace" : "io.infinitic.workflows.data", + "fields" : [ { + "name" : "channelName", + "type" : "string" + }, { + "name" : "channelSignalType", + "type" : [ "null", "string" ] + }, { + "name" : "channelEventFilter", + "type" : [ "null", "ChannelEventFilter" ] + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "commandId", + "type" : "string" + }, { + "name" : "receivedSignalLimit", + "type" : [ "int", "null" ], + "default" : 1 + }, { + "name" : "receivedSignalCount", + "type" : "int", + "default" : 0 + } ] + } + } + }, { + "name" : "currentPropertiesNameHash", + "type" : { + "type" : "map", + "values" : "string" + } + }, { + "name" : "propertiesHashValue", + "type" : { + "type" : "map", + "values" : "io.infinitic.data.SerializedData" + } + }, { + "name" : "messagesBuffer", + "type" : { + "type" : "array", + "items" : [ { + "type" : "record", + "name" : "CancelWorkflow", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "reason", + "type" : { + "type" : "enum", + "name" : "WorkflowCancellationReason", + "namespace" : "io.infinitic.workflows.data", + "symbols" : [ "CANCELED_BY_CLIENT", "CANCELED_BY_PARENT" ] + } + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "ChildMethodCanceled", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "childCanceledWorkflowError", + "type" : "CanceledWorkflowError" + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "ChildMethodCompleted", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "childWorkflowReturnValue", + "type" : { + "type" : "record", + "name" : "WorkflowReturnValue", + "namespace" : "io.infinitic.workflows.data", + "fields" : [ { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "returnValue", + "type" : "io.infinitic.data.SerializedData" + } ] + } + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "ChildMethodFailed", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "childFailedWorkflowError", + "type" : "FailedWorkflowError" + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "ChildMethodUnknown", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "childUnknownWorkflowError", + "type" : "UnknownWorkflowError" + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "CompleteTimers", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "CompleteWorkflow", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "workflowReturnValue", + "type" : "io.infinitic.data.SerializedData" + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "DispatchMethod", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : "io.infinitic.data.SerializedData" + } + }, { + "name" : "methodParameterTypes", + "type" : [ "null", { + "type" : "array", + "items" : "string" + } ] + }, { + "name" : "parentWorkflowId", + "type" : [ "null", "string" ] + }, { + "name" : "parentWorkflowName", + "type" : [ "null", "string" ] + }, { + "name" : "parentMethodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "clientWaiting", + "type" : "boolean" + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "DispatchWorkflow", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : "io.infinitic.data.SerializedData" + } + }, { + "name" : "methodParameterTypes", + "type" : [ "null", { + "type" : "array", + "items" : "string" + } ] + }, { + "name" : "workflowTags", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "workflowMeta", + "type" : { + "type" : "map", + "values" : "bytes" + } + }, { + "name" : "parentWorkflowName", + "type" : [ "null", "string" ] + }, { + "name" : "parentWorkflowId", + "type" : [ "null", "string" ] + }, { + "name" : "parentMethodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "clientWaiting", + "type" : "boolean" + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "RetryTasks", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "taskId", + "type" : [ "null", "string" ] + }, { + "name" : "taskStatus", + "type" : [ "null", { + "type" : "enum", + "name" : "DeferredStatus", + "namespace" : "io.infinitic.workflows", + "symbols" : [ "ONGOING", "UNKNOWN", "CANCELED", "FAILED", "COMPLETED" ] + } ] + }, { + "name" : "taskName", + "type" : [ "null", "string" ] + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "RetryWorkflowTask", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "SendSignal", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "channelName", + "type" : "string" + }, { + "name" : "channelSignalId", + "type" : "string" + }, { + "name" : "channelSignal", + "type" : "io.infinitic.data.SerializedData" + }, { + "name" : "channelSignalTypes", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "TaskCanceled", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "canceledTaskError", + "type" : "CanceledTaskError" + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "TaskCompleted", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "taskReturnValue", + "type" : { + "type" : "record", + "name" : "TaskReturnValue", + "namespace" : "io.infinitic.tasks.data", + "fields" : [ { + "name" : "taskId", + "type" : "string" + }, { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskMeta", + "type" : { + "type" : "map", + "values" : "bytes" + } + }, { + "name" : "returnValue", + "type" : "io.infinitic.data.SerializedData" + } ] + } + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "TaskFailed", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "failedTaskError", + "type" : "FailedTaskError" + }, { + "name" : "deferredError", + "type" : [ "null", "CanceledTaskError", "CanceledWorkflowError", "FailedTaskError", "FailedWorkflowError", "FailedWorkflowTaskError", "TimedOutTaskError", "TimedOutWorkflowError", "UnknownTaskError", "UnknownWorkflowError" ] + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "TimerCompleted", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "timerId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "WaitWorkflow", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + } + } ] +} \ No newline at end of file diff --git a/infinitic-common/src/main/resources/schemas/workflowTagEnvelope-0.11.7.avsc b/infinitic-common/src/main/resources/schemas/workflowTagEnvelope-0.11.7.avsc new file mode 100644 index 000000000..c7f897aca --- /dev/null +++ b/infinitic-common/src/main/resources/schemas/workflowTagEnvelope-0.11.7.avsc @@ -0,0 +1,353 @@ +{ + "type" : "record", + "name" : "WorkflowTagEnvelope", + "namespace" : "io.infinitic.workflows.tag", + "fields" : [ { + "name" : "name", + "type" : "string" + }, { + "name" : "type", + "type" : { + "type" : "enum", + "name" : "WorkflowTagMessageType", + "symbols" : [ "DISPATCH_WORKFLOW_BY_CUSTOM_ID", "DISPATCH_METHOD_BY_TAG", "ADD_TAG_TO_WORKFLOW", "REMOVE_TAG_FROM_WORKFLOW", "SEND_SIGNAL_BY_TAG", "CANCEL_WORKFLOW_BY_TAG", "RETRY_WORKFLOW_TASK_BY_TAG", "RETRY_TASKS_BY_TAG", "COMPLETE_TIMER_BY_TAG", "GET_WORKFLOW_IDS_BY_TAG" ] + } + }, { + "name" : "dispatchWorkflowByCustomId", + "type" : [ "null", { + "type" : "record", + "name" : "DispatchWorkflowByCustomId", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowTag", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : { + "type" : "record", + "name" : "SerializedData", + "namespace" : "io.infinitic.data", + "fields" : [ { + "name" : "bytes", + "type" : "bytes" + }, { + "name" : "type", + "type" : { + "type" : "enum", + "name" : "SerializedDataType", + "symbols" : [ "NULL", "JSON_JACKSON", "JSON_KOTLIN" ] + } + }, { + "name" : "meta", + "type" : { + "type" : "map", + "values" : "bytes" + } + } ] + } + } + }, { + "name" : "methodParameterTypes", + "type" : [ "null", { + "type" : "array", + "items" : "string" + } ] + }, { + "name" : "workflowTags", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "workflowMeta", + "type" : { + "type" : "map", + "values" : "bytes" + } + }, { + "name" : "parentWorkflowName", + "type" : [ "null", "string" ] + }, { + "name" : "parentWorkflowId", + "type" : [ "null", "string" ] + }, { + "name" : "parentMethodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "clientWaiting", + "type" : "boolean" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ], + "default" : null + }, { + "name" : "dispatchMethodByTag", + "type" : [ "null", { + "type" : "record", + "name" : "DispatchMethodByTag", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowTag", + "type" : "string" + }, { + "name" : "parentWorkflowId", + "type" : [ "null", "string" ] + }, { + "name" : "parentWorkflowName", + "type" : [ "null", "string" ] + }, { + "name" : "parentMethodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameterTypes", + "type" : [ "null", { + "type" : "array", + "items" : "string" + } ] + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : "io.infinitic.data.SerializedData" + } + }, { + "name" : "clientWaiting", + "type" : "boolean" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "addTagToWorkflow", + "type" : [ "null", { + "type" : "record", + "name" : "AddTagToWorkflow", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowTag", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "removeTagFromWorkflow", + "type" : [ "null", { + "type" : "record", + "name" : "RemoveTagFromWorkflow", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowTag", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "sendSignalByTag", + "type" : [ "null", { + "type" : "record", + "name" : "SendSignalByTag", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowTag", + "type" : "string" + }, { + "name" : "channelName", + "type" : "string" + }, { + "name" : "channelSignalId", + "type" : "string" + }, { + "name" : "channelSignal", + "type" : "io.infinitic.data.SerializedData" + }, { + "name" : "channelSignalTypes", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "emitterWorkflowId", + "type" : [ "null", "string" ] + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "cancelWorkflowByTag", + "type" : [ "null", { + "type" : "record", + "name" : "CancelWorkflowByTag", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowTag", + "type" : "string" + }, { + "name" : "reason", + "type" : { + "type" : "enum", + "name" : "WorkflowCancellationReason", + "namespace" : "io.infinitic.workflows.data", + "symbols" : [ "CANCELED_BY_CLIENT", "CANCELED_BY_PARENT" ] + } + }, { + "name" : "emitterWorkflowId", + "type" : [ "null", "string" ] + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "retryWorkflowTaskByTag", + "type" : [ "null", { + "type" : "record", + "name" : "RetryWorkflowTaskByTag", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowTag", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "retryTasksByTag", + "type" : [ "null", { + "type" : "record", + "name" : "RetryTasksByTag", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowTag", + "type" : "string" + }, { + "name" : "taskId", + "type" : [ "null", "string" ] + }, { + "name" : "taskStatus", + "type" : [ "null", { + "type" : "enum", + "name" : "DeferredStatus", + "namespace" : "io.infinitic.workflows", + "symbols" : [ "ONGOING", "UNKNOWN", "CANCELED", "FAILED", "COMPLETED" ] + } ] + }, { + "name" : "taskName", + "type" : [ "null", "string" ] + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + }, { + "name" : "completeTimersByTag", + "type" : [ "null", { + "type" : "record", + "name" : "CompleteTimersByTag", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowTag", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ], + "default" : null + }, { + "name" : "getWorkflowIdsByTag", + "type" : [ "null", { + "type" : "record", + "name" : "GetWorkflowIdsByTag", + "fields" : [ { + "name" : "messageId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowTag", + "type" : "string" + }, { + "name" : "emitterName", + "type" : "string" + } ] + } ] + } ] +} \ No newline at end of file diff --git a/infinitic-common/src/main/resources/schemas/workflowTaskParameters-0.11.7.avsc b/infinitic-common/src/main/resources/schemas/workflowTaskParameters-0.11.7.avsc new file mode 100644 index 000000000..d030e5a4b --- /dev/null +++ b/infinitic-common/src/main/resources/schemas/workflowTaskParameters-0.11.7.avsc @@ -0,0 +1,817 @@ +{ + "type" : "record", + "name" : "WorkflowTaskParameters", + "namespace" : "io.infinitic.common.workflows.data.workflowTasks", + "fields" : [ { + "name" : "version", + "type" : "string", + "default" : "0.9.7" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowVersion", + "type" : [ "null", "int" ], + "default" : null + }, { + "name" : "workflowTags", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "workflowMeta", + "type" : { + "type" : "map", + "values" : "bytes" + } + }, { + "name" : "workflowPropertiesHashValue", + "type" : { + "type" : "map", + "values" : { + "type" : "record", + "name" : "SerializedData", + "namespace" : "io.infinitic.data", + "fields" : [ { + "name" : "bytes", + "type" : "bytes" + }, { + "name" : "type", + "type" : { + "type" : "enum", + "name" : "SerializedDataType", + "symbols" : [ "NULL", "JSON_JACKSON", "JSON_KOTLIN" ] + } + }, { + "name" : "meta", + "type" : { + "type" : "map", + "values" : "bytes" + } + } ] + } + } + }, { + "name" : "workflowTaskIndex", + "type" : "int" + }, { + "name" : "methodRun", + "type" : { + "type" : "record", + "name" : "MethodRun", + "namespace" : "io.infinitic.workflows.data", + "fields" : [ { + "name" : "waitingClients", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "methodRunId", + "type" : "string" + }, { + "name" : "parentWorkflowId", + "type" : [ "null", "string" ] + }, { + "name" : "parentWorkflowName", + "type" : [ "null", "string" ] + }, { + "name" : "parentMethodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameterTypes", + "type" : [ "null", { + "type" : "array", + "items" : "string" + } ] + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : "io.infinitic.data.SerializedData" + } + }, { + "name" : "methodReturnValue", + "type" : [ "null", "io.infinitic.data.SerializedData" ] + }, { + "name" : "workflowTaskIndexAtStart", + "type" : "int" + }, { + "name" : "propertiesNameHashAtStart", + "type" : { + "type" : "map", + "values" : "string" + } + }, { + "name" : "pastCommands", + "type" : { + "type" : "array", + "items" : [ { + "type" : "record", + "name" : "DispatchMethod", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "DispatchMethod", + "namespace" : "Command", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : [ "null", "string" ] + }, { + "name" : "workflowTag", + "type" : [ "null", "string" ] + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameterTypes", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : "io.infinitic.data.SerializedData" + } + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ { + "type" : "record", + "name" : "Canceled", + "namespace" : "CommandStatus", + "fields" : [ { + "name" : "canceledDeferredError", + "type" : [ { + "type" : "record", + "name" : "CanceledTaskError", + "namespace" : "", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "CanceledWorkflowError", + "namespace" : "", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + } ] + } ] + }, { + "name" : "cancellationWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "Completed", + "namespace" : "CommandStatus", + "fields" : [ { + "name" : "returnIndex", + "type" : "int", + "default" : 0 + }, { + "name" : "returnValue", + "type" : "io.infinitic.data.SerializedData" + }, { + "name" : "completionWorkflowTaskIndex", + "type" : "int" + }, { + "name" : "signalId", + "type" : [ "null", "string" ], + "default" : null + } ] + }, { + "type" : "record", + "name" : "Failed", + "namespace" : "CommandStatus", + "fields" : [ { + "name" : "failedDeferredError", + "type" : [ { + "type" : "record", + "name" : "FailedTaskError", + "namespace" : "", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "cause", + "type" : { + "type" : "record", + "name" : "WorkerError", + "namespace" : "io.infinitic.tasks.executor", + "fields" : [ { + "name" : "workerName", + "type" : "string" + }, { + "name" : "name", + "type" : "string" + }, { + "name" : "message", + "type" : [ "null", "string" ] + }, { + "name" : "stackTraceToString", + "type" : "string" + }, { + "name" : "cause", + "type" : [ "null", "WorkerError" ] + } ] + } + } ] + }, { + "type" : "record", + "name" : "FailedWorkflowError", + "namespace" : "", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "deferredError", + "type" : [ "CanceledTaskError", "CanceledWorkflowError", "FailedTaskError", "FailedWorkflowError", { + "type" : "record", + "name" : "FailedWorkflowTaskError", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "workflowTaskId", + "type" : "string" + }, { + "name" : "cause", + "type" : "io.infinitic.tasks.executor.WorkerError" + } ] + }, { + "type" : "record", + "name" : "TimedOutTaskError", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "TimedOutWorkflowError", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + } ] + }, { + "type" : "record", + "name" : "UnknownTaskError", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "UnknownWorkflowError", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + } ] + } ] + } ] + }, "FailedWorkflowTaskError" ] + }, { + "name" : "failureWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "Ongoing", + "namespace" : "CommandStatus", + "fields" : [ ] + }, { + "type" : "record", + "name" : "Unknown", + "namespace" : "CommandStatus", + "fields" : [ { + "name" : "unknownDeferredError", + "type" : [ "UnknownTaskError", "UnknownWorkflowError" ] + }, { + "name" : "unknowingWorkflowTaskIndex", + "type" : "int" + } ] + } ] + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "DispatchTask", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "DispatchTask", + "namespace" : "Command", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameterTypes", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : "io.infinitic.data.SerializedData" + } + }, { + "name" : "taskTags", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "taskMeta", + "type" : { + "type" : "map", + "values" : "bytes" + } + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "taskRetrySequence", + "type" : "int" + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "DispatchWorkflow", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "DispatchWorkflow", + "namespace" : "Command", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameterTypes", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : "io.infinitic.data.SerializedData" + } + }, { + "name" : "workflowTags", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "workflowMeta", + "type" : { + "type" : "map", + "values" : "bytes" + } + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "InlineTask", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "InlineTask", + "namespace" : "Command", + "fields" : [ { + "name" : "task", + "type" : "string" + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "ReceiveSignal", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "ReceiveSignal", + "namespace" : "Command", + "fields" : [ { + "name" : "channelName", + "type" : "string" + }, { + "name" : "channelSignalType", + "type" : [ "null", "string" ] + }, { + "name" : "channelEventFilter", + "type" : [ "null", { + "type" : "record", + "name" : "ChannelEventFilter", + "namespace" : "io.infinitic.workflows.data", + "fields" : [ { + "name" : "jsonPath", + "type" : "string" + }, { + "name" : "filter", + "type" : [ "null", "string" ] + } ] + } ] + }, { + "name" : "receivedSignalLimit", + "type" : [ "int", "null" ], + "default" : 1 + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + }, { + "name" : "commandStatuses", + "type" : { + "type" : "array", + "items" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, + "default" : [ ] + } ] + }, { + "type" : "record", + "name" : "SendSignal", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "SendSignal", + "namespace" : "Command", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : [ "null", "string" ] + }, { + "name" : "workflowTag", + "type" : [ "null", "string" ] + }, { + "name" : "channelName", + "type" : "string" + }, { + "name" : "channelSignal", + "type" : "io.infinitic.data.SerializedData" + }, { + "name" : "channelSignalTypes", + "type" : { + "type" : "array", + "items" : "string" + } + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "StartDurationTimer", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "StartDurationTimer", + "namespace" : "Command", + "fields" : [ { + "name" : "duration", + "type" : "long" + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "StartInstantTimer", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "StartInstantTimer", + "namespace" : "Command", + "fields" : [ { + "name" : "instant", + "type" : "long" + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + } ] + } ] + } + }, { + "name" : "pastSteps", + "type" : { + "type" : "array", + "items" : { + "type" : "record", + "name" : "PastStep", + "fields" : [ { + "name" : "stepPosition", + "type" : "int" + }, { + "name" : "step", + "type" : [ { + "type" : "record", + "name" : "And", + "namespace" : "Step", + "fields" : [ { + "name" : "steps", + "type" : { + "type" : "array", + "items" : [ "And", { + "type" : "record", + "name" : "Id", + "fields" : [ { + "name" : "commandId", + "type" : "string" + }, { + "name" : "awaitIndex", + "type" : "int", + "default" : 0 + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + } ] + }, { + "type" : "record", + "name" : "Or", + "fields" : [ { + "name" : "steps", + "type" : { + "type" : "array", + "items" : [ "And", "Id", "Or" ] + } + } ] + } ] + } + } ] + }, "Step.Id", "Step.Or" ] + }, { + "name" : "stepHash", + "type" : "string" + }, { + "name" : "workflowTaskIndexAtStart", + "type" : "int" + }, { + "name" : "stepStatus", + "type" : [ { + "type" : "record", + "name" : "Canceled", + "namespace" : "StepStatus", + "fields" : [ { + "name" : "canceledDeferredError", + "type" : [ "CanceledTaskError", "CanceledWorkflowError" ] + }, { + "name" : "cancellationWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "Completed", + "namespace" : "StepStatus", + "fields" : [ { + "name" : "returnValue", + "type" : "io.infinitic.data.SerializedData" + }, { + "name" : "completionWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "CurrentlyFailed", + "namespace" : "StepStatus", + "fields" : [ { + "name" : "failedDeferredError", + "type" : [ "FailedTaskError", "FailedWorkflowError", "FailedWorkflowTaskError" ] + }, { + "name" : "failureWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "Failed", + "namespace" : "StepStatus", + "fields" : [ { + "name" : "failedDeferredError", + "type" : [ "FailedTaskError", "FailedWorkflowError", "FailedWorkflowTaskError" ] + }, { + "name" : "failureWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "Unknown", + "namespace" : "StepStatus", + "fields" : [ { + "name" : "unknownDeferredError", + "type" : [ "UnknownTaskError", "UnknownWorkflowError" ] + }, { + "name" : "unknowingWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "Waiting", + "namespace" : "StepStatus", + "fields" : [ ] + } ] + }, { + "name" : "propertiesNameHashAtTermination", + "type" : [ "null", { + "type" : "map", + "values" : "string" + } ] + }, { + "name" : "workflowTaskIndexAtTermination", + "type" : [ "null", "int" ] + } ] + } + } + }, { + "name" : "currentStep", + "type" : [ "null", "PastStep" ] + } ] + } + }, { + "name" : "emitterName", + "type" : "string" + } ] +} \ No newline at end of file diff --git a/infinitic-common/src/main/resources/schemas/workflowTaskReturnValue-0.11.7.avsc b/infinitic-common/src/main/resources/schemas/workflowTaskReturnValue-0.11.7.avsc new file mode 100644 index 000000000..2a765ed0d --- /dev/null +++ b/infinitic-common/src/main/resources/schemas/workflowTaskReturnValue-0.11.7.avsc @@ -0,0 +1,660 @@ +{ + "type" : "record", + "name" : "WorkflowTaskReturnValue", + "namespace" : "io.infinitic.common.workflows.data.workflowTasks", + "fields" : [ { + "name" : "version", + "type" : "string", + "default" : "0.9.7" + }, { + "name" : "newCommands", + "type" : { + "type" : "array", + "items" : [ { + "type" : "record", + "name" : "DispatchMethod", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "DispatchMethod", + "namespace" : "Command", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : [ "null", "string" ] + }, { + "name" : "workflowTag", + "type" : [ "null", "string" ] + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameterTypes", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : { + "type" : "record", + "name" : "SerializedData", + "namespace" : "io.infinitic.data", + "fields" : [ { + "name" : "bytes", + "type" : "bytes" + }, { + "name" : "type", + "type" : { + "type" : "enum", + "name" : "SerializedDataType", + "symbols" : [ "NULL", "JSON_JACKSON", "JSON_KOTLIN" ] + } + }, { + "name" : "meta", + "type" : { + "type" : "map", + "values" : "bytes" + } + } ] + } + } + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ { + "type" : "record", + "name" : "Canceled", + "namespace" : "CommandStatus", + "fields" : [ { + "name" : "canceledDeferredError", + "type" : [ { + "type" : "record", + "name" : "CanceledTaskError", + "namespace" : "", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "CanceledWorkflowError", + "namespace" : "", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + } ] + } ] + }, { + "name" : "cancellationWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "Completed", + "namespace" : "CommandStatus", + "fields" : [ { + "name" : "returnIndex", + "type" : "int", + "default" : 0 + }, { + "name" : "returnValue", + "type" : "io.infinitic.data.SerializedData" + }, { + "name" : "completionWorkflowTaskIndex", + "type" : "int" + }, { + "name" : "signalId", + "type" : [ "null", "string" ], + "default" : null + } ] + }, { + "type" : "record", + "name" : "Failed", + "namespace" : "CommandStatus", + "fields" : [ { + "name" : "failedDeferredError", + "type" : [ { + "type" : "record", + "name" : "FailedTaskError", + "namespace" : "", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "cause", + "type" : { + "type" : "record", + "name" : "WorkerError", + "namespace" : "io.infinitic.tasks.executor", + "fields" : [ { + "name" : "workerName", + "type" : "string" + }, { + "name" : "name", + "type" : "string" + }, { + "name" : "message", + "type" : [ "null", "string" ] + }, { + "name" : "stackTraceToString", + "type" : "string" + }, { + "name" : "cause", + "type" : [ "null", "WorkerError" ] + } ] + } + } ] + }, { + "type" : "record", + "name" : "FailedWorkflowError", + "namespace" : "", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + }, { + "name" : "deferredError", + "type" : [ "CanceledTaskError", "CanceledWorkflowError", "FailedTaskError", "FailedWorkflowError", { + "type" : "record", + "name" : "FailedWorkflowTaskError", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "workflowTaskId", + "type" : "string" + }, { + "name" : "cause", + "type" : "io.infinitic.tasks.executor.WorkerError" + } ] + }, { + "type" : "record", + "name" : "TimedOutTaskError", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "TimedOutWorkflowError", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + } ] + }, { + "type" : "record", + "name" : "UnknownTaskError", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "taskId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "UnknownWorkflowError", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : "string" + }, { + "name" : "methodRunId", + "type" : [ "null", "string" ] + } ] + } ] + } ] + }, "FailedWorkflowTaskError" ] + }, { + "name" : "failureWorkflowTaskIndex", + "type" : "int" + } ] + }, { + "type" : "record", + "name" : "Ongoing", + "namespace" : "CommandStatus", + "fields" : [ ] + }, { + "type" : "record", + "name" : "Unknown", + "namespace" : "CommandStatus", + "fields" : [ { + "name" : "unknownDeferredError", + "type" : [ "UnknownTaskError", "UnknownWorkflowError" ] + }, { + "name" : "unknowingWorkflowTaskIndex", + "type" : "int" + } ] + } ] + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "DispatchTask", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "DispatchTask", + "namespace" : "Command", + "fields" : [ { + "name" : "taskName", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameterTypes", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : "io.infinitic.data.SerializedData" + } + }, { + "name" : "taskTags", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "taskMeta", + "type" : { + "type" : "map", + "values" : "bytes" + } + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "taskRetrySequence", + "type" : "int" + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "DispatchWorkflow", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "DispatchWorkflow", + "namespace" : "Command", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "methodName", + "type" : "string" + }, { + "name" : "methodParameterTypes", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "methodParameters", + "type" : { + "type" : "array", + "items" : "io.infinitic.data.SerializedData" + } + }, { + "name" : "workflowTags", + "type" : { + "type" : "array", + "items" : "string" + } + }, { + "name" : "workflowMeta", + "type" : { + "type" : "map", + "values" : "bytes" + } + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "InlineTask", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "InlineTask", + "namespace" : "Command", + "fields" : [ { + "name" : "task", + "type" : "string" + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "ReceiveSignal", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "ReceiveSignal", + "namespace" : "Command", + "fields" : [ { + "name" : "channelName", + "type" : "string" + }, { + "name" : "channelSignalType", + "type" : [ "null", "string" ] + }, { + "name" : "channelEventFilter", + "type" : [ "null", { + "type" : "record", + "name" : "ChannelEventFilter", + "namespace" : "io.infinitic.workflows.data", + "fields" : [ { + "name" : "jsonPath", + "type" : "string" + }, { + "name" : "filter", + "type" : [ "null", "string" ] + } ] + } ] + }, { + "name" : "receivedSignalLimit", + "type" : [ "int", "null" ], + "default" : 1 + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + }, { + "name" : "commandStatuses", + "type" : { + "type" : "array", + "items" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, + "default" : [ ] + } ] + }, { + "type" : "record", + "name" : "SendSignal", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "SendSignal", + "namespace" : "Command", + "fields" : [ { + "name" : "workflowName", + "type" : "string" + }, { + "name" : "workflowId", + "type" : [ "null", "string" ] + }, { + "name" : "workflowTag", + "type" : [ "null", "string" ] + }, { + "name" : "channelName", + "type" : "string" + }, { + "name" : "channelSignal", + "type" : "io.infinitic.data.SerializedData" + }, { + "name" : "channelSignalTypes", + "type" : { + "type" : "array", + "items" : "string" + } + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "StartDurationTimer", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "StartDurationTimer", + "namespace" : "Command", + "fields" : [ { + "name" : "duration", + "type" : "long" + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + } ] + }, { + "type" : "record", + "name" : "StartInstantTimer", + "namespace" : "PastCommand", + "fields" : [ { + "name" : "command", + "type" : { + "type" : "record", + "name" : "StartInstantTimer", + "namespace" : "Command", + "fields" : [ { + "name" : "instant", + "type" : "long" + } ] + } + }, { + "name" : "commandPosition", + "type" : "int" + }, { + "name" : "commandSimpleName", + "type" : "string" + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + }, { + "name" : "commandId", + "type" : "string" + } ] + } ] + } + }, { + "name" : "newStep", + "type" : [ "null", { + "type" : "record", + "name" : "NewStep", + "namespace" : "io.infinitic.workflows.data", + "fields" : [ { + "name" : "stepId", + "type" : "string" + }, { + "name" : "step", + "type" : [ { + "type" : "record", + "name" : "And", + "namespace" : "Step", + "fields" : [ { + "name" : "steps", + "type" : { + "type" : "array", + "items" : [ "And", { + "type" : "record", + "name" : "Id", + "fields" : [ { + "name" : "commandId", + "type" : "string" + }, { + "name" : "awaitIndex", + "type" : "int", + "default" : 0 + }, { + "name" : "commandStatus", + "type" : [ "CommandStatus.Canceled", "CommandStatus.Completed", "CommandStatus.Failed", "CommandStatus.Ongoing", "CommandStatus.Unknown" ] + } ] + }, { + "type" : "record", + "name" : "Or", + "fields" : [ { + "name" : "steps", + "type" : { + "type" : "array", + "items" : [ "And", "Id", "Or" ] + } + } ] + } ] + } + } ] + }, "Step.Id", "Step.Or" ] + }, { + "name" : "stepPosition", + "type" : "int" + } ] + } ] + }, { + "name" : "properties", + "type" : { + "type" : "map", + "values" : "io.infinitic.data.SerializedData" + } + }, { + "name" : "methodReturnValue", + "type" : [ "null", "io.infinitic.data.SerializedData" ] + }, { + "name" : "workflowVersion", + "type" : "int", + "default" : 0 + } ] +} \ No newline at end of file diff --git a/infinitic-common/src/main/resources/version b/infinitic-common/src/main/resources/version index 13ca94b17..12edb292a 100644 --- a/infinitic-common/src/main/resources/version +++ b/infinitic-common/src/main/resources/version @@ -1 +1 @@ -0.11.6 \ No newline at end of file +0.11.7 \ No newline at end of file diff --git a/infinitic-common/src/main/resources/versions b/infinitic-common/src/main/resources/versions index cbd5e9617..feaf5dfde 100644 --- a/infinitic-common/src/main/resources/versions +++ b/infinitic-common/src/main/resources/versions @@ -20,3 +20,4 @@ 0.11.4 0.11.5 0.11.6 +0.11.7 diff --git a/infinitic-common/src/test/kotlin/io/infinitic/common/tasks/DataTests.kt b/infinitic-common/src/test/kotlin/io/infinitic/common/tasks/DataTests.kt index 98fd28e94..d1b7c64b0 100644 --- a/infinitic-common/src/test/kotlin/io/infinitic/common/tasks/DataTests.kt +++ b/infinitic-common/src/test/kotlin/io/infinitic/common/tasks/DataTests.kt @@ -38,7 +38,6 @@ import io.infinitic.common.tasks.data.TaskRetrySequence import io.infinitic.common.tasks.data.TaskTag import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe -import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json diff --git a/infinitic-common/src/test/kotlin/io/infinitic/common/workflows/DataTests.kt b/infinitic-common/src/test/kotlin/io/infinitic/common/workflows/DataTests.kt index 160700d0b..6703eaf7b 100644 --- a/infinitic-common/src/test/kotlin/io/infinitic/common/workflows/DataTests.kt +++ b/infinitic-common/src/test/kotlin/io/infinitic/common/workflows/DataTests.kt @@ -48,7 +48,6 @@ import io.infinitic.common.workflows.data.workflows.WorkflowTag import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json diff --git a/infinitic-common/src/test/kotlin/io/infinitic/workflows/DataTests.kt b/infinitic-common/src/test/kotlin/io/infinitic/workflows/DataTests.kt index 147238552..be388b778 100644 --- a/infinitic-common/src/test/kotlin/io/infinitic/workflows/DataTests.kt +++ b/infinitic-common/src/test/kotlin/io/infinitic/workflows/DataTests.kt @@ -28,7 +28,6 @@ import io.infinitic.common.workflows.data.steps.Step import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.mockk.mockk -import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json diff --git a/infinitic-common/src/test/kotlin/io/infinitic/workflows/samples/TaskA.kt b/infinitic-common/src/test/kotlin/io/infinitic/workflows/samples/TaskA.kt index 02e6ad9a4..a01edcf79 100644 --- a/infinitic-common/src/test/kotlin/io/infinitic/workflows/samples/TaskA.kt +++ b/infinitic-common/src/test/kotlin/io/infinitic/workflows/samples/TaskA.kt @@ -28,6 +28,8 @@ interface ParentInterface { interface TaskA : ParentInterface { fun concat(str1: String, str2: String): String + fun reverse(str: String): String + fun await(delay: Long): Long } diff --git a/infinitic-common/src/test/kotlin/io/infinitic/workflows/samples/WorkflowA.kt b/infinitic-common/src/test/kotlin/io/infinitic/workflows/samples/WorkflowA.kt index e21b131af..d850d0b87 100644 --- a/infinitic-common/src/test/kotlin/io/infinitic/workflows/samples/WorkflowA.kt +++ b/infinitic-common/src/test/kotlin/io/infinitic/workflows/samples/WorkflowA.kt @@ -38,10 +38,15 @@ interface WorkflowA { val channelString: SendChannel fun empty(): String + fun syncTask(duration: Long): Long + fun asyncTask(duration: Long): Deferred + fun syncWorkflow(duration: Long): Long + fun asyncWorkflow(duration: Long): Deferred + fun dispatchSelf(): Deferred } @@ -59,9 +64,13 @@ class WorkflowAImpl : Workflow(), WorkflowA { meta = mapOf("foo" to "bar".toByteArray())) override fun empty() = "void" + override fun syncTask(duration: Long) = taskA.await(duration) + override fun asyncTask(duration: Long) = dispatch(taskA::await, duration) + override fun syncWorkflow(duration: Long) = workflowA.syncTask(duration) + override fun asyncWorkflow(duration: Long) = dispatch(workflowA::syncTask, duration) override fun dispatchSelf(): Deferred = dispatch(self::empty) diff --git a/infinitic-dashboard/README.md b/infinitic-dashboard/README.md index 5d7749dad..80d725d90 100644 --- a/infinitic-dashboard/README.md +++ b/infinitic-dashboard/README.md @@ -1,4 +1,3 @@ - ``` npm i ``` diff --git a/infinitic-dashboard/build.gradle.kts b/infinitic-dashboard/build.gradle.kts index 9aa6aba15..fae1d6aee 100644 --- a/infinitic-dashboard/build.gradle.kts +++ b/infinitic-dashboard/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,24 +20,17 @@ * * Licensor: infinitic.io */ +repositories { maven("https://jitpack.io") } -repositories { - maven("https://jitpack.io") -} - -plugins { - application -} +plugins { application } -application { - mainClass.set("io.infinitic.dashboard.MainKt") -} +application { mainClass.set("io.infinitic.dashboard.MainKt") } dependencies { - implementation(Libs.Kweb.core) + implementation(Libs.Kweb.core) - implementation(project(":infinitic-pulsar")) - implementation(project(":infinitic-transport")) + implementation(project(":infinitic-pulsar")) + implementation(project(":infinitic-transport")) } apply("../publish.gradle.kts") diff --git a/infinitic-dashboard/postcss.config.js b/infinitic-dashboard/postcss.config.js index 6eab3833f..8a5cbc20d 100644 --- a/infinitic-dashboard/postcss.config.js +++ b/infinitic-dashboard/postcss.config.js @@ -23,9 +23,9 @@ * Licensor: infinitic.io */ - module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - } +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + } } diff --git a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllJobsPanel.kt b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllJobsPanel.kt index d711a7eef..51aee7f35 100644 --- a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllJobsPanel.kt +++ b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllJobsPanel.kt @@ -34,9 +34,6 @@ import io.infinitic.dashboard.panels.infrastructure.task.TaskPanel import io.infinitic.dashboard.panels.infrastructure.workflow.WorkflowPanel import io.infinitic.dashboard.routeTo import io.infinitic.dashboard.slideovers.Slideover -import java.text.SimpleDateFormat -import java.time.Instant -import java.util.Date import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -57,6 +54,9 @@ import kweb.th import kweb.thead import kweb.tr import org.apache.pulsar.common.policies.data.PartitionedTopicStats +import java.text.SimpleDateFormat +import java.time.Instant +import java.util.* object AllJobsPanel : Panel() { override val menu = InfraMenu diff --git a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllJobsState.kt b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllJobsState.kt index e8156cdb5..51bf35415 100644 --- a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllJobsState.kt +++ b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllJobsState.kt @@ -26,7 +26,6 @@ import io.infinitic.dashboard.panels.infrastructure.requests.Completed import io.infinitic.dashboard.panels.infrastructure.requests.Failed import io.infinitic.dashboard.panels.infrastructure.requests.Loading import io.infinitic.dashboard.panels.infrastructure.requests.Request -import java.time.Instant import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.isActive @@ -34,6 +33,7 @@ import kotlinx.coroutines.launch import kweb.state.KVar import mu.KotlinLogging import org.apache.pulsar.common.policies.data.PartitionedTopicStats +import java.time.Instant private val logger = KotlinLogging.logger {} @@ -68,11 +68,13 @@ abstract class AllJobsState( } fun namesLoading() = create(names = names.copyLoading()) + fun statsLoading() = create(stats = stats.mapValues { it.value.copyLoading() }) abstract fun create(names: JobNames = this.names, stats: JobStats = this.stats): AllJobsState abstract fun getNames(): Set + abstract fun getPartitionedStats(name: String): PartitionedTopicStats } diff --git a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllTasksState.kt b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllTasksState.kt index 87f0d951c..9a062b922 100644 --- a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllTasksState.kt +++ b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllTasksState.kt @@ -26,8 +26,8 @@ import io.infinitic.common.tasks.data.ServiceName import io.infinitic.dashboard.Infinitic import io.infinitic.dashboard.panels.infrastructure.requests.Loading import io.infinitic.transport.pulsar.topics.ServiceTopics -import java.time.Instant import org.apache.pulsar.common.policies.data.PartitionedTopicStats +import java.time.Instant data class AllTasksState( override val names: JobNames = Loading(), diff --git a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllWorkflowsState.kt b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllWorkflowsState.kt index f8785991b..20543f0e9 100644 --- a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllWorkflowsState.kt +++ b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/AllWorkflowsState.kt @@ -26,8 +26,8 @@ import io.infinitic.common.workflows.data.workflows.WorkflowName import io.infinitic.dashboard.Infinitic import io.infinitic.dashboard.panels.infrastructure.requests.Loading import io.infinitic.transport.pulsar.topics.WorkflowTaskTopics -import java.time.Instant import org.apache.pulsar.common.policies.data.PartitionedTopicStats +import java.time.Instant data class AllWorkflowsState( override val names: JobNames = Loading(), diff --git a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/jobs/JobState.kt b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/jobs/JobState.kt index 750fa9588..905c99074 100644 --- a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/jobs/JobState.kt +++ b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/jobs/JobState.kt @@ -27,7 +27,6 @@ import io.infinitic.dashboard.panels.infrastructure.requests.Completed import io.infinitic.dashboard.panels.infrastructure.requests.Failed import io.infinitic.dashboard.panels.infrastructure.requests.Request import io.infinitic.transport.pulsar.topics.TopicType -import java.time.Instant import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.isActive @@ -35,6 +34,7 @@ import kotlinx.coroutines.launch import kweb.state.KVar import mu.KotlinLogging import org.apache.pulsar.common.policies.data.PartitionedTopicStats +import java.time.Instant private const val UPDATE_DELAY = 5000L @@ -50,6 +50,7 @@ abstract class JobState( companion object { fun isLoading(topicsStats: TopicsStats): Boolean = topicsStats.any { it.value.isLoading } + fun lastUpdatedAt(topicsStats: TopicsStats): Instant = topicsStats.maxOfOrNull { it.value.lastUpdated } ?: Instant.now() } diff --git a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/jobs/displayJobSectionHeader.kt b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/jobs/displayJobSectionHeader.kt index 969c30b18..3c120ddd1 100644 --- a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/jobs/displayJobSectionHeader.kt +++ b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/jobs/displayJobSectionHeader.kt @@ -24,7 +24,6 @@ package io.infinitic.dashboard.panels.infrastructure.jobs import io.infinitic.dashboard.panels.infrastructure.lastUpdated import io.infinitic.dashboard.svgs.icons.iconRefresh -import java.time.Instant import kweb.Element import kweb.ElementCreator import kweb.div @@ -32,6 +31,7 @@ import kweb.h3 import kweb.new import kweb.span import kweb.state.KVar +import java.time.Instant internal fun ElementCreator.displayJobSectionHeader( title: String, diff --git a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/requests/Request.kt b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/requests/Request.kt index 77e7aead1..c2e4ec632 100644 --- a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/requests/Request.kt +++ b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/requests/Request.kt @@ -22,17 +22,19 @@ */ package io.infinitic.dashboard.panels.infrastructure.requests -import java.time.Instant import org.apache.pulsar.client.admin.PulsarAdminException +import java.time.Instant sealed class Request { abstract val isLoading: Boolean abstract val lastUpdated: Instant + abstract fun copyLoading(): Request } data class Loading(override val lastUpdated: Instant = Instant.now()) : Request() { override val isLoading = true + override fun copyLoading() = copy() } diff --git a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/task/TaskPanel.kt b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/task/TaskPanel.kt index 8258edc28..dd702972d 100644 --- a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/task/TaskPanel.kt +++ b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/task/TaskPanel.kt @@ -35,7 +35,6 @@ import io.infinitic.dashboard.panels.infrastructure.requests.Request import io.infinitic.dashboard.svgs.icons.iconChevron import io.infinitic.transport.pulsar.topics.ServiceTopics import io.infinitic.transport.pulsar.topics.TopicType -import java.util.concurrent.ConcurrentHashMap import kotlinx.coroutines.Job import kotlinx.coroutines.launch import kweb.Element @@ -52,6 +51,7 @@ import kweb.span import kweb.state.KVar import kweb.state.property import org.apache.pulsar.common.policies.data.PartitionedTopicStats +import java.util.concurrent.ConcurrentHashMap class TaskPanel private constructor(private val taskName: String) : Panel() { diff --git a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/workflow/WorkflowPanel.kt b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/workflow/WorkflowPanel.kt index 50f2e8de2..6ac163736 100644 --- a/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/workflow/WorkflowPanel.kt +++ b/infinitic-dashboard/src/main/kotlin/io/infinitic/dashboard/panels/infrastructure/workflow/WorkflowPanel.kt @@ -37,8 +37,6 @@ import io.infinitic.dashboard.svgs.icons.iconChevron import io.infinitic.transport.pulsar.topics.TopicType import io.infinitic.transport.pulsar.topics.WorkflowTaskTopics import io.infinitic.transport.pulsar.topics.WorkflowTopics -import java.time.Instant -import java.util.concurrent.ConcurrentHashMap import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -56,6 +54,8 @@ import kweb.span import kweb.state.KVar import kweb.state.property import org.apache.pulsar.common.policies.data.PartitionedTopicStats +import java.time.Instant +import java.util.concurrent.ConcurrentHashMap class WorkflowPanel private constructor(private val workflowName: String) : Panel() { companion object { diff --git a/infinitic-dashboard/src/main/resources/css/compiled.css b/infinitic-dashboard/src/main/resources/css/compiled.css index 8bbf5a57c..ef5fb2ae8 100644 --- a/infinitic-dashboard/src/main/resources/css/compiled.css +++ b/infinitic-dashboard/src/main/resources/css/compiled.css @@ -34,15 +34,15 @@ *, ::before, ::after { - box-sizing: border-box; /* 1 */ - border-width: 0; /* 2 */ - border-style: solid; /* 2 */ - border-color: #e5e7eb; /* 2 */ + box-sizing: border-box; /* 1 */ + border-width: 0; /* 2 */ + border-style: solid; /* 2 */ + border-color: #e5e7eb; /* 2 */ } ::before, ::after { - --tw-content: ''; + --tw-content: ''; } /* @@ -53,12 +53,12 @@ */ html { - line-height: 1.5; /* 1 */ - -webkit-text-size-adjust: 100%; /* 2 */ - -moz-tab-size: 4; /* 3 */ - -o-tab-size: 4; - tab-size: 4; /* 3 */ - font-family: Inter var, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 4 */ + line-height: 1.5; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ + -moz-tab-size: 4; /* 3 */ + -o-tab-size: 4; + tab-size: 4; /* 3 */ + font-family: Inter var, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 4 */ } /* @@ -67,8 +67,8 @@ html { */ body { - margin: 0; /* 1 */ - line-height: inherit; /* 2 */ + margin: 0; /* 1 */ + line-height: inherit; /* 2 */ } /* @@ -78,9 +78,9 @@ body { */ hr { - height: 0; /* 1 */ - color: inherit; /* 2 */ - border-top-width: 1px; /* 3 */ + height: 0; /* 1 */ + color: inherit; /* 2 */ + border-top-width: 1px; /* 3 */ } /* @@ -88,8 +88,8 @@ Add the correct text decoration in Chrome, Edge, and Safari. */ abbr:where([title]) { - -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; } /* @@ -102,8 +102,8 @@ h3, h4, h5, h6 { - font-size: inherit; - font-weight: inherit; + font-size: inherit; + font-weight: inherit; } /* @@ -111,8 +111,8 @@ Reset links to optimize for opt-in styling instead of opt-out. */ a { - color: inherit; - text-decoration: inherit; + color: inherit; + text-decoration: inherit; } /* @@ -121,7 +121,7 @@ Add the correct font weight in Edge and Safari. b, strong { - font-weight: bolder; + font-weight: bolder; } /* @@ -133,8 +133,8 @@ code, kbd, samp, pre { - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* 1 */ - font-size: 1em; /* 2 */ + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* 1 */ + font-size: 1em; /* 2 */ } /* @@ -142,7 +142,7 @@ Add the correct font size in all browsers. */ small { - font-size: 80%; + font-size: 80%; } /* @@ -151,18 +151,18 @@ Prevent `sub` and `sup` elements from affecting the line height in all browsers. sub, sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } sub { - bottom: -0.25em; + bottom: -0.25em; } sup { - top: -0.5em; + top: -0.5em; } /* @@ -172,9 +172,9 @@ sup { */ table { - text-indent: 0; /* 1 */ - border-color: inherit; /* 2 */ - border-collapse: collapse; /* 3 */ + text-indent: 0; /* 1 */ + border-color: inherit; /* 2 */ + border-collapse: collapse; /* 3 */ } /* @@ -188,13 +188,13 @@ input, optgroup, select, textarea { - font-family: inherit; /* 1 */ - font-size: 100%; /* 1 */ - font-weight: inherit; /* 1 */ - line-height: inherit; /* 1 */ - color: inherit; /* 1 */ - margin: 0; /* 2 */ - padding: 0; /* 3 */ + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + font-weight: inherit; /* 1 */ + line-height: inherit; /* 1 */ + color: inherit; /* 1 */ + margin: 0; /* 2 */ + padding: 0; /* 3 */ } /* @@ -203,7 +203,7 @@ Remove the inheritance of text transform in Edge and Firefox. button, select { - text-transform: none; + text-transform: none; } /* @@ -215,9 +215,9 @@ button, [type='button'], [type='reset'], [type='submit'] { - -webkit-appearance: button; /* 1 */ - background-color: transparent; /* 2 */ - background-image: none; /* 2 */ + -webkit-appearance: button; /* 1 */ + background-color: transparent; /* 2 */ + background-image: none; /* 2 */ } /* @@ -225,7 +225,7 @@ Use the modern Firefox focus style for all focusable elements. */ :-moz-focusring { - outline: auto; + outline: auto; } /* @@ -233,7 +233,7 @@ Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/ */ :-moz-ui-invalid { - box-shadow: none; + box-shadow: none; } /* @@ -241,7 +241,7 @@ Add the correct vertical alignment in Chrome and Firefox. */ progress { - vertical-align: baseline; + vertical-align: baseline; } /* @@ -250,7 +250,7 @@ Correct the cursor style of increment and decrement buttons in Safari. ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { - height: auto; + height: auto; } /* @@ -259,8 +259,8 @@ Correct the cursor style of increment and decrement buttons in Safari. */ [type='search'] { - -webkit-appearance: textfield; /* 1 */ - outline-offset: -2px; /* 2 */ + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ } /* @@ -268,7 +268,7 @@ Remove the inner padding in Chrome and Safari on macOS. */ ::-webkit-search-decoration { - -webkit-appearance: none; + -webkit-appearance: none; } /* @@ -277,8 +277,8 @@ Remove the inner padding in Chrome and Safari on macOS. */ ::-webkit-file-upload-button { - -webkit-appearance: button; /* 1 */ - font: inherit; /* 2 */ + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ } /* @@ -286,7 +286,7 @@ Add the correct display in Chrome and Safari. */ summary { - display: list-item; + display: list-item; } /* @@ -306,24 +306,24 @@ hr, figure, p, pre { - margin: 0; + margin: 0; } fieldset { - margin: 0; - padding: 0; + margin: 0; + padding: 0; } legend { - padding: 0; + padding: 0; } ol, ul, menu { - list-style: none; - margin: 0; - padding: 0; + list-style: none; + margin: 0; + padding: 0; } /* @@ -331,7 +331,7 @@ Prevent resizing textareas horizontally by default. */ textarea { - resize: vertical; + resize: vertical; } /* @@ -340,14 +340,14 @@ textarea { */ input::-moz-placeholder, textarea::-moz-placeholder { - opacity: 1; /* 1 */ - color: #9ca3af; /* 2 */ + opacity: 1; /* 1 */ + color: #9ca3af; /* 2 */ } input::placeholder, textarea::placeholder { - opacity: 1; /* 1 */ - color: #9ca3af; /* 2 */ + opacity: 1; /* 1 */ + color: #9ca3af; /* 2 */ } /* @@ -356,7 +356,7 @@ Set the default cursor for buttons. button, [role="button"] { - cursor: pointer; + cursor: pointer; } /* @@ -364,7 +364,7 @@ Make sure disabled buttons don't get the pointer cursor. */ :disabled { - cursor: default; + cursor: default; } /* @@ -381,8 +381,8 @@ audio, iframe, embed, object { - display: block; /* 1 */ - vertical-align: middle; /* 2 */ + display: block; /* 1 */ + vertical-align: middle; /* 2 */ } /* @@ -391,990 +391,1188 @@ Constrain images and videos to the parent width and preserve their intrinsic asp img, video { - max-width: 100%; - height: auto; + max-width: 100%; + height: auto; } *, ::before, ::after { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; } ::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; } + .sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; } + .static { - position: static; + position: static; } + .fixed { - position: fixed; + position: fixed; } + .absolute { - position: absolute; + position: absolute; } + .relative { - position: relative; + position: relative; } + .inset-0 { - top: 0px; - right: 0px; - bottom: 0px; - left: 0px; + top: 0px; + right: 0px; + bottom: 0px; + left: 0px; } + .inset-y-0 { - top: 0px; - bottom: 0px; + top: 0px; + bottom: 0px; } + .top-0 { - top: 0px; + top: 0px; } + .right-0 { - right: 0px; + right: 0px; } + .z-40 { - z-index: 40; + z-index: 40; } + .z-0 { - z-index: 0; + z-index: 0; } + .z-10 { - z-index: 10; + z-index: 10; } + .mx-auto { - margin-left: auto; - margin-right: auto; + margin-left: auto; + margin-right: auto; } + .-my-2 { - margin-top: -0.5rem; - margin-bottom: -0.5rem; + margin-top: -0.5rem; + margin-bottom: -0.5rem; } + .mt-5 { - margin-top: 1.25rem; + margin-top: 1.25rem; } + .-ml-0\.5 { - margin-left: -0.125rem; + margin-left: -0.125rem; } + .-mt-0\.5 { - margin-top: -0.125rem; + margin-top: -0.125rem; } + .-ml-0 { - margin-left: -0px; + margin-left: -0px; } + .-mt-0 { - margin-top: -0px; + margin-top: -0px; } + .mt-2 { - margin-top: 0.5rem; + margin-top: 0.5rem; } + .mt-6 { - margin-top: 1.5rem; + margin-top: 1.5rem; } + .mr-4 { - margin-right: 1rem; + margin-right: 1rem; } + .mr-3 { - margin-right: 0.75rem; + margin-right: 0.75rem; } + .-mr-12 { - margin-right: -3rem; + margin-right: -3rem; } + .ml-1 { - margin-left: 0.25rem; + margin-left: 0.25rem; } + .mt-3 { - margin-top: 0.75rem; + margin-top: 0.75rem; } + .ml-3 { - margin-left: 0.75rem; + margin-left: 0.75rem; } + .mt-7 { - margin-top: 1.75rem; + margin-top: 1.75rem; } + .mr-1\.5 { - margin-right: 0.375rem; + margin-right: 0.375rem; } + .mr-1 { - margin-right: 0.25rem; + margin-right: 0.25rem; } + .inline-block { - display: inline-block; + display: inline-block; } + .flex { - display: flex; + display: flex; } + .inline-flex { - display: inline-flex; + display: inline-flex; } + .table { - display: table; + display: table; } + .contents { - display: contents; + display: contents; } + .hidden { - display: none; + display: none; } + .h-screen { - height: 100vh; + height: 100vh; } + .h-0 { - height: 0px; + height: 0px; } + .h-12 { - height: 3rem; + height: 3rem; } + .h-6 { - height: 1.5rem; + height: 1.5rem; } + .h-10 { - height: 2.5rem; + height: 2.5rem; } + .h-full { - height: 100%; + height: 100%; } + .h-7 { - height: 1.75rem; + height: 1.75rem; } + .h-96 { - height: 24rem; + height: 24rem; } + .h-44 { - height: 11rem; + height: 11rem; } + .h-5 { - height: 1.25rem; + height: 1.25rem; } + .min-h-screen { - min-height: 100vh; + min-height: 100vh; } + .w-full { - width: 100%; + width: 100%; } + .w-14 { - width: 3.5rem; + width: 3.5rem; } + .w-64 { - width: 16rem; + width: 16rem; } + .w-0 { - width: 0px; + width: 0px; } + .w-12 { - width: 3rem; + width: 3rem; } + .w-auto { - width: auto; + width: auto; } + .w-6 { - width: 1.5rem; + width: 1.5rem; } + .w-10 { - width: 2.5rem; + width: 2.5rem; } + .w-screen { - width: 100vw; + width: 100vw; } + .w-5 { - width: 1.25rem; + width: 1.25rem; } + .min-w-0 { - min-width: 0px; + min-width: 0px; } + .min-w-full { - min-width: 100%; + min-width: 100%; } + .max-w-xs { - max-width: 20rem; + max-width: 20rem; } + .max-w-7xl { - max-width: 80rem; + max-width: 80rem; } + .max-w-full { - max-width: 100%; + max-width: 100%; } + .max-w-3xl { - max-width: 48rem; + max-width: 48rem; } + .max-w-none { - max-width: none; + max-width: none; } + .flex-1 { - flex: 1 1 0%; + flex: 1 1 0%; } + .flex-shrink-0 { - flex-shrink: 0; + flex-shrink: 0; } + .shrink { - flex-shrink: 1; + flex-shrink: 1; } + .flex-grow { - flex-grow: 1; + flex-grow: 1; } + .translate-x-0 { - --tw-translate-x: 0px; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + --tw-translate-x: 0px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } + .-translate-x-full { - --tw-translate-x: -100%; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + --tw-translate-x: -100%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } + .translate-y-0 { - --tw-translate-y: 0px; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + --tw-translate-y: 0px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } + .translate-y-4 { - --tw-translate-y: 1rem; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + --tw-translate-y: 1rem; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } + .translate-x-full { - --tw-translate-x: 100%; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + --tw-translate-x: 100%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } + .transform { - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } + @keyframes spin { - to { - transform: rotate(360deg); - } + to { + transform: rotate(360deg); + } } + .animate-spin { - animation: spin 1s linear infinite; + animation: spin 1s linear infinite; } + .cursor-pointer { - cursor: pointer; + cursor: pointer; } + .flex-col { - flex-direction: column; + flex-direction: column; } + .items-start { - align-items: flex-start; + align-items: flex-start; } + .items-end { - align-items: flex-end; + align-items: flex-end; } + .items-center { - align-items: center; + align-items: center; } + .justify-center { - justify-content: center; + justify-content: center; } + .justify-between { - justify-content: space-between; + justify-content: space-between; } + .space-y-1 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(0.25rem * var(--tw-space-y-reverse)); + --tw-space-y-reverse: 0; + margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.25rem * var(--tw-space-y-reverse)); } + .space-x-4 > :not([hidden]) ~ :not([hidden]) { - --tw-space-x-reverse: 0; - margin-right: calc(1rem * var(--tw-space-x-reverse)); - margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); + --tw-space-x-reverse: 0; + margin-right: calc(1rem * var(--tw-space-x-reverse)); + margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); } + .divide-y > :not([hidden]) ~ :not([hidden]) { - --tw-divide-y-reverse: 0; - border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); - border-bottom-width: calc(1px * var(--tw-divide-y-reverse)); + --tw-divide-y-reverse: 0; + border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); + border-bottom-width: calc(1px * var(--tw-divide-y-reverse)); } + .divide-gray-200 > :not([hidden]) ~ :not([hidden]) { - --tw-divide-opacity: 1; - border-color: rgb(229 231 235 / var(--tw-divide-opacity)); + --tw-divide-opacity: 1; + border-color: rgb(229 231 235 / var(--tw-divide-opacity)); } + .overflow-hidden { - overflow: hidden; + overflow: hidden; } + .overflow-x-auto { - overflow-x: auto; + overflow-x: auto; } + .overflow-y-auto { - overflow-y: auto; + overflow-y: auto; } + .overflow-y-scroll { - overflow-y: scroll; + overflow-y: scroll; } + .rounded-md { - border-radius: 0.375rem; + border-radius: 0.375rem; } + .rounded-full { - border-radius: 9999px; + border-radius: 9999px; } + .rounded-lg { - border-radius: 0.5rem; + border-radius: 0.5rem; } + .border { - border-width: 1px; + border-width: 1px; } + .border-2 { - border-width: 2px; + border-width: 2px; } + .border-4 { - border-width: 4px; + border-width: 4px; } + .border-r { - border-right-width: 1px; + border-right-width: 1px; } + .border-b { - border-bottom-width: 1px; + border-bottom-width: 1px; } + .border-dashed { - border-style: dashed; + border-style: dashed; } + .border-gray-200 { - --tw-border-opacity: 1; - border-color: rgb(229 231 235 / var(--tw-border-opacity)); + --tw-border-opacity: 1; + border-color: rgb(229 231 235 / var(--tw-border-opacity)); } + .border-transparent { - border-color: transparent; + border-color: transparent; } + .border-gray-300 { - --tw-border-opacity: 1; - border-color: rgb(209 213 219 / var(--tw-border-opacity)); + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); } + .bg-gray-100 { - --tw-bg-opacity: 1; - background-color: rgb(243 244 246 / var(--tw-bg-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); } + .bg-white { - --tw-bg-opacity: 1; - background-color: rgb(255 255 255 / var(--tw-bg-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } + .bg-gray-600 { - --tw-bg-opacity: 1; - background-color: rgb(75 85 99 / var(--tw-bg-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(75 85 99 / var(--tw-bg-opacity)); } + .bg-gray-500 { - --tw-bg-opacity: 1; - background-color: rgb(107 114 128 / var(--tw-bg-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(107 114 128 / var(--tw-bg-opacity)); } + .bg-red-100 { - --tw-bg-opacity: 1; - background-color: rgb(254 226 226 / var(--tw-bg-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(254 226 226 / var(--tw-bg-opacity)); } + .bg-red-600 { - --tw-bg-opacity: 1; - background-color: rgb(220 38 38 / var(--tw-bg-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(220 38 38 / var(--tw-bg-opacity)); } + .bg-gray-50 { - --tw-bg-opacity: 1; - background-color: rgb(249 250 251 / var(--tw-bg-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(249 250 251 / var(--tw-bg-opacity)); } + .bg-opacity-75 { - --tw-bg-opacity: 0.75; + --tw-bg-opacity: 0.75; } + .px-2 { - padding-left: 0.5rem; - padding-right: 0.5rem; + padding-left: 0.5rem; + padding-right: 0.5rem; } + .px-4 { - padding-left: 1rem; - padding-right: 1rem; + padding-left: 1rem; + padding-right: 1rem; } + .py-16 { - padding-top: 4rem; - padding-bottom: 4rem; + padding-top: 4rem; + padding-bottom: 4rem; } + .py-2 { - padding-top: 0.5rem; - padding-bottom: 0.5rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; } + .py-6 { - padding-top: 1.5rem; - padding-bottom: 1.5rem; + padding-top: 1.5rem; + padding-bottom: 1.5rem; } + .py-8 { - padding-top: 2rem; - padding-bottom: 2rem; + padding-top: 2rem; + padding-bottom: 2rem; } + .px-6 { - padding-left: 1.5rem; - padding-right: 1.5rem; + padding-left: 1.5rem; + padding-right: 1.5rem; } + .py-3 { - padding-top: 0.75rem; - padding-bottom: 0.75rem; + padding-top: 0.75rem; + padding-bottom: 0.75rem; } + .py-4 { - padding-top: 1rem; - padding-bottom: 1rem; + padding-top: 1rem; + padding-bottom: 1rem; } + .pt-5 { - padding-top: 1.25rem; + padding-top: 1.25rem; } + .pb-4 { - padding-bottom: 1rem; + padding-bottom: 1rem; } + .pl-1 { - padding-left: 0.25rem; + padding-left: 0.25rem; } + .pt-1 { - padding-top: 0.25rem; + padding-top: 0.25rem; } + .pt-16 { - padding-top: 4rem; + padding-top: 4rem; } + .pb-12 { - padding-bottom: 3rem; + padding-bottom: 3rem; } + .pt-2 { - padding-top: 0.5rem; + padding-top: 0.5rem; } + .pt-4 { - padding-top: 1rem; + padding-top: 1rem; } + .pb-20 { - padding-bottom: 5rem; + padding-bottom: 5rem; } + .pr-4 { - padding-right: 1rem; + padding-right: 1rem; } + .pl-10 { - padding-left: 2.5rem; + padding-left: 2.5rem; } + .pt-12 { - padding-top: 3rem; + padding-top: 3rem; } + .pt-0 { - padding-top: 0px; + padding-top: 0px; } + .pt-8 { - padding-top: 2rem; + padding-top: 2rem; } + .pb-8 { - padding-bottom: 2rem; + padding-bottom: 2rem; } + .pb-5 { - padding-bottom: 1.25rem; + padding-bottom: 1.25rem; } + .text-left { - text-align: left; + text-align: left; } + .text-center { - text-align: center; + text-align: center; } + .align-middle { - vertical-align: middle; + vertical-align: middle; } + .align-bottom { - vertical-align: bottom; + vertical-align: bottom; } + .text-sm { - font-size: 0.875rem; - line-height: 1.25rem; + font-size: 0.875rem; + line-height: 1.25rem; } + .text-4xl { - font-size: 2.25rem; - line-height: 2.5rem; + font-size: 2.25rem; + line-height: 2.5rem; } + .text-base { - font-size: 1rem; - line-height: 1.5rem; + font-size: 1rem; + line-height: 1.5rem; } + .text-lg { - font-size: 1.125rem; - line-height: 1.75rem; + font-size: 1.125rem; + line-height: 1.75rem; } + .text-2xl { - font-size: 1.5rem; - line-height: 2rem; + font-size: 1.5rem; + line-height: 2rem; } + .text-xs { - font-size: 0.75rem; - line-height: 1rem; + font-size: 0.75rem; + line-height: 1rem; } + .font-semibold { - font-weight: 600; + font-weight: 600; } + .font-extrabold { - font-weight: 800; + font-weight: 800; } + .font-medium { - font-weight: 500; + font-weight: 500; } + .font-bold { - font-weight: 700; + font-weight: 700; } + .uppercase { - text-transform: uppercase; + text-transform: uppercase; } + .italic { - font-style: italic; + font-style: italic; } + .leading-6 { - line-height: 1.5rem; + line-height: 1.5rem; } + .leading-7 { - line-height: 1.75rem; + line-height: 1.75rem; } + .tracking-wide { - letter-spacing: 0.025em; + letter-spacing: 0.025em; } + .tracking-tight { - letter-spacing: -0.025em; + letter-spacing: -0.025em; } + .tracking-wider { - letter-spacing: 0.05em; + letter-spacing: 0.05em; } + .text-gray-500 { - --tw-text-opacity: 1; - color: rgb(107 114 128 / var(--tw-text-opacity)); + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); } + .text-indigo-600 { - --tw-text-opacity: 1; - color: rgb(79 70 229 / var(--tw-text-opacity)); + --tw-text-opacity: 1; + color: rgb(79 70 229 / var(--tw-text-opacity)); } + .text-gray-900 { - --tw-text-opacity: 1; - color: rgb(17 24 39 / var(--tw-text-opacity)); + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); } + .text-gray-600 { - --tw-text-opacity: 1; - color: rgb(75 85 99 / var(--tw-text-opacity)); + --tw-text-opacity: 1; + color: rgb(75 85 99 / var(--tw-text-opacity)); } + .text-gray-400 { - --tw-text-opacity: 1; - color: rgb(156 163 175 / var(--tw-text-opacity)); + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); } + .text-white { - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity)); + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); } + .text-red-600 { - --tw-text-opacity: 1; - color: rgb(220 38 38 / var(--tw-text-opacity)); + --tw-text-opacity: 1; + color: rgb(220 38 38 / var(--tw-text-opacity)); } + .text-gray-700 { - --tw-text-opacity: 1; - color: rgb(55 65 81 / var(--tw-text-opacity)); + --tw-text-opacity: 1; + color: rgb(55 65 81 / var(--tw-text-opacity)); } + .underline { - text-decoration-line: underline; + text-decoration-line: underline; } + .opacity-100 { - opacity: 1; + opacity: 1; } + .opacity-0 { - opacity: 0; + opacity: 0; } + .shadow-xl { - --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } + .shadow-sm { - --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); - --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); + --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } + .shadow { - --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } + .transition { - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; } + .transition-opacity { - transition-property: opacity; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; + transition-property: opacity; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; } + .transition-all { - transition-property: all; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; } + .duration-300 { - transition-duration: 300ms; + transition-duration: 300ms; } + .duration-200 { - transition-duration: 200ms; + transition-duration: 200ms; } + .duration-500 { - transition-duration: 500ms; + transition-duration: 500ms; } + .ease-in-out { - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); } + .ease-linear { - transition-timing-function: linear; + transition-timing-function: linear; } + .ease-out { - transition-timing-function: cubic-bezier(0, 0, 0.2, 1); + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); } + .ease-in { - transition-timing-function: cubic-bezier(0.4, 0, 1, 1); + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); } + .hover\:bg-gray-50:hover { - --tw-bg-opacity: 1; - background-color: rgb(249 250 251 / var(--tw-bg-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(249 250 251 / var(--tw-bg-opacity)); } + .hover\:bg-red-700:hover { - --tw-bg-opacity: 1; - background-color: rgb(185 28 28 / var(--tw-bg-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(185 28 28 / var(--tw-bg-opacity)); } + .hover\:text-gray-900:hover { - --tw-text-opacity: 1; - color: rgb(17 24 39 / var(--tw-text-opacity)); + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); } + .hover\:text-indigo-500:hover { - --tw-text-opacity: 1; - color: rgb(99 102 241 / var(--tw-text-opacity)); + --tw-text-opacity: 1; + color: rgb(99 102 241 / var(--tw-text-opacity)); } + .hover\:text-gray-500:hover { - --tw-text-opacity: 1; - color: rgb(107 114 128 / var(--tw-text-opacity)); + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); } + .hover\:text-gray-700:hover { - --tw-text-opacity: 1; - color: rgb(55 65 81 / var(--tw-text-opacity)); + --tw-text-opacity: 1; + color: rgb(55 65 81 / var(--tw-text-opacity)); } + .focus\:outline-none:focus { - outline: 2px solid transparent; - outline-offset: 2px; + outline: 2px solid transparent; + outline-offset: 2px; } + .focus\:ring-2:focus { - --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); - --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); - box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); } + .focus\:ring-inset:focus { - --tw-ring-inset: inset; + --tw-ring-inset: inset; } + .focus\:ring-indigo-500:focus { - --tw-ring-opacity: 1; - --tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity)); + --tw-ring-opacity: 1; + --tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity)); } + .focus\:ring-white:focus { - --tw-ring-opacity: 1; - --tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity)); + --tw-ring-opacity: 1; + --tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity)); } + .focus\:ring-red-500:focus { - --tw-ring-opacity: 1; - --tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity)); + --tw-ring-opacity: 1; + --tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity)); } + .focus\:ring-offset-2:focus { - --tw-ring-offset-width: 2px; + --tw-ring-offset-width: 2px; } + .group:hover .group-hover\:text-gray-500 { - --tw-text-opacity: 1; - color: rgb(107 114 128 / var(--tw-text-opacity)); + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); } -@media (min-width: 640px) { - - .sm\:my-8 { - margin-top: 2rem; - margin-bottom: 2rem; - } - - .sm\:mx-0 { - margin-left: 0px; - margin-right: 0px; - } - - .sm\:-mx-6 { - margin-left: -1.5rem; - margin-right: -1.5rem; - } - - .sm\:mt-0 { - margin-top: 0px; - } - - .sm\:ml-4 { - margin-left: 1rem; - } - - .sm\:mt-4 { - margin-top: 1rem; - } - - .sm\:ml-3 { - margin-left: 0.75rem; - } - - .sm\:block { - display: block; - } - - .sm\:inline-block { - display: inline-block; - } - - .sm\:flex { - display: flex; - } - - .sm\:h-screen { - height: 100vh; - } - - .sm\:h-10 { - height: 2.5rem; - } - - .sm\:w-full { - width: 100%; - } - - .sm\:w-10 { - width: 2.5rem; - } - - .sm\:w-auto { - width: auto; - } - - .sm\:max-w-lg { - max-width: 32rem; - } - - .sm\:translate-y-0 { - --tw-translate-y: 0px; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - } - - .sm\:scale-100 { - --tw-scale-x: 1; - --tw-scale-y: 1; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - } - - .sm\:scale-95 { - --tw-scale-x: .95; - --tw-scale-y: .95; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - } - - .sm\:flex-row-reverse { - flex-direction: row-reverse; - } - - .sm\:items-start { - align-items: flex-start; - } - - .sm\:items-center { - align-items: center; - } - - .sm\:justify-between { - justify-content: space-between; - } - - .sm\:truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .sm\:rounded-lg { - border-radius: 0.5rem; - } - - .sm\:p-0 { - padding: 0px; - } - - .sm\:p-6 { - padding: 1.5rem; - } - .sm\:px-6 { - padding-left: 1.5rem; - padding-right: 1.5rem; - } - - .sm\:pl-3 { - padding-left: 0.75rem; - } - - .sm\:pt-3 { - padding-top: 0.75rem; - } - - .sm\:pl-16 { - padding-left: 4rem; - } - - .sm\:text-left { - text-align: left; - } - - .sm\:align-middle { - vertical-align: middle; - } - - .sm\:text-5xl { - font-size: 3rem; - line-height: 1; - } - - .sm\:text-sm { - font-size: 0.875rem; - line-height: 1.25rem; - } - - .sm\:text-3xl { - font-size: 1.875rem; - line-height: 2.25rem; - } - - .sm\:shadow { - --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - } +@media (min-width: 640px) { - .sm\:duration-700 { - transition-duration: 700ms; - } + .sm\:my-8 { + margin-top: 2rem; + margin-bottom: 2rem; + } + + .sm\:mx-0 { + margin-left: 0px; + margin-right: 0px; + } + + .sm\:-mx-6 { + margin-left: -1.5rem; + margin-right: -1.5rem; + } + + .sm\:mt-0 { + margin-top: 0px; + } + + .sm\:ml-4 { + margin-left: 1rem; + } + + .sm\:mt-4 { + margin-top: 1rem; + } + + .sm\:ml-3 { + margin-left: 0.75rem; + } + + .sm\:block { + display: block; + } + + .sm\:inline-block { + display: inline-block; + } + + .sm\:flex { + display: flex; + } + + .sm\:h-screen { + height: 100vh; + } + + .sm\:h-10 { + height: 2.5rem; + } + + .sm\:w-full { + width: 100%; + } + + .sm\:w-10 { + width: 2.5rem; + } + + .sm\:w-auto { + width: auto; + } + + .sm\:max-w-lg { + max-width: 32rem; + } + + .sm\:translate-y-0 { + --tw-translate-y: 0px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + } + + .sm\:scale-100 { + --tw-scale-x: 1; + --tw-scale-y: 1; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + } + + .sm\:scale-95 { + --tw-scale-x: .95; + --tw-scale-y: .95; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + } + + .sm\:flex-row-reverse { + flex-direction: row-reverse; + } + + .sm\:items-start { + align-items: flex-start; + } + + .sm\:items-center { + align-items: center; + } + + .sm\:justify-between { + justify-content: space-between; + } + + .sm\:truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .sm\:rounded-lg { + border-radius: 0.5rem; + } + + .sm\:p-0 { + padding: 0px; + } + + .sm\:p-6 { + padding: 1.5rem; + } + + .sm\:px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; + } + + .sm\:pl-3 { + padding-left: 0.75rem; + } + + .sm\:pt-3 { + padding-top: 0.75rem; + } + + .sm\:pl-16 { + padding-left: 4rem; + } + + .sm\:text-left { + text-align: left; + } + + .sm\:align-middle { + vertical-align: middle; + } + + .sm\:text-5xl { + font-size: 3rem; + line-height: 1; + } + + .sm\:text-sm { + font-size: 0.875rem; + line-height: 1.25rem; + } + + .sm\:text-3xl { + font-size: 1.875rem; + line-height: 2.25rem; + } + + .sm\:shadow { + --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + } + + .sm\:duration-700 { + transition-duration: 700ms; + } } + @media (min-width: 768px) { - .md\:flex { - display: flex; - } + .md\:flex { + display: flex; + } - .md\:hidden { - display: none; - } + .md\:hidden { + display: none; + } - .md\:flex-shrink-0 { - flex-shrink: 0; - } + .md\:flex-shrink-0 { + flex-shrink: 0; + } - .md\:px-8 { - padding-left: 2rem; - padding-right: 2rem; - } + .md\:px-8 { + padding-left: 2rem; + padding-right: 2rem; + } - .md\:pt-0 { - padding-top: 0px; - } + .md\:pt-0 { + padding-top: 0px; + } } + @media (min-width: 1024px) { - .lg\:-mx-8 { - margin-left: -2rem; - margin-right: -2rem; - } + .lg\:-mx-8 { + margin-left: -2rem; + margin-right: -2rem; + } - .lg\:flex { - display: flex; - } + .lg\:flex { + display: flex; + } - .lg\:items-center { - align-items: center; - } + .lg\:items-center { + align-items: center; + } - .lg\:justify-between { - justify-content: space-between; - } + .lg\:justify-between { + justify-content: space-between; + } - .lg\:px-8 { - padding-left: 2rem; - padding-right: 2rem; - } + .lg\:px-8 { + padding-left: 2rem; + padding-right: 2rem; + } } diff --git a/infinitic-dashboard/src/main/resources/simplelogger.properties b/infinitic-dashboard/src/main/resources/simplelogger.properties index f929148ae..217cdad2a 100644 --- a/infinitic-dashboard/src/main/resources/simplelogger.properties +++ b/infinitic-dashboard/src/main/resources/simplelogger.properties @@ -1,38 +1,29 @@ # SLF4J's SimpleLogger configuration file # Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err. - # Log file #org.slf4j.simpleLogger.logFile=infinitic.log - - # Default logging detail level for all instances of SimpleLogger. # Must be one of ("trace", "debug", "info", "warn", or "error"). # If not specified, defaults to "info". org.slf4j.simpleLogger.defaultLogLevel=warn - # Logging detail level for a SimpleLogger instance named "xxxxx". # Must be one of ("trace", "debug", "info", "warn", or "error"). # If not specified, the default logging detail level is used. #org.slf4j.simpleLogger.log.io.infinitic.services.engine.TaskEngine=debug - # Set to true if you want the current date and time to be included in output messages. # Default is false, and will output the number of milliseconds elapsed since startup. org.slf4j.simpleLogger.showDateTime=true - # The date and time format to be used in the output messages. # The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat. # If the format is not specified or is invalid, the default format is used. # The default format is yyyy-MM-dd HH:mm:ss:SSS Z. org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z - # Set to true if you want to output the current thread name. # Defaults to true. org.slf4j.simpleLogger.showThreadName=false - # Set to true if you want the Logger instance name to be included in output messages. # Defaults to true. # org.slf4j.simpleLogger.showLogName=true - # Set to true if you want the last component of the name to be included in output messages. # Defaults to false. org.slf4j.simpleLogger.showShortLogName=true diff --git a/infinitic-dashboard/tailwind.config.js b/infinitic-dashboard/tailwind.config.js index 90e519d68..82aa6aacd 100644 --- a/infinitic-dashboard/tailwind.config.js +++ b/infinitic-dashboard/tailwind.config.js @@ -26,14 +26,14 @@ const defaultTheme = require('tailwindcss/defaultTheme') module.exports = { - content: [ - './src/**/*.kt' - ], - theme: { - extend: { - fontFamily: { - sans: ['Inter var', ...defaultTheme.fontFamily.sans], + content: [ + './src/**/*.kt' + ], + theme: { + extend: { + fontFamily: { + sans: ['Inter var', ...defaultTheme.fontFamily.sans], + }, }, - }, - } + } } diff --git a/infinitic-inMemory/build.gradle.kts b/infinitic-inMemory/build.gradle.kts index 4254e7833..7aa2cc3a7 100644 --- a/infinitic-inMemory/build.gradle.kts +++ b/infinitic-inMemory/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,21 +20,20 @@ * * Licensor: infinitic.io */ - dependencies { - implementation(Libs.Coroutines.core) - implementation(Libs.Coroutines.jdk8) + implementation(Libs.Coroutines.core) + implementation(Libs.Coroutines.jdk8) - api(project(":infinitic-common")) - api(project(":infinitic-transport")) - api(project(":infinitic-transport-inmemory")) - api(project(":infinitic-client-base")) - api(project(":infinitic-storage")) - implementation(project(":infinitic-cache")) - implementation(project(":infinitic-workflow-tag")) - implementation(project(":infinitic-workflow-engine")) - implementation(project(":infinitic-task-executor")) - implementation(project(":infinitic-worker-base")) + api(project(":infinitic-common")) + api(project(":infinitic-transport")) + api(project(":infinitic-transport-inmemory")) + api(project(":infinitic-client-base")) + api(project(":infinitic-storage")) + implementation(project(":infinitic-cache")) + implementation(project(":infinitic-workflow-tag")) + implementation(project(":infinitic-workflow-engine")) + implementation(project(":infinitic-task-executor")) + implementation(project(":infinitic-worker-base")) } apply("../publish.gradle.kts") diff --git a/infinitic-inMemory/src/test/resources/simplelogger.properties b/infinitic-inMemory/src/test/resources/simplelogger.properties index 6cab8950b..61abd000d 100644 --- a/infinitic-inMemory/src/test/resources/simplelogger.properties +++ b/infinitic-inMemory/src/test/resources/simplelogger.properties @@ -1,23 +1,17 @@ # SLF4J's SimpleLogger configuration file # Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err. - # Uncomment this line to use a log file #org.slf4j.simpleLogger.logFile=infinitic.log - # Default logging detail level for all instances of SimpleLogger. # Must be one of ("trace", "debug", "info", "warn", or "error"). # If not specified, defaults to "info". org.slf4j.simpleLogger.defaultLogLevel=info - # Set to true if you want the current date and time to be included in output messages. # Default is false, and will output the number of milliseconds elapsed since startup. org.slf4j.simpleLogger.showDateTime=true - # Set to true if you want to output the current thread name. # Defaults to true. org.slf4j.simpleLogger.showThreadName=false - - # Set to true if you want the last component of the name to be included in output messages. # Defaults to false. org.slf4j.simpleLogger.showShortLogName=true diff --git a/infinitic-pulsar/build.gradle.kts b/infinitic-pulsar/build.gradle.kts index de5fa733a..09fc9d7d7 100644 --- a/infinitic-pulsar/build.gradle.kts +++ b/infinitic-pulsar/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,32 +20,29 @@ * * Licensor: infinitic.io */ - -plugins { - `java-library` -} +plugins { `java-library` } dependencies { - implementation(Libs.Coroutines.core) - implementation(Libs.Coroutines.jdk8) - implementation(Libs.Pulsar.functions) - implementation(Libs.Hoplite.core) - implementation(Libs.Hoplite.yaml) + implementation(Libs.Coroutines.core) + implementation(Libs.Coroutines.jdk8) + implementation(Libs.Pulsar.functions) + implementation(Libs.Hoplite.core) + implementation(Libs.Hoplite.yaml) - api(Libs.Pulsar.client) - api(Libs.Pulsar.clientAdmin) - api(Libs.Pulsar.authAthenz) - api(Libs.Pulsar.authSasl) - api(project(":infinitic-common")) - api(project(":infinitic-client-base")) - api(project(":infinitic-worker-base")) - api(project(":infinitic-task-executor")) - api(project(":infinitic-transport")) + api(Libs.Pulsar.client) + api(Libs.Pulsar.clientAdmin) + api(Libs.Pulsar.authAthenz) + api(Libs.Pulsar.authSasl) + api(project(":infinitic-common")) + api(project(":infinitic-client-base")) + api(project(":infinitic-worker-base")) + api(project(":infinitic-task-executor")) + api(project(":infinitic-transport")) - implementation(project(":infinitic-workflow-tag")) - implementation(project(":infinitic-workflow-engine")) + implementation(project(":infinitic-workflow-tag")) + implementation(project(":infinitic-workflow-engine")) - testImplementation(Libs.Kotlin.reflect) + testImplementation(Libs.Kotlin.reflect) } apply("../publish.gradle.kts") diff --git a/infinitic-pulsar/src/main/kotlin/io/infinitic/pulsar/PulsarInfiniticAdmin.kt b/infinitic-pulsar/src/main/kotlin/io/infinitic/pulsar/PulsarInfiniticAdmin.kt index 474b4ccff..b7d52e7bf 100644 --- a/infinitic-pulsar/src/main/kotlin/io/infinitic/pulsar/PulsarInfiniticAdmin.kt +++ b/infinitic-pulsar/src/main/kotlin/io/infinitic/pulsar/PulsarInfiniticAdmin.kt @@ -30,7 +30,6 @@ import io.infinitic.transport.pulsar.topics.PerNameTopics import io.infinitic.transport.pulsar.topics.ServiceTopics import io.infinitic.transport.pulsar.topics.WorkflowTaskTopics import io.infinitic.transport.pulsar.topics.WorkflowTopics -import java.io.Closeable import mu.KotlinLogging import org.apache.pulsar.client.admin.Clusters import org.apache.pulsar.client.admin.Namespaces @@ -45,6 +44,7 @@ import org.apache.pulsar.common.policies.data.TenantInfo import org.apache.pulsar.common.policies.data.TopicType import org.apache.pulsar.common.policies.data.impl.AutoTopicCreationOverrideImpl import org.apache.pulsar.common.policies.data.impl.DelayedDeliveryPoliciesImpl +import java.io.Closeable @Suppress("unused", "MemberVisibilityCanBePrivate") class PulsarInfiniticAdmin constructor(val pulsarAdmin: PulsarAdmin, val pulsar: Pulsar) : @@ -75,7 +75,8 @@ class PulsarInfiniticAdmin constructor(val pulsarAdmin: PulsarAdmin, val pulsar: // retention policies retention_policies = RetentionPolicies( - pulsar.policies.retentionTimeInMinutes, pulsar.policies.retentionSizeInMB) + pulsar.policies.retentionTimeInMinutes, pulsar.policies.retentionSizeInMB.toLong() + ) message_ttl_in_seconds = pulsar.policies.messageTTLInSeconds delayed_delivery_policies = DelayedDeliveryPoliciesImpl(pulsar.policies.delayedDeliveryTickTimeMillis, true) diff --git a/infinitic-pulsar/src/main/kotlin/io/infinitic/pulsar/PulsarInfiniticWorker.kt b/infinitic-pulsar/src/main/kotlin/io/infinitic/pulsar/PulsarInfiniticWorker.kt index 27996b743..95a2b35b5 100644 --- a/infinitic-pulsar/src/main/kotlin/io/infinitic/pulsar/PulsarInfiniticWorker.kt +++ b/infinitic-pulsar/src/main/kotlin/io/infinitic/pulsar/PulsarInfiniticWorker.kt @@ -32,8 +32,6 @@ import io.infinitic.transport.pulsar.topics.WorkflowTaskTopics import io.infinitic.transport.pulsar.topics.WorkflowTopics import io.infinitic.workers.WorkerAbstract import io.infinitic.workers.register.WorkerRegister -import java.util.concurrent.CompletableFuture -import java.util.concurrent.Executors import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.asCoroutineDispatcher @@ -46,6 +44,8 @@ import org.apache.pulsar.client.admin.Tenants import org.apache.pulsar.client.admin.TopicPolicies import org.apache.pulsar.client.admin.Topics import org.apache.pulsar.client.api.PulsarClient +import java.util.concurrent.CompletableFuture +import java.util.concurrent.Executors @Suppress("MemberVisibilityCanBePrivate", "unused") class PulsarInfiniticWorker( diff --git a/infinitic-pulsar/src/main/kotlin/io/infinitic/pulsar/getProducerName.kt b/infinitic-pulsar/src/main/kotlin/io/infinitic/pulsar/getProducerName.kt index ee4005876..c37d064f9 100644 --- a/infinitic-pulsar/src/main/kotlin/io/infinitic/pulsar/getProducerName.kt +++ b/infinitic-pulsar/src/main/kotlin/io/infinitic/pulsar/getProducerName.kt @@ -24,9 +24,9 @@ package io.infinitic.pulsar import io.infinitic.transport.pulsar.topics.GlobalTopics import io.infinitic.transport.pulsar.topics.TopicNames -import kotlin.system.exitProcess import org.apache.pulsar.client.api.PulsarClient import org.apache.pulsar.client.api.PulsarClientException +import kotlin.system.exitProcess /** Useful to check the uniqueness of a connected producer's name or to provide a unique name */ internal fun getProducerName( diff --git a/infinitic-pulsar/src/test/kotlin/io/infinitic/pulsar/samples/TaskA.kt b/infinitic-pulsar/src/test/kotlin/io/infinitic/pulsar/samples/TaskA.kt index 429d9bf85..8324e7a30 100644 --- a/infinitic-pulsar/src/test/kotlin/io/infinitic/pulsar/samples/TaskA.kt +++ b/infinitic-pulsar/src/test/kotlin/io/infinitic/pulsar/samples/TaskA.kt @@ -27,12 +27,16 @@ import kotlinx.coroutines.runBlocking interface TaskA { fun concat(str1: String, str2: String): String + fun reverse(str: String): String + fun await(delay: Long) } class TaskAImpl : TaskA { override fun concat(str1: String, str2: String) = str1 + str2 + override fun reverse(str: String) = str.reversed() + override fun await(delay: Long) = runBlocking { delay(delay) } } diff --git a/infinitic-pulsar/src/test/kotlin/io/infinitic/pulsar/samples/WorkflowA.kt b/infinitic-pulsar/src/test/kotlin/io/infinitic/pulsar/samples/WorkflowA.kt index fc32b9d50..e9d65ab3d 100644 --- a/infinitic-pulsar/src/test/kotlin/io/infinitic/pulsar/samples/WorkflowA.kt +++ b/infinitic-pulsar/src/test/kotlin/io/infinitic/pulsar/samples/WorkflowA.kt @@ -30,26 +30,47 @@ import java.time.LocalDateTime interface WorkflowA { fun empty(): String + fun seq1(): String + fun seq2(): String + fun seq3(): String + fun seq4(): String + fun or1(): String + fun or2(): Any + fun or3(): String + fun and1(): List + fun and2(): List + fun and3(): List + fun inline(): String + fun inline2(): String + fun inline3(): String + fun child1(): String + fun child2(): String + fun prop1(): String + fun prop2(): String + fun prop3(): String + fun prop4(): String + fun prop5(): String + fun prop6(): String } diff --git a/infinitic-pulsar/src/test/kotlin/io/infinitic/pulsar/samples/WorkflowB.kt b/infinitic-pulsar/src/test/kotlin/io/infinitic/pulsar/samples/WorkflowB.kt index 19c9b3975..e4f0919f9 100644 --- a/infinitic-pulsar/src/test/kotlin/io/infinitic/pulsar/samples/WorkflowB.kt +++ b/infinitic-pulsar/src/test/kotlin/io/infinitic/pulsar/samples/WorkflowB.kt @@ -26,6 +26,7 @@ import io.infinitic.workflows.Workflow interface WorkflowB { fun concat(input: String): String + fun factorial(n: Long): Long } diff --git a/infinitic-storage/build.gradle.kts b/infinitic-storage/build.gradle.kts index f2379f701..23f30133c 100644 --- a/infinitic-storage/build.gradle.kts +++ b/infinitic-storage/build.gradle.kts @@ -34,9 +34,9 @@ dependencies { // MySql // For connection pooling implementation("com.zaxxer:HikariCP:5.0.1") - implementation("mysql:mysql-connector-java:8.0.33") + implementation("com.mysql:mysql-connector-j:8.2.0") // For integration tests - testImplementation("org.testcontainers:mysql:1.18.3") + testImplementation("org.testcontainers:mysql:1.19.1") testImplementation(Libs.Hoplite.yaml) } diff --git a/infinitic-storage/src/main/kotlin/io/infinitic/storage/keySet/KeySetStorage.kt b/infinitic-storage/src/main/kotlin/io/infinitic/storage/keySet/KeySetStorage.kt index a6e03d2c2..7b7b84362 100644 --- a/infinitic-storage/src/main/kotlin/io/infinitic/storage/keySet/KeySetStorage.kt +++ b/infinitic-storage/src/main/kotlin/io/infinitic/storage/keySet/KeySetStorage.kt @@ -26,6 +26,8 @@ import io.infinitic.storage.Flushable interface KeySetStorage : Flushable { suspend fun get(key: String): Set + suspend fun add(key: String, value: ByteArray) + suspend fun remove(key: String, value: ByteArray) } diff --git a/infinitic-storage/src/main/kotlin/io/infinitic/storage/keyValue/KeyValueStorage.kt b/infinitic-storage/src/main/kotlin/io/infinitic/storage/keyValue/KeyValueStorage.kt index 86b6bdf68..6ebd93014 100644 --- a/infinitic-storage/src/main/kotlin/io/infinitic/storage/keyValue/KeyValueStorage.kt +++ b/infinitic-storage/src/main/kotlin/io/infinitic/storage/keyValue/KeyValueStorage.kt @@ -26,6 +26,8 @@ import io.infinitic.storage.Flushable interface KeyValueStorage : Flushable { suspend fun get(key: String): ByteArray? + suspend fun put(key: String, value: ByteArray) + suspend fun del(key: String) } diff --git a/infinitic-storage/src/test/kotlin/io/infinitic/storage/config/StorageTests.kt b/infinitic-storage/src/test/kotlin/io/infinitic/storage/config/StorageTests.kt index 2b2d34acd..cabe12e2b 100644 --- a/infinitic-storage/src/test/kotlin/io/infinitic/storage/config/StorageTests.kt +++ b/infinitic-storage/src/test/kotlin/io/infinitic/storage/config/StorageTests.kt @@ -91,44 +91,45 @@ class StorageTests : .pool shouldBe RedisKeyValueStorage.of(Redis()).pool } - "properties of MySQL".config(enabledIf = { DockerOnly.shouldRun }) { - val mysqlServer = - MySQLContainer("mysql:5.7") - .apply { - startupAttempts = 1 - withUsername("test") - withPassword("password") - withDatabaseName("infinitic") - } - .let { - it.start() - it - } - - val mysql = - MySQL( - host = mysqlServer.host, - port = mysqlServer.firstMappedPort, - user = mysqlServer.username, - password = Secret(mysqlServer.password), - database = mysqlServer.databaseName) - - val config = Storage(mysql = mysql, compression = null) - - config.type shouldBe "mysql" - - // config.keySet should be MySQLKeySetStorage(pool) - config.keySet::class shouldBe MySQLKeySetStorage::class - (config.keySet as MySQLKeySetStorage).pool shouldBe MySQLKeySetStorage.of(mysql).pool - - // config.keyValue should be CompressedKeyValueStorage(MySQLKeyValueStorage(pool)) - config.keyValue::class shouldBe CompressedKeyValueStorage::class - (config.keyValue as CompressedKeyValueStorage).storage::class shouldBe - MySQLKeyValueStorage::class - (((config.keyValue as CompressedKeyValueStorage)).storage as MySQLKeyValueStorage) - .pool shouldBe MySQLKeyValueStorage.of(mysql).pool - - mysql.close() - mysqlServer.close() - } + "properties of MySQL" + .config(enabledIf = { DockerOnly.shouldRun }) { + val mysqlServer = + MySQLContainer("mysql:5.7") + .apply { + startupAttempts = 1 + withUsername("test") + withPassword("password") + withDatabaseName("infinitic") + } + .let { + it.start() + it + } + + val mysql = + MySQL( + host = mysqlServer.host, + port = mysqlServer.firstMappedPort, + user = mysqlServer.username, + password = Secret(mysqlServer.password), + database = mysqlServer.databaseName) + + val config = Storage(mysql = mysql, compression = null) + + config.type shouldBe "mysql" + + // config.keySet should be MySQLKeySetStorage(pool) + config.keySet::class shouldBe MySQLKeySetStorage::class + (config.keySet as MySQLKeySetStorage).pool shouldBe MySQLKeySetStorage.of(mysql).pool + + // config.keyValue should be CompressedKeyValueStorage(MySQLKeyValueStorage(pool)) + config.keyValue::class shouldBe CompressedKeyValueStorage::class + (config.keyValue as CompressedKeyValueStorage).storage::class shouldBe + MySQLKeyValueStorage::class + (((config.keyValue as CompressedKeyValueStorage)).storage as MySQLKeyValueStorage) + .pool shouldBe MySQLKeyValueStorage.of(mysql).pool + + mysql.close() + mysqlServer.close() + } }) diff --git a/infinitic-task-executor/build.gradle.kts b/infinitic-task-executor/build.gradle.kts index 667698d0d..938b1f383 100644 --- a/infinitic-task-executor/build.gradle.kts +++ b/infinitic-task-executor/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,14 +20,13 @@ * * Licensor: infinitic.io */ - dependencies { - implementation(kotlin("reflect")) - implementation(Libs.Coroutines.core) + implementation(kotlin("reflect")) + implementation(Libs.Coroutines.core) - implementation(project(":infinitic-client-base")) - implementation(project(":infinitic-common")) - implementation(project(":infinitic-workflow-task")) + implementation(project(":infinitic-client-base")) + implementation(project(":infinitic-common")) + implementation(project(":infinitic-workflow-task")) } apply("../publish.gradle.kts") diff --git a/infinitic-task-executor/src/main/kotlin/io/infinitic/tasks/executor/TaskExecutor.kt b/infinitic-task-executor/src/main/kotlin/io/infinitic/tasks/executor/TaskExecutor.kt index 72b55b986..43d51149e 100644 --- a/infinitic-task-executor/src/main/kotlin/io/infinitic/tasks/executor/TaskExecutor.kt +++ b/infinitic-task-executor/src/main/kotlin/io/infinitic/tasks/executor/TaskExecutor.kt @@ -232,9 +232,9 @@ class TaskExecutor( } this.withTimeout = // use timeout from registry, if it exists - registered.withTimeout // else use withTimeout from method annotation - ?: workflowMethod.getAnnotation(Timeout::class.java)?.getInstance() + registered.withTimeout + ?: workflowMethod.getAnnotation(Timeout::class.java)?.getInstance() // else use withRetry from class annotation ?: workflow::class.java.getAnnotation(Timeout::class.java)?.getInstance() // else use workflow if WithTimeout @@ -246,9 +246,9 @@ class TaskExecutor( ?: DEFAULT_WORKFLOW_TASK_TIMEOUT this.withRetry = // use timeout from registry, if it exists - registered.withRetry // else use withTimeout from method annotation - ?: workflowMethod.getAnnotation(Retry::class.java)?.getInstance() + registered.withRetry + ?: workflowMethod.getAnnotation(Retry::class.java)?.getInstance() // else use withRetry from class annotation ?: workflow::class.java.getAnnotation(Retry::class.java)?.getInstance() // else use workflow if WithTimeout @@ -261,9 +261,9 @@ class TaskExecutor( val checkMode = // get checkMode from registry - registered.checkMode // else get mode from method annotation - ?: workflowMethod.getAnnotation(CheckMode::class.java)?.mode + registered.checkMode + ?: workflowMethod.getAnnotation(CheckMode::class.java)?.mode // else get mode from class annotation ?: workflow::class.java.getAnnotation(CheckMode::class.java)?.mode // else use default value @@ -280,9 +280,9 @@ class TaskExecutor( this.withTimeout = // use withTimeout from registry, if it exists - registered.withTimeout // else use withTimeout from method annotation - ?: taskMethod.getAnnotation(Timeout::class.java)?.getInstance() + registered.withTimeout + ?: taskMethod.getAnnotation(Timeout::class.java)?.getInstance() // else use withTimeout from class annotation ?: service::class.java.getAnnotation(Timeout::class.java)?.getInstance() // else use service if WithRetry @@ -295,9 +295,9 @@ class TaskExecutor( this.withRetry = // use withRetry from registry, if it exists - registered.withRetry // else use withRetry from method annotation - ?: taskMethod.getAnnotation(Retry::class.java)?.getInstance() + registered.withRetry + ?: taskMethod.getAnnotation(Retry::class.java)?.getInstance() // else use withRetry from class annotation ?: service::class.java.getAnnotation(Retry::class.java)?.getInstance() // else use service if WithRetry diff --git a/infinitic-task-executor/src/test/kotlin/io/infinitic/tasks/executor/samples/SimpleService.kt b/infinitic-task-executor/src/test/kotlin/io/infinitic/tasks/executor/samples/SimpleService.kt index c98f29f84..fd5e83442 100644 --- a/infinitic-task-executor/src/test/kotlin/io/infinitic/tasks/executor/samples/SimpleService.kt +++ b/infinitic-task-executor/src/test/kotlin/io/infinitic/tasks/executor/samples/SimpleService.kt @@ -32,13 +32,17 @@ import io.infinitic.tasks.WithTimeout interface SimpleService { fun handle(i: Int, j: String): String + fun handle(i: Int, j: Int): Int + fun other(i: Int, j: String): String } class ServiceImplService : SimpleService { override fun handle(i: Int, j: String) = (i * j.toInt()).toString() + override fun handle(i: Int, j: Int) = (i * j) + override fun other(i: Int, j: String) = (i * j.toInt()).toString() } @@ -53,6 +57,7 @@ internal class SimpleServiceWithRetry : WithRetry { fun handle(i: Int, j: String): String = if (i < 0) (i * j.toInt()).toString() else throw IllegalStateException() + override fun getSecondsBeforeRetry(retry: Int, exception: Exception) = DELAY } diff --git a/infinitic-task-tag/build.gradle.kts b/infinitic-task-tag/build.gradle.kts index 718a8bb95..21e13b7a4 100644 --- a/infinitic-task-tag/build.gradle.kts +++ b/infinitic-task-tag/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,14 +20,13 @@ * * Licensor: infinitic.io */ - dependencies { - api(Libs.Coroutines.core) - api(Libs.Coroutines.jdk8) + api(Libs.Coroutines.core) + api(Libs.Coroutines.jdk8) - api(project(":infinitic-common")) - api(project(":infinitic-cache")) - api(project(":infinitic-storage")) + api(project(":infinitic-common")) + api(project(":infinitic-cache")) + api(project(":infinitic-storage")) } apply("../publish.gradle.kts") diff --git a/infinitic-tests/build.gradle.kts b/infinitic-tests/build.gradle.kts index bf980daaa..5e28610a1 100644 --- a/infinitic-tests/build.gradle.kts +++ b/infinitic-tests/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,18 +20,17 @@ * * Licensor: infinitic.io */ - dependencies { - testImplementation(Libs.Coroutines.core) - testImplementation(Libs.Coroutines.jdk8) - testImplementation(Libs.Hoplite.core) - testImplementation(Libs.Hoplite.yaml) + testImplementation(Libs.Coroutines.core) + testImplementation(Libs.Coroutines.jdk8) + testImplementation(Libs.Hoplite.core) + testImplementation(Libs.Hoplite.yaml) - testImplementation(project(":infinitic-client")) - testImplementation(project(":infinitic-worker")) - testImplementation(project(":infinitic-workflow-engine")) - testImplementation(project(":infinitic-task-executor")) - testImplementation(project(":infinitic-inMemory")) - testImplementation(project(":infinitic-transport")) - testImplementation(project(":infinitic-pulsar")) + testImplementation(project(":infinitic-client")) + testImplementation(project(":infinitic-worker")) + testImplementation(project(":infinitic-workflow-engine")) + testImplementation(project(":infinitic-task-executor")) + testImplementation(project(":infinitic-inMemory")) + testImplementation(project(":infinitic-transport")) + testImplementation(project(":infinitic-pulsar")) } diff --git a/infinitic-tests/src/test/kotlin/io/infinitic/tests/branches/BranchesWorkflow.kt b/infinitic-tests/src/test/kotlin/io/infinitic/tests/branches/BranchesWorkflow.kt index 880d893e7..033eff160 100644 --- a/infinitic-tests/src/test/kotlin/io/infinitic/tests/branches/BranchesWorkflow.kt +++ b/infinitic-tests/src/test/kotlin/io/infinitic/tests/branches/BranchesWorkflow.kt @@ -30,12 +30,19 @@ import java.time.Duration interface BranchesWorkflow { fun seq3(): String + fun seq3bis(): String + fun seq4(): String + fun seq4bis(): String + fun deferred1(): String + fun deferred1bis(): String + fun async1() + fun async1bis() } diff --git a/infinitic-tests/src/test/kotlin/io/infinitic/tests/channels/ChannelWorkflowTests.kt b/infinitic-tests/src/test/kotlin/io/infinitic/tests/channels/ChannelWorkflowTests.kt index 400d4ef04..49f35e09b 100644 --- a/infinitic-tests/src/test/kotlin/io/infinitic/tests/channels/ChannelWorkflowTests.kt +++ b/infinitic-tests/src/test/kotlin/io/infinitic/tests/channels/ChannelWorkflowTests.kt @@ -33,8 +33,8 @@ import io.infinitic.workers.InfiniticWorker import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe -import java.time.Instant import kotlinx.coroutines.delay +import java.time.Instant internal class ChannelWorkflowTests : StringSpec({ diff --git a/infinitic-tests/src/test/kotlin/io/infinitic/tests/channels/ChannelsWorkflow.kt b/infinitic-tests/src/test/kotlin/io/infinitic/tests/channels/ChannelsWorkflow.kt index c29cb6594..5dcf7e8d8 100644 --- a/infinitic-tests/src/test/kotlin/io/infinitic/tests/channels/ChannelsWorkflow.kt +++ b/infinitic-tests/src/test/kotlin/io/infinitic/tests/channels/ChannelsWorkflow.kt @@ -39,18 +39,31 @@ interface ChannelsWorkflow { val channelB: SendChannel fun channel1(): String + fun channel2(): Any + fun channel3(): Any + fun channel4(): Obj + fun channel4bis(): Obj + fun channel4ter(): Obj + fun channel5(): Obj1 + fun channel5bis(): Obj1 + fun channel5ter(): Obj1 + fun channel6(): String + fun channel6bis(): String + fun channel6ter(): String + fun channel7(count: Int, max: Int? = null): String + fun channel8(): String } diff --git a/infinitic-tests/src/test/kotlin/io/infinitic/tests/children/ChildrenWorkflow.kt b/infinitic-tests/src/test/kotlin/io/infinitic/tests/children/ChildrenWorkflow.kt index 0456d4653..bcd799867 100644 --- a/infinitic-tests/src/test/kotlin/io/infinitic/tests/children/ChildrenWorkflow.kt +++ b/infinitic-tests/src/test/kotlin/io/infinitic/tests/children/ChildrenWorkflow.kt @@ -31,10 +31,13 @@ interface ChildrenWorkflow { fun await() fun parent(): String + fun wparent(): String fun child1(): String + fun child2(): String + fun factorial(n: Long): Long fun cancel() diff --git a/infinitic-tests/src/test/kotlin/io/infinitic/tests/context/ContextWorkflow.kt b/infinitic-tests/src/test/kotlin/io/infinitic/tests/context/ContextWorkflow.kt index 354cd984a..afde832c9 100644 --- a/infinitic-tests/src/test/kotlin/io/infinitic/tests/context/ContextWorkflow.kt +++ b/infinitic-tests/src/test/kotlin/io/infinitic/tests/context/ContextWorkflow.kt @@ -31,13 +31,21 @@ import io.infinitic.workflows.Workflow interface ContextWorkflow { fun context1(): String + fun context2(): Set + fun context3(): WorkflowMeta + fun context4(): String? + fun context5(): String? + fun context6(): Set + fun context7(): TaskMeta + fun context8(): WithRetry? + fun context9(): WithTimeout? } diff --git a/infinitic-tests/src/test/kotlin/io/infinitic/tests/deferred/DeferredWorkflow.kt b/infinitic-tests/src/test/kotlin/io/infinitic/tests/deferred/DeferredWorkflow.kt index 608d27063..0cf954a53 100644 --- a/infinitic-tests/src/test/kotlin/io/infinitic/tests/deferred/DeferredWorkflow.kt +++ b/infinitic-tests/src/test/kotlin/io/infinitic/tests/deferred/DeferredWorkflow.kt @@ -33,16 +33,27 @@ import java.time.Duration interface DeferredWorkflow { fun await(duration: Long): Long + fun seq1(): String + fun seq2(): String + fun seq5(): Long + fun seq6(): Long + fun or1(): String + fun or2(): Any + fun or3(): String + fun or4(): String + fun and1(): List + fun and2(): List + fun and3(): List } diff --git a/infinitic-tests/src/test/kotlin/io/infinitic/tests/errors/ErrorsWorkflow.kt b/infinitic-tests/src/test/kotlin/io/infinitic/tests/errors/ErrorsWorkflow.kt index 5f7ad1e75..0957ba985 100644 --- a/infinitic-tests/src/test/kotlin/io/infinitic/tests/errors/ErrorsWorkflow.kt +++ b/infinitic-tests/src/test/kotlin/io/infinitic/tests/errors/ErrorsWorkflow.kt @@ -34,27 +34,45 @@ import java.time.Duration interface ErrorsWorkflow { fun waiting(): String + fun failing1(): String + fun failing2() + fun failing2a(): Long + fun failing3(): Long + fun failing3bis() + fun failing3bException() + fun failing3b(): Long // fun failing4(): Long // fun failing5(): Long fun failing5bis(deferred: Deferred): Long + fun failing6() + fun failing7(): Long + fun failing7bis() + fun failing7ter(): String + fun failing8(): String + fun failing9(): Boolean + fun failing10(): String + fun failing10bis() + fun failing11() + fun failing12(): String + fun failing13() } diff --git a/infinitic-tests/src/test/kotlin/io/infinitic/tests/inline/InlineWorkflow.kt b/infinitic-tests/src/test/kotlin/io/infinitic/tests/inline/InlineWorkflow.kt index 2c0cb9b44..1ba0318f2 100644 --- a/infinitic-tests/src/test/kotlin/io/infinitic/tests/inline/InlineWorkflow.kt +++ b/infinitic-tests/src/test/kotlin/io/infinitic/tests/inline/InlineWorkflow.kt @@ -27,7 +27,9 @@ import io.infinitic.workflows.Workflow interface InlineWorkflow { fun inline1(i: Int): String + fun inline2(i: Int): String + fun inline3(i: Int): String } diff --git a/infinitic-tests/src/test/kotlin/io/infinitic/tests/properties/PropertiesWorkflow.kt b/infinitic-tests/src/test/kotlin/io/infinitic/tests/properties/PropertiesWorkflow.kt index ad01ec2f3..1f1cbbe29 100644 --- a/infinitic-tests/src/test/kotlin/io/infinitic/tests/properties/PropertiesWorkflow.kt +++ b/infinitic-tests/src/test/kotlin/io/infinitic/tests/properties/PropertiesWorkflow.kt @@ -29,21 +29,37 @@ import io.infinitic.workflows.Workflow interface PropertiesWorkflow { fun prop1(): String + fun prop1bis() + fun prop2(): String + fun prop2bis() + fun prop3(): String + fun prop3bis() + fun prop4(): String + fun prop4bis() + fun prop5(): String + fun prop5bis() + fun prop5ter() + fun prop6(): String + fun prop6bis(deferred: Deferred): String + fun prop7(): String + fun prop7bis(): String + fun prop8(): String + fun prop8bis() } diff --git a/infinitic-tests/src/test/kotlin/io/infinitic/tests/scaffolds/engine.kt b/infinitic-tests/src/test/kotlin/io/infinitic/tests/scaffolds/engine.kt index b9bd256cb..d3d2a20f7 100644 --- a/infinitic-tests/src/test/kotlin/io/infinitic/tests/scaffolds/engine.kt +++ b/infinitic-tests/src/test/kotlin/io/infinitic/tests/scaffolds/engine.kt @@ -22,7 +22,6 @@ */ package io.infinitic.tests.scaffolds -import java.util.concurrent.Executors import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.asCoroutineDispatcher @@ -30,6 +29,7 @@ import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import java.util.concurrent.Executors /** * This code checks: diff --git a/infinitic-tests/src/test/kotlin/io/infinitic/tests/syntax/SyntaxWorkflow.kt b/infinitic-tests/src/test/kotlin/io/infinitic/tests/syntax/SyntaxWorkflow.kt index ae8caeb16..bed4a78ec 100644 --- a/infinitic-tests/src/test/kotlin/io/infinitic/tests/syntax/SyntaxWorkflow.kt +++ b/infinitic-tests/src/test/kotlin/io/infinitic/tests/syntax/SyntaxWorkflow.kt @@ -28,7 +28,9 @@ import io.infinitic.workflows.Workflow interface SyntaxWorkflow : ParentInterface { fun empty(): String + fun await(duration: Long): Long + fun wparent(): String } diff --git a/infinitic-tests/src/test/kotlin/io/infinitic/tests/timers/TimerWorkflowTests.kt b/infinitic-tests/src/test/kotlin/io/infinitic/tests/timers/TimerWorkflowTests.kt index 5147db5d1..377d0a16c 100644 --- a/infinitic-tests/src/test/kotlin/io/infinitic/tests/timers/TimerWorkflowTests.kt +++ b/infinitic-tests/src/test/kotlin/io/infinitic/tests/timers/TimerWorkflowTests.kt @@ -26,136 +26,140 @@ import io.infinitic.clients.InfiniticClient import io.infinitic.common.fixtures.later import io.infinitic.workers.InfiniticWorker import io.kotest.core.spec.style.StringSpec +import io.kotest.matchers.comparables.shouldBeGreaterThanOrEqualTo import io.kotest.matchers.longs.shouldBeGreaterThan import io.kotest.matchers.longs.shouldBeLessThan import io.kotest.matchers.shouldBe import java.time.Instant internal class TimerWorkflowTests : - StringSpec({ + StringSpec( + { - // each test should not be longer than 10s - timeout = 10000 + // each test should not be longer than 10s + timeout = 10000 - val worker = autoClose(InfiniticWorker.fromConfigResource("/pulsar.yml")) - val client = autoClose(InfiniticClient.fromConfigResource("/pulsar.yml")) + val worker = autoClose(InfiniticWorker.fromConfigResource("/pulsar.yml")) + val client = autoClose(InfiniticClient.fromConfigResource("/pulsar.yml")) - val timerWorkflow = client.newWorkflow(TimerWorkflow::class.java, tags = setOf("foo", "bar")) + val timerWorkflow = + client.newWorkflow(TimerWorkflow::class.java, tags = setOf("foo", "bar")) - beforeSpec { worker.startAsync() } + beforeSpec { worker.startAsync() } - beforeTest { worker.registry.flush() } + beforeTest { worker.registry.flush() } - "Wait for a duration timer" { - val start = Instant.now().toEpochMilli() + "Wait for a duration timer" { + val start = Instant.now().toEpochMilli() - val deferred = client.dispatch(timerWorkflow::await, 200L) + val deferred = client.dispatch(timerWorkflow::await, 200L) - (deferred.await().toEpochMilli() - start) shouldBeLessThan (2000L) - } + (deferred.await().toEpochMilli() - start) shouldBeLessThan (2000L) + } + + "Wait for a long duration timer" { + val start = Instant.now().toEpochMilli() - "Wait for a long duration timer" { - val start = Instant.now().toEpochMilli() + val deferred = client.dispatch(timerWorkflow::await, 2000L) - val deferred = client.dispatch(timerWorkflow::await, 2000L) + (deferred.await().toEpochMilli() - start) shouldBeGreaterThan (2000L) + } - (deferred.await().toEpochMilli() - start) shouldBeGreaterThan (2000L) - } + "Wait for a instant timer" { + val start = Instant.now().toEpochMilli() - "Wait for a instant timer" { - val start = Instant.now().toEpochMilli() + val deferred = client.dispatch(timerWorkflow::await, Instant.now().plusMillis(200)) - val deferred = client.dispatch(timerWorkflow::await, Instant.now().plusMillis(200)) + (deferred.await().toEpochMilli() - start) shouldBeLessThan (2000L) + } - (deferred.await().toEpochMilli() - start) shouldBeLessThan (2000L) - } + "Wait for a long instant timer" { + val start = Instant.now().toEpochMilli() - "Wait for a long instant timer" { - val start = Instant.now().toEpochMilli() + val deferred = client.dispatch(timerWorkflow::await, Instant.now().plusMillis(2000)) - val deferred = client.dispatch(timerWorkflow::await, Instant.now().plusMillis(2000)) + (deferred.await().toEpochMilli() - start) shouldBeGreaterThanOrEqualTo (2000L) + } - (deferred.await().toEpochMilli() - start) shouldBeGreaterThan (2000L) - } + "Wait for a timer or a signal - timer wins" { + val deferred = client.dispatch(timerWorkflow::awaitSignal, 200L) - "Wait for a timer or a signal - timer wins" { - val deferred = client.dispatch(timerWorkflow::awaitSignal, 200L) + deferred.await()::class shouldBe Instant::class + } - deferred.await()::class shouldBe Instant::class - } + "Wait for a timer or a signal - signal wins" { + val deferred = client.dispatch(timerWorkflow::awaitSignal, 10000L) - "Wait for a timer or a signal - signal wins" { - val deferred = client.dispatch(timerWorkflow::awaitSignal, 10000L) + later { + val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) + w.channel.send("bingo") + } - later { - val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) - w.channel.send("bingo") + deferred.await() shouldBe "bingo" } - deferred.await() shouldBe "bingo" - } + "Wait for a timer or a signal - timer wins after manual completion by id" { + val deferred = client.dispatch(timerWorkflow::awaitSignal, 10000L) - "Wait for a timer or a signal - timer wins after manual completion by id" { - val deferred = client.dispatch(timerWorkflow::awaitSignal, 10000L) + later(200) { + val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) + client.completeTimers(w) + } - later(200) { - val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) - client.completeTimers(w) - } + later(500) { + val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) + w.channel.send("bingo") + } - later(500) { - val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) - w.channel.send("bingo") + deferred.await()::class shouldBe Instant::class } - deferred.await()::class shouldBe Instant::class - } + "Wait for a timer or a signal - timer wins after manual completion by tag" { + val deferred = client.dispatch(timerWorkflow::awaitSignal, 10000L) - "Wait for a timer or a signal - timer wins after manual completion by tag" { - val deferred = client.dispatch(timerWorkflow::awaitSignal, 10000L) + later(200) { + val w = client.getWorkflowByTag(TimerWorkflow::class.java, "foo") + client.completeTimers(w) + } - later(200) { - val w = client.getWorkflowByTag(TimerWorkflow::class.java, "foo") - client.completeTimers(w) - } + later(500) { + val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) + w.channel.send("bingo") + } - later(500) { - val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) - w.channel.send("bingo") + deferred.await()::class shouldBe Instant::class } - deferred.await()::class shouldBe Instant::class - } + "Wait for a timer or a signal - signal wins after manual timer completion with wrong methodRunId" { + val deferred = client.dispatch(timerWorkflow::awaitSignal, 10000L) - "Wait for a timer or a signal - signal wins after manual timer completion with wrong methodRunId" { - val deferred = client.dispatch(timerWorkflow::awaitSignal, 10000L) + later(200) { + val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) + client.completeTimers(w, "wrong") + } - later(200) { - val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) - client.completeTimers(w, "wrong") - } + later(500) { + val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) + w.channel.send("bingo") + } - later(500) { - val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) - w.channel.send("bingo") + deferred.await() shouldBe "bingo" } - deferred.await() shouldBe "bingo" - } + "Wait for a timer or a signal - timer wins after manual completion with correct methodRunId" { + val deferred = client.dispatch(timerWorkflow::awaitSignal, 10000L) - "Wait for a timer or a signal - timer wins after manual completion with correct methodRunId" { - val deferred = client.dispatch(timerWorkflow::awaitSignal, 10000L) + later(200) { + val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) + client.completeTimers(w, deferred.id) + } - later(200) { - val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) - client.completeTimers(w, deferred.id) - } + later(500) { + val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) + w.channel.send("bingo") + } - later(500) { - val w = client.getWorkflowById(TimerWorkflow::class.java, deferred.id) - w.channel.send("bingo") + deferred.await()::class shouldBe Instant::class } - - deferred.await()::class shouldBe Instant::class - } - }) + }, + ) diff --git a/infinitic-tests/src/test/kotlin/io/infinitic/tests/utils/TestService.kt b/infinitic-tests/src/test/kotlin/io/infinitic/tests/utils/TestService.kt index 4704fe3e6..8bfb0164a 100644 --- a/infinitic-tests/src/test/kotlin/io/infinitic/tests/utils/TestService.kt +++ b/infinitic-tests/src/test/kotlin/io/infinitic/tests/utils/TestService.kt @@ -27,6 +27,7 @@ import io.infinitic.tasks.WithRetry interface TestService { fun log(): String + fun await(delay: Long): Long } diff --git a/infinitic-tests/src/test/kotlin/io/infinitic/tests/utils/UtilService.kt b/infinitic-tests/src/test/kotlin/io/infinitic/tests/utils/UtilService.kt index 07c19e4de..f338baffc 100644 --- a/infinitic-tests/src/test/kotlin/io/infinitic/tests/utils/UtilService.kt +++ b/infinitic-tests/src/test/kotlin/io/infinitic/tests/utils/UtilService.kt @@ -34,16 +34,25 @@ interface ParentInterface { interface UtilService : ParentInterface { fun concat(str1: String, str2: String): String + fun reverse(str: String): String + fun await(delay: Long): Long + fun workflowId(): String? + fun workflowName(): String? + fun retryFailedTasks(workflowName: String, id: String) + fun cancelWorkflow(workflowName: String, id: String) + fun failing() + fun successAtRetry(): String fun tags(): Set + fun meta(): TaskMeta fun withRetry(): WithRetry? diff --git a/infinitic-tests/src/test/kotlin/io/infinitic/tests/utils/UtilWorkflow.kt b/infinitic-tests/src/test/kotlin/io/infinitic/tests/utils/UtilWorkflow.kt index 0e65d29ea..faa3e4fc1 100644 --- a/infinitic-tests/src/test/kotlin/io/infinitic/tests/utils/UtilWorkflow.kt +++ b/infinitic-tests/src/test/kotlin/io/infinitic/tests/utils/UtilWorkflow.kt @@ -31,12 +31,19 @@ import io.infinitic.workflows.Workflow interface UtilWorkflow { val log: String val channelA: SendChannel + fun concat(input: String): String + fun receive(str: String): String + fun add(str: String): String + fun factorial(n: Long): Long + fun cancelChild1(): Long + fun cancelChild2(): Long + fun cancelChild2bis(deferred: Deferred): String } diff --git a/infinitic-tests/src/test/resources/simplelogger.properties b/infinitic-tests/src/test/resources/simplelogger.properties index d19220c63..7f5d10e95 100644 --- a/infinitic-tests/src/test/resources/simplelogger.properties +++ b/infinitic-tests/src/test/resources/simplelogger.properties @@ -1,15 +1,11 @@ # SLF4J's SimpleLogger configuration file # Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err. - # Log file #org.slf4j.simpleLogger.logFile=infinitic.log - - # Default logging detail level for all instances of SimpleLogger. # Must be one of ("trace", "debug", "info", "warn", or "error"). # If not specified, defaults to "info". org.slf4j.simpleLogger.defaultLogLevel=warn - # Logging detail level for a SimpleLogger instance named "xxxxx". # Must be one of ("trace", "debug", "info", "warn", or "error"). # If not specified, the default logging detail level is used. @@ -18,25 +14,20 @@ org.slf4j.simpleLogger.defaultLogLevel=warn #org.slf4j.simpleLogger.log.io.infinitic.transport.inMemory.InMemoryStarter=debug #org.slf4j.simpleLogger.log.io.infinitic.transport.pulsar.PulsarProducer=debug #org.slf4j.simpleLogger.log.io.infinitic.transport.pulsar.PulsarConsumer=debug - # Set to true if you want the current date and time to be included in output messages. # Default is false, and will output the number of milliseconds elapsed since startup. org.slf4j.simpleLogger.showDateTime=true - # The date and time format to be used in the output messages. # The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat. # If the format is not specified or is invalid, the default format is used. # The default format is yyyy-MM-dd HH:mm:ss:SSS Z. org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z - # Set to true if you want to output the current thread name. # Defaults to true. org.slf4j.simpleLogger.showThreadName=false - # Set to true if you want the Logger instance name to be included in output messages. # Defaults to true. # org.slf4j.simpleLogger.showLogName=true - # Set to true if you want the last component of the name to be included in output messages. # Defaults to false. org.slf4j.simpleLogger.showShortLogName=true diff --git a/infinitic-transport-inmemory/build.gradle.kts b/infinitic-transport-inmemory/build.gradle.kts index abcee77f7..8c4b4a052 100644 --- a/infinitic-transport-inmemory/build.gradle.kts +++ b/infinitic-transport-inmemory/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,19 +20,18 @@ * * Licensor: infinitic.io */ - dependencies { - implementation(Libs.Coroutines.core) - implementation(Libs.Coroutines.jdk8) + implementation(Libs.Coroutines.core) + implementation(Libs.Coroutines.jdk8) - api(project(":infinitic-common")) - api(project(":infinitic-client-base")) - api(project(":infinitic-storage")) - implementation(project(":infinitic-cache")) - implementation(project(":infinitic-workflow-tag")) - implementation(project(":infinitic-workflow-engine")) - implementation(project(":infinitic-task-tag")) - implementation(project(":infinitic-task-executor")) + api(project(":infinitic-common")) + api(project(":infinitic-client-base")) + api(project(":infinitic-storage")) + implementation(project(":infinitic-cache")) + implementation(project(":infinitic-workflow-tag")) + implementation(project(":infinitic-workflow-engine")) + implementation(project(":infinitic-task-tag")) + implementation(project(":infinitic-task-executor")) } apply("../publish.gradle.kts") diff --git a/infinitic-transport-inmemory/src/main/kotlin/io/infinitic/transport/inMemory/InMemoryStarter.kt b/infinitic-transport-inmemory/src/main/kotlin/io/infinitic/transport/inMemory/InMemoryStarter.kt index fc9d69e22..e6087cb9f 100644 --- a/infinitic-transport-inmemory/src/main/kotlin/io/infinitic/transport/inMemory/InMemoryStarter.kt +++ b/infinitic-transport-inmemory/src/main/kotlin/io/infinitic/transport/inMemory/InMemoryStarter.kt @@ -51,13 +51,13 @@ import io.infinitic.tasks.executor.TaskExecutor import io.infinitic.tasks.tag.TaskTagEngine import io.infinitic.workflows.engine.WorkflowEngine import io.infinitic.workflows.tag.WorkflowTagEngine -import java.util.concurrent.CompletableFuture -import java.util.concurrent.ConcurrentHashMap import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.delay import kotlinx.coroutines.future.future import mu.KotlinLogging +import java.util.concurrent.CompletableFuture +import java.util.concurrent.ConcurrentHashMap class InMemoryStarter(private val scope: CoroutineScope, name: String) : ClientStarter, WorkerStarter { diff --git a/infinitic-transport-inmemory/src/test/resources/simplelogger.properties b/infinitic-transport-inmemory/src/test/resources/simplelogger.properties index 6cab8950b..61abd000d 100644 --- a/infinitic-transport-inmemory/src/test/resources/simplelogger.properties +++ b/infinitic-transport-inmemory/src/test/resources/simplelogger.properties @@ -1,23 +1,17 @@ # SLF4J's SimpleLogger configuration file # Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err. - # Uncomment this line to use a log file #org.slf4j.simpleLogger.logFile=infinitic.log - # Default logging detail level for all instances of SimpleLogger. # Must be one of ("trace", "debug", "info", "warn", or "error"). # If not specified, defaults to "info". org.slf4j.simpleLogger.defaultLogLevel=info - # Set to true if you want the current date and time to be included in output messages. # Default is false, and will output the number of milliseconds elapsed since startup. org.slf4j.simpleLogger.showDateTime=true - # Set to true if you want to output the current thread name. # Defaults to true. org.slf4j.simpleLogger.showThreadName=false - - # Set to true if you want the last component of the name to be included in output messages. # Defaults to false. org.slf4j.simpleLogger.showShortLogName=true diff --git a/infinitic-transport-pulsar/build.gradle.kts b/infinitic-transport-pulsar/build.gradle.kts index a5206714f..0da09441f 100644 --- a/infinitic-transport-pulsar/build.gradle.kts +++ b/infinitic-transport-pulsar/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,22 +20,21 @@ * * Licensor: infinitic.io */ - dependencies { - implementation(Libs.Coroutines.core) - implementation(Libs.Hoplite.core) - implementation(Libs.Pulsar.client) - implementation(Libs.Pulsar.clientAdmin) - implementation(Libs.Pulsar.authAthenz) - implementation(Libs.Pulsar.authSasl) - implementation(Libs.Pulsar.functions) + implementation(Libs.Coroutines.core) + implementation(Libs.Hoplite.core) + implementation(Libs.Pulsar.client) + implementation(Libs.Pulsar.clientAdmin) + implementation(Libs.Pulsar.authAthenz) + implementation(Libs.Pulsar.authSasl) + implementation(Libs.Pulsar.functions) - implementation(project(":infinitic-common")) - implementation(project(":infinitic-client-base")) - implementation(project(":infinitic-workflow-engine")) - implementation(project(":infinitic-workflow-tag")) - implementation(project(":infinitic-task-tag")) - implementation(project(":infinitic-task-executor")) + implementation(project(":infinitic-common")) + implementation(project(":infinitic-client-base")) + implementation(project(":infinitic-workflow-engine")) + implementation(project(":infinitic-workflow-tag")) + implementation(project(":infinitic-task-tag")) + implementation(project(":infinitic-task-executor")) } apply("../publish.gradle.kts") diff --git a/infinitic-transport-pulsar/src/main/kotlin/io/infinitic/transport/pulsar/topics/TopicNames.kt b/infinitic-transport-pulsar/src/main/kotlin/io/infinitic/transport/pulsar/topics/TopicNames.kt index 77500edbb..4332ba307 100644 --- a/infinitic-transport-pulsar/src/main/kotlin/io/infinitic/transport/pulsar/topics/TopicNames.kt +++ b/infinitic-transport-pulsar/src/main/kotlin/io/infinitic/transport/pulsar/topics/TopicNames.kt @@ -41,12 +41,15 @@ interface TopicNames { fun topic(type: ClientTopics, clientName: ClientName): String fun topic(type: WorkflowTopics, workflowName: WorkflowName): String + fun topicDLQ(type: WorkflowTopics, workflowName: WorkflowName): String fun topic(type: ServiceTopics, serviceName: ServiceName): String + fun topicDLQ(type: ServiceTopics, serviceName: ServiceName): String fun topic(type: WorkflowTaskTopics, workflowName: WorkflowName): String + fun topicDLQ(type: WorkflowTaskTopics, workflowName: WorkflowName): String fun topic(type: TopicType, name: String) = diff --git a/infinitic-transport/build.gradle.kts b/infinitic-transport/build.gradle.kts index 20e8658bd..30be983de 100644 --- a/infinitic-transport/build.gradle.kts +++ b/infinitic-transport/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,9 +20,6 @@ * * Licensor: infinitic.io */ - -dependencies { - api(project(":infinitic-transport-pulsar")) -} +dependencies { api(project(":infinitic-transport-pulsar")) } apply("../publish.gradle.kts") diff --git a/infinitic-worker-base/build.gradle.kts b/infinitic-worker-base/build.gradle.kts index 1d4d69f2c..4b61e6127 100644 --- a/infinitic-worker-base/build.gradle.kts +++ b/infinitic-worker-base/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,21 +20,20 @@ * * Licensor: infinitic.io */ - dependencies { - implementation(kotlin("reflect")) - implementation(Libs.Coroutines.core) - implementation(Libs.Coroutines.jdk8) + implementation(kotlin("reflect")) + implementation(Libs.Coroutines.core) + implementation(Libs.Coroutines.jdk8) - implementation(project(":infinitic-common")) - implementation(project(":infinitic-storage")) - implementation(project(":infinitic-cache")) - implementation(project(":infinitic-task-tag")) - implementation(project(":infinitic-workflow-tag")) - implementation(project(":infinitic-workflow-engine")) + implementation(project(":infinitic-common")) + implementation(project(":infinitic-storage")) + implementation(project(":infinitic-cache")) + implementation(project(":infinitic-task-tag")) + implementation(project(":infinitic-workflow-tag")) + implementation(project(":infinitic-workflow-engine")) - testImplementation(Libs.Hoplite.core) - testImplementation(Libs.Hoplite.yaml) + testImplementation(Libs.Hoplite.core) + testImplementation(Libs.Hoplite.yaml) } apply("../publish.gradle.kts") diff --git a/infinitic-worker-base/src/main/kotlin/io/infinitic/workers/WorkerAbstract.kt b/infinitic-worker-base/src/main/kotlin/io/infinitic/workers/WorkerAbstract.kt index 3f6c4c145..281ecf5c3 100644 --- a/infinitic-worker-base/src/main/kotlin/io/infinitic/workers/WorkerAbstract.kt +++ b/infinitic-worker-base/src/main/kotlin/io/infinitic/workers/WorkerAbstract.kt @@ -25,11 +25,11 @@ package io.infinitic.workers import io.infinitic.common.clients.ClientFactory import io.infinitic.common.workers.WorkerStarter import io.infinitic.workers.register.WorkerRegister -import java.util.concurrent.CompletableFuture import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.job import mu.KotlinLogging +import java.util.concurrent.CompletableFuture @Suppress("MemberVisibilityCanBePrivate", "unused") abstract class WorkerAbstract(val workerRegister: WorkerRegister) : diff --git a/infinitic-worker/build.gradle.kts b/infinitic-worker/build.gradle.kts index c9ee89864..aa46a472b 100644 --- a/infinitic-worker/build.gradle.kts +++ b/infinitic-worker/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,29 +20,28 @@ * * Licensor: infinitic.io */ - dependencies { - implementation(kotlin("reflect")) - implementation(Libs.Coroutines.core) - implementation(Libs.Coroutines.jdk8) + implementation(kotlin("reflect")) + implementation(Libs.Coroutines.core) + implementation(Libs.Coroutines.jdk8) - api(project(":infinitic-worker-base")) - api(project(":infinitic-workflow-tag")) - api(project(":infinitic-task-tag")) - api(project(":infinitic-storage")) - api(project(":infinitic-cache")) + api(project(":infinitic-worker-base")) + api(project(":infinitic-workflow-tag")) + api(project(":infinitic-task-tag")) + api(project(":infinitic-storage")) + api(project(":infinitic-cache")) - implementation(project(":infinitic-client-base")) - implementation(project(":infinitic-common")) - implementation(project(":infinitic-transport")) - implementation(project(":infinitic-task-executor")) - implementation(project(":infinitic-workflow-engine")) - implementation(project(":infinitic-workflow-task")) - implementation(project(":infinitic-pulsar")) - implementation(project(":infinitic-inMemory")) + implementation(project(":infinitic-client-base")) + implementation(project(":infinitic-common")) + implementation(project(":infinitic-transport")) + implementation(project(":infinitic-task-executor")) + implementation(project(":infinitic-workflow-engine")) + implementation(project(":infinitic-workflow-task")) + implementation(project(":infinitic-pulsar")) + implementation(project(":infinitic-inMemory")) - testImplementation(Libs.Hoplite.core) - testImplementation(Libs.Hoplite.yaml) + testImplementation(Libs.Hoplite.core) + testImplementation(Libs.Hoplite.yaml) } apply("../publish.gradle.kts") diff --git a/infinitic-worker/src/main/kotlin/io/infinitic/workers/config/Workflow.kt b/infinitic-worker/src/main/kotlin/io/infinitic/workers/config/Workflow.kt index 93bcb6a3d..5b3dae782 100644 --- a/infinitic-worker/src/main/kotlin/io/infinitic/workers/config/Workflow.kt +++ b/infinitic-worker/src/main/kotlin/io/infinitic/workers/config/Workflow.kt @@ -24,11 +24,11 @@ package io.infinitic.workers.config import io.infinitic.common.workers.config.RetryPolicy import io.infinitic.workers.register.WorkerRegister -import io.infinitic.workflows.Workflow as WorkflowBase import io.infinitic.workflows.Workflow import io.infinitic.workflows.WorkflowCheckMode import io.infinitic.workflows.engine.config.WorkflowEngine import io.infinitic.workflows.tag.config.WorkflowTag +import io.infinitic.workflows.Workflow as WorkflowBase data class Workflow( val name: String, diff --git a/infinitic-workflow-engine/build.gradle.kts b/infinitic-workflow-engine/build.gradle.kts index 05d33e7e5..e133e23f0 100644 --- a/infinitic-workflow-engine/build.gradle.kts +++ b/infinitic-workflow-engine/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,14 +20,13 @@ * * Licensor: infinitic.io */ - dependencies { - implementation(Libs.Coroutines.core) + implementation(Libs.Coroutines.core) - implementation(project(":infinitic-common")) - implementation(project(":infinitic-cache")) - implementation(project(":infinitic-storage")) - implementation(project(":infinitic-task-executor")) + implementation(project(":infinitic-common")) + implementation(project(":infinitic-cache")) + implementation(project(":infinitic-storage")) + implementation(project(":infinitic-task-executor")) } apply("../publish.gradle.kts") diff --git a/infinitic-workflow-engine/src/main/kotlin/io/infinitic/workflows/engine/WorkflowEngine.kt b/infinitic-workflow-engine/src/main/kotlin/io/infinitic/workflows/engine/WorkflowEngine.kt index b2a8c78e0..1abd851d1 100644 --- a/infinitic-workflow-engine/src/main/kotlin/io/infinitic/workflows/engine/WorkflowEngine.kt +++ b/infinitic-workflow-engine/src/main/kotlin/io/infinitic/workflows/engine/WorkflowEngine.kt @@ -237,7 +237,7 @@ class WorkflowEngine( // process all buffered messages while (state.runningWorkflowTaskId == null && // if a workflowTask is not ongoing - state.messagesBuffer.size > 0 // if there is some buffered message + state.messagesBuffer.size > 0 // if there is some buffered message ) { val bufferedMsg = state.messagesBuffer.removeAt(0) logger.debug { diff --git a/infinitic-workflow-engine/src/main/kotlin/io/infinitic/workflows/engine/handlers/SendSignal.kt b/infinitic-workflow-engine/src/main/kotlin/io/infinitic/workflows/engine/handlers/SendSignal.kt index fe08348c4..296d34b83 100644 --- a/infinitic-workflow-engine/src/main/kotlin/io/infinitic/workflows/engine/handlers/SendSignal.kt +++ b/infinitic-workflow-engine/src/main/kotlin/io/infinitic/workflows/engine/handlers/SendSignal.kt @@ -62,6 +62,5 @@ internal fun CoroutineScope.sendSignal( returnValue = ReturnValue(message.signalData.serializedData), completionWorkflowTaskIndex = state.workflowTaskIndex, signalId = message.signalId)) - } - ?: logger.debug { "discarding non-waited signal $message" } + } ?: logger.debug { "discarding non-waited signal $message" } } diff --git a/infinitic-workflow-engine/src/test/kotlin/io/infinitic/workflows/engine/WorkflowEngineTests.kt b/infinitic-workflow-engine/src/test/kotlin/io/infinitic/workflows/engine/WorkflowEngineTests.kt index e37536247..7c39040a4 100644 --- a/infinitic-workflow-engine/src/test/kotlin/io/infinitic/workflows/engine/WorkflowEngineTests.kt +++ b/infinitic-workflow-engine/src/test/kotlin/io/infinitic/workflows/engine/WorkflowEngineTests.kt @@ -55,8 +55,8 @@ import io.mockk.coEvery import io.mockk.just import io.mockk.mockk import io.mockk.slot -import java.util.concurrent.CopyOnWriteArrayList import kotlinx.coroutines.coroutineScope +import java.util.concurrent.CopyOnWriteArrayList class WorkflowEngineTests : StringSpec({ diff --git a/infinitic-workflow-tag/build.gradle.kts b/infinitic-workflow-tag/build.gradle.kts index 718a8bb95..21e13b7a4 100644 --- a/infinitic-workflow-tag/build.gradle.kts +++ b/infinitic-workflow-tag/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,14 +20,13 @@ * * Licensor: infinitic.io */ - dependencies { - api(Libs.Coroutines.core) - api(Libs.Coroutines.jdk8) + api(Libs.Coroutines.core) + api(Libs.Coroutines.jdk8) - api(project(":infinitic-common")) - api(project(":infinitic-cache")) - api(project(":infinitic-storage")) + api(project(":infinitic-common")) + api(project(":infinitic-cache")) + api(project(":infinitic-storage")) } apply("../publish.gradle.kts") diff --git a/infinitic-workflow-task/build.gradle.kts b/infinitic-workflow-task/build.gradle.kts index 6513a1a69..94272aa58 100644 --- a/infinitic-workflow-task/build.gradle.kts +++ b/infinitic-workflow-task/build.gradle.kts @@ -1,20 +1,18 @@ /** * "Commons Clause" License Condition v1.0 * - * The Software is provided to you by the Licensor under the License, as defined - * below, subject to the following condition. + * The Software is provided to you by the Licensor under the License, as defined below, subject to + * the following condition. * - * Without limiting other conditions in the License, the grant of rights under the - * License will not include, and the License does not grant to you, the right to - * Sell the Software. + * Without limiting other conditions in the License, the grant of rights under the License will not + * include, and the License does not grant to you, the right to Sell the Software. * - * For purposes of the foregoing, “Sell” means practicing any or all of the rights - * granted to you under the License to provide to third parties, for a fee or - * other consideration (including without limitation fees for hosting or - * consulting/ support services related to the Software), a product or service - * whose value derives, entirely or substantially, from the functionality of the - * Software. Any license notice or attribution required by the License must also - * include this Commons Clause License Condition notice. + * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you + * under the License to provide to third parties, for a fee or other consideration (including + * without limitation fees for hosting or consulting/ support services related to the Software), a + * product or service whose value derives, entirely or substantially, from the functionality of the + * Software. Any license notice or attribution required by the License must also include this + * Commons Clause License Condition notice. * * Software: Infinitic * @@ -22,14 +20,13 @@ * * Licensor: infinitic.io */ - dependencies { - implementation(kotlin("reflect")) - implementation(Libs.Coroutines.core) - implementation(Libs.JsonPath.jayway) + implementation(kotlin("reflect")) + implementation(Libs.Coroutines.core) + implementation(Libs.JsonPath.jayway) - implementation(project(":infinitic-common")) - implementation(project(":infinitic-client-base")) + implementation(project(":infinitic-common")) + implementation(project(":infinitic-client-base")) } apply("../publish.gradle.kts") diff --git a/infinitic-workflow-task/src/test/kotlin/io/infinitic/workflows/workflowTask/workflows/WorkflowA.kt b/infinitic-workflow-task/src/test/kotlin/io/infinitic/workflows/workflowTask/workflows/WorkflowA.kt index 5bf78900e..47de851a8 100644 --- a/infinitic-workflow-task/src/test/kotlin/io/infinitic/workflows/workflowTask/workflows/WorkflowA.kt +++ b/infinitic-workflow-task/src/test/kotlin/io/infinitic/workflows/workflowTask/workflows/WorkflowA.kt @@ -26,10 +26,10 @@ import io.infinitic.annotations.Ignore import io.infinitic.workflows.SendChannel import io.infinitic.workflows.Workflow import io.infinitic.workflows.workflowTask.tasks.TaskA -import java.util.UUID import kotlinx.serialization.Serializable import mu.KotlinLogging import org.slf4j.LoggerFactory +import java.util.* sealed class Obj diff --git a/pulsar/README.md b/pulsar/README.md index 49faf9f60..128261ce4 100644 --- a/pulsar/README.md +++ b/pulsar/README.md @@ -3,10 +3,11 @@ ## Run Standalone Pulsar > Create those directories, if you don't have them yet: -/engine/build/libs -/engine/build/schemas +> /engine/build/libs +> /engine/build/schemas In the same directory than `docker-compose.yaml`, do: + ```bash docker-compose up ``` @@ -18,26 +19,31 @@ docker exec -it pulsar_pulsar_1 /bin/bash ``` To clean everything + ```bash docker-compose down --volumes ``` To install Infinitic: + ```bash gradle install ``` To remove Infinitic + ```bash gradle delete ``` To update Infinitic + ```bash gradle update ``` ## Pulsar Manager + Once Docker run, you can access it at `http://localhost:9527` Create an admin user with: @@ -59,5 +65,6 @@ To obtain the service url of Pulsar *from the Pulsar Manager container*, do: ```bash docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' pulsar-pulsar-1 ``` + you should obtain something like `172.18.0.3`. Then the service url to use for adding an environment is `http://172.18.0.3:8080`