diff --git a/.golangci.yml b/.golangci.yml index 7b9ca51c..067c27f7 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,22 +1,22 @@ run: deadline: 60s skip-dirs: - - hack - - website - - ui + - hack + - website + - ui linters: enable: - - misspell - - gofumpt - - importas - - gci + - misspell + - gofumpt + - importas + - gci issues: exclude-rules: - - path: _test\.go - linters: - - errcheck + - path: _test\.go + linters: + - errcheck linters-settings: gci: @@ -32,11 +32,7 @@ linters-settings: no-unaliased: true no-extra-aliases: false alias: - - pkg: go.uber.org/cadence - alias: cadencesdk - - pkg: go.uber.org/cadence/(\w+) - alias: cadencesdk_$1 - - pkg: go.uber.org/cadence/.gen/go/shared - alias: cadencesdk_gen_shared - - pkg: go.uber.org/cadence/.gen/go/cadence/workflowserviceclient - alias: cadencesdk_gen_workflowserviceclient + - pkg: go.temporal.io/sdk/(\w+) + alias: temporalsdk_$1 + - pkg: go.temporal.io/api/(\w+) + alias: temporalapi_$1 diff --git a/Makefile b/Makefile index fb682b63..c90e3ae1 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,6 @@ IGNORED_PACKAGES := \ github.com/artefactual-labs/enduro/internal/batch/fake \ github.com/artefactual-labs/enduro/internal/collection/fake \ github.com/artefactual-labs/enduro/internal/pipeline/fake \ - github.com/artefactual-labs/enduro/internal/testutil \ github.com/artefactual-labs/enduro/internal/watcher/fake PACKAGES := $(shell go list ./...) TEST_PACKAGES := $(filter-out $(IGNORED_PACKAGES),$(PACKAGES)) @@ -126,27 +125,12 @@ ui-client: @echo "@@@@ Please, review all warnings generated by openapi-generator-cli above!" @echo "@@@@ We're using \`--skip-validate-spec\` to deal with Goa spec generation issues." -cadence-flush: - docker-compose exec mysql mysql -hlocalhost -uroot -proot123 -e "DROP DATABASE IF EXISTS cadence;" - docker-compose exec mysql mysql -hlocalhost -uroot -proot123 -e "DROP DATABASE IF EXISTS cadence_visibility;" - docker-compose exec mysql mysql -hlocalhost -uroot -proot123 -e "CREATE DATABASE IF NOT EXISTS cadence;" - docker-compose exec mysql mysql -hlocalhost -uroot -proot123 -e "CREATE DATABASE IF NOT EXISTS cadence_visibility;" - docker-compose run --rm cadence /seed.sh - docker-compose restart cadence - $(MAKE) cadence-domain - -cadence-seed: - docker-compose run --rm cadence /seed.sh - -cadence-domain: - docker run -it --network=host --rm ubercadence/cli:master --address=127.0.0.1:7400 --domain=enduro domain register --global_domain=false --active_cluster=active - db: - docker-compose exec --user=root mysql mysql -hlocalhost -uroot -proot123 + docker compose exec --user=root mysql mysql -hlocalhost -uroot -proot123 flush: - docker-compose exec --user=root mysql mysql -hlocalhost -uroot -proot123 -e "drop database enduro" - docker-compose exec --user=root mysql mysql -hlocalhost -uroot -proot123 -e "create database enduro" + docker compose exec --user=root mysql mysql -hlocalhost -uroot -proot123 -e "drop database enduro" + docker compose exec --user=root mysql mysql -hlocalhost -uroot -proot123 -e "create database enduro" gen-mock: $(MOCKGEN) -destination=./internal/batch/fake/mock_batch.go -package=fake github.com/artefactual-labs/enduro/internal/batch Service diff --git a/docker-compose.yml b/docker-compose.yml index a32f92b4..72ad96b4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,8 +3,7 @@ version: "3" services: mysql: - image: "mysql:5.7" - command: "--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci" + image: "mysql:8.0" environment: MYSQL_ROOT_PASSWORD: "root123" MYSQL_USER: "enduro" @@ -14,37 +13,31 @@ services: ports: - "127.0.0.1:7450:3306" - cadence: - image: "ubercadence/server:0.9.5" - command: ["cadence-server", "--root=/etc/cadence", "--env=docker", "start", "--services=frontend,matching,history,worker"] - restart: "on-failure" + temporal: + image: "temporalio/auto-setup:1.21.1" + environment: + - "DB=mysql" + - "DB_PORT=3306" + - "MYSQL_USER=root" + - "MYSQL_PWD=root123" + - "MYSQL_SEEDS=mysql" ports: - # frontend service - - "127.0.0.1:7400:7400" # rpc - - "127.0.0.1:7401:7401" # prom - - "127.0.0.1:7402:7402" # pprof - # matching service - - "127.0.0.1:7410:7410" # rpc - - "127.0.0.1:7411:7411" # prom - - "127.0.0.1:7412:7412" # pprof - # history service - - "127.0.0.1:7420:7420" # rpc - - "127.0.0.1:7421:7421" # prom - - "127.0.0.1:7422:7422" # pprof - # worker service - - "127.0.0.1:7430:7430" # rpc - - "127.0.0.1:7431:7431" # prom - - "127.0.0.1:7432:7432" # pprof - volumes: - - "./hack/cadence/seed.sh:/seed.sh:ro" - - "./hack/cadence/config.yml:/etc/cadence/config/docker.yaml:ro" + - "127.0.0.1:7233:7233" + + temporal-admin-tools: + environment: + - "TEMPORAL_CLI_ADDRESS=temporal:7233" + image: "temporalio/admin-tools:1.21.1" + stdin_open: true + tty: true - cadence-web: - image: "ubercadence/web:3.13.0" + temporal-ui: + image: "temporalio/ui:2.16.2" environment: - - "CADENCE_TCHANNEL_PEERS=cadence:7400" + - "TEMPORAL_ADDRESS=temporal:7233" + - "TEMPORAL_CORS_ORIGINS=http://localhost:7440" ports: - - "127.0.0.1:7440:8088" + - "127.0.0.1:7440:8080" minio: image: "minio/minio:RELEASE.2020-04-28T23-56-56Z" diff --git a/enduro.toml b/enduro.toml index 207023b6..b69c5900 100644 --- a/enduro.toml +++ b/enduro.toml @@ -3,9 +3,10 @@ debug = true debugListen = "127.0.0.1:9001" -[cadence] -domain = "enduro" -address = "127.0.0.1:7400" +[temporal] +namespace = "default" +address = "127.0.0.1:7233" +taskQueue = "global" [api] listen = "127.0.0.1:9000" diff --git a/go.mod b/go.mod index 4b7fab1f..6b9f2837 100644 --- a/go.mod +++ b/go.mod @@ -28,11 +28,9 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.16.0 github.com/stretchr/testify v1.8.4 - github.com/uber-go/tally v3.4.3+incompatible - go.artefactual.dev/tools v0.1.0 - go.uber.org/cadence v0.19.1 - go.uber.org/yarpc v1.70.3 - go.uber.org/zap v1.24.0 + go.artefactual.dev/tools v0.3.0 + go.temporal.io/api v1.21.0 + go.temporal.io/sdk v1.23.1 goa.design/goa/v3 v3.11.3 goa.design/plugins/v3 v3.11.3 gocloud.dev v0.30.0 @@ -41,11 +39,8 @@ require ( ) require ( - github.com/BurntSushi/toml v1.0.0 // indirect github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect github.com/andybalholm/brotli v1.0.4 // indirect - github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect - github.com/apache/thrift v0.16.0 // indirect github.com/aws/aws-sdk-go-v2 v1.18.1 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect github.com/aws/aws-sdk-go-v2/config v1.18.27 // indirect @@ -67,26 +62,26 @@ require ( github.com/aws/smithy-go v1.13.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cristalhq/jwt/v3 v3.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 // indirect github.com/dimfeld/httptreemux/v5 v5.5.0 // indirect github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect - github.com/fatih/structtag v1.2.0 // indirect github.com/go-logr/zapr v1.2.4 // indirect + github.com/gogo/googleapis v1.4.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/gogo/status v1.1.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/wire v0.5.0 // indirect github.com/googleapis/gax-go/v2 v2.11.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/jessevdk/go-flags v1.5.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/kisielk/errcheck v1.6.0 // indirect github.com/klauspost/compress v1.15.11 // indirect github.com/klauspost/pgzip v1.2.5 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -94,7 +89,6 @@ require ( github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/nwaples/rardecode v1.1.2 // indirect - github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pborman/uuid v1.2.1 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pierrec/lz4/v4 v4.1.16 // indirect @@ -108,9 +102,6 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect - github.com/twmb/murmur3 v1.1.6 // indirect - github.com/uber-go/mapdecode v1.0.0 // indirect - github.com/uber/tchannel-go v1.22.2 // indirect github.com/ulikunitz/xz v0.5.10 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/yuin/gopher-lua v1.1.0 // indirect @@ -118,11 +109,9 @@ require ( go.opencensus.io v0.24.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/net/metrics v1.3.1 // indirect - go.uber.org/thriftrw v1.29.2 // indirect - golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e // indirect - golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/mod v0.10.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect + golang.org/x/mod v0.11.0 // indirect golang.org/x/net v0.11.0 // indirect golang.org/x/sys v0.9.0 // indirect golang.org/x/text v0.10.0 // indirect @@ -134,9 +123,7 @@ require ( google.golang.org/grpc v1.56.0 // indirect google.golang.org/protobuf v1.30.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - honnef.co/go/tools v0.3.2 // indirect ) // ringpop-go and tchannel-go depends on older version of thrift, yarpc brings up newer version diff --git a/go.sum b/go.sum index 50e1449a..d688f7ed 100644 --- a/go.sum +++ b/go.sum @@ -683,9 +683,6 @@ github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9s github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0= github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= -github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/GoogleCloudPlatform/cloudsql-proxy v1.33.7/go.mod h1:JBp/RvKNOoIkR5BdMSXswBksHcPZ/41sbBV+GhSjgMY= @@ -751,13 +748,9 @@ github.com/alicebob/miniredis/v2 v2.30.3/go.mod h1:b25qWj4fCEsBeAAR2mlb0ufImGC6u github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= -github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7 h1:Fv9bK1Q+ly/ROk4aJsVMeuIwPel4bEnD8EPiI91nZMg= github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= @@ -846,8 +839,6 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b h1:AP/Y7sqYicnjGDfD5VcY4CIfh1hRXBUavxrvELjTiOE= -github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= @@ -858,7 +849,6 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2 github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/cactus/go-statsd-client/statsd v0.0.0-20191106001114-12b4e2b38748/go.mod h1:l/bIBLeOl9eX+wxJAzxS4TveKRtAqlyDpHjhkfO0MEI= github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= @@ -914,7 +904,6 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= @@ -1036,8 +1025,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cristalhq/jwt/v3 v3.1.0 h1:iLeL9VzB0SCtjCy9Kg53rMwTcrNm+GHyVcz2eUujz6s= -github.com/cristalhq/jwt/v3 v3.1.0/go.mod h1:XOnIXst8ozq/esy5N1XOlSyQqBd+84fxJ99FK+1jgL8= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= @@ -1052,7 +1039,6 @@ github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8l github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -1135,14 +1121,10 @@ github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGE github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= -github.com/fatih/structtag v1.0.0/go.mod h1:IKitwq45uXL/yqi5mYghiD3w9H6eTOvI9vnk8tXMphA= -github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= -github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= @@ -1308,19 +1290,18 @@ github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= -github.com/gogo/googleapis v1.3.2/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= -github.com/gogo/googleapis v1.4.0 h1:zgVt4UpGxcqVOw97aRGxT4svlcmdK35fynLNctY32zI= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= +github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/gogo/status v1.1.0 h1:+eIkrewn5q6b30y+g/BJINVVdi2xH7je5MPJ3ZPK3JA= -github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= +github.com/gogo/status v1.1.1 h1:DuHXlSFHNKqTQ+/ACf5Vs6r4X/dH2EgIzR9Vr+H65kg= +github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci7oU= github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= @@ -1356,7 +1337,6 @@ github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+Licev github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3-0.20190920234318-1680a479a2cf/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= @@ -1508,6 +1488,7 @@ github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWf github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= @@ -1650,8 +1631,6 @@ github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/U github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc= github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -1672,7 +1651,6 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -1691,8 +1669,6 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:C github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/errcheck v1.6.0 h1:YTDO4pNy7AUN/021p+JGHycQyYNIyMoenM1YDVK6RlY= -github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= @@ -1783,7 +1759,6 @@ github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= @@ -1947,7 +1922,6 @@ github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3 github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= github.com/otiai10/copy v1.12.0 h1:cLMgSQnXBs1eehF0Wy/FAGsgDTDmAqFR7rQylBb1nDY= @@ -1956,7 +1930,6 @@ github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= github.com/ovh/go-ovh v1.4.1/go.mod h1:6bL6pPyUT7tBfI0pqOegJgRjgjuO+mOo+MyXd1EEC0M= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pborman/uuid v0.0.0-20160209185913-a97ce2ca70fa/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw= github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -1995,8 +1968,6 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= -github.com/prashantv/protectmem v0.0.0-20171002184600-e20412882b3a h1:AA9vgIBDjMHPC2McaGPojgV2dcI78ZC0TLNhYCXEKH8= -github.com/prashantv/protectmem v0.0.0-20171002184600-e20412882b3a/go.mod h1:lzZQ3Noex5pfAy7mkAeCjcBDteYU85uWWnJ/y6gKU8k= github.com/prometheus/alertmanager v0.24.0/go.mod h1:r6fy/D7FRuZh5YbnX6J3MBY0eI4Pb5yPYS7/bPSXXqI= github.com/prometheus/alertmanager v0.25.0/go.mod h1:MEZ3rFVHqKZsw7IcNS/m4AWZeXThmJhumpiWR4eHU/w= github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -2004,9 +1975,7 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= @@ -2020,7 +1989,6 @@ github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1: github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= @@ -2029,8 +1997,6 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/common v0.8.0/go.mod h1:PC/OgXc+UN7B4ALwvn1yzVZmVwvhXp5JsbBv6wSv6i0= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= @@ -2057,7 +2023,6 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.0.9/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= @@ -2099,8 +2064,6 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= -github.com/samuel/go-thrift v0.0.0-20191111193933-5165175b40af h1:EiWVfh8mr40yFZEui2oF0d45KgH48PkB2H0Z0GANvSI= -github.com/samuel/go-thrift v0.0.0-20191111193933-5165175b40af/go.mod h1:Vrkh1pnjV9Bl8c3P9zH0/D4NlOHWP5d4/hF4YTULaec= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.15/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= @@ -2171,8 +2134,6 @@ github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= -github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25 h1:7z3LSn867ex6VSaahyKadf4WtSsJIgne6A1WLOAGM8A= -github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU= github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -2211,24 +2172,6 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1 github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= -github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= -github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= -github.com/uber-common/bark v1.2.1/go.mod h1:g0ZuPcD7XiExKHynr93Q742G/sbrdVQkghrqLGOoFuY= -github.com/uber-go/mapdecode v1.0.0 h1:euUEFM9KnuCa1OBixz1xM+FIXmpixyay5DLymceOVrU= -github.com/uber-go/mapdecode v1.0.0/go.mod h1:b5nP15FwXTgpjTjeA9A2uTHXV5UJCl4arwKpP0FP1Hw= -github.com/uber-go/tally v3.3.12+incompatible/go.mod h1:YDTIBxdXyOU/sCWilKB4bgyufu1cEi0jdVnRdxvjnmU= -github.com/uber-go/tally v3.3.15+incompatible/go.mod h1:YDTIBxdXyOU/sCWilKB4bgyufu1cEi0jdVnRdxvjnmU= -github.com/uber-go/tally v3.4.3+incompatible h1:Oq25FXV8cWHPRo+EPeNdbN3LfuozC9mDK2/4vZ1k38U= -github.com/uber-go/tally v3.4.3+incompatible/go.mod h1:YDTIBxdXyOU/sCWilKB4bgyufu1cEi0jdVnRdxvjnmU= -github.com/uber/cadence-idl v0.0.0-20211111101836-d6b70b60eb8c/go.mod h1:oyUK7GCNCRHCCyWyzifSzXpVrRYVBbAMHAzF5dXiKws= -github.com/uber/jaeger-client-go v2.22.1+incompatible h1:NHcubEkVbahf9t3p75TOCR83gdUHXjRJvjoBh1yACsM= -github.com/uber/jaeger-client-go v2.22.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw= -github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/uber/ringpop-go v0.8.5/go.mod h1:zVI6eGO6L7pG14GkntHsSOfmUAWQ7B4lvmzly4IT4ls= -github.com/uber/tchannel-go v1.16.0/go.mod h1:Rrgz1eL8kMjW/nEzZos0t+Heq0O4LhnUJVA32OvWKHo= -github.com/uber/tchannel-go v1.22.2 h1:NKA5FVESYh6Ij6V+tujK+IFZnBKDyUHdsBY264UYhgk= -github.com/uber/tchannel-go v1.22.2/go.mod h1:Rrgz1eL8kMjW/nEzZos0t+Heq0O4LhnUJVA32OvWKHo= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= @@ -2285,8 +2228,8 @@ github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea/go.mod h github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.artefactual.dev/tools v0.1.0 h1:+UTyUXQbvq32X0AuIjkfoVvrEdxIvzsCyj+vWjxLGQ0= -go.artefactual.dev/tools v0.1.0/go.mod h1:VM9uoKuK6IcDIitYuWvqyaxxLajGxJHDbqnwNfgaCpU= +go.artefactual.dev/tools v0.3.0 h1:0Lq91Xo5hwn7Xcy2pYnytKocEmTZmzagzNXyjMtv0Ps= +go.artefactual.dev/tools v0.3.0/go.mod h1:bPOawySv59dJUPitqreJTLgeQkQvA5E2JGQj/zpunJ0= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= @@ -2367,10 +2310,13 @@ go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg go.opentelemetry.io/proto/otlp v0.12.1/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.temporal.io/api v1.21.0 h1:l2HrMI/gE5JwFu9wgmZdofBIQ5MzziOEBs8mnbJUcJs= +go.temporal.io/api v1.21.0/go.mod h1:xlsUEakkN2vU2/WV7e5NqMG4N93nfuNfvbXdaXUpU8w= +go.temporal.io/sdk v1.23.1 h1:HzOaw5+f6QgDW/HH1jzwgupII7nVz+fzxFPjmFJqKiQ= +go.temporal.io/sdk v1.23.1/go.mod h1:S7vWxU01lGcCny0sWx03bkkYw4VtVrpzeqBTn2A6y+E= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -2379,16 +2325,6 @@ go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66vU6XU= go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= -go.uber.org/cadence v0.19.1 h1:uPKGi2WHNja8fwlGyybRqX4NZVm36E2sLxaPU3j2QPg= -go.uber.org/cadence v0.19.1/go.mod h1:s91dOf0kcJbumPscRIVFV/4Xq/exhefzpXmnDiRRTxs= -go.uber.org/dig v1.8.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= -go.uber.org/dig v1.10.0 h1:yLmDDj9/zuDjv3gz8GQGviXMs9TfysIUMUilCpgzUJY= -go.uber.org/dig v1.10.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= -go.uber.org/fx v1.10.0/go.mod h1:vLRicqpG/qQEzno4SYU86iCwfT95EZza+Eba0ItuxqY= -go.uber.org/fx v1.13.1 h1:CFNTr1oin5OJ0VCZ8EycL3wzF29Jz2g0xe55RFsf2a4= -go.uber.org/fx v1.13.1/go.mod h1:bREWhavnedxpJeTq9pQT53BbvwhUv7TcpsOqcH4a+3w= -go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= -go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= @@ -2397,23 +2333,12 @@ go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/net/metrics v1.3.0/go.mod h1:pEQrSDGNWT5IVpekWzee5//uHjI4gmgZFkobfw3bv8I= -go.uber.org/net/metrics v1.3.1 h1:Dqx/FCnqWhsTwSeNcV+Dl8dHWWZ1dd4+yhHJajy3/tQ= -go.uber.org/net/metrics v1.3.1/go.mod h1:pEQrSDGNWT5IVpekWzee5//uHjI4gmgZFkobfw3bv8I= -go.uber.org/thriftrw v1.25.0/go.mod h1:IcIfSeZgc59AlYb0xr0DlDKIdD7SgjnFpG9BXCPyy9g= -go.uber.org/thriftrw v1.29.2 h1:pRuFLzbGvTcnYwGSjizWRHlbJUzGhu84sRiL1h1kUd8= -go.uber.org/thriftrw v1.29.2/go.mod h1:YcjXveberDd28/Bs34SwHy3yu85x/jB4UA2gIcz/Eo0= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/yarpc v1.55.0/go.mod h1:V2JUPDWHYGNpvyuroYjf0KFjwvBCtcFJLuvZqv7TWA0= -go.uber.org/yarpc v1.70.3 h1:yykHwzRD9/bgDtlOWoVuXbSZoU91Id2dWJO1CDSRHnI= -go.uber.org/yarpc v1.70.3/go.mod h1:EH6I6K1HxBbOxZIJfhdDf+H+cvXPHmJyRvpfPqES20U= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= @@ -2491,8 +2416,8 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/exp v0.0.0-20230108222341-4b8118a2686a/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e h1:qyrTQ++p1afMkO4DPEeLGq/3oTsdlvdH4vqZUBWzUKM= -golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -2517,7 +2442,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -2538,8 +2462,9 @@ golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2737,12 +2662,10 @@ golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200117145432-59e60aa80a0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2884,7 +2807,6 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20170927054726-6dc17368e09b/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2934,27 +2856,22 @@ golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191030062658-86caa796c7ab/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191114200427-caa0b0f7d508/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191226212025-6b505debf4bc/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117215004-fe56e6335763/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200216192241-b320d3a0f5a2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= @@ -2989,7 +2906,6 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.11-0.20220513221640-090b14e8501f/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= @@ -3246,6 +3162,7 @@ google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOl google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/genproto v0.0.0-20230525154841-bd750badd5c6/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY= google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc h1:8DyZCyvI8mE1IdLy/60bS+52xfymkE72wv1asokgtao= google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= @@ -3389,8 +3306,6 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -honnef.co/go/tools v0.3.2 h1:ytYb4rOqyp1TSa2EPvNVwtPQJctSELKaMyLfqNP4+34= -honnef.co/go/tools v0.3.2/go.mod h1:jzwdWgg7Jdq75wlfblQxO4neNaFFSvgc1tD5Wv8U0Yw= k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= diff --git a/hack/cadence.sh b/hack/cadence.sh deleted file mode 100755 index ce73b1e1..00000000 --- a/hack/cadence.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o pipefail -set -o nounset - -__cur="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -__root="$(cd "$(dirname "${__cur}")" && pwd)" - -CADENCE_CLI_DOCKER_IMAGE=ubercadence/cli:0.21.3 - -docker run -it \ - --network=host --rm \ - --env CADENCE_CLI_ADDRESS=127.0.0.1:7400 \ - --env CADENCE_CLI_DOMAIN=enduro \ - ${CADENCE_CLI_DOCKER_IMAGE} $@ diff --git a/hack/cadence/config.yml b/hack/cadence/config.yml deleted file mode 100644 index 9f2b04af..00000000 --- a/hack/cadence/config.yml +++ /dev/null @@ -1,111 +0,0 @@ -log: - level: "info" - -services: - frontend: - rpc: - port: 7400 - bindOnLocalHost: false - metrics: - prometheus: - timerType: "histogram" - listenAddress: "127.0.0.1:7401" - pprof: - port: 7402 - matching: - rpc: - port: 7410 - bindOnLocalHost: false - metrics: - prometheus: - timerType: "histogram" - listenAddress: "127.0.0.1:7411" - pprof: - port: 7412 - history: - rpc: - port: 7420 - bindOnLocalHost: false - metrics: - prometheus: - timerType: "histogram" - listenAddress: "127.0.0.1:7421" - pprof: - port: 7422 - worker: - rpc: - port: 7430 - bindOnLocalHost: false - metrics: - prometheus: - timerType: "histogram" - listenAddress: "127.0.0.1:7431" - pprof: - port: 7432 - -ringpop: - name: "cadence" - bootstrapMode: "hosts" - bootstrapHosts: - - "cadence:7400" - - "cadence:7410" - - "cadence:7420" - - "cadence:7430" - maxJoinDuration: "10s" - -clusterMetadata: - enableGlobalDomain: false - failoverVersionIncrement: 10 - masterClusterName: "active" - currentClusterName: "active" - clusterInformation: - active: - enabled: true - initialFailoverVersion: 0 - rpcName: "cadence-frontend" - rpcAddress: "127.0.0.1:7400" - -publicClient: - hostPort: "localhost:7400" - -persistence: - defaultStore: "default" - visibilityStore: "visibility" - numHistoryShards: 4 - datastores: - default: - sql: - driverName: "mysql" - databaseName: "cadence" - connectAddr: "mysql:3306" - connectProtocol: "tcp" - user: "enduro" - password: "enduro123" - visibility: - sql: - driverName: "mysql" - databaseName: "cadence_visibility" - connectAddr: "mysql:3306" - connectProtocol: "tcp" - user: "enduro" - password: "enduro123" - -archival: - history: - status: "enabled" - enableRead: true - provider: - filestore: - fileMode: "0666" - dirMode: "0766" - visibility: - status: "disabled" - enableRead: false - -domainDefaults: - archival: - history: - status: "enabled" - URI: "file:///tmp/cadence_archival_history/development" - visibility: - status: "disabled" diff --git a/hack/cadence/seed.sh b/hack/cadence/seed.sh deleted file mode 100755 index de2096d9..00000000 --- a/hack/cadence/seed.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -set -e -set -x - -SCHEMA_DIR="/etc/cadence/schema/mysql/v57/cadence/versioned" -VISIBILITY_SCHEMA_DIR="/etc/cadence/schema/mysql/v57/visibility/versioned" -DBNAME="cadence" -VISIBILITY_DBNAME="cadence_visibility" -MYSQL_ADDR="mysql" -MYSQL_USER="root" -MYSQL_PWD="root123" - -cadence-sql-tool --ep $MYSQL_ADDR -u $MYSQL_USER --pw $MYSQL_PWD --db $DBNAME setup-schema -v 0.0 -cadence-sql-tool --ep $MYSQL_ADDR -u $MYSQL_USER --pw $MYSQL_PWD --db $DBNAME update-schema -d $SCHEMA_DIR -cadence-sql-tool --ep $MYSQL_ADDR -u $MYSQL_USER --pw $MYSQL_PWD --db $VISIBILITY_DBNAME setup-schema -v 0.0 -cadence-sql-tool --ep $MYSQL_ADDR -u $MYSQL_USER --pw $MYSQL_PWD --db $VISIBILITY_DBNAME update-schema -d $VISIBILITY_SCHEMA_DIR diff --git a/hack/docker-init-mysql.sql b/hack/docker-init-mysql.sql index 7afcab88..09f5206a 100644 --- a/hack/docker-init-mysql.sql +++ b/hack/docker-init-mysql.sql @@ -1,8 +1,2 @@ CREATE DATABASE IF NOT EXISTS enduro; GRANT ALL PRIVILEGES ON enduro.* TO 'enduro'@'%'; - -CREATE DATABASE IF NOT EXISTS cadence; -GRANT ALL PRIVILEGES ON cadence.* TO 'enduro'@'%'; - -CREATE DATABASE IF NOT EXISTS cadence_visibility; -GRANT ALL PRIVILEGES ON cadence_visibility.* TO 'enduro'@'%'; diff --git a/hack/tctl.sh b/hack/tctl.sh new file mode 100755 index 00000000..8be96091 --- /dev/null +++ b/hack/tctl.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -o errexit +set -o pipefail +set -o nounset + +docker compose exec temporal-admin-tools tctl $@ diff --git a/internal/api/design/collection.go b/internal/api/design/collection.go index 5820ef6a..33ac8d3d 100644 --- a/internal/api/design/collection.go +++ b/internal/api/design/collection.go @@ -283,7 +283,7 @@ var WorkflowStatus = ResultType("application/vnd.enduro.collection-workflow-stat }) var WorkflowHistoryEvent = ResultType("application/vnd.enduro.collection-workflow-history", func() { - Description("WorkflowHistoryEvent describes a history event in Cadence.") + Description("WorkflowHistoryEvent describes a history event in Temporal.") Attributes(func() { Attribute("id", UInt, "Identifier of collection") Attribute("type", String, "Type of the event") diff --git a/internal/api/gen/collection/service.go b/internal/api/gen/collection/service.go index d0481643..cb3597ae 100644 --- a/internal/api/gen/collection/service.go +++ b/internal/api/gen/collection/service.go @@ -126,7 +126,7 @@ type DownloadPayload struct { ID uint } -// WorkflowHistoryEvent describes a history event in Cadence. +// WorkflowHistoryEvent describes a history event in Temporal. type EnduroCollectionWorkflowHistory struct { // Identifier of collection ID *uint diff --git a/internal/api/gen/http/cli/enduro/cli.go b/internal/api/gen/http/cli/enduro/cli.go index 8e7a449b..9533173d 100644 --- a/internal/api/gen/http/cli/enduro/cli.go +++ b/internal/api/gen/http/cli/enduro/cli.go @@ -368,7 +368,7 @@ Show pipeline by ID -id STRING: Identifier of pipeline to show Example: - %[1]s pipeline show --id "d07f4165-11a8-11ee-ade5-7085c27bdeb0" + %[1]s pipeline show --id "3aa29fec-1c21-11ee-bb08-7085c27bdeb0" `, os.Args[0]) } @@ -379,7 +379,7 @@ List all processing configurations of a pipeline given its ID -id STRING: Identifier of pipeline Example: - %[1]s pipeline processing --id "d07f5dac-11a8-11ee-ade5-7085c27bdeb0" + %[1]s pipeline processing --id "3aa2b5c8-1c21-11ee-bb08-7085c27bdeb0" `, os.Args[0]) } @@ -484,7 +484,7 @@ List all stored collections -cursor STRING: Example: - %[1]s collection list --name "Laudantium eos fugiat iure sit ea." --original-id "Et dolor ullam consequatur dignissimos." --transfer-id "d07c5264-11a8-11ee-ade5-7085c27bdeb0" --aip-id "d07c5451-11a8-11ee-ade5-7085c27bdeb0" --pipeline-id "d07c5618-11a8-11ee-ade5-7085c27bdeb0" --earliest-created-time "1996-05-01T14:23:24Z" --latest-created-time "1987-02-15T23:56:43Z" --status "error" --cursor "Sit et inventore et." + %[1]s collection list --name "Laudantium eos fugiat iure sit ea." --original-id "Et dolor ullam consequatur dignissimos." --transfer-id "3aa19814-1c21-11ee-bb08-7085c27bdeb0" --aip-id "3aa199c9-1c21-11ee-bb08-7085c27bdeb0" --pipeline-id "3aa19b92-1c21-11ee-bb08-7085c27bdeb0" --earliest-created-time "1996-05-01T14:23:24Z" --latest-created-time "1987-02-15T23:56:43Z" --status "error" --cursor "Sit et inventore et." `, os.Args[0]) } diff --git a/internal/api/gen/http/openapi.json b/internal/api/gen/http/openapi.json index 5b4efa49..b3f50f94 100644 --- a/internal/api/gen/http/openapi.json +++ b/internal/api/gen/http/openapi.json @@ -1 +1 @@ -{"swagger":"2.0","info":{"title":"Enduro API","version":""},"host":"localhost:9000","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/batch":{"get":{"tags":["batch"],"summary":"status batch","description":"Retrieve status of current batch operation.","operationId":"batch#status","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/BatchStatusResponseBody","required":["running"]}}},"schemes":["http"]},"post":{"tags":["batch"],"summary":"submit batch","description":"Submit a new batch","operationId":"batch#submit","parameters":[{"name":"SubmitRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/BatchSubmitRequestBody","required":["path"]}}],"responses":{"202":{"description":"Accepted response.","schema":{"$ref":"#/definitions/BatchSubmitResponseBody","required":["workflow_id","run_id"]}},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/BatchSubmitNotValidResponseBody"}},"409":{"description":"Conflict response.","schema":{"$ref":"#/definitions/BatchSubmitNotAvailableResponseBody"}}},"schemes":["http"]}},"/batch/hints":{"get":{"tags":["batch"],"summary":"hints batch","description":"Retrieve form hints","operationId":"batch#hints","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/BatchHintsResponseBody"}}},"schemes":["http"]}},"/collection":{"get":{"tags":["collection"],"summary":"list collection","description":"List all stored collections","operationId":"collection#list","parameters":[{"name":"name","in":"query","required":false,"type":"string"},{"name":"original_id","in":"query","required":false,"type":"string"},{"name":"transfer_id","in":"query","required":false,"type":"string","format":"uuid"},{"name":"aip_id","in":"query","required":false,"type":"string","format":"uuid"},{"name":"pipeline_id","in":"query","required":false,"type":"string","format":"uuid"},{"name":"earliest_created_time","in":"query","required":false,"type":"string","format":"date-time"},{"name":"latest_created_time","in":"query","required":false,"type":"string","format":"date-time"},{"name":"status","in":"query","required":false,"type":"string","enum":["new","in progress","done","error","unknown","queued","pending","abandoned"]},{"name":"cursor","in":"query","description":"Pagination cursor","required":false,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/CollectionListResponseBody","required":["items"]}}},"schemes":["http"]}},"/collection/bulk":{"get":{"tags":["collection"],"summary":"bulk_status collection","description":"Retrieve status of current bulk operation.","operationId":"collection#bulk_status","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/CollectionBulkStatusResponseBody","required":["running"]}}},"schemes":["http"]},"post":{"tags":["collection"],"summary":"bulk collection","description":"Bulk operations (retry, cancel...).","operationId":"collection#bulk","parameters":[{"name":"BulkRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/CollectionBulkRequestBody","required":["operation","status"]}}],"responses":{"202":{"description":"Accepted response.","schema":{"$ref":"#/definitions/CollectionBulkResponseBody","required":["workflow_id","run_id"]}},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/CollectionBulkNotValidResponseBody"}},"409":{"description":"Conflict response.","schema":{"$ref":"#/definitions/CollectionBulkNotAvailableResponseBody"}}},"schemes":["http"]}},"/collection/monitor":{"get":{"tags":["collection"],"summary":"monitor collection","operationId":"collection#monitor","responses":{"101":{"description":"Switching Protocols response.","schema":{"$ref":"#/definitions/CollectionMonitorResponseBody"}}},"schemes":["ws"]}},"/collection/{id}":{"get":{"tags":["collection"],"summary":"show collection","description":"Show collection by ID","operationId":"collection#show","parameters":[{"name":"id","in":"path","description":"Identifier of collection to show","required":true,"type":"integer"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/CollectionShowResponseBody"}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/CollectionShowNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]},"delete":{"tags":["collection"],"summary":"delete collection","description":"Delete collection by ID","operationId":"collection#delete","parameters":[{"name":"id","in":"path","description":"Identifier of collection to delete","required":true,"type":"integer"}],"responses":{"204":{"description":"No Content response."},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/CollectionDeleteNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/collection/{id}/cancel":{"post":{"tags":["collection"],"summary":"cancel collection","description":"Cancel collection processing by ID","operationId":"collection#cancel","parameters":[{"name":"id","in":"path","description":"Identifier of collection to remove","required":true,"type":"integer"}],"responses":{"200":{"description":"OK response."},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/CollectionCancelNotRunningResponseBody"}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/CollectionCancelNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/collection/{id}/decision":{"post":{"tags":["collection"],"summary":"decide collection","description":"Make decision for a pending collection by ID","operationId":"collection#decide","parameters":[{"name":"id","in":"path","description":"Identifier of collection to look up","required":true,"type":"integer"},{"name":"object","in":"body","required":true,"schema":{"type":"object","properties":{"option":{"type":"string","description":"Decision option to proceed with","example":"Maiores aliquid voluptate necessitatibus iure sunt."}}}}],"responses":{"200":{"description":"OK response."},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/CollectionDecideNotValidResponseBody"}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/CollectionDecideNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/collection/{id}/download":{"get":{"tags":["collection"],"summary":"download collection","description":"Download collection by ID","operationId":"collection#download","parameters":[{"name":"id","in":"path","description":"Identifier of collection to look up","required":true,"type":"integer"}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"byte"}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/CollectionDownloadNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/collection/{id}/retry":{"post":{"tags":["collection"],"summary":"retry collection","description":"Retry collection processing by ID","operationId":"collection#retry","parameters":[{"name":"id","in":"path","description":"Identifier of collection to retry","required":true,"type":"integer"}],"responses":{"200":{"description":"OK response."},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/CollectionRetryNotRunningResponseBody"}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/CollectionRetryNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/collection/{id}/workflow":{"get":{"tags":["collection"],"summary":"workflow collection","description":"Retrieve workflow status by ID","operationId":"collection#workflow","parameters":[{"name":"id","in":"path","description":"Identifier of collection to look up","required":true,"type":"integer"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/CollectionWorkflowResponseBody"}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/CollectionWorkflowNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/pipeline":{"get":{"tags":["pipeline"],"summary":"list pipeline","description":"List all known pipelines","operationId":"pipeline#list","parameters":[{"name":"name","in":"query","required":false,"type":"string"},{"name":"status","in":"query","required":false,"type":"boolean","default":false}],"responses":{"200":{"description":"OK response.","schema":{"type":"array","items":{"$ref":"#/definitions/EnduroStoredPipelineResponse"}}}},"schemes":["http"]}},"/pipeline/{id}":{"get":{"tags":["pipeline"],"summary":"show pipeline","description":"Show pipeline by ID","operationId":"pipeline#show","parameters":[{"name":"id","in":"path","description":"Identifier of pipeline to show","required":true,"type":"string","format":"uuid"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/PipelineShowResponseBody"}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/PipelineShowNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/pipeline/{id}/processing":{"get":{"tags":["pipeline"],"summary":"processing pipeline","description":"List all processing configurations of a pipeline given its ID","operationId":"pipeline#processing","parameters":[{"name":"id","in":"path","description":"Identifier of pipeline","required":true,"type":"string","format":"uuid"}],"responses":{"200":{"description":"OK response.","schema":{"type":"array","items":{"type":"string","example":"Est praesentium officiis occaecati magnam est veritatis."}}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/PipelineProcessingNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/swagger/swagger.json":{"get":{"tags":["swagger"],"summary":"Download internal/api/gen/http/openapi.json","description":"JSON document containing the API swagger definition.","operationId":"swagger#/swagger/swagger.json","responses":{"200":{"description":"File downloaded","schema":{"type":"file"}}},"schemes":["http"]}}},"definitions":{"BatchHintsResponseBody":{"title":"BatchHintsResponseBody","type":"object","properties":{"completed_dirs":{"type":"array","items":{"type":"string","example":"Eligendi et."},"description":"A list of known values of completedDir used by existing watchers.","example":["Aspernatur enim fuga quam aut sit quo.","Est sed.","Ipsum dolores."]}},"example":{"completed_dirs":["Quibusdam aut magnam itaque occaecati.","Quo deserunt vitae suscipit quia ullam cumque.","Quae porro corporis blanditiis sequi rerum.","Non quas laborum eos."]}},"BatchStatusResponseBody":{"title":"BatchStatusResponseBody","type":"object","properties":{"run_id":{"type":"string","example":"Natus illum laborum."},"running":{"type":"boolean","example":true},"status":{"type":"string","example":"Omnis corporis et sunt ut esse consectetur."},"workflow_id":{"type":"string","example":"Quis accusamus enim consequatur laudantium."}},"example":{"run_id":"Doloribus sit corrupti veniam maiores ducimus.","running":false,"status":"Possimus fuga esse modi aut.","workflow_id":"Et quaerat tempore nostrum aliquid fugiat optio."},"required":["running"]},"BatchSubmitNotAvailableResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":true},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":false}},"description":"submit_not_available_response_body result type (default view)","example":{"fault":true,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"BatchSubmitNotValidResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":false},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":true}},"description":"submit_not_valid_response_body result type (default view)","example":{"fault":false,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":true},"required":["name","id","message","temporary","timeout","fault"]},"BatchSubmitRequestBody":{"title":"BatchSubmitRequestBody","type":"object","properties":{"completed_dir":{"type":"string","example":"Sint omnis dolor quas corrupti."},"path":{"type":"string","example":"Esse qui est."},"pipeline":{"type":"string","example":"Architecto optio."},"processing_config":{"type":"string","example":"Labore iste eveniet."},"retention_period":{"type":"string","example":"Cumque qui facilis omnis."}},"example":{"completed_dir":"Aperiam velit.","path":"Officia voluptate.","pipeline":"Sit sint est qui cum nihil quis.","processing_config":"Sit quibusdam quidem consectetur praesentium.","retention_period":"Nobis delectus."},"required":["path"]},"BatchSubmitResponseBody":{"title":"BatchSubmitResponseBody","type":"object","properties":{"run_id":{"type":"string","example":"Fugit ipsam."},"workflow_id":{"type":"string","example":"Aut aliquid enim ex sint laboriosam."}},"example":{"run_id":"Est iure optio suscipit.","workflow_id":"Ab consectetur."},"required":["workflow_id","run_id"]},"CollectionBulkNotAvailableResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":true}},"description":"bulk_not_available_response_body result type (default view)","example":{"fault":true,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":false,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"CollectionBulkNotValidResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":true},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":false},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":true}},"description":"bulk_not_valid_response_body result type (default view)","example":{"fault":true,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"CollectionBulkRequestBody":{"title":"CollectionBulkRequestBody","type":"object","properties":{"operation":{"type":"string","example":"abandon","enum":["retry","cancel","abandon"]},"size":{"type":"integer","default":100,"example":6372128085676335385,"format":"int64"},"status":{"type":"string","example":"pending","enum":["new","in progress","done","error","unknown","queued","pending","abandoned"]}},"example":{"operation":"retry","size":17066834106240065650,"status":"queued"},"required":["operation","status"]},"CollectionBulkResponseBody":{"title":"CollectionBulkResponseBody","type":"object","properties":{"run_id":{"type":"string","example":"Aut et."},"workflow_id":{"type":"string","example":"Voluptate minima."}},"example":{"run_id":"Facere omnis ab nihil magni.","workflow_id":"Harum quia."},"required":["workflow_id","run_id"]},"CollectionBulkStatusResponseBody":{"title":"CollectionBulkStatusResponseBody","type":"object","properties":{"closed_at":{"type":"string","example":"2000-07-10T03:42:21Z","format":"date-time"},"run_id":{"type":"string","example":"Quia odit."},"running":{"type":"boolean","example":false},"started_at":{"type":"string","example":"1977-11-07T02:10:43Z","format":"date-time"},"status":{"type":"string","example":"Ratione voluptatem nesciunt."},"workflow_id":{"type":"string","example":"Nihil veniam ipsa a et."}},"example":{"closed_at":"1987-12-11T01:45:20Z","run_id":"Culpa et.","running":false,"started_at":"1971-03-02T17:29:30Z","status":"Vel consequatur ut cum velit cumque quo.","workflow_id":"Inventore sit cumque necessitatibus soluta sapiente deleniti."},"required":["running"]},"CollectionCancelNotFoundResponseBody":{"title":"CollectionCancelNotFoundResponseBody","type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":8281239400323966825,"format":"int64"},"message":{"type":"string","description":"Message of error","example":"Quia et dolores rerum."}},"description":"Collection not found","example":{"id":7484765762935055342,"message":"Facilis exercitationem ducimus architecto magnam asperiores."},"required":["message","id"]},"CollectionCancelNotRunningResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":true}},"description":"cancel_not_running_response_body result type (default view)","example":{"fault":true,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":true},"required":["name","id","message","temporary","timeout","fault"]},"CollectionDecideNotFoundResponseBody":{"title":"CollectionDecideNotFoundResponseBody","type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":15909502977177845960,"format":"int64"},"message":{"type":"string","description":"Message of error","example":"Sed nam aliquid."}},"description":"Collection not found","example":{"id":10992204314310215240,"message":"Dignissimos accusamus distinctio omnis qui quidem."},"required":["message","id"]},"CollectionDecideNotValidResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":false},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":false}},"description":"decide_not_valid_response_body result type (default view)","example":{"fault":false,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":true},"required":["name","id","message","temporary","timeout","fault"]},"CollectionDeleteNotFoundResponseBody":{"title":"CollectionDeleteNotFoundResponseBody","type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":15719896702208706234,"format":"int64"},"message":{"type":"string","description":"Message of error","example":"Deserunt provident provident repellendus voluptatem exercitationem atque."}},"description":"Collection not found","example":{"id":10629914060260803936,"message":"Non dicta culpa id dolorem consequuntur fuga."},"required":["message","id"]},"CollectionDownloadNotFoundResponseBody":{"title":"CollectionDownloadNotFoundResponseBody","type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":3143202457039915320,"format":"int64"},"message":{"type":"string","description":"Message of error","example":"Et expedita distinctio voluptatem et."}},"description":"Collection not found","example":{"id":810008205606960290,"message":"Vel assumenda."},"required":["message","id"]},"CollectionListResponseBody":{"title":"CollectionListResponseBody","type":"object","properties":{"items":{"$ref":"#/definitions/EnduroStoredCollectionResponseBodyCollection"},"next_cursor":{"type":"string","example":"Cum in aliquam aliquid non tempore vel."}},"example":{"items":[{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"},{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"},{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"},{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"}],"next_cursor":"Non cupiditate."},"required":["items"]},"CollectionMonitorResponseBody":{"title":"Mediatype identifier: application/vnd.enduro.monitor-update; view=default","type":"object","properties":{"id":{"type":"integer","description":"Identifier of collection","example":17877819967277681986,"format":"int64"},"item":{"$ref":"#/definitions/EnduroStoredCollectionResponseBody"},"type":{"type":"string","description":"Type of the event","example":"Et qui expedita asperiores et."}},"description":"MonitorResponseBody result type (default view)","example":{"id":2274206577310456200,"item":{"aip_id":"d07b2f9b-11a8-11ee-ade5-7085c27bdeb0","completed_at":"1997-08-27T00:00:04Z","created_at":"1989-09-24T08:53:28Z","id":4957819645449742263,"name":"Labore totam harum repellat.","original_id":"Nostrum delectus dolor nisi.","pipeline_id":"d07c1db6-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07b2a3c-11a8-11ee-ade5-7085c27bdeb0","started_at":"1998-02-12T04:24:46Z","status":"unknown","transfer_id":"d07b2cc3-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07b27e7-11a8-11ee-ade5-7085c27bdeb0"},"type":"Quam vitae odio non laborum."},"required":["id","type"]},"CollectionRetryNotFoundResponseBody":{"title":"CollectionRetryNotFoundResponseBody","type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":1376202291394847879,"format":"int64"},"message":{"type":"string","description":"Message of error","example":"Quasi nihil corrupti repellat aut quibusdam."}},"description":"Collection not found","example":{"id":17034853208141038925,"message":"Magnam culpa."},"required":["message","id"]},"CollectionRetryNotRunningResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":true},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":false}},"description":"retry_not_running_response_body result type (default view)","example":{"fault":true,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":false,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"CollectionShowNotFoundResponseBody":{"title":"CollectionShowNotFoundResponseBody","type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":17409311576880797983,"format":"int64"},"message":{"type":"string","description":"Message of error","example":"Expedita aut."}},"description":"Collection not found","example":{"id":9420818705968035943,"message":"Nisi amet in accusamus eum dolores."},"required":["message","id"]},"CollectionShowResponseBody":{"title":"Mediatype identifier: application/vnd.enduro.stored-collection; view=default","type":"object","properties":{"aip_id":{"type":"string","description":"Identifier of Archivematica AIP","example":"d07fcb90-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"completed_at":{"type":"string","description":"Completion datetime","example":"2011-05-16T16:36:29Z","format":"date-time"},"created_at":{"type":"string","description":"Creation datetime","example":"1973-03-21T19:25:16Z","format":"date-time"},"id":{"type":"integer","description":"Identifier of collection","example":15649628273186382483,"format":"int64"},"name":{"type":"string","description":"Name of the collection","example":"Voluptatem cum incidunt voluptatem error adipisci."},"original_id":{"type":"string","description":"Identifier provided by the client","example":"Voluptate consequatur illo."},"pipeline_id":{"type":"string","description":"Identifier of Archivematica pipeline","example":"d07fcd1d-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"run_id":{"type":"string","description":"Identifier of latest processing workflow run","example":"d07fc90e-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"started_at":{"type":"string","description":"Start datetime","example":"2001-08-02T19:18:49Z","format":"date-time"},"status":{"type":"string","description":"Status of the collection","default":"new","example":"new","enum":["new","in progress","done","error","unknown","queued","pending","abandoned"]},"transfer_id":{"type":"string","description":"Identifier of Archivematica transfer","example":"d07fca5f-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"workflow_id":{"type":"string","description":"Identifier of processing workflow","example":"d07fc7ae-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"}},"description":"ShowResponseBody result type (default view)","example":{"aip_id":"d07fd5ca-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2005-09-09T14:24:39Z","created_at":"2007-10-14T22:27:23Z","id":9029712482372070690,"name":"Ipsam adipisci voluptas fugit aut.","original_id":"Consequatur magnam.","pipeline_id":"d07fd708-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07fd380-11a8-11ee-ade5-7085c27bdeb0","started_at":"1972-09-08T06:52:05Z","status":"pending","transfer_id":"d07fd4a7-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07fd24e-11a8-11ee-ade5-7085c27bdeb0"},"required":["id","status","created_at"]},"CollectionWorkflowNotFoundResponseBody":{"title":"CollectionWorkflowNotFoundResponseBody","type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":5069398403880905247,"format":"int64"},"message":{"type":"string","description":"Message of error","example":"Iusto modi quis distinctio."}},"description":"Collection not found","example":{"id":6957179250620142883,"message":"A a odit architecto quisquam nisi recusandae."},"required":["message","id"]},"CollectionWorkflowResponseBody":{"title":"Mediatype identifier: application/vnd.enduro.collection-workflow-status; view=default","type":"object","properties":{"history":{"$ref":"#/definitions/EnduroCollectionWorkflowHistoryResponseBodyCollection"},"status":{"type":"string","example":"Aut voluptatibus."}},"description":"WorkflowResponseBody result type (default view)","example":{"history":[{"details":"Ut eveniet et rerum nemo corporis.","id":9720827093168823906,"type":"Omnis doloremque sint dolorum quasi ex labore."},{"details":"Ut eveniet et rerum nemo corporis.","id":9720827093168823906,"type":"Omnis doloremque sint dolorum quasi ex labore."},{"details":"Ut eveniet et rerum nemo corporis.","id":9720827093168823906,"type":"Omnis doloremque sint dolorum quasi ex labore."},{"details":"Ut eveniet et rerum nemo corporis.","id":9720827093168823906,"type":"Omnis doloremque sint dolorum quasi ex labore."}],"status":"Explicabo perferendis sunt quas eos odio aut."}},"EnduroCollectionWorkflowHistoryResponseBody":{"title":"Mediatype identifier: application/vnd.enduro.collection-workflow-history; view=default","type":"object","properties":{"details":{"type":"string","description":"Contents of the event","example":"Quis itaque.","format":"binary"},"id":{"type":"integer","description":"Identifier of collection","example":13704534446480092276,"format":"int64"},"type":{"type":"string","description":"Type of the event","example":"Quaerat voluptatum necessitatibus non cum."}},"description":"WorkflowHistoryEvent describes a history event in Cadence. (default view)","example":{"details":"Quibusdam natus aut animi praesentium cupiditate.","id":4511670572085541767,"type":"Quasi dolor veritatis voluptatem dicta."}},"EnduroCollectionWorkflowHistoryResponseBodyCollection":{"title":"Mediatype identifier: application/vnd.enduro.collection-workflow-history; type=collection; view=default","type":"array","items":{"$ref":"#/definitions/EnduroCollectionWorkflowHistoryResponseBody"},"description":"EnduroCollection-Workflow-HistoryCollectionResponseBody is the result type for an array of EnduroCollection-Workflow-HistoryResponseBody (default view)","example":[{"details":"Ut eveniet et rerum nemo corporis.","id":9720827093168823906,"type":"Omnis doloremque sint dolorum quasi ex labore."},{"details":"Ut eveniet et rerum nemo corporis.","id":9720827093168823906,"type":"Omnis doloremque sint dolorum quasi ex labore."},{"details":"Ut eveniet et rerum nemo corporis.","id":9720827093168823906,"type":"Omnis doloremque sint dolorum quasi ex labore."}]},"EnduroStoredCollectionResponseBody":{"title":"Mediatype identifier: application/vnd.enduro.stored-collection; view=default","type":"object","properties":{"aip_id":{"type":"string","description":"Identifier of Archivematica AIP","example":"d07fae89-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"completed_at":{"type":"string","description":"Completion datetime","example":"1978-11-18T10:22:37Z","format":"date-time"},"created_at":{"type":"string","description":"Creation datetime","example":"1992-11-28T22:46:05Z","format":"date-time"},"id":{"type":"integer","description":"Identifier of collection","example":16783261364902862921,"format":"int64"},"name":{"type":"string","description":"Name of the collection","example":"Quia ut commodi nihil."},"original_id":{"type":"string","description":"Identifier provided by the client","example":"Dolores ipsam facilis adipisci."},"pipeline_id":{"type":"string","description":"Identifier of Archivematica pipeline","example":"d07faff9-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"run_id":{"type":"string","description":"Identifier of latest processing workflow run","example":"d07fabe6-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"started_at":{"type":"string","description":"Start datetime","example":"1974-07-18T05:21:30Z","format":"date-time"},"status":{"type":"string","description":"Status of the collection","default":"new","example":"queued","enum":["new","in progress","done","error","unknown","queued","pending","abandoned"]},"transfer_id":{"type":"string","description":"Identifier of Archivematica transfer","example":"d07fad35-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"workflow_id":{"type":"string","description":"Identifier of processing workflow","example":"d07faa6f-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"}},"description":"StoredCollection describes a collection retrieved by the service. (default view)","example":{"aip_id":"d07fb942-11a8-11ee-ade5-7085c27bdeb0","completed_at":"1992-09-23T06:18:58Z","created_at":"1983-06-28T18:36:02Z","id":828828406215854043,"name":"Nostrum aut deserunt.","original_id":"Animi praesentium omnis dignissimos cumque omnis.","pipeline_id":"d07fba9b-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07fb6a5-11a8-11ee-ade5-7085c27bdeb0","started_at":"2007-09-04T21:44:52Z","status":"unknown","transfer_id":"d07fb801-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07fb56e-11a8-11ee-ade5-7085c27bdeb0"},"required":["id","status","created_at"]},"EnduroStoredCollectionResponseBodyCollection":{"title":"Mediatype identifier: application/vnd.enduro.stored-collection; type=collection; view=default","type":"array","items":{"$ref":"#/definitions/EnduroStoredCollectionResponseBody"},"description":"EnduroStored-CollectionCollectionResponseBody is the result type for an array of EnduroStored-CollectionResponseBody (default view)","example":[{"aip_id":"d07b2f9b-11a8-11ee-ade5-7085c27bdeb0","completed_at":"1997-08-27T00:00:04Z","created_at":"1989-09-24T08:53:28Z","id":4957819645449742263,"name":"Labore totam harum repellat.","original_id":"Nostrum delectus dolor nisi.","pipeline_id":"d07c1db6-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07b2a3c-11a8-11ee-ade5-7085c27bdeb0","started_at":"1998-02-12T04:24:46Z","status":"unknown","transfer_id":"d07b2cc3-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07b27e7-11a8-11ee-ade5-7085c27bdeb0"},{"aip_id":"d07b2f9b-11a8-11ee-ade5-7085c27bdeb0","completed_at":"1997-08-27T00:00:04Z","created_at":"1989-09-24T08:53:28Z","id":4957819645449742263,"name":"Labore totam harum repellat.","original_id":"Nostrum delectus dolor nisi.","pipeline_id":"d07c1db6-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07b2a3c-11a8-11ee-ade5-7085c27bdeb0","started_at":"1998-02-12T04:24:46Z","status":"unknown","transfer_id":"d07b2cc3-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07b27e7-11a8-11ee-ade5-7085c27bdeb0"},{"aip_id":"d07b2f9b-11a8-11ee-ade5-7085c27bdeb0","completed_at":"1997-08-27T00:00:04Z","created_at":"1989-09-24T08:53:28Z","id":4957819645449742263,"name":"Labore totam harum repellat.","original_id":"Nostrum delectus dolor nisi.","pipeline_id":"d07c1db6-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07b2a3c-11a8-11ee-ade5-7085c27bdeb0","started_at":"1998-02-12T04:24:46Z","status":"unknown","transfer_id":"d07b2cc3-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07b27e7-11a8-11ee-ade5-7085c27bdeb0"}]},"EnduroStoredPipelineResponse":{"title":"Mediatype identifier: application/vnd.enduro.stored-pipeline; view=default","type":"object","properties":{"capacity":{"type":"integer","description":"Maximum concurrent transfers","example":6985482064020189961,"format":"int64"},"current":{"type":"integer","description":"Current transfers","example":3701726448145747138,"format":"int64"},"id":{"type":"string","description":"Identifier of the pipeline","example":"d08013c1-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"name":{"type":"string","description":"Name of the pipeline","example":"Veniam totam."},"status":{"type":"string","example":"Qui ipsa."}},"description":"StoredPipeline describes a pipeline retrieved by this service. (default view)","example":{"capacity":7322691743128068194,"current":72660884889227336,"id":"d08016b4-11a8-11ee-ade5-7085c27bdeb0","name":"Tempore et eligendi laudantium ea illo hic.","status":"Id minima velit provident explicabo consequatur."},"required":["name"]},"PipelineProcessingNotFoundResponseBody":{"title":"PipelineProcessingNotFoundResponseBody","type":"object","properties":{"id":{"type":"string","description":"Identifier of missing pipeline","example":"Inventore impedit voluptates vel omnis id."},"message":{"type":"string","description":"Message of error","example":"Autem adipisci suscipit distinctio qui harum totam."}},"description":"Pipeline not found","example":{"id":"Inventore hic voluptates eos distinctio sed.","message":"Quia praesentium incidunt."},"required":["message","id"]},"PipelineShowNotFoundResponseBody":{"title":"PipelineShowNotFoundResponseBody","type":"object","properties":{"id":{"type":"string","description":"Identifier of missing pipeline","example":"Ut tenetur dolorum error aut quibusdam."},"message":{"type":"string","description":"Message of error","example":"Veniam omnis dolores sed."}},"description":"Pipeline not found","example":{"id":"Sed sunt molestiae animi et aliquid voluptatem.","message":"Ut hic."},"required":["message","id"]},"PipelineShowResponseBody":{"title":"Mediatype identifier: application/vnd.enduro.stored-pipeline; view=default","type":"object","properties":{"capacity":{"type":"integer","description":"Maximum concurrent transfers","example":4612770856566959488,"format":"int64"},"current":{"type":"integer","description":"Current transfers","example":1302819909344103813,"format":"int64"},"id":{"type":"string","description":"Identifier of the pipeline","example":"d0801ab8-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"name":{"type":"string","description":"Name of the pipeline","example":"Illum autem accusamus."},"status":{"type":"string","example":"Qui tempora itaque illum vitae aliquid quia."}},"description":"ShowResponseBody result type (default view)","example":{"capacity":1349942446066623917,"current":3978574075782434602,"id":"d0801db8-11a8-11ee-ade5-7085c27bdeb0","name":"Eveniet quam consequatur eveniet.","status":"Similique unde molestiae esse consequatur reprehenderit."},"required":["name"]}}} \ No newline at end of file +{"swagger":"2.0","info":{"title":"Enduro API","version":""},"host":"localhost:9000","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/batch":{"get":{"tags":["batch"],"summary":"status batch","description":"Retrieve status of current batch operation.","operationId":"batch#status","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/BatchStatusResponseBody","required":["running"]}}},"schemes":["http"]},"post":{"tags":["batch"],"summary":"submit batch","description":"Submit a new batch","operationId":"batch#submit","parameters":[{"name":"SubmitRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/BatchSubmitRequestBody","required":["path"]}}],"responses":{"202":{"description":"Accepted response.","schema":{"$ref":"#/definitions/BatchSubmitResponseBody","required":["workflow_id","run_id"]}},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/BatchSubmitNotValidResponseBody"}},"409":{"description":"Conflict response.","schema":{"$ref":"#/definitions/BatchSubmitNotAvailableResponseBody"}}},"schemes":["http"]}},"/batch/hints":{"get":{"tags":["batch"],"summary":"hints batch","description":"Retrieve form hints","operationId":"batch#hints","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/BatchHintsResponseBody"}}},"schemes":["http"]}},"/collection":{"get":{"tags":["collection"],"summary":"list collection","description":"List all stored collections","operationId":"collection#list","parameters":[{"name":"name","in":"query","required":false,"type":"string"},{"name":"original_id","in":"query","required":false,"type":"string"},{"name":"transfer_id","in":"query","required":false,"type":"string","format":"uuid"},{"name":"aip_id","in":"query","required":false,"type":"string","format":"uuid"},{"name":"pipeline_id","in":"query","required":false,"type":"string","format":"uuid"},{"name":"earliest_created_time","in":"query","required":false,"type":"string","format":"date-time"},{"name":"latest_created_time","in":"query","required":false,"type":"string","format":"date-time"},{"name":"status","in":"query","required":false,"type":"string","enum":["new","in progress","done","error","unknown","queued","pending","abandoned"]},{"name":"cursor","in":"query","description":"Pagination cursor","required":false,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/CollectionListResponseBody","required":["items"]}}},"schemes":["http"]}},"/collection/bulk":{"get":{"tags":["collection"],"summary":"bulk_status collection","description":"Retrieve status of current bulk operation.","operationId":"collection#bulk_status","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/CollectionBulkStatusResponseBody","required":["running"]}}},"schemes":["http"]},"post":{"tags":["collection"],"summary":"bulk collection","description":"Bulk operations (retry, cancel...).","operationId":"collection#bulk","parameters":[{"name":"BulkRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/CollectionBulkRequestBody","required":["operation","status"]}}],"responses":{"202":{"description":"Accepted response.","schema":{"$ref":"#/definitions/CollectionBulkResponseBody","required":["workflow_id","run_id"]}},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/CollectionBulkNotValidResponseBody"}},"409":{"description":"Conflict response.","schema":{"$ref":"#/definitions/CollectionBulkNotAvailableResponseBody"}}},"schemes":["http"]}},"/collection/monitor":{"get":{"tags":["collection"],"summary":"monitor collection","operationId":"collection#monitor","responses":{"101":{"description":"Switching Protocols response.","schema":{"$ref":"#/definitions/CollectionMonitorResponseBody"}}},"schemes":["ws"]}},"/collection/{id}":{"get":{"tags":["collection"],"summary":"show collection","description":"Show collection by ID","operationId":"collection#show","parameters":[{"name":"id","in":"path","description":"Identifier of collection to show","required":true,"type":"integer"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/CollectionShowResponseBody"}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/CollectionShowNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]},"delete":{"tags":["collection"],"summary":"delete collection","description":"Delete collection by ID","operationId":"collection#delete","parameters":[{"name":"id","in":"path","description":"Identifier of collection to delete","required":true,"type":"integer"}],"responses":{"204":{"description":"No Content response."},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/CollectionDeleteNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/collection/{id}/cancel":{"post":{"tags":["collection"],"summary":"cancel collection","description":"Cancel collection processing by ID","operationId":"collection#cancel","parameters":[{"name":"id","in":"path","description":"Identifier of collection to remove","required":true,"type":"integer"}],"responses":{"200":{"description":"OK response."},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/CollectionCancelNotRunningResponseBody"}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/CollectionCancelNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/collection/{id}/decision":{"post":{"tags":["collection"],"summary":"decide collection","description":"Make decision for a pending collection by ID","operationId":"collection#decide","parameters":[{"name":"id","in":"path","description":"Identifier of collection to look up","required":true,"type":"integer"},{"name":"object","in":"body","required":true,"schema":{"type":"object","properties":{"option":{"type":"string","description":"Decision option to proceed with","example":"Maiores aliquid voluptate necessitatibus iure sunt."}}}}],"responses":{"200":{"description":"OK response."},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/CollectionDecideNotValidResponseBody"}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/CollectionDecideNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/collection/{id}/download":{"get":{"tags":["collection"],"summary":"download collection","description":"Download collection by ID","operationId":"collection#download","parameters":[{"name":"id","in":"path","description":"Identifier of collection to look up","required":true,"type":"integer"}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"byte"}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/CollectionDownloadNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/collection/{id}/retry":{"post":{"tags":["collection"],"summary":"retry collection","description":"Retry collection processing by ID","operationId":"collection#retry","parameters":[{"name":"id","in":"path","description":"Identifier of collection to retry","required":true,"type":"integer"}],"responses":{"200":{"description":"OK response."},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/CollectionRetryNotRunningResponseBody"}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/CollectionRetryNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/collection/{id}/workflow":{"get":{"tags":["collection"],"summary":"workflow collection","description":"Retrieve workflow status by ID","operationId":"collection#workflow","parameters":[{"name":"id","in":"path","description":"Identifier of collection to look up","required":true,"type":"integer"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/CollectionWorkflowResponseBody"}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/CollectionWorkflowNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/pipeline":{"get":{"tags":["pipeline"],"summary":"list pipeline","description":"List all known pipelines","operationId":"pipeline#list","parameters":[{"name":"name","in":"query","required":false,"type":"string"},{"name":"status","in":"query","required":false,"type":"boolean","default":false}],"responses":{"200":{"description":"OK response.","schema":{"type":"array","items":{"$ref":"#/definitions/EnduroStoredPipelineResponse"}}}},"schemes":["http"]}},"/pipeline/{id}":{"get":{"tags":["pipeline"],"summary":"show pipeline","description":"Show pipeline by ID","operationId":"pipeline#show","parameters":[{"name":"id","in":"path","description":"Identifier of pipeline to show","required":true,"type":"string","format":"uuid"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/PipelineShowResponseBody"}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/PipelineShowNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/pipeline/{id}/processing":{"get":{"tags":["pipeline"],"summary":"processing pipeline","description":"List all processing configurations of a pipeline given its ID","operationId":"pipeline#processing","parameters":[{"name":"id","in":"path","description":"Identifier of pipeline","required":true,"type":"string","format":"uuid"}],"responses":{"200":{"description":"OK response.","schema":{"type":"array","items":{"type":"string","example":"Est praesentium officiis occaecati magnam est veritatis."}}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/PipelineProcessingNotFoundResponseBody","required":["message","id"]}}},"schemes":["http"]}},"/swagger/swagger.json":{"get":{"tags":["swagger"],"summary":"Download internal/api/gen/http/openapi.json","description":"JSON document containing the API swagger definition.","operationId":"swagger#/swagger/swagger.json","responses":{"200":{"description":"File downloaded","schema":{"type":"file"}}},"schemes":["http"]}}},"definitions":{"BatchHintsResponseBody":{"title":"BatchHintsResponseBody","type":"object","properties":{"completed_dirs":{"type":"array","items":{"type":"string","example":"Eligendi et."},"description":"A list of known values of completedDir used by existing watchers.","example":["Aspernatur enim fuga quam aut sit quo.","Est sed.","Ipsum dolores."]}},"example":{"completed_dirs":["Quibusdam aut magnam itaque occaecati.","Quo deserunt vitae suscipit quia ullam cumque.","Quae porro corporis blanditiis sequi rerum.","Non quas laborum eos."]}},"BatchStatusResponseBody":{"title":"BatchStatusResponseBody","type":"object","properties":{"run_id":{"type":"string","example":"Natus illum laborum."},"running":{"type":"boolean","example":true},"status":{"type":"string","example":"Omnis corporis et sunt ut esse consectetur."},"workflow_id":{"type":"string","example":"Quis accusamus enim consequatur laudantium."}},"example":{"run_id":"Doloribus sit corrupti veniam maiores ducimus.","running":false,"status":"Possimus fuga esse modi aut.","workflow_id":"Et quaerat tempore nostrum aliquid fugiat optio."},"required":["running"]},"BatchSubmitNotAvailableResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":true},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":false}},"description":"submit_not_available_response_body result type (default view)","example":{"fault":true,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"BatchSubmitNotValidResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":false},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":true}},"description":"submit_not_valid_response_body result type (default view)","example":{"fault":false,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":true},"required":["name","id","message","temporary","timeout","fault"]},"BatchSubmitRequestBody":{"title":"BatchSubmitRequestBody","type":"object","properties":{"completed_dir":{"type":"string","example":"Sint omnis dolor quas corrupti."},"path":{"type":"string","example":"Esse qui est."},"pipeline":{"type":"string","example":"Architecto optio."},"processing_config":{"type":"string","example":"Labore iste eveniet."},"retention_period":{"type":"string","example":"Cumque qui facilis omnis."}},"example":{"completed_dir":"Aperiam velit.","path":"Officia voluptate.","pipeline":"Sit sint est qui cum nihil quis.","processing_config":"Sit quibusdam quidem consectetur praesentium.","retention_period":"Nobis delectus."},"required":["path"]},"BatchSubmitResponseBody":{"title":"BatchSubmitResponseBody","type":"object","properties":{"run_id":{"type":"string","example":"Fugit ipsam."},"workflow_id":{"type":"string","example":"Aut aliquid enim ex sint laboriosam."}},"example":{"run_id":"Est iure optio suscipit.","workflow_id":"Ab consectetur."},"required":["workflow_id","run_id"]},"CollectionBulkNotAvailableResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":true}},"description":"bulk_not_available_response_body result type (default view)","example":{"fault":true,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":false,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"CollectionBulkNotValidResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":true},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":false},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":true}},"description":"bulk_not_valid_response_body result type (default view)","example":{"fault":true,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"CollectionBulkRequestBody":{"title":"CollectionBulkRequestBody","type":"object","properties":{"operation":{"type":"string","example":"abandon","enum":["retry","cancel","abandon"]},"size":{"type":"integer","default":100,"example":6372128085676335385,"format":"int64"},"status":{"type":"string","example":"pending","enum":["new","in progress","done","error","unknown","queued","pending","abandoned"]}},"example":{"operation":"retry","size":17066834106240065650,"status":"queued"},"required":["operation","status"]},"CollectionBulkResponseBody":{"title":"CollectionBulkResponseBody","type":"object","properties":{"run_id":{"type":"string","example":"Aut et."},"workflow_id":{"type":"string","example":"Voluptate minima."}},"example":{"run_id":"Facere omnis ab nihil magni.","workflow_id":"Harum quia."},"required":["workflow_id","run_id"]},"CollectionBulkStatusResponseBody":{"title":"CollectionBulkStatusResponseBody","type":"object","properties":{"closed_at":{"type":"string","example":"2000-07-10T03:42:21Z","format":"date-time"},"run_id":{"type":"string","example":"Quia odit."},"running":{"type":"boolean","example":false},"started_at":{"type":"string","example":"1977-11-07T02:10:43Z","format":"date-time"},"status":{"type":"string","example":"Ratione voluptatem nesciunt."},"workflow_id":{"type":"string","example":"Nihil veniam ipsa a et."}},"example":{"closed_at":"1987-12-11T01:45:20Z","run_id":"Culpa et.","running":false,"started_at":"1971-03-02T17:29:30Z","status":"Vel consequatur ut cum velit cumque quo.","workflow_id":"Inventore sit cumque necessitatibus soluta sapiente deleniti."},"required":["running"]},"CollectionCancelNotFoundResponseBody":{"title":"CollectionCancelNotFoundResponseBody","type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":8281239400323966825,"format":"int64"},"message":{"type":"string","description":"Message of error","example":"Quia et dolores rerum."}},"description":"Collection not found","example":{"id":7484765762935055342,"message":"Facilis exercitationem ducimus architecto magnam asperiores."},"required":["message","id"]},"CollectionCancelNotRunningResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":true}},"description":"cancel_not_running_response_body result type (default view)","example":{"fault":true,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":true},"required":["name","id","message","temporary","timeout","fault"]},"CollectionDecideNotFoundResponseBody":{"title":"CollectionDecideNotFoundResponseBody","type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":15909502977177845960,"format":"int64"},"message":{"type":"string","description":"Message of error","example":"Sed nam aliquid."}},"description":"Collection not found","example":{"id":10992204314310215240,"message":"Dignissimos accusamus distinctio omnis qui quidem."},"required":["message","id"]},"CollectionDecideNotValidResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":false},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":false}},"description":"decide_not_valid_response_body result type (default view)","example":{"fault":false,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":true},"required":["name","id","message","temporary","timeout","fault"]},"CollectionDeleteNotFoundResponseBody":{"title":"CollectionDeleteNotFoundResponseBody","type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":15719896702208706234,"format":"int64"},"message":{"type":"string","description":"Message of error","example":"Deserunt provident provident repellendus voluptatem exercitationem atque."}},"description":"Collection not found","example":{"id":10629914060260803936,"message":"Non dicta culpa id dolorem consequuntur fuga."},"required":["message","id"]},"CollectionDownloadNotFoundResponseBody":{"title":"CollectionDownloadNotFoundResponseBody","type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":3143202457039915320,"format":"int64"},"message":{"type":"string","description":"Message of error","example":"Et expedita distinctio voluptatem et."}},"description":"Collection not found","example":{"id":810008205606960290,"message":"Vel assumenda."},"required":["message","id"]},"CollectionListResponseBody":{"title":"CollectionListResponseBody","type":"object","properties":{"items":{"$ref":"#/definitions/EnduroStoredCollectionResponseBodyCollection"},"next_cursor":{"type":"string","example":"Cum in aliquam aliquid non tempore vel."}},"example":{"items":[{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"},{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"},{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"},{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"}],"next_cursor":"Non cupiditate."},"required":["items"]},"CollectionMonitorResponseBody":{"title":"Mediatype identifier: application/vnd.enduro.monitor-update; view=default","type":"object","properties":{"id":{"type":"integer","description":"Identifier of collection","example":17877819967277681986,"format":"int64"},"item":{"$ref":"#/definitions/EnduroStoredCollectionResponseBody"},"type":{"type":"string","description":"Type of the event","example":"Et qui expedita asperiores et."}},"description":"MonitorResponseBody result type (default view)","example":{"id":2274206577310456200,"item":{"aip_id":"3aa1790a-1c21-11ee-bb08-7085c27bdeb0","completed_at":"1997-08-27T00:00:04Z","created_at":"1989-09-24T08:53:28Z","id":4957819645449742263,"name":"Labore totam harum repellat.","original_id":"Nostrum delectus dolor nisi.","pipeline_id":"3aa17a49-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa17689-1c21-11ee-bb08-7085c27bdeb0","started_at":"1998-02-12T04:24:46Z","status":"unknown","transfer_id":"3aa177ba-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa1753b-1c21-11ee-bb08-7085c27bdeb0"},"type":"Quam vitae odio non laborum."},"required":["id","type"]},"CollectionRetryNotFoundResponseBody":{"title":"CollectionRetryNotFoundResponseBody","type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":1376202291394847879,"format":"int64"},"message":{"type":"string","description":"Message of error","example":"Quasi nihil corrupti repellat aut quibusdam."}},"description":"Collection not found","example":{"id":17034853208141038925,"message":"Magnam culpa."},"required":["message","id"]},"CollectionRetryNotRunningResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":true},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":false}},"description":"retry_not_running_response_body result type (default view)","example":{"fault":true,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":false,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"CollectionShowNotFoundResponseBody":{"title":"CollectionShowNotFoundResponseBody","type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":17409311576880797983,"format":"int64"},"message":{"type":"string","description":"Message of error","example":"Expedita aut."}},"description":"Collection not found","example":{"id":9420818705968035943,"message":"Nisi amet in accusamus eum dolores."},"required":["message","id"]},"CollectionShowResponseBody":{"title":"Mediatype identifier: application/vnd.enduro.stored-collection; view=default","type":"object","properties":{"aip_id":{"type":"string","description":"Identifier of Archivematica AIP","example":"3aa324e2-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"completed_at":{"type":"string","description":"Completion datetime","example":"2011-05-16T16:36:29Z","format":"date-time"},"created_at":{"type":"string","description":"Creation datetime","example":"1973-03-21T19:25:16Z","format":"date-time"},"id":{"type":"integer","description":"Identifier of collection","example":15649628273186382483,"format":"int64"},"name":{"type":"string","description":"Name of the collection","example":"Voluptatem cum incidunt voluptatem error adipisci."},"original_id":{"type":"string","description":"Identifier provided by the client","example":"Voluptate consequatur illo."},"pipeline_id":{"type":"string","description":"Identifier of Archivematica pipeline","example":"3aa32634-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"run_id":{"type":"string","description":"Identifier of latest processing workflow run","example":"3aa3229a-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"started_at":{"type":"string","description":"Start datetime","example":"2001-08-02T19:18:49Z","format":"date-time"},"status":{"type":"string","description":"Status of the collection","default":"new","example":"new","enum":["new","in progress","done","error","unknown","queued","pending","abandoned"]},"transfer_id":{"type":"string","description":"Identifier of Archivematica transfer","example":"3aa323c5-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"workflow_id":{"type":"string","description":"Identifier of processing workflow","example":"3aa32167-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"}},"description":"ShowResponseBody result type (default view)","example":{"aip_id":"3aa32e79-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2005-09-09T14:24:39Z","created_at":"2007-10-14T22:27:23Z","id":9029712482372070690,"name":"Ipsam adipisci voluptas fugit aut.","original_id":"Consequatur magnam.","pipeline_id":"3aa32fc2-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa32c4a-1c21-11ee-bb08-7085c27bdeb0","started_at":"1972-09-08T06:52:05Z","status":"pending","transfer_id":"3aa32d61-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa32b2a-1c21-11ee-bb08-7085c27bdeb0"},"required":["id","status","created_at"]},"CollectionWorkflowNotFoundResponseBody":{"title":"CollectionWorkflowNotFoundResponseBody","type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":5069398403880905247,"format":"int64"},"message":{"type":"string","description":"Message of error","example":"Iusto modi quis distinctio."}},"description":"Collection not found","example":{"id":6957179250620142883,"message":"A a odit architecto quisquam nisi recusandae."},"required":["message","id"]},"CollectionWorkflowResponseBody":{"title":"Mediatype identifier: application/vnd.enduro.collection-workflow-status; view=default","type":"object","properties":{"history":{"$ref":"#/definitions/EnduroCollectionWorkflowHistoryResponseBodyCollection"},"status":{"type":"string","example":"Aut voluptatibus."}},"description":"WorkflowResponseBody result type (default view)","example":{"history":[{"details":"Ut eveniet et rerum nemo corporis.","id":9720827093168823906,"type":"Omnis doloremque sint dolorum quasi ex labore."},{"details":"Ut eveniet et rerum nemo corporis.","id":9720827093168823906,"type":"Omnis doloremque sint dolorum quasi ex labore."},{"details":"Ut eveniet et rerum nemo corporis.","id":9720827093168823906,"type":"Omnis doloremque sint dolorum quasi ex labore."},{"details":"Ut eveniet et rerum nemo corporis.","id":9720827093168823906,"type":"Omnis doloremque sint dolorum quasi ex labore."}],"status":"Explicabo perferendis sunt quas eos odio aut."}},"EnduroCollectionWorkflowHistoryResponseBody":{"title":"Mediatype identifier: application/vnd.enduro.collection-workflow-history; view=default","type":"object","properties":{"details":{"type":"string","description":"Contents of the event","example":"Quis itaque.","format":"binary"},"id":{"type":"integer","description":"Identifier of collection","example":13704534446480092276,"format":"int64"},"type":{"type":"string","description":"Type of the event","example":"Quaerat voluptatum necessitatibus non cum."}},"description":"WorkflowHistoryEvent describes a history event in Temporal. (default view)","example":{"details":"Quibusdam natus aut animi praesentium cupiditate.","id":4511670572085541767,"type":"Quasi dolor veritatis voluptatem dicta."}},"EnduroCollectionWorkflowHistoryResponseBodyCollection":{"title":"Mediatype identifier: application/vnd.enduro.collection-workflow-history; type=collection; view=default","type":"array","items":{"$ref":"#/definitions/EnduroCollectionWorkflowHistoryResponseBody"},"description":"EnduroCollection-Workflow-HistoryCollectionResponseBody is the result type for an array of EnduroCollection-Workflow-HistoryResponseBody (default view)","example":[{"details":"Ut eveniet et rerum nemo corporis.","id":9720827093168823906,"type":"Omnis doloremque sint dolorum quasi ex labore."},{"details":"Ut eveniet et rerum nemo corporis.","id":9720827093168823906,"type":"Omnis doloremque sint dolorum quasi ex labore."},{"details":"Ut eveniet et rerum nemo corporis.","id":9720827093168823906,"type":"Omnis doloremque sint dolorum quasi ex labore."}]},"EnduroStoredCollectionResponseBody":{"title":"Mediatype identifier: application/vnd.enduro.stored-collection; view=default","type":"object","properties":{"aip_id":{"type":"string","description":"Identifier of Archivematica AIP","example":"3aa30d16-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"completed_at":{"type":"string","description":"Completion datetime","example":"1978-11-18T10:22:37Z","format":"date-time"},"created_at":{"type":"string","description":"Creation datetime","example":"1992-11-28T22:46:05Z","format":"date-time"},"id":{"type":"integer","description":"Identifier of collection","example":16783261364902862921,"format":"int64"},"name":{"type":"string","description":"Name of the collection","example":"Quia ut commodi nihil."},"original_id":{"type":"string","description":"Identifier provided by the client","example":"Dolores ipsam facilis adipisci."},"pipeline_id":{"type":"string","description":"Identifier of Archivematica pipeline","example":"3aa30eaf-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"run_id":{"type":"string","description":"Identifier of latest processing workflow run","example":"3aa30a79-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"started_at":{"type":"string","description":"Start datetime","example":"1974-07-18T05:21:30Z","format":"date-time"},"status":{"type":"string","description":"Status of the collection","default":"new","example":"queued","enum":["new","in progress","done","error","unknown","queued","pending","abandoned"]},"transfer_id":{"type":"string","description":"Identifier of Archivematica transfer","example":"3aa30bda-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"workflow_id":{"type":"string","description":"Identifier of processing workflow","example":"3aa30919-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"}},"description":"StoredCollection describes a collection retrieved by the service. (default view)","example":{"aip_id":"3aa317af-1c21-11ee-bb08-7085c27bdeb0","completed_at":"1992-09-23T06:18:58Z","created_at":"1983-06-28T18:36:02Z","id":828828406215854043,"name":"Nostrum aut deserunt.","original_id":"Animi praesentium omnis dignissimos cumque omnis.","pipeline_id":"3aa318dd-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa3154d-1c21-11ee-bb08-7085c27bdeb0","started_at":"2007-09-04T21:44:52Z","status":"unknown","transfer_id":"3aa31673-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa31428-1c21-11ee-bb08-7085c27bdeb0"},"required":["id","status","created_at"]},"EnduroStoredCollectionResponseBodyCollection":{"title":"Mediatype identifier: application/vnd.enduro.stored-collection; type=collection; view=default","type":"array","items":{"$ref":"#/definitions/EnduroStoredCollectionResponseBody"},"description":"EnduroStored-CollectionCollectionResponseBody is the result type for an array of EnduroStored-CollectionResponseBody (default view)","example":[{"aip_id":"3aa1790a-1c21-11ee-bb08-7085c27bdeb0","completed_at":"1997-08-27T00:00:04Z","created_at":"1989-09-24T08:53:28Z","id":4957819645449742263,"name":"Labore totam harum repellat.","original_id":"Nostrum delectus dolor nisi.","pipeline_id":"3aa17a49-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa17689-1c21-11ee-bb08-7085c27bdeb0","started_at":"1998-02-12T04:24:46Z","status":"unknown","transfer_id":"3aa177ba-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa1753b-1c21-11ee-bb08-7085c27bdeb0"},{"aip_id":"3aa1790a-1c21-11ee-bb08-7085c27bdeb0","completed_at":"1997-08-27T00:00:04Z","created_at":"1989-09-24T08:53:28Z","id":4957819645449742263,"name":"Labore totam harum repellat.","original_id":"Nostrum delectus dolor nisi.","pipeline_id":"3aa17a49-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa17689-1c21-11ee-bb08-7085c27bdeb0","started_at":"1998-02-12T04:24:46Z","status":"unknown","transfer_id":"3aa177ba-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa1753b-1c21-11ee-bb08-7085c27bdeb0"},{"aip_id":"3aa1790a-1c21-11ee-bb08-7085c27bdeb0","completed_at":"1997-08-27T00:00:04Z","created_at":"1989-09-24T08:53:28Z","id":4957819645449742263,"name":"Labore totam harum repellat.","original_id":"Nostrum delectus dolor nisi.","pipeline_id":"3aa17a49-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa17689-1c21-11ee-bb08-7085c27bdeb0","started_at":"1998-02-12T04:24:46Z","status":"unknown","transfer_id":"3aa177ba-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa1753b-1c21-11ee-bb08-7085c27bdeb0"}]},"EnduroStoredPipelineResponse":{"title":"Mediatype identifier: application/vnd.enduro.stored-pipeline; view=default","type":"object","properties":{"capacity":{"type":"integer","description":"Maximum concurrent transfers","example":6985482064020189961,"format":"int64"},"current":{"type":"integer","description":"Current transfers","example":3701726448145747138,"format":"int64"},"id":{"type":"string","description":"Identifier of the pipeline","example":"3aa34822-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"name":{"type":"string","description":"Name of the pipeline","example":"Veniam totam."},"status":{"type":"string","example":"Qui ipsa."}},"description":"StoredPipeline describes a pipeline retrieved by this service. (default view)","example":{"capacity":7322691743128068194,"current":72660884889227336,"id":"3aa34991-1c21-11ee-bb08-7085c27bdeb0","name":"Tempore et eligendi laudantium ea illo hic.","status":"Id minima velit provident explicabo consequatur."},"required":["name"]},"PipelineProcessingNotFoundResponseBody":{"title":"PipelineProcessingNotFoundResponseBody","type":"object","properties":{"id":{"type":"string","description":"Identifier of missing pipeline","example":"Inventore impedit voluptates vel omnis id."},"message":{"type":"string","description":"Message of error","example":"Autem adipisci suscipit distinctio qui harum totam."}},"description":"Pipeline not found","example":{"id":"Inventore hic voluptates eos distinctio sed.","message":"Quia praesentium incidunt."},"required":["message","id"]},"PipelineShowNotFoundResponseBody":{"title":"PipelineShowNotFoundResponseBody","type":"object","properties":{"id":{"type":"string","description":"Identifier of missing pipeline","example":"Ut tenetur dolorum error aut quibusdam."},"message":{"type":"string","description":"Message of error","example":"Veniam omnis dolores sed."}},"description":"Pipeline not found","example":{"id":"Sed sunt molestiae animi et aliquid voluptatem.","message":"Ut hic."},"required":["message","id"]},"PipelineShowResponseBody":{"title":"Mediatype identifier: application/vnd.enduro.stored-pipeline; view=default","type":"object","properties":{"capacity":{"type":"integer","description":"Maximum concurrent transfers","example":4612770856566959488,"format":"int64"},"current":{"type":"integer","description":"Current transfers","example":1302819909344103813,"format":"int64"},"id":{"type":"string","description":"Identifier of the pipeline","example":"3aa34bb3-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"name":{"type":"string","description":"Name of the pipeline","example":"Illum autem accusamus."},"status":{"type":"string","example":"Qui tempora itaque illum vitae aliquid quia."}},"description":"ShowResponseBody result type (default view)","example":{"capacity":1349942446066623917,"current":3978574075782434602,"id":"3aa34d72-1c21-11ee-bb08-7085c27bdeb0","name":"Eveniet quam consequatur eveniet.","status":"Similique unde molestiae esse consequatur reprehenderit."},"required":["name"]}}} \ No newline at end of file diff --git a/internal/api/gen/http/openapi.yaml b/internal/api/gen/http/openapi.yaml index bd888382..f3057453 100644 --- a/internal/api/gen/http/openapi.yaml +++ b/internal/api/gen/http/openapi.yaml @@ -1026,54 +1026,54 @@ definitions: example: Cum in aliquam aliquid non tempore vel. example: items: - - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + - aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 - - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 + - aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 - - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 + - aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 - - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 + - aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 next_cursor: Non cupiditate. required: - items @@ -1096,18 +1096,18 @@ definitions: example: id: 2274206577310456200 item: - aip_id: d07b2f9b-11a8-11ee-ade5-7085c27bdeb0 + aip_id: 3aa1790a-1c21-11ee-bb08-7085c27bdeb0 completed_at: "1997-08-27T00:00:04Z" created_at: "1989-09-24T08:53:28Z" id: 4957819645449742263 name: Labore totam harum repellat. original_id: Nostrum delectus dolor nisi. - pipeline_id: d07c1db6-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07b2a3c-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa17a49-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa17689-1c21-11ee-bb08-7085c27bdeb0 started_at: "1998-02-12T04:24:46Z" status: unknown - transfer_id: d07b2cc3-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07b27e7-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa177ba-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa1753b-1c21-11ee-bb08-7085c27bdeb0 type: Quam vitae odio non laborum. required: - id @@ -1202,7 +1202,7 @@ definitions: aip_id: type: string description: Identifier of Archivematica AIP - example: d07fcb90-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa324e2-1c21-11ee-bb08-7085c27bdeb0 format: uuid completed_at: type: string @@ -1230,12 +1230,12 @@ definitions: pipeline_id: type: string description: Identifier of Archivematica pipeline - example: d07fcd1d-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa32634-1c21-11ee-bb08-7085c27bdeb0 format: uuid run_id: type: string description: Identifier of latest processing workflow run - example: d07fc90e-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa3229a-1c21-11ee-bb08-7085c27bdeb0 format: uuid started_at: type: string @@ -1259,27 +1259,27 @@ definitions: transfer_id: type: string description: Identifier of Archivematica transfer - example: d07fca5f-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa323c5-1c21-11ee-bb08-7085c27bdeb0 format: uuid workflow_id: type: string description: Identifier of processing workflow - example: d07fc7ae-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa32167-1c21-11ee-bb08-7085c27bdeb0 format: uuid description: ShowResponseBody result type (default view) example: - aip_id: d07fd5ca-11a8-11ee-ade5-7085c27bdeb0 + aip_id: 3aa32e79-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2005-09-09T14:24:39Z" created_at: "2007-10-14T22:27:23Z" id: 9029712482372070690 name: Ipsam adipisci voluptas fugit aut. original_id: Consequatur magnam. - pipeline_id: d07fd708-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07fd380-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa32fc2-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa32c4a-1c21-11ee-bb08-7085c27bdeb0 started_at: "1972-09-08T06:52:05Z" status: pending - transfer_id: d07fd4a7-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07fd24e-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa32d61-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa32b2a-1c21-11ee-bb08-7085c27bdeb0 required: - id - status @@ -1347,7 +1347,7 @@ definitions: type: string description: Type of the event example: Quaerat voluptatum necessitatibus non cum. - description: WorkflowHistoryEvent describes a history event in Cadence. (default view) + description: WorkflowHistoryEvent describes a history event in Temporal. (default view) example: details: Quibusdam natus aut animi praesentium cupiditate. id: 4511670572085541767 @@ -1375,7 +1375,7 @@ definitions: aip_id: type: string description: Identifier of Archivematica AIP - example: d07fae89-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa30d16-1c21-11ee-bb08-7085c27bdeb0 format: uuid completed_at: type: string @@ -1403,12 +1403,12 @@ definitions: pipeline_id: type: string description: Identifier of Archivematica pipeline - example: d07faff9-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa30eaf-1c21-11ee-bb08-7085c27bdeb0 format: uuid run_id: type: string description: Identifier of latest processing workflow run - example: d07fabe6-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa30a79-1c21-11ee-bb08-7085c27bdeb0 format: uuid started_at: type: string @@ -1432,27 +1432,27 @@ definitions: transfer_id: type: string description: Identifier of Archivematica transfer - example: d07fad35-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa30bda-1c21-11ee-bb08-7085c27bdeb0 format: uuid workflow_id: type: string description: Identifier of processing workflow - example: d07faa6f-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa30919-1c21-11ee-bb08-7085c27bdeb0 format: uuid description: StoredCollection describes a collection retrieved by the service. (default view) example: - aip_id: d07fb942-11a8-11ee-ade5-7085c27bdeb0 + aip_id: 3aa317af-1c21-11ee-bb08-7085c27bdeb0 completed_at: "1992-09-23T06:18:58Z" created_at: "1983-06-28T18:36:02Z" id: 828828406215854043 name: Nostrum aut deserunt. original_id: Animi praesentium omnis dignissimos cumque omnis. - pipeline_id: d07fba9b-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07fb6a5-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa318dd-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa3154d-1c21-11ee-bb08-7085c27bdeb0 started_at: "2007-09-04T21:44:52Z" status: unknown - transfer_id: d07fb801-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07fb56e-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa31673-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa31428-1c21-11ee-bb08-7085c27bdeb0 required: - id - status @@ -1464,42 +1464,42 @@ definitions: $ref: '#/definitions/EnduroStoredCollectionResponseBody' description: EnduroStored-CollectionCollectionResponseBody is the result type for an array of EnduroStored-CollectionResponseBody (default view) example: - - aip_id: d07b2f9b-11a8-11ee-ade5-7085c27bdeb0 + - aip_id: 3aa1790a-1c21-11ee-bb08-7085c27bdeb0 completed_at: "1997-08-27T00:00:04Z" created_at: "1989-09-24T08:53:28Z" id: 4957819645449742263 name: Labore totam harum repellat. original_id: Nostrum delectus dolor nisi. - pipeline_id: d07c1db6-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07b2a3c-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa17a49-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa17689-1c21-11ee-bb08-7085c27bdeb0 started_at: "1998-02-12T04:24:46Z" status: unknown - transfer_id: d07b2cc3-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07b27e7-11a8-11ee-ade5-7085c27bdeb0 - - aip_id: d07b2f9b-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa177ba-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa1753b-1c21-11ee-bb08-7085c27bdeb0 + - aip_id: 3aa1790a-1c21-11ee-bb08-7085c27bdeb0 completed_at: "1997-08-27T00:00:04Z" created_at: "1989-09-24T08:53:28Z" id: 4957819645449742263 name: Labore totam harum repellat. original_id: Nostrum delectus dolor nisi. - pipeline_id: d07c1db6-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07b2a3c-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa17a49-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa17689-1c21-11ee-bb08-7085c27bdeb0 started_at: "1998-02-12T04:24:46Z" status: unknown - transfer_id: d07b2cc3-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07b27e7-11a8-11ee-ade5-7085c27bdeb0 - - aip_id: d07b2f9b-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa177ba-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa1753b-1c21-11ee-bb08-7085c27bdeb0 + - aip_id: 3aa1790a-1c21-11ee-bb08-7085c27bdeb0 completed_at: "1997-08-27T00:00:04Z" created_at: "1989-09-24T08:53:28Z" id: 4957819645449742263 name: Labore totam harum repellat. original_id: Nostrum delectus dolor nisi. - pipeline_id: d07c1db6-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07b2a3c-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa17a49-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa17689-1c21-11ee-bb08-7085c27bdeb0 started_at: "1998-02-12T04:24:46Z" status: unknown - transfer_id: d07b2cc3-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07b27e7-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa177ba-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa1753b-1c21-11ee-bb08-7085c27bdeb0 EnduroStoredPipelineResponse: title: 'Mediatype identifier: application/vnd.enduro.stored-pipeline; view=default' type: object @@ -1517,7 +1517,7 @@ definitions: id: type: string description: Identifier of the pipeline - example: d08013c1-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa34822-1c21-11ee-bb08-7085c27bdeb0 format: uuid name: type: string @@ -1530,7 +1530,7 @@ definitions: example: capacity: 7322691743128068194 current: 72660884889227336 - id: d08016b4-11a8-11ee-ade5-7085c27bdeb0 + id: 3aa34991-1c21-11ee-bb08-7085c27bdeb0 name: Tempore et eligendi laudantium ea illo hic. status: Id minima velit provident explicabo consequatur. required: @@ -1590,7 +1590,7 @@ definitions: id: type: string description: Identifier of the pipeline - example: d0801ab8-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa34bb3-1c21-11ee-bb08-7085c27bdeb0 format: uuid name: type: string @@ -1603,7 +1603,7 @@ definitions: example: capacity: 1349942446066623917 current: 3978574075782434602 - id: d0801db8-11a8-11ee-ade5-7085c27bdeb0 + id: 3aa34d72-1c21-11ee-bb08-7085c27bdeb0 name: Eveniet quam consequatur eveniet. status: Similique unde molestiae esse consequatur reprehenderit. required: diff --git a/internal/api/gen/http/openapi3.json b/internal/api/gen/http/openapi3.json index c61dd70f..67545369 100644 --- a/internal/api/gen/http/openapi3.json +++ b/internal/api/gen/http/openapi3.json @@ -1 +1 @@ -{"openapi":"3.0.3","info":{"title":"Enduro API","version":"1.0"},"servers":[{"url":"http://localhost:9000"}],"paths":{"/batch":{"get":{"tags":["batch"],"summary":"status batch","description":"Retrieve status of current batch operation.","operationId":"batch#status","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchStatusResult"},"example":{"run_id":"Vel sint ducimus officia labore eius qui.","running":true,"status":"Nam sed nostrum enim laborum ea facilis.","workflow_id":"Dolor illum excepturi magni quidem."}}}}}},"post":{"tags":["batch"],"summary":"submit batch","description":"Submit a new batch","operationId":"batch#submit","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitRequestBody"},"example":{"completed_dir":"Laboriosam odit.","path":"Laboriosam nam sit nihil.","pipeline":"Necessitatibus vel aut deleniti quia qui.","processing_config":"Vel voluptatem.","retention_period":"Sed perferendis illum illum omnis et officiis."}}}},"responses":{"202":{"description":"Accepted response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchResult"},"example":{"run_id":"Debitis rerum.","workflow_id":"Velit possimus et ea aut harum."}}}},"400":{"description":"not_valid: Bad Request response.","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"not_available: Conflict response.","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/batch/hints":{"get":{"tags":["batch"],"summary":"hints batch","description":"Retrieve form hints","operationId":"batch#hints","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchHintsResult"},"example":{"completed_dirs":["Impedit vero ducimus.","Quo illo natus et.","Eaque suscipit in cum et quia facere.","Doloribus sed tempore voluptatum quo."]}}}}}}},"/collection":{"get":{"tags":["collection"],"summary":"list collection","description":"List all stored collections","operationId":"collection#list","parameters":[{"name":"name","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"Dolorem rerum ullam provident hic aut."},"example":"Magni blanditiis sequi sunt neque velit."},{"name":"original_id","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"Ducimus minima totam veritatis."},"example":"Aliquam unde sit omnis quos."},{"name":"transfer_id","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"d080641c-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"example":"d080665a-11a8-11ee-ade5-7085c27bdeb0"},{"name":"aip_id","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"d0806858-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"example":"d0806a74-11a8-11ee-ade5-7085c27bdeb0"},{"name":"pipeline_id","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"d0806c72-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"example":"d0806e98-11a8-11ee-ade5-7085c27bdeb0"},{"name":"earliest_created_time","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"1997-12-25T18:16:26Z","format":"date-time"},"example":"1979-05-02T21:10:22Z"},{"name":"latest_created_time","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"1999-12-17T11:47:57Z","format":"date-time"},"example":"2014-10-13T03:53:49Z"},{"name":"status","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"done","enum":["new","in progress","done","error","unknown","queued","pending","abandoned"]},"example":"in progress"},{"name":"cursor","in":"query","description":"Pagination cursor","allowEmptyValue":true,"schema":{"type":"string","description":"Pagination cursor","example":"In ut qui aut quo."},"example":"Sunt iste facilis rerum inventore architecto tempora."}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponseBody"},"example":{"items":[{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"},{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"},{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"},{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"}],"next_cursor":"Ad aut rerum."}}}}}}},"/collection/bulk":{"get":{"tags":["collection"],"summary":"bulk_status collection","description":"Retrieve status of current bulk operation.","operationId":"collection#bulk_status","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkStatusResult"},"example":{"closed_at":"1983-11-09T08:33:50Z","run_id":"Officiis eum pariatur.","running":false,"started_at":"2006-08-01T01:39:09Z","status":"Repellat architecto dolore harum.","workflow_id":"Excepturi dolor aut rerum."}}}}}},"post":{"tags":["collection"],"summary":"bulk collection","description":"Bulk operations (retry, cancel...).","operationId":"collection#bulk","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkRequestBody"},"example":{"operation":"cancel","size":15492129042979125718,"status":"in progress"}}}},"responses":{"202":{"description":"Accepted response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchResult"},"example":{"run_id":"Deserunt illum et tempora.","workflow_id":"Explicabo et numquam aut dolores et voluptas."}}}},"400":{"description":"not_valid: Bad Request response.","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"not_available: Conflict response.","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/collection/monitor":{"get":{"tags":["collection"],"summary":"monitor collection","operationId":"collection#monitor","responses":{"101":{"description":"Switching Protocols response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnduroMonitorUpdate"},"example":{"id":2293355532387428117,"item":{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"},"type":"Deleniti ea tenetur deleniti."}}}}}}},"/collection/{id}":{"delete":{"tags":["collection"],"summary":"delete collection","description":"Delete collection by ID","operationId":"collection#delete","parameters":[{"name":"id","in":"path","description":"Identifier of collection to delete","required":true,"schema":{"type":"integer","description":"Identifier of collection to delete","example":17387408872735771929},"example":18321251186215423685}],"responses":{"204":{"description":"No Content response."},"404":{"description":"not_found: Collection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionNotfound"}}}}}},"get":{"tags":["collection"],"summary":"show collection","description":"Show collection by ID","operationId":"collection#show","parameters":[{"name":"id","in":"path","description":"Identifier of collection to show","required":true,"schema":{"type":"integer","description":"Identifier of collection to show","example":10131890621733502138},"example":12151494561344357633}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnduroStoredCollection"},"example":{"aip_id":"d07c8a6f-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2000-10-04T09:57:15Z","created_at":"2010-07-22T22:55:51Z","id":12024565834601469556,"name":"Quam quas.","original_id":"Et consequatur aut enim consequuntur debitis temporibus.","pipeline_id":"d07c8ba4-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07c87c3-11a8-11ee-ade5-7085c27bdeb0","started_at":"2014-07-31T20:44:18Z","status":"queued","transfer_id":"d07c892a-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07c8679-11a8-11ee-ade5-7085c27bdeb0"}}}},"404":{"description":"not_found: Collection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionNotfound"}}}}}}},"/collection/{id}/cancel":{"post":{"tags":["collection"],"summary":"cancel collection","description":"Cancel collection processing by ID","operationId":"collection#cancel","parameters":[{"name":"id","in":"path","description":"Identifier of collection to remove","required":true,"schema":{"type":"integer","description":"Identifier of collection to remove","example":8238362425834670988},"example":7926296436146036015}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"not_running: Bad Request response.","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: Collection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionNotfound"}}}}}}},"/collection/{id}/decision":{"post":{"tags":["collection"],"summary":"decide collection","description":"Make decision for a pending collection by ID","operationId":"collection#decide","parameters":[{"name":"id","in":"path","description":"Identifier of collection to look up","required":true,"schema":{"type":"integer","description":"Identifier of collection to look up","example":9198655460133316854},"example":7412982194674710965}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"option":{"type":"string","description":"Decision option to proceed with","example":"Aut dolorem praesentium asperiores commodi earum neque."}},"example":{"option":"Eaque ipsam."}},"example":{"option":"Excepturi architecto illum et consequatur optio corporis."}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"not_valid: Bad Request response.","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: Collection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionNotfound"}}}}}}},"/collection/{id}/download":{"get":{"tags":["collection"],"summary":"download collection","description":"Download collection by ID","operationId":"collection#download","parameters":[{"name":"id","in":"path","description":"Identifier of collection to look up","required":true,"schema":{"type":"integer","description":"Identifier of collection to look up","example":17608551620639562459},"example":1156397374729870360}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"SXBzYW0gbmVjZXNzaXRhdGlidXMgc2ltaWxpcXVlIGFkaXBpc2NpIG1hZ25hbSBhbmltaSBhZGlwaXNjaS4=","format":"binary"},"example":"UmVpY2llbmRpcyB2b2x1cHRhcyBkb2xvcnVtLg=="}}},"404":{"description":"not_found: Collection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionNotfound"}}}}}}},"/collection/{id}/retry":{"post":{"tags":["collection"],"summary":"retry collection","description":"Retry collection processing by ID","operationId":"collection#retry","parameters":[{"name":"id","in":"path","description":"Identifier of collection to retry","required":true,"schema":{"type":"integer","description":"Identifier of collection to retry","example":1414840750630874316},"example":14468688610787245765}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"not_running: Bad Request response.","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: Collection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionNotfound"}}}}}}},"/collection/{id}/workflow":{"get":{"tags":["collection"],"summary":"workflow collection","description":"Retrieve workflow status by ID","operationId":"collection#workflow","parameters":[{"name":"id","in":"path","description":"Identifier of collection to look up","required":true,"schema":{"type":"integer","description":"Identifier of collection to look up","example":17826339955967178467},"example":15122940082992273340}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnduroCollectionWorkflowStatus"},"example":{"history":[{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."}],"status":"Qui dolor."}}}},"404":{"description":"not_found: Collection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionNotfound"}}}}}}},"/pipeline":{"get":{"tags":["pipeline"],"summary":"list pipeline","description":"List all known pipelines","operationId":"pipeline#list","parameters":[{"name":"name","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"Excepturi vitae et saepe."},"example":"Quia perspiciatis."},{"name":"status","in":"query","allowEmptyValue":true,"schema":{"type":"boolean","default":false,"example":false},"example":true}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnduroStoredPipeline"},"example":[{"capacity":8406108818872523115,"current":1737602466879989319,"id":"d07aad12-11a8-11ee-ade5-7085c27bdeb0","name":"Eius perferendis et corrupti harum nisi voluptatibus.","status":"Qui explicabo qui error sint."},{"capacity":8406108818872523115,"current":1737602466879989319,"id":"d07aad12-11a8-11ee-ade5-7085c27bdeb0","name":"Eius perferendis et corrupti harum nisi voluptatibus.","status":"Qui explicabo qui error sint."}]},"example":[{"capacity":8406108818872523115,"current":1737602466879989319,"id":"d07aad12-11a8-11ee-ade5-7085c27bdeb0","name":"Eius perferendis et corrupti harum nisi voluptatibus.","status":"Qui explicabo qui error sint."},{"capacity":8406108818872523115,"current":1737602466879989319,"id":"d07aad12-11a8-11ee-ade5-7085c27bdeb0","name":"Eius perferendis et corrupti harum nisi voluptatibus.","status":"Qui explicabo qui error sint."},{"capacity":8406108818872523115,"current":1737602466879989319,"id":"d07aad12-11a8-11ee-ade5-7085c27bdeb0","name":"Eius perferendis et corrupti harum nisi voluptatibus.","status":"Qui explicabo qui error sint."},{"capacity":8406108818872523115,"current":1737602466879989319,"id":"d07aad12-11a8-11ee-ade5-7085c27bdeb0","name":"Eius perferendis et corrupti harum nisi voluptatibus.","status":"Qui explicabo qui error sint."}]}}}}}},"/pipeline/{id}":{"get":{"tags":["pipeline"],"summary":"show pipeline","description":"Show pipeline by ID","operationId":"pipeline#show","parameters":[{"name":"id","in":"path","description":"Identifier of pipeline to show","required":true,"schema":{"type":"string","description":"Identifier of pipeline to show","example":"d0807f61-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"example":"d080816d-11a8-11ee-ade5-7085c27bdeb0"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnduroStoredPipeline"},"example":{"capacity":604697410197609923,"current":1321092956144830636,"id":"d07f4c47-11a8-11ee-ade5-7085c27bdeb0","name":"Tempora error inventore molestias animi asperiores blanditiis.","status":"Quam assumenda saepe omnis et eius."}}}},"404":{"description":"not_found: Pipeline not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineNotFound"}}}}}}},"/pipeline/{id}/processing":{"get":{"tags":["pipeline"],"summary":"processing pipeline","description":"List all processing configurations of a pipeline given its ID","operationId":"pipeline#processing","parameters":[{"name":"id","in":"path","description":"Identifier of pipeline","required":true,"schema":{"type":"string","description":"Identifier of pipeline","example":"d0808432-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"example":"d0808660-11a8-11ee-ade5-7085c27bdeb0"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"array","items":{"type":"string","example":"Tenetur iste numquam rem quo eligendi."},"example":["Autem magnam.","In enim amet architecto non repudiandae."]},"example":["Maiores et dolores sed rerum est et.","Molestias natus aut."]}}},"404":{"description":"not_found: Pipeline not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineNotFound"}}}}}}},"/swagger/swagger.json":{"get":{"tags":["swagger"],"summary":"Download internal/api/gen/http/openapi.json","description":"JSON document containing the API swagger definition.","operationId":"swagger#/swagger/swagger.json","responses":{"200":{"description":"File downloaded"}}}}},"components":{"schemas":{"BatchHintsResult":{"type":"object","properties":{"completed_dirs":{"type":"array","items":{"type":"string","example":"Suscipit tempore est quisquam ratione."},"description":"A list of known values of completedDir used by existing watchers.","example":["Perferendis maiores.","Praesentium voluptatum delectus commodi.","Non eos consequuntur aliquam."]}},"example":{"completed_dirs":["Aliquid perspiciatis aperiam.","Optio repellendus molestias.","Mollitia aut tempora quia aperiam saepe."]}},"BatchResult":{"type":"object","properties":{"run_id":{"type":"string","example":"Deserunt a enim cum ad quasi qui."},"workflow_id":{"type":"string","example":"Qui rerum asperiores qui."}},"example":{"run_id":"Beatae blanditiis qui et ut recusandae id.","workflow_id":"Vitae fugit quis tempore animi ad ab."},"required":["workflow_id","run_id"]},"BatchStatusResult":{"type":"object","properties":{"run_id":{"type":"string","example":"Et rem et."},"running":{"type":"boolean","example":false},"status":{"type":"string","example":"Dolor saepe dolores."},"workflow_id":{"type":"string","example":"Quis delectus quia."}},"example":{"run_id":"Et culpa beatae fuga.","running":false,"status":"Sunt laborum.","workflow_id":"In qui."},"required":["running"]},"BulkRequestBody":{"type":"object","properties":{"operation":{"type":"string","example":"abandon","enum":["retry","cancel","abandon"]},"size":{"type":"integer","default":100,"example":7049186774788407004},"status":{"type":"string","example":"unknown","enum":["new","in progress","done","error","unknown","queued","pending","abandoned"]}},"example":{"operation":"cancel","size":10756257245132189908,"status":"new"},"required":["operation","status"]},"BulkStatusResult":{"type":"object","properties":{"closed_at":{"type":"string","example":"1988-07-12T21:32:29Z","format":"date-time"},"run_id":{"type":"string","example":"Et molestiae alias qui omnis reiciendis quae."},"running":{"type":"boolean","example":true},"started_at":{"type":"string","example":"2004-09-15T21:11:47Z","format":"date-time"},"status":{"type":"string","example":"Mollitia est officiis nostrum dignissimos ut."},"workflow_id":{"type":"string","example":"Eligendi mollitia ut voluptate tempora iusto et."}},"example":{"closed_at":"1997-01-23T03:40:32Z","run_id":"Animi quia ut culpa aut explicabo placeat.","running":false,"started_at":"2010-10-16T14:05:06Z","status":"Similique assumenda doloremque cumque quia consequuntur.","workflow_id":"Nobis hic debitis."},"required":["running"]},"CollectionNotfound":{"type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":18225317793911514815},"message":{"type":"string","description":"Message of error","example":"Voluptas autem culpa quos tempore."}},"description":"Collection not found","example":{"id":13607598706967279877,"message":"Neque recusandae et perferendis."},"required":["message","id"]},"EnduroCollectionWorkflowHistory":{"type":"object","properties":{"details":{"type":"string","description":"Contents of the event","example":"Nobis maiores commodi odit iure unde.","format":"binary"},"id":{"type":"integer","description":"Identifier of collection","example":6353654755516871806},"type":{"type":"string","description":"Type of the event","example":"Possimus voluptatem."}},"description":"WorkflowHistoryEvent describes a history event in Cadence.","example":{"details":"Neque voluptas quasi deserunt excepturi tempora.","id":12911299265168543401,"type":"Rem quia qui omnis aut."}},"EnduroCollectionWorkflowHistoryCollection":{"type":"array","items":{"$ref":"#/components/schemas/EnduroCollectionWorkflowHistory"},"example":[{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."}]},"EnduroCollectionWorkflowStatus":{"type":"object","properties":{"history":{"$ref":"#/components/schemas/EnduroCollectionWorkflowHistoryCollection"},"status":{"type":"string","example":"Neque voluptatem porro omnis et distinctio vero."}},"example":{"history":[{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."}],"status":"Nulla quod sed."}},"EnduroMonitorUpdate":{"type":"object","properties":{"id":{"type":"integer","description":"Identifier of collection","example":17019269049155146495},"item":{"$ref":"#/components/schemas/EnduroStoredCollection"},"type":{"type":"string","description":"Type of the event","example":"Deserunt enim voluptas ut cupiditate expedita distinctio."}},"example":{"id":18173606350330826349,"item":{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"},"type":"Perspiciatis porro veritatis et."},"required":["id","type"]},"EnduroStoredCollection":{"type":"object","properties":{"aip_id":{"type":"string","description":"Identifier of Archivematica AIP","example":"d080307d-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"completed_at":{"type":"string","description":"Completion datetime","example":"1985-09-21T14:48:23Z","format":"date-time"},"created_at":{"type":"string","description":"Creation datetime","example":"2011-02-18T18:59:59Z","format":"date-time"},"id":{"type":"integer","description":"Identifier of collection","example":4919145112566344839},"name":{"type":"string","description":"Name of the collection","example":"Dolor labore quis aut sint recusandae eum."},"original_id":{"type":"string","description":"Identifier provided by the client","example":"Assumenda qui assumenda suscipit."},"pipeline_id":{"type":"string","description":"Identifier of Archivematica pipeline","example":"d0803284-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"run_id":{"type":"string","description":"Identifier of latest processing workflow run","example":"d0802c60-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"started_at":{"type":"string","description":"Start datetime","example":"2006-08-17T11:55:03Z","format":"date-time"},"status":{"type":"string","description":"Status of the collection","default":"new","example":"pending","enum":["new","in progress","done","error","unknown","queued","pending","abandoned"]},"transfer_id":{"type":"string","description":"Identifier of Archivematica transfer","example":"d0802e82-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"workflow_id":{"type":"string","description":"Identifier of processing workflow","example":"d08029f4-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"}},"description":"StoredCollection describes a collection retrieved by the service.","example":{"aip_id":"d080404c-11a8-11ee-ade5-7085c27bdeb0","completed_at":"1986-04-15T08:25:16Z","created_at":"2002-08-25T21:29:42Z","id":3007180406968656670,"name":"Saepe officia veritatis.","original_id":"Reiciendis corporis recusandae optio possimus id et.","pipeline_id":"d080427e-11a8-11ee-ade5-7085c27bdeb0","run_id":"d0803c98-11a8-11ee-ade5-7085c27bdeb0","started_at":"2002-10-30T11:51:06Z","status":"error","transfer_id":"d0803e7e-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d0803ab9-11a8-11ee-ade5-7085c27bdeb0"},"required":["id","status","created_at"]},"EnduroStoredCollectionCollection":{"type":"array","items":{"$ref":"#/components/schemas/EnduroStoredCollection"},"example":[{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"},{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"}]},"EnduroStoredPipeline":{"type":"object","properties":{"capacity":{"type":"integer","description":"Maximum concurrent transfers","example":675308295529917391,"format":"int64"},"current":{"type":"integer","description":"Current transfers","example":1126670102776995078,"format":"int64"},"id":{"type":"string","description":"Identifier of the pipeline","example":"d0805a4a-11a8-11ee-ade5-7085c27bdeb0","format":"uuid"},"name":{"type":"string","description":"Name of the pipeline","example":"Est provident sint at modi est."},"status":{"type":"string","example":"Repellat inventore culpa qui sapiente inventore non."}},"description":"StoredPipeline describes a pipeline retrieved by this service.","example":{"capacity":3260630790103415086,"current":7000442574851704032,"id":"d0805cd1-11a8-11ee-ade5-7085c27bdeb0","name":"Ut corrupti velit enim.","status":"Illum voluptas vel nesciunt."},"required":["name"]},"Error":{"type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":false},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":false}},"example":{"id":"3F1FKVRR","message":"Value of ID must be an integer","name":"bad_request"},"required":["name","id","message","temporary","timeout","fault"]},"ListResponseBody":{"type":"object","properties":{"items":{"$ref":"#/components/schemas/EnduroStoredCollectionCollection"},"next_cursor":{"type":"string","example":"Reiciendis iste quis asperiores voluptate temporibus."}},"example":{"items":[{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"},{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"},{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"},{"aip_id":"d07a4bb6-11a8-11ee-ade5-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"d07a4d34-11a8-11ee-ade5-7085c27bdeb0","run_id":"d07a48d6-11a8-11ee-ade5-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"d07a4a4f-11a8-11ee-ade5-7085c27bdeb0","workflow_id":"d07a3817-11a8-11ee-ade5-7085c27bdeb0"}],"next_cursor":"Facilis officiis dicta et vitae consequatur nihil."},"required":["items"]},"PipelineNotFound":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of missing pipeline","example":"Beatae quidem illo ducimus et deleniti voluptatibus."},"message":{"type":"string","description":"Message of error","example":"Quis nisi ut."}},"description":"Pipeline not found","example":{"id":"Voluptatem ducimus aut at optio.","message":"Ut repellendus similique minima."},"required":["message","id"]},"SubmitRequestBody":{"type":"object","properties":{"completed_dir":{"type":"string","example":"Sunt ut."},"path":{"type":"string","example":"Qui non unde ut."},"pipeline":{"type":"string","example":"Et voluptatem quibusdam facilis magnam."},"processing_config":{"type":"string","example":"Veritatis vel eos."},"retention_period":{"type":"string","example":"Illum illum tenetur."}},"example":{"completed_dir":"Fugiat a officiis ipsum.","path":"Voluptates nulla autem et perspiciatis libero voluptas.","pipeline":"Voluptates et molestiae eum et occaecati.","processing_config":"Et et eligendi voluptatem.","retention_period":"Necessitatibus voluptas mollitia dolore."},"required":["path"]}}},"tags":[{"name":"batch","description":"The batch service manages batches of collections."},{"name":"collection","description":"The collection service manages packages being transferred to Archivematica."},{"name":"pipeline","description":"The pipeline service manages Archivematica pipelines."},{"name":"swagger","description":"The swagger service serves the API swagger definition."}]} \ No newline at end of file +{"openapi":"3.0.3","info":{"title":"Enduro API","version":"1.0"},"servers":[{"url":"http://localhost:9000"}],"paths":{"/batch":{"get":{"tags":["batch"],"summary":"status batch","description":"Retrieve status of current batch operation.","operationId":"batch#status","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchStatusResult"},"example":{"run_id":"Vel sint ducimus officia labore eius qui.","running":true,"status":"Nam sed nostrum enim laborum ea facilis.","workflow_id":"Dolor illum excepturi magni quidem."}}}}}},"post":{"tags":["batch"],"summary":"submit batch","description":"Submit a new batch","operationId":"batch#submit","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitRequestBody"},"example":{"completed_dir":"Laboriosam odit.","path":"Laboriosam nam sit nihil.","pipeline":"Necessitatibus vel aut deleniti quia qui.","processing_config":"Vel voluptatem.","retention_period":"Sed perferendis illum illum omnis et officiis."}}}},"responses":{"202":{"description":"Accepted response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchResult"},"example":{"run_id":"Debitis rerum.","workflow_id":"Velit possimus et ea aut harum."}}}},"400":{"description":"not_valid: Bad Request response.","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"not_available: Conflict response.","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/batch/hints":{"get":{"tags":["batch"],"summary":"hints batch","description":"Retrieve form hints","operationId":"batch#hints","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchHintsResult"},"example":{"completed_dirs":["Impedit vero ducimus.","Quo illo natus et.","Eaque suscipit in cum et quia facere.","Doloribus sed tempore voluptatum quo."]}}}}}}},"/collection":{"get":{"tags":["collection"],"summary":"list collection","description":"List all stored collections","operationId":"collection#list","parameters":[{"name":"name","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"Dolorem rerum ullam provident hic aut."},"example":"Magni blanditiis sequi sunt neque velit."},{"name":"original_id","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"Ducimus minima totam veritatis."},"example":"Aliquam unde sit omnis quos."},{"name":"transfer_id","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"3aa38b35-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"example":"3aa38c90-1c21-11ee-bb08-7085c27bdeb0"},{"name":"aip_id","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"3aa38de7-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"example":"3aa38f17-1c21-11ee-bb08-7085c27bdeb0"},{"name":"pipeline_id","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"3aa3903e-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"example":"3aa3916a-1c21-11ee-bb08-7085c27bdeb0"},{"name":"earliest_created_time","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"1997-12-25T18:16:26Z","format":"date-time"},"example":"1979-05-02T21:10:22Z"},{"name":"latest_created_time","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"1999-12-17T11:47:57Z","format":"date-time"},"example":"2014-10-13T03:53:49Z"},{"name":"status","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"done","enum":["new","in progress","done","error","unknown","queued","pending","abandoned"]},"example":"in progress"},{"name":"cursor","in":"query","description":"Pagination cursor","allowEmptyValue":true,"schema":{"type":"string","description":"Pagination cursor","example":"In ut qui aut quo."},"example":"Sunt iste facilis rerum inventore architecto tempora."}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponseBody"},"example":{"items":[{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"},{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"},{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"},{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"}],"next_cursor":"Ad aut rerum."}}}}}}},"/collection/bulk":{"get":{"tags":["collection"],"summary":"bulk_status collection","description":"Retrieve status of current bulk operation.","operationId":"collection#bulk_status","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkStatusResult"},"example":{"closed_at":"1983-11-09T08:33:50Z","run_id":"Officiis eum pariatur.","running":false,"started_at":"2006-08-01T01:39:09Z","status":"Repellat architecto dolore harum.","workflow_id":"Excepturi dolor aut rerum."}}}}}},"post":{"tags":["collection"],"summary":"bulk collection","description":"Bulk operations (retry, cancel...).","operationId":"collection#bulk","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkRequestBody"},"example":{"operation":"cancel","size":15492129042979125718,"status":"in progress"}}}},"responses":{"202":{"description":"Accepted response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchResult"},"example":{"run_id":"Deserunt illum et tempora.","workflow_id":"Explicabo et numquam aut dolores et voluptas."}}}},"400":{"description":"not_valid: Bad Request response.","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"not_available: Conflict response.","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/collection/monitor":{"get":{"tags":["collection"],"summary":"monitor collection","operationId":"collection#monitor","responses":{"101":{"description":"Switching Protocols response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnduroMonitorUpdate"},"example":{"id":2293355532387428117,"item":{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"},"type":"Deleniti ea tenetur deleniti."}}}}}}},"/collection/{id}":{"delete":{"tags":["collection"],"summary":"delete collection","description":"Delete collection by ID","operationId":"collection#delete","parameters":[{"name":"id","in":"path","description":"Identifier of collection to delete","required":true,"schema":{"type":"integer","description":"Identifier of collection to delete","example":17387408872735771929},"example":18321251186215423685}],"responses":{"204":{"description":"No Content response."},"404":{"description":"not_found: Collection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionNotfound"}}}}}},"get":{"tags":["collection"],"summary":"show collection","description":"Show collection by ID","operationId":"collection#show","parameters":[{"name":"id","in":"path","description":"Identifier of collection to show","required":true,"schema":{"type":"integer","description":"Identifier of collection to show","example":10131890621733502138},"example":12151494561344357633}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnduroStoredCollection"},"example":{"aip_id":"3aa1cccb-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2000-10-04T09:57:15Z","created_at":"2010-07-22T22:55:51Z","id":12024565834601469556,"name":"Quam quas.","original_id":"Et consequatur aut enim consequuntur debitis temporibus.","pipeline_id":"3aa1ce07-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa1ca35-1c21-11ee-bb08-7085c27bdeb0","started_at":"2014-07-31T20:44:18Z","status":"queued","transfer_id":"3aa1cb70-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa1c8fb-1c21-11ee-bb08-7085c27bdeb0"}}}},"404":{"description":"not_found: Collection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionNotfound"}}}}}}},"/collection/{id}/cancel":{"post":{"tags":["collection"],"summary":"cancel collection","description":"Cancel collection processing by ID","operationId":"collection#cancel","parameters":[{"name":"id","in":"path","description":"Identifier of collection to remove","required":true,"schema":{"type":"integer","description":"Identifier of collection to remove","example":8238362425834670988},"example":7926296436146036015}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"not_running: Bad Request response.","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: Collection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionNotfound"}}}}}}},"/collection/{id}/decision":{"post":{"tags":["collection"],"summary":"decide collection","description":"Make decision for a pending collection by ID","operationId":"collection#decide","parameters":[{"name":"id","in":"path","description":"Identifier of collection to look up","required":true,"schema":{"type":"integer","description":"Identifier of collection to look up","example":9198655460133316854},"example":7412982194674710965}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"option":{"type":"string","description":"Decision option to proceed with","example":"Aut dolorem praesentium asperiores commodi earum neque."}},"example":{"option":"Eaque ipsam."}},"example":{"option":"Excepturi architecto illum et consequatur optio corporis."}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"not_valid: Bad Request response.","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: Collection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionNotfound"}}}}}}},"/collection/{id}/download":{"get":{"tags":["collection"],"summary":"download collection","description":"Download collection by ID","operationId":"collection#download","parameters":[{"name":"id","in":"path","description":"Identifier of collection to look up","required":true,"schema":{"type":"integer","description":"Identifier of collection to look up","example":17608551620639562459},"example":1156397374729870360}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"SXBzYW0gbmVjZXNzaXRhdGlidXMgc2ltaWxpcXVlIGFkaXBpc2NpIG1hZ25hbSBhbmltaSBhZGlwaXNjaS4=","format":"binary"},"example":"UmVpY2llbmRpcyB2b2x1cHRhcyBkb2xvcnVtLg=="}}},"404":{"description":"not_found: Collection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionNotfound"}}}}}}},"/collection/{id}/retry":{"post":{"tags":["collection"],"summary":"retry collection","description":"Retry collection processing by ID","operationId":"collection#retry","parameters":[{"name":"id","in":"path","description":"Identifier of collection to retry","required":true,"schema":{"type":"integer","description":"Identifier of collection to retry","example":1414840750630874316},"example":14468688610787245765}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"not_running: Bad Request response.","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: Collection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionNotfound"}}}}}}},"/collection/{id}/workflow":{"get":{"tags":["collection"],"summary":"workflow collection","description":"Retrieve workflow status by ID","operationId":"collection#workflow","parameters":[{"name":"id","in":"path","description":"Identifier of collection to look up","required":true,"schema":{"type":"integer","description":"Identifier of collection to look up","example":17826339955967178467},"example":15122940082992273340}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnduroCollectionWorkflowStatus"},"example":{"history":[{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."}],"status":"Qui dolor."}}}},"404":{"description":"not_found: Collection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionNotfound"}}}}}}},"/pipeline":{"get":{"tags":["pipeline"],"summary":"list pipeline","description":"List all known pipelines","operationId":"pipeline#list","parameters":[{"name":"name","in":"query","allowEmptyValue":true,"schema":{"type":"string","example":"Excepturi vitae et saepe."},"example":"Quia perspiciatis."},{"name":"status","in":"query","allowEmptyValue":true,"schema":{"type":"boolean","default":false,"example":false},"example":true}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnduroStoredPipeline"},"example":[{"capacity":8406108818872523115,"current":1737602466879989319,"id":"3aa13013-1c21-11ee-bb08-7085c27bdeb0","name":"Eius perferendis et corrupti harum nisi voluptatibus.","status":"Qui explicabo qui error sint."},{"capacity":8406108818872523115,"current":1737602466879989319,"id":"3aa13013-1c21-11ee-bb08-7085c27bdeb0","name":"Eius perferendis et corrupti harum nisi voluptatibus.","status":"Qui explicabo qui error sint."}]},"example":[{"capacity":8406108818872523115,"current":1737602466879989319,"id":"3aa13013-1c21-11ee-bb08-7085c27bdeb0","name":"Eius perferendis et corrupti harum nisi voluptatibus.","status":"Qui explicabo qui error sint."},{"capacity":8406108818872523115,"current":1737602466879989319,"id":"3aa13013-1c21-11ee-bb08-7085c27bdeb0","name":"Eius perferendis et corrupti harum nisi voluptatibus.","status":"Qui explicabo qui error sint."},{"capacity":8406108818872523115,"current":1737602466879989319,"id":"3aa13013-1c21-11ee-bb08-7085c27bdeb0","name":"Eius perferendis et corrupti harum nisi voluptatibus.","status":"Qui explicabo qui error sint."},{"capacity":8406108818872523115,"current":1737602466879989319,"id":"3aa13013-1c21-11ee-bb08-7085c27bdeb0","name":"Eius perferendis et corrupti harum nisi voluptatibus.","status":"Qui explicabo qui error sint."}]}}}}}},"/pipeline/{id}":{"get":{"tags":["pipeline"],"summary":"show pipeline","description":"Show pipeline by ID","operationId":"pipeline#show","parameters":[{"name":"id","in":"path","description":"Identifier of pipeline to show","required":true,"schema":{"type":"string","description":"Identifier of pipeline to show","example":"3aa39b4b-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"example":"3aa39c8c-1c21-11ee-bb08-7085c27bdeb0"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnduroStoredPipeline"},"example":{"capacity":604697410197609923,"current":1321092956144830636,"id":"3aa2a8cf-1c21-11ee-bb08-7085c27bdeb0","name":"Tempora error inventore molestias animi asperiores blanditiis.","status":"Quam assumenda saepe omnis et eius."}}}},"404":{"description":"not_found: Pipeline not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineNotFound"}}}}}}},"/pipeline/{id}/processing":{"get":{"tags":["pipeline"],"summary":"processing pipeline","description":"List all processing configurations of a pipeline given its ID","operationId":"pipeline#processing","parameters":[{"name":"id","in":"path","description":"Identifier of pipeline","required":true,"schema":{"type":"string","description":"Identifier of pipeline","example":"3aa39e15-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"example":"3aa39f3a-1c21-11ee-bb08-7085c27bdeb0"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"array","items":{"type":"string","example":"Tenetur iste numquam rem quo eligendi."},"example":["Autem magnam.","In enim amet architecto non repudiandae."]},"example":["Maiores et dolores sed rerum est et.","Molestias natus aut."]}}},"404":{"description":"not_found: Pipeline not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineNotFound"}}}}}}},"/swagger/swagger.json":{"get":{"tags":["swagger"],"summary":"Download internal/api/gen/http/openapi.json","description":"JSON document containing the API swagger definition.","operationId":"swagger#/swagger/swagger.json","responses":{"200":{"description":"File downloaded"}}}}},"components":{"schemas":{"BatchHintsResult":{"type":"object","properties":{"completed_dirs":{"type":"array","items":{"type":"string","example":"Suscipit tempore est quisquam ratione."},"description":"A list of known values of completedDir used by existing watchers.","example":["Perferendis maiores.","Praesentium voluptatum delectus commodi.","Non eos consequuntur aliquam."]}},"example":{"completed_dirs":["Aliquid perspiciatis aperiam.","Optio repellendus molestias.","Mollitia aut tempora quia aperiam saepe."]}},"BatchResult":{"type":"object","properties":{"run_id":{"type":"string","example":"Deserunt a enim cum ad quasi qui."},"workflow_id":{"type":"string","example":"Qui rerum asperiores qui."}},"example":{"run_id":"Beatae blanditiis qui et ut recusandae id.","workflow_id":"Vitae fugit quis tempore animi ad ab."},"required":["workflow_id","run_id"]},"BatchStatusResult":{"type":"object","properties":{"run_id":{"type":"string","example":"Et rem et."},"running":{"type":"boolean","example":false},"status":{"type":"string","example":"Dolor saepe dolores."},"workflow_id":{"type":"string","example":"Quis delectus quia."}},"example":{"run_id":"Et culpa beatae fuga.","running":false,"status":"Sunt laborum.","workflow_id":"In qui."},"required":["running"]},"BulkRequestBody":{"type":"object","properties":{"operation":{"type":"string","example":"abandon","enum":["retry","cancel","abandon"]},"size":{"type":"integer","default":100,"example":7049186774788407004},"status":{"type":"string","example":"unknown","enum":["new","in progress","done","error","unknown","queued","pending","abandoned"]}},"example":{"operation":"cancel","size":10756257245132189908,"status":"new"},"required":["operation","status"]},"BulkStatusResult":{"type":"object","properties":{"closed_at":{"type":"string","example":"1988-07-12T21:32:29Z","format":"date-time"},"run_id":{"type":"string","example":"Et molestiae alias qui omnis reiciendis quae."},"running":{"type":"boolean","example":true},"started_at":{"type":"string","example":"2004-09-15T21:11:47Z","format":"date-time"},"status":{"type":"string","example":"Mollitia est officiis nostrum dignissimos ut."},"workflow_id":{"type":"string","example":"Eligendi mollitia ut voluptate tempora iusto et."}},"example":{"closed_at":"1997-01-23T03:40:32Z","run_id":"Animi quia ut culpa aut explicabo placeat.","running":false,"started_at":"2010-10-16T14:05:06Z","status":"Similique assumenda doloremque cumque quia consequuntur.","workflow_id":"Nobis hic debitis."},"required":["running"]},"CollectionNotfound":{"type":"object","properties":{"id":{"type":"integer","description":"Identifier of missing collection","example":18225317793911514815},"message":{"type":"string","description":"Message of error","example":"Voluptas autem culpa quos tempore."}},"description":"Collection not found","example":{"id":13607598706967279877,"message":"Neque recusandae et perferendis."},"required":["message","id"]},"EnduroCollectionWorkflowHistory":{"type":"object","properties":{"details":{"type":"string","description":"Contents of the event","example":"Nobis maiores commodi odit iure unde.","format":"binary"},"id":{"type":"integer","description":"Identifier of collection","example":6353654755516871806},"type":{"type":"string","description":"Type of the event","example":"Possimus voluptatem."}},"description":"WorkflowHistoryEvent describes a history event in Temporal.","example":{"details":"Neque voluptas quasi deserunt excepturi tempora.","id":12911299265168543401,"type":"Rem quia qui omnis aut."}},"EnduroCollectionWorkflowHistoryCollection":{"type":"array","items":{"$ref":"#/components/schemas/EnduroCollectionWorkflowHistory"},"example":[{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."}]},"EnduroCollectionWorkflowStatus":{"type":"object","properties":{"history":{"$ref":"#/components/schemas/EnduroCollectionWorkflowHistoryCollection"},"status":{"type":"string","example":"Neque voluptatem porro omnis et distinctio vero."}},"example":{"history":[{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."},{"details":"In quis sed.","id":2015423930972900414,"type":"Enim esse aut accusantium deleniti beatae voluptas."}],"status":"Nulla quod sed."}},"EnduroMonitorUpdate":{"type":"object","properties":{"id":{"type":"integer","description":"Identifier of collection","example":17019269049155146495},"item":{"$ref":"#/components/schemas/EnduroStoredCollection"},"type":{"type":"string","description":"Type of the event","example":"Deserunt enim voluptas ut cupiditate expedita distinctio."}},"example":{"id":18173606350330826349,"item":{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"},"type":"Perspiciatis porro veritatis et."},"required":["id","type"]},"EnduroStoredCollection":{"type":"object","properties":{"aip_id":{"type":"string","description":"Identifier of Archivematica AIP","example":"3aa36a17-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"completed_at":{"type":"string","description":"Completion datetime","example":"1985-09-21T14:48:23Z","format":"date-time"},"created_at":{"type":"string","description":"Creation datetime","example":"2011-02-18T18:59:59Z","format":"date-time"},"id":{"type":"integer","description":"Identifier of collection","example":4919145112566344839},"name":{"type":"string","description":"Name of the collection","example":"Dolor labore quis aut sint recusandae eum."},"original_id":{"type":"string","description":"Identifier provided by the client","example":"Assumenda qui assumenda suscipit."},"pipeline_id":{"type":"string","description":"Identifier of Archivematica pipeline","example":"3aa36b7e-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"run_id":{"type":"string","description":"Identifier of latest processing workflow run","example":"3aa35efa-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"started_at":{"type":"string","description":"Start datetime","example":"2006-08-17T11:55:03Z","format":"date-time"},"status":{"type":"string","description":"Status of the collection","default":"new","example":"pending","enum":["new","in progress","done","error","unknown","queued","pending","abandoned"]},"transfer_id":{"type":"string","description":"Identifier of Archivematica transfer","example":"3aa367ab-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"workflow_id":{"type":"string","description":"Identifier of processing workflow","example":"3aa35c99-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"}},"description":"StoredCollection describes a collection retrieved by the service.","example":{"aip_id":"3aa3743c-1c21-11ee-bb08-7085c27bdeb0","completed_at":"1986-04-15T08:25:16Z","created_at":"2002-08-25T21:29:42Z","id":3007180406968656670,"name":"Saepe officia veritatis.","original_id":"Reiciendis corporis recusandae optio possimus id et.","pipeline_id":"3aa37568-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa371fa-1c21-11ee-bb08-7085c27bdeb0","started_at":"2002-10-30T11:51:06Z","status":"error","transfer_id":"3aa37322-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa37096-1c21-11ee-bb08-7085c27bdeb0"},"required":["id","status","created_at"]},"EnduroStoredCollectionCollection":{"type":"array","items":{"$ref":"#/components/schemas/EnduroStoredCollection"},"example":[{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"},{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"}]},"EnduroStoredPipeline":{"type":"object","properties":{"capacity":{"type":"integer","description":"Maximum concurrent transfers","example":675308295529917391,"format":"int64"},"current":{"type":"integer","description":"Current transfers","example":1126670102776995078,"format":"int64"},"id":{"type":"string","description":"Identifier of the pipeline","example":"3aa3835f-1c21-11ee-bb08-7085c27bdeb0","format":"uuid"},"name":{"type":"string","description":"Name of the pipeline","example":"Est provident sint at modi est."},"status":{"type":"string","example":"Repellat inventore culpa qui sapiente inventore non."}},"description":"StoredPipeline describes a pipeline retrieved by this service.","example":{"capacity":3260630790103415086,"current":7000442574851704032,"id":"3aa386a1-1c21-11ee-bb08-7085c27bdeb0","name":"Ut corrupti velit enim.","status":"Illum voluptas vel nesciunt."},"required":["name"]},"Error":{"type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":false},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":false}},"example":{"id":"3F1FKVRR","message":"Value of ID must be an integer","name":"bad_request"},"required":["name","id","message","temporary","timeout","fault"]},"ListResponseBody":{"type":"object","properties":{"items":{"$ref":"#/components/schemas/EnduroStoredCollectionCollection"},"next_cursor":{"type":"string","example":"Reiciendis iste quis asperiores voluptate temporibus."}},"example":{"items":[{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"},{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"},{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"},{"aip_id":"3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0","completed_at":"2014-01-26T22:52:33Z","created_at":"2006-09-07T19:48:15Z","id":5273261262554249024,"name":"Iusto laudantium assumenda.","original_id":"Voluptatem eum et rerum.","pipeline_id":"3aa0d854-1c21-11ee-bb08-7085c27bdeb0","run_id":"3aa0d415-1c21-11ee-bb08-7085c27bdeb0","started_at":"1986-05-13T23:32:21Z","status":"unknown","transfer_id":"3aa0d569-1c21-11ee-bb08-7085c27bdeb0","workflow_id":"3aa0be66-1c21-11ee-bb08-7085c27bdeb0"}],"next_cursor":"Facilis officiis dicta et vitae consequatur nihil."},"required":["items"]},"PipelineNotFound":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of missing pipeline","example":"Beatae quidem illo ducimus et deleniti voluptatibus."},"message":{"type":"string","description":"Message of error","example":"Quis nisi ut."}},"description":"Pipeline not found","example":{"id":"Voluptatem ducimus aut at optio.","message":"Ut repellendus similique minima."},"required":["message","id"]},"SubmitRequestBody":{"type":"object","properties":{"completed_dir":{"type":"string","example":"Sunt ut."},"path":{"type":"string","example":"Qui non unde ut."},"pipeline":{"type":"string","example":"Et voluptatem quibusdam facilis magnam."},"processing_config":{"type":"string","example":"Veritatis vel eos."},"retention_period":{"type":"string","example":"Illum illum tenetur."}},"example":{"completed_dir":"Fugiat a officiis ipsum.","path":"Voluptates nulla autem et perspiciatis libero voluptas.","pipeline":"Voluptates et molestiae eum et occaecati.","processing_config":"Et et eligendi voluptatem.","retention_period":"Necessitatibus voluptas mollitia dolore."},"required":["path"]}}},"tags":[{"name":"batch","description":"The batch service manages batches of collections."},{"name":"collection","description":"The collection service manages packages being transferred to Archivematica."},{"name":"pipeline","description":"The pipeline service manages Archivematica pipelines."},{"name":"swagger","description":"The swagger service serves the API swagger definition."}]} \ No newline at end of file diff --git a/internal/api/gen/http/openapi3.yaml b/internal/api/gen/http/openapi3.yaml index 6d409f4c..8e665504 100644 --- a/internal/api/gen/http/openapi3.yaml +++ b/internal/api/gen/http/openapi3.yaml @@ -111,25 +111,25 @@ paths: allowEmptyValue: true schema: type: string - example: d080641c-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa38b35-1c21-11ee-bb08-7085c27bdeb0 format: uuid - example: d080665a-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa38c90-1c21-11ee-bb08-7085c27bdeb0 - name: aip_id in: query allowEmptyValue: true schema: type: string - example: d0806858-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa38de7-1c21-11ee-bb08-7085c27bdeb0 format: uuid - example: d0806a74-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa38f17-1c21-11ee-bb08-7085c27bdeb0 - name: pipeline_id in: query allowEmptyValue: true schema: type: string - example: d0806c72-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa3903e-1c21-11ee-bb08-7085c27bdeb0 format: uuid - example: d0806e98-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa3916a-1c21-11ee-bb08-7085c27bdeb0 - name: earliest_created_time in: query allowEmptyValue: true @@ -180,54 +180,54 @@ paths: $ref: '#/components/schemas/ListResponseBody' example: items: - - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + - aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 - - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 + - aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 - - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 + - aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 - - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 + - aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 next_cursor: Ad aut rerum. /collection/{id}: delete: @@ -279,18 +279,18 @@ paths: schema: $ref: '#/components/schemas/EnduroStoredCollection' example: - aip_id: d07c8a6f-11a8-11ee-ade5-7085c27bdeb0 + aip_id: 3aa1cccb-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2000-10-04T09:57:15Z" created_at: "2010-07-22T22:55:51Z" id: 12024565834601469556 name: Quam quas. original_id: Et consequatur aut enim consequuntur debitis temporibus. - pipeline_id: d07c8ba4-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07c87c3-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa1ce07-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa1ca35-1c21-11ee-bb08-7085c27bdeb0 started_at: "2014-07-31T20:44:18Z" status: queued - transfer_id: d07c892a-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07c8679-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa1cb70-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa1c8fb-1c21-11ee-bb08-7085c27bdeb0 "404": description: 'not_found: Collection not found' content: @@ -666,18 +666,18 @@ paths: example: id: 2293355532387428117 item: - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 type: Deleniti ea tenetur deleniti. /pipeline: get: @@ -714,33 +714,33 @@ paths: example: - capacity: 8406108818872523115 current: 1737602466879989319 - id: d07aad12-11a8-11ee-ade5-7085c27bdeb0 + id: 3aa13013-1c21-11ee-bb08-7085c27bdeb0 name: Eius perferendis et corrupti harum nisi voluptatibus. status: Qui explicabo qui error sint. - capacity: 8406108818872523115 current: 1737602466879989319 - id: d07aad12-11a8-11ee-ade5-7085c27bdeb0 + id: 3aa13013-1c21-11ee-bb08-7085c27bdeb0 name: Eius perferendis et corrupti harum nisi voluptatibus. status: Qui explicabo qui error sint. example: - capacity: 8406108818872523115 current: 1737602466879989319 - id: d07aad12-11a8-11ee-ade5-7085c27bdeb0 + id: 3aa13013-1c21-11ee-bb08-7085c27bdeb0 name: Eius perferendis et corrupti harum nisi voluptatibus. status: Qui explicabo qui error sint. - capacity: 8406108818872523115 current: 1737602466879989319 - id: d07aad12-11a8-11ee-ade5-7085c27bdeb0 + id: 3aa13013-1c21-11ee-bb08-7085c27bdeb0 name: Eius perferendis et corrupti harum nisi voluptatibus. status: Qui explicabo qui error sint. - capacity: 8406108818872523115 current: 1737602466879989319 - id: d07aad12-11a8-11ee-ade5-7085c27bdeb0 + id: 3aa13013-1c21-11ee-bb08-7085c27bdeb0 name: Eius perferendis et corrupti harum nisi voluptatibus. status: Qui explicabo qui error sint. - capacity: 8406108818872523115 current: 1737602466879989319 - id: d07aad12-11a8-11ee-ade5-7085c27bdeb0 + id: 3aa13013-1c21-11ee-bb08-7085c27bdeb0 name: Eius perferendis et corrupti harum nisi voluptatibus. status: Qui explicabo qui error sint. /pipeline/{id}: @@ -758,9 +758,9 @@ paths: schema: type: string description: Identifier of pipeline to show - example: d0807f61-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa39b4b-1c21-11ee-bb08-7085c27bdeb0 format: uuid - example: d080816d-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa39c8c-1c21-11ee-bb08-7085c27bdeb0 responses: "200": description: OK response. @@ -771,7 +771,7 @@ paths: example: capacity: 604697410197609923 current: 1321092956144830636 - id: d07f4c47-11a8-11ee-ade5-7085c27bdeb0 + id: 3aa2a8cf-1c21-11ee-bb08-7085c27bdeb0 name: Tempora error inventore molestias animi asperiores blanditiis. status: Quam assumenda saepe omnis et eius. "404": @@ -795,9 +795,9 @@ paths: schema: type: string description: Identifier of pipeline - example: d0808432-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa39e15-1c21-11ee-bb08-7085c27bdeb0 format: uuid - example: d0808660-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa39f3a-1c21-11ee-bb08-7085c27bdeb0 responses: "200": description: OK response. @@ -986,7 +986,7 @@ components: type: string description: Type of the event example: Possimus voluptatem. - description: WorkflowHistoryEvent describes a history event in Cadence. + description: WorkflowHistoryEvent describes a history event in Temporal. example: details: Neque voluptas quasi deserunt excepturi tempora. id: 12911299265168543401 @@ -1044,18 +1044,18 @@ components: example: id: 18173606350330826349 item: - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 type: Perspiciatis porro veritatis et. required: - id @@ -1066,7 +1066,7 @@ components: aip_id: type: string description: Identifier of Archivematica AIP - example: d080307d-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa36a17-1c21-11ee-bb08-7085c27bdeb0 format: uuid completed_at: type: string @@ -1093,12 +1093,12 @@ components: pipeline_id: type: string description: Identifier of Archivematica pipeline - example: d0803284-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa36b7e-1c21-11ee-bb08-7085c27bdeb0 format: uuid run_id: type: string description: Identifier of latest processing workflow run - example: d0802c60-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa35efa-1c21-11ee-bb08-7085c27bdeb0 format: uuid started_at: type: string @@ -1122,27 +1122,27 @@ components: transfer_id: type: string description: Identifier of Archivematica transfer - example: d0802e82-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa367ab-1c21-11ee-bb08-7085c27bdeb0 format: uuid workflow_id: type: string description: Identifier of processing workflow - example: d08029f4-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa35c99-1c21-11ee-bb08-7085c27bdeb0 format: uuid description: StoredCollection describes a collection retrieved by the service. example: - aip_id: d080404c-11a8-11ee-ade5-7085c27bdeb0 + aip_id: 3aa3743c-1c21-11ee-bb08-7085c27bdeb0 completed_at: "1986-04-15T08:25:16Z" created_at: "2002-08-25T21:29:42Z" id: 3007180406968656670 name: Saepe officia veritatis. original_id: Reiciendis corporis recusandae optio possimus id et. - pipeline_id: d080427e-11a8-11ee-ade5-7085c27bdeb0 - run_id: d0803c98-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa37568-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa371fa-1c21-11ee-bb08-7085c27bdeb0 started_at: "2002-10-30T11:51:06Z" status: error - transfer_id: d0803e7e-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d0803ab9-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa37322-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa37096-1c21-11ee-bb08-7085c27bdeb0 required: - id - status @@ -1152,30 +1152,30 @@ components: items: $ref: '#/components/schemas/EnduroStoredCollection' example: - - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + - aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 - - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 + - aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 EnduroStoredPipeline: type: object properties: @@ -1192,7 +1192,7 @@ components: id: type: string description: Identifier of the pipeline - example: d0805a4a-11a8-11ee-ade5-7085c27bdeb0 + example: 3aa3835f-1c21-11ee-bb08-7085c27bdeb0 format: uuid name: type: string @@ -1205,7 +1205,7 @@ components: example: capacity: 3260630790103415086 current: 7000442574851704032 - id: d0805cd1-11a8-11ee-ade5-7085c27bdeb0 + id: 3aa386a1-1c21-11ee-bb08-7085c27bdeb0 name: Ut corrupti velit enim. status: Illum voluptas vel nesciunt. required: @@ -1258,54 +1258,54 @@ components: example: Reiciendis iste quis asperiores voluptate temporibus. example: items: - - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + - aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 - - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 + - aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 - - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 + - aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 - - aip_id: d07a4bb6-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 + - aip_id: 3aa0d6b1-1c21-11ee-bb08-7085c27bdeb0 completed_at: "2014-01-26T22:52:33Z" created_at: "2006-09-07T19:48:15Z" id: 5273261262554249024 name: Iusto laudantium assumenda. original_id: Voluptatem eum et rerum. - pipeline_id: d07a4d34-11a8-11ee-ade5-7085c27bdeb0 - run_id: d07a48d6-11a8-11ee-ade5-7085c27bdeb0 + pipeline_id: 3aa0d854-1c21-11ee-bb08-7085c27bdeb0 + run_id: 3aa0d415-1c21-11ee-bb08-7085c27bdeb0 started_at: "1986-05-13T23:32:21Z" status: unknown - transfer_id: d07a4a4f-11a8-11ee-ade5-7085c27bdeb0 - workflow_id: d07a3817-11a8-11ee-ade5-7085c27bdeb0 + transfer_id: 3aa0d569-1c21-11ee-bb08-7085c27bdeb0 + workflow_id: 3aa0be66-1c21-11ee-bb08-7085c27bdeb0 next_cursor: Facilis officiis dicta et vitae consequatur nihil. required: - items diff --git a/internal/batch/service.go b/internal/batch/service.go index c0db0e4a..e138819d 100644 --- a/internal/batch/service.go +++ b/internal/batch/service.go @@ -8,11 +8,12 @@ import ( "time" "github.com/go-logr/logr" - cadencesdk_gen_shared "go.uber.org/cadence/.gen/go/shared" - cadencesdk_client "go.uber.org/cadence/client" + "go.artefactual.dev/tools/ref" + temporalapi_enums "go.temporal.io/api/enums/v1" + temporalapi_serviceerror "go.temporal.io/api/serviceerror" + temporalsdk_client "go.temporal.io/sdk/client" goabatch "github.com/artefactual-labs/enduro/internal/api/gen/batch" - "github.com/artefactual-labs/enduro/internal/cadence" "github.com/artefactual-labs/enduro/internal/collection" "github.com/artefactual-labs/enduro/internal/validation" ) @@ -27,8 +28,9 @@ type Service interface { } type batchImpl struct { - logger logr.Logger - cc cadencesdk_client.Client + logger logr.Logger + cc temporalsdk_client.Client + taskQueue string // A list of completedDirs reported by the watcher configuration. This is // used to provide the user with possible known values. @@ -37,10 +39,11 @@ type batchImpl struct { var _ Service = (*batchImpl)(nil) -func NewService(logger logr.Logger, cc cadencesdk_client.Client, completedDirs []string) *batchImpl { +func NewService(logger logr.Logger, cc temporalsdk_client.Client, taskQueue string, completedDirs []string) *batchImpl { return &batchImpl{ logger: logger, cc: cc, + taskQueue: taskQueue, completedDirs: completedDirs, } } @@ -68,28 +71,29 @@ func (s *batchImpl) Submit(ctx context.Context, payload *goabatch.SubmitPayload) } input.RetentionPeriod = &dur } - opts := cadencesdk_client.StartWorkflowOptions{ - ID: BatchWorkflowID, - WorkflowIDReusePolicy: cadencesdk_client.WorkflowIDReusePolicyAllowDuplicate, - TaskList: cadence.GlobalTaskListName, - DecisionTaskStartToCloseTimeout: time.Second * 10, - ExecutionStartToCloseTimeout: time.Hour, + opts := temporalsdk_client.StartWorkflowOptions{ + ID: BatchWorkflowID, + WorkflowIDReusePolicy: temporalapi_enums.WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE, + TaskQueue: s.taskQueue, + WorkflowExecutionTimeout: time.Hour, + WorkflowTaskTimeout: time.Second * 10, } - exec, err := s.cc.StartWorkflow(ctx, opts, BatchWorkflowName, input) + exec, err := s.cc.ExecuteWorkflow(ctx, opts, BatchWorkflowName, input) if err != nil { switch err := err.(type) { - case *cadencesdk_gen_shared.WorkflowExecutionAlreadyStartedError: + case *temporalapi_serviceerror.WorkflowExecutionAlreadyStarted: return nil, goabatch.MakeNotAvailable( fmt.Errorf("error starting batch - operation is already in progress (workflowID=%s runID=%s)", - BatchWorkflowID, *err.RunId)) + BatchWorkflowID, err.RunId)) default: s.logger.Info("error starting batch", "err", err) return nil, fmt.Errorf("error starting batch") } } + result := &goabatch.BatchResult{ - WorkflowID: exec.ID, - RunID: exec.RunID, + WorkflowID: exec.GetID(), + RunID: exec.GetRunID(), } return result, nil } @@ -99,7 +103,7 @@ func (s *batchImpl) Status(ctx context.Context) (*goabatch.BatchStatusResult, er resp, err := s.cc.DescribeWorkflowExecution(ctx, BatchWorkflowID, "") if err != nil { switch err := err.(type) { - case *cadencesdk_gen_shared.EntityNotExistsError: + case *temporalapi_serviceerror.NotFound: return result, nil default: s.logger.Info("error retrieving workflow", "err", err) @@ -110,14 +114,13 @@ func (s *batchImpl) Status(ctx context.Context) (*goabatch.BatchStatusResult, er s.logger.Info("error retrieving workflow execution details") return nil, ErrBatchStatusUnavailable } - result.WorkflowID = resp.WorkflowExecutionInfo.Execution.WorkflowId - result.RunID = resp.WorkflowExecutionInfo.Execution.RunId - if resp.WorkflowExecutionInfo.CloseStatus != nil { - st := strings.ToLower(resp.WorkflowExecutionInfo.CloseStatus.String()) - result.Status = &st + result.WorkflowID = &resp.WorkflowExecutionInfo.Execution.WorkflowId + result.RunID = &resp.WorkflowExecutionInfo.Execution.RunId + if resp.WorkflowExecutionInfo.Status == temporalapi_enums.WORKFLOW_EXECUTION_STATUS_RUNNING { + result.Running = true return result, nil } - result.Running = true + result.Status = ref.New(strings.ToLower(resp.WorkflowExecutionInfo.Status.String())) return result, nil } @@ -130,7 +133,7 @@ func (s *batchImpl) Hints(ctx context.Context) (*goabatch.BatchHintsResult, erro func (s *batchImpl) InitProcessingWorkflow(ctx context.Context, req *collection.ProcessingWorkflowRequest) error { req.ValidationConfig = validation.Config{} - err := collection.InitProcessingWorkflow(ctx, s.cc, req) + err := collection.InitProcessingWorkflow(ctx, s.cc, s.taskQueue, req) if err != nil { s.logger.Error(err, "Error initializing processing workflow.") } diff --git a/internal/batch/service_test.go b/internal/batch/service_test.go index d2116e75..547bf7a9 100644 --- a/internal/batch/service_test.go +++ b/internal/batch/service_test.go @@ -7,16 +7,22 @@ import ( "github.com/go-logr/logr" "github.com/stretchr/testify/mock" - cadencesdk_gen_shared "go.uber.org/cadence/.gen/go/shared" - cadencesdk_mocks "go.uber.org/cadence/mocks" - cadencesdk_workflow "go.uber.org/cadence/workflow" + temporalapi_common "go.temporal.io/api/common/v1" + temporalapi_enums "go.temporal.io/api/enums/v1" + temporalapi_serviceerror "go.temporal.io/api/serviceerror" + temporalapi_workflow "go.temporal.io/api/workflow/v1" + temporalapi_workflowservice "go.temporal.io/api/workflowservice/v1" + temporalsdk_mocks "go.temporal.io/sdk/mocks" "gotest.tools/v3/assert" goabatch "github.com/artefactual-labs/enduro/internal/api/gen/batch" "github.com/artefactual-labs/enduro/internal/collection" ) -var completedDirs = []string{"/tmp/xyz"} +var ( + completedDirs = []string{"/tmp/xyz"} + taskQueue = "global" +) func TestBatchServiceSubmit(t *testing.T) { ctx := context.Background() @@ -24,8 +30,8 @@ func TestBatchServiceSubmit(t *testing.T) { pipeline := "am" t.Run("Fails with empty or invalid parameters parameters", func(t *testing.T) { - client := &cadencesdk_mocks.Client{} - batchsvc := NewService(logger, client, completedDirs) + client := &temporalsdk_mocks.Client{} + batchsvc := NewService(logger, client, taskQueue, completedDirs) _, err := batchsvc.Submit(ctx, &goabatch.SubmitPayload{Pipeline: &pipeline}) assert.Error(t, err, "error starting batch - path is empty") @@ -35,13 +41,40 @@ func TestBatchServiceSubmit(t *testing.T) { assert.Error(t, err, "error starting batch - retention period format is invalid") }) - t.Run("Fails with empty parameters", func(t *testing.T) { - client := &cadencesdk_mocks.Client{} + t.Run("Fails when workflow engine is unavailable", func(t *testing.T) { + client := &temporalsdk_mocks.Client{} + + client.On( + "ExecuteWorkflow", + mock.AnythingOfType("*context.emptyCtx"), + mock.AnythingOfType("internal.StartWorkflowOptions"), + mock.AnythingOfType("string"), + mock.AnythingOfType("batch.BatchWorkflowInput"), + ).Return( + &temporalsdk_mocks.WorkflowRun{}, + &temporalapi_serviceerror.InvalidArgument{}, + ) + + batchsvc := NewService(logger, client, taskQueue, completedDirs) + _, err := batchsvc.Submit(ctx, &goabatch.SubmitPayload{Path: "asdf"}) + + assert.ErrorContains(t, err, "error starting batch") + }) + + t.Run("Returns batch result", func(t *testing.T) { + client := &temporalsdk_mocks.Client{} processingConfig, completedDir, retentionPeriod := "default", "/tmp", "2h" + workflowRun := &temporalsdk_mocks.WorkflowRun{} + workflowRun.On("GetID").Return("batch-workflow") + workflowRun.On("GetRunID").Return("some-run-id") + dur := time.Duration(time.Hour * 2) client.On( - "StartWorkflow", mock.Anything, mock.Anything, "batch-workflow", + "ExecuteWorkflow", + mock.AnythingOfType("*context.emptyCtx"), + mock.AnythingOfType("internal.StartWorkflowOptions"), + "batch-workflow", BatchWorkflowInput{ Path: "/some/path", PipelineName: "am", @@ -50,13 +83,10 @@ func TestBatchServiceSubmit(t *testing.T) { RetentionPeriod: &dur, }, ).Return( - &cadencesdk_workflow.Execution{ - ID: "batch-workflow", - RunID: "some-run-id", - }, nil, + workflowRun, nil, ) - batchsvc := NewService(logger, client, completedDirs) + batchsvc := NewService(logger, client, taskQueue, completedDirs) result, err := batchsvc.Submit(ctx, &goabatch.SubmitPayload{ Path: "/some/path", Pipeline: &pipeline, @@ -79,30 +109,30 @@ func TestBatchServiceStatus(t *testing.T) { wid, rid := "batch-workflow", "some-run-id" t.Run("Fails if the workflow information is unavailable", func(t *testing.T) { - client := &cadencesdk_mocks.Client{} - client.On("DescribeWorkflowExecution", mock.Anything, "batch-workflow", "").Return(nil, &cadencesdk_gen_shared.ServiceBusyError{}) + client := &temporalsdk_mocks.Client{} + client.On("DescribeWorkflowExecution", mock.AnythingOfType("*context.emptyCtx"), "batch-workflow", "").Return(nil, &temporalapi_serviceerror.Unavailable{}) - batchsvc := NewService(logger, client, completedDirs) + batchsvc := NewService(logger, client, taskQueue, completedDirs) _, err := batchsvc.Status(ctx) assert.ErrorIs(t, err, ErrBatchStatusUnavailable) }) t.Run("Fails if the workflow information is incomplete", func(t *testing.T) { - client := &cadencesdk_mocks.Client{} - client.On("DescribeWorkflowExecution", mock.Anything, "batch-workflow", "").Return(&cadencesdk_gen_shared.DescribeWorkflowExecutionResponse{}, nil) + client := &temporalsdk_mocks.Client{} + client.On("DescribeWorkflowExecution", mock.AnythingOfType("*context.emptyCtx"), "batch-workflow", "").Return(&temporalapi_workflowservice.DescribeWorkflowExecutionResponse{}, nil) - batchsvc := NewService(logger, client, completedDirs) + batchsvc := NewService(logger, client, taskQueue, completedDirs) _, err := batchsvc.Status(ctx) assert.ErrorIs(t, err, ErrBatchStatusUnavailable) }) t.Run("Identifies a non-running batch", func(t *testing.T) { - client := &cadencesdk_mocks.Client{} - client.On("DescribeWorkflowExecution", mock.Anything, "batch-workflow", "").Return(nil, &cadencesdk_gen_shared.EntityNotExistsError{}) + client := &temporalsdk_mocks.Client{} + client.On("DescribeWorkflowExecution", mock.AnythingOfType("*context.emptyCtx"), "batch-workflow", "").Return(nil, &temporalapi_serviceerror.NotFound{}) - batchsvc := NewService(logger, client, completedDirs) + batchsvc := NewService(logger, client, taskQueue, completedDirs) result, err := batchsvc.Status(ctx) assert.NilError(t, err) @@ -112,17 +142,18 @@ func TestBatchServiceStatus(t *testing.T) { }) t.Run("Identifies a running batch", func(t *testing.T) { - client := &cadencesdk_mocks.Client{} - client.On("DescribeWorkflowExecution", mock.Anything, "batch-workflow", "").Return(&cadencesdk_gen_shared.DescribeWorkflowExecutionResponse{ - WorkflowExecutionInfo: &cadencesdk_gen_shared.WorkflowExecutionInfo{ - Execution: &cadencesdk_gen_shared.WorkflowExecution{ - WorkflowId: &wid, - RunId: &rid, + client := &temporalsdk_mocks.Client{} + client.On("DescribeWorkflowExecution", mock.AnythingOfType("*context.emptyCtx"), "batch-workflow", "").Return(&temporalapi_workflowservice.DescribeWorkflowExecutionResponse{ + WorkflowExecutionInfo: &temporalapi_workflow.WorkflowExecutionInfo{ + Execution: &temporalapi_common.WorkflowExecution{ + WorkflowId: wid, + RunId: rid, }, + Status: temporalapi_enums.WORKFLOW_EXECUTION_STATUS_RUNNING, }, }, nil) - batchsvc := NewService(logger, client, completedDirs) + batchsvc := NewService(logger, client, taskQueue, completedDirs) result, err := batchsvc.Status(ctx) assert.NilError(t, err) @@ -134,18 +165,18 @@ func TestBatchServiceStatus(t *testing.T) { }) t.Run("Identifies a closed batch", func(t *testing.T) { - client := &cadencesdk_mocks.Client{} - client.On("DescribeWorkflowExecution", mock.Anything, "batch-workflow", "").Return(&cadencesdk_gen_shared.DescribeWorkflowExecutionResponse{ - WorkflowExecutionInfo: &cadencesdk_gen_shared.WorkflowExecutionInfo{ - Execution: &cadencesdk_gen_shared.WorkflowExecution{ - WorkflowId: &wid, - RunId: &rid, + client := &temporalsdk_mocks.Client{} + client.On("DescribeWorkflowExecution", mock.AnythingOfType("*context.emptyCtx"), "batch-workflow", "").Return(&temporalapi_workflowservice.DescribeWorkflowExecutionResponse{ + WorkflowExecutionInfo: &temporalapi_workflow.WorkflowExecutionInfo{ + Execution: &temporalapi_common.WorkflowExecution{ + WorkflowId: wid, + RunId: rid, }, - CloseStatus: cadencesdk_gen_shared.WorkflowExecutionCloseStatusCompleted.Ptr(), + Status: temporalapi_enums.WORKFLOW_EXECUTION_STATUS_COMPLETED, }, }, nil) - batchsvc := NewService(logger, client, completedDirs) + batchsvc := NewService(logger, client, taskQueue, completedDirs) result, err := batchsvc.Status(ctx) st := "completed" @@ -162,9 +193,9 @@ func TestBatchServiceStatus(t *testing.T) { func TestBatchServiceHints(t *testing.T) { ctx := context.Background() logger := logr.Discard() - client := &cadencesdk_mocks.Client{} + client := &temporalsdk_mocks.Client{} - batchsvc := NewService(logger, client, completedDirs) + batchsvc := NewService(logger, client, taskQueue, completedDirs) result, err := batchsvc.Hints(ctx) assert.NilError(t, err) @@ -176,20 +207,20 @@ func TestBatchServiceHints(t *testing.T) { func TestBatchServiceInitProcessingWorkflow(t *testing.T) { ctx := context.Background() logger := logr.Discard() - client := &cadencesdk_mocks.Client{} + client := &temporalsdk_mocks.Client{} client.On( - "StartWorkflow", + "ExecuteWorkflow", mock.AnythingOfType("*context.timerCtx"), mock.AnythingOfType("internal.StartWorkflowOptions"), mock.AnythingOfType("string"), mock.AnythingOfType("*collection.ProcessingWorkflowRequest"), ).Return( nil, - &cadencesdk_gen_shared.InternalServiceError{}, + &temporalapi_serviceerror.Internal{}, ) - batchsvc := NewService(logger, client, completedDirs) + batchsvc := NewService(logger, client, taskQueue, completedDirs) err := batchsvc.InitProcessingWorkflow(ctx, &collection.ProcessingWorkflowRequest{}) - assert.ErrorType(t, err, &cadencesdk_gen_shared.InternalServiceError{}) + assert.ErrorType(t, err, &temporalapi_serviceerror.Internal{}) } diff --git a/internal/batch/workflow.go b/internal/batch/workflow.go index 7bed41b4..49c0e2c7 100644 --- a/internal/batch/workflow.go +++ b/internal/batch/workflow.go @@ -5,10 +5,11 @@ import ( "os" "time" - cadencesdk_workflow "go.uber.org/cadence/workflow" + temporalsdk_temporal "go.temporal.io/sdk/temporal" + temporalsdk_workflow "go.temporal.io/sdk/workflow" "github.com/artefactual-labs/enduro/internal/collection" - wferrors "github.com/artefactual-labs/enduro/internal/workflow/errors" + "github.com/artefactual-labs/enduro/internal/temporal" ) const ( @@ -29,13 +30,15 @@ type BatchWorkflowInput struct { RetentionPeriod *time.Duration } -func BatchWorkflow(ctx cadencesdk_workflow.Context, params BatchWorkflowInput) error { - opts := cadencesdk_workflow.WithActivityOptions(ctx, cadencesdk_workflow.ActivityOptions{ - ScheduleToStartTimeout: time.Hour * 24 * 365, - StartToCloseTimeout: time.Hour * 24 * 365, - WaitForCancellation: true, +func BatchWorkflow(ctx temporalsdk_workflow.Context, params BatchWorkflowInput) error { + opts := temporalsdk_workflow.WithActivityOptions(ctx, temporalsdk_workflow.ActivityOptions{ + StartToCloseTimeout: time.Hour * 24 * 365, + WaitForCancellation: true, + RetryPolicy: &temporalsdk_temporal.RetryPolicy{ + MaximumAttempts: 1, + }, }) - return cadencesdk_workflow.ExecuteActivity(opts, BatchActivityName, params).Get(opts, nil) + return temporalsdk_workflow.ExecuteActivity(opts, BatchActivityName, params).Get(opts, nil) } type BatchActivity struct { @@ -51,7 +54,7 @@ func NewBatchActivity(batchsvc Service) *BatchActivity { func (a *BatchActivity) Execute(ctx context.Context, params BatchWorkflowInput) error { files, err := os.ReadDir(params.Path) if err != nil { - return wferrors.NonRetryableError(err) + return temporal.NewNonRetryableError(err) } pipelines := []string{} if params.PipelineName != "" { diff --git a/internal/batch/workflow_test.go b/internal/batch/workflow_test.go index 13ded8e1..7d93e2b4 100644 --- a/internal/batch/workflow_test.go +++ b/internal/batch/workflow_test.go @@ -69,5 +69,5 @@ func TestBatchActivityFailsWithBogusBatchPath(t *testing.T) { Path: "/non/existent/path", PipelineName: "am", }) - assert.Error(t, err, "non retryable error") + assert.Error(t, err, "open /non/existent/path: no such file or directory") } diff --git a/internal/cadence/cadence.go b/internal/cadence/cadence.go deleted file mode 100644 index 4694ed61..00000000 --- a/internal/cadence/cadence.go +++ /dev/null @@ -1,94 +0,0 @@ -/* -Package cadence provide some utilities to interact with Cadence. -*/ -package cadence - -import ( - "fmt" - - "github.com/uber-go/tally" - cadencesdk_gen_workflowserviceclient "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient" - cadencesdk_client "go.uber.org/cadence/client" - cadencesdk_worker "go.uber.org/cadence/worker" - "go.uber.org/yarpc" - "go.uber.org/yarpc/transport/tchannel" - "go.uber.org/zap" -) - -const ( - // This is the task list name we use to identify our global client worker. - // It also identifies the group of workflow and activity implementations - // that are hosted by a single worker process. - GlobalTaskListName = "global" - - // Name of the Cadence service, used by YARPC. - cadenceServiceName = "cadence-frontend" -) - -type Config struct { - Domain string - Address string -} - -func NewWorker(logger *zap.Logger, appName string, config Config) (cadencesdk_worker.Worker, error) { - svc, err := serviceClient(logger, appName, config.Address) - if err != nil { - return nil, err - } - opts := cadencesdk_worker.Options{ - MetricsScope: tally.NoopScope, - Logger: logger, - EnableSessionWorker: true, - MaxConcurrentSessionExecutionSize: 5000, - } - return cadencesdk_worker.New(svc, config.Domain, GlobalTaskListName, opts), nil -} - -// NewWorkflowClient returns a new Cadence client. -func NewWorkflowClient(logger *zap.Logger, appName string, config Config) (cadencesdk_client.Client, error) { - svc, err := serviceClient(logger, appName, config.Address) - if err != nil { - return nil, err - } - opts := &cadencesdk_client.Options{ - MetricsScope: tally.NoopScope, - } - return cadencesdk_client.NewClient(svc, config.Domain, opts), nil -} - -// NewDomainClient returns a Cadence Domain client. -func NewDomainClient(logger *zap.Logger, appName string, config Config) (cadencesdk_client.DomainClient, error) { - svc, err := serviceClient(logger, appName, config.Address) - if err != nil { - return nil, err - } - opts := &cadencesdk_client.Options{ - MetricsScope: tally.NoopScope, - } - return cadencesdk_client.NewDomainClient(svc, opts), nil -} - -// serviceClient returns a new client for the WorkflowService service. -func serviceClient(logger *zap.Logger, appName, addr string) (cadencesdk_gen_workflowserviceclient.Interface, error) { - ch, err := tchannel.NewChannelTransport( - tchannel.ServiceName(appName), - tchannel.Logger(logger), - ) - if err != nil { - return nil, fmt.Errorf("failed to set up tchannel: %w", err) - } - - dispatcher := yarpc.NewDispatcher(yarpc.Config{ - Name: appName, - Outbounds: yarpc.Outbounds{ - cadenceServiceName: { - Unary: ch.NewSingleOutbound(addr), - }, - }, - }) - if err := dispatcher.Start(); err != nil { - return nil, fmt.Errorf("failed to start yarpc dispatcher: %w", err) - } - - return cadencesdk_gen_workflowserviceclient.New(dispatcher.ClientConfig(cadenceServiceName)), nil -} diff --git a/internal/cadence/history.go b/internal/cadence/history.go deleted file mode 100644 index 30a9add7..00000000 --- a/internal/cadence/history.go +++ /dev/null @@ -1,45 +0,0 @@ -package cadence - -import ( - "context" - "errors" - "fmt" - - cadencesdk_gen_shared "go.uber.org/cadence/.gen/go/shared" - cadencesdk_client "go.uber.org/cadence/client" -) - -func HistoryEvents(ctx context.Context, cc cadencesdk_client.Client, exec *cadencesdk_gen_shared.WorkflowExecution, poll bool) ([]*cadencesdk_gen_shared.HistoryEvent, error) { - iter := cc.GetWorkflowHistory(ctx, exec.GetWorkflowId(), exec.GetRunId(), poll, cadencesdk_gen_shared.HistoryEventFilterTypeAllEvent) - var events []*cadencesdk_gen_shared.HistoryEvent - for iter.HasNext() { - event, err := iter.Next() - if err != nil { - return nil, fmt.Errorf("error looking up history events: %w", err) - } - - events = append(events, event) - } - - if len(events) == 0 { - return nil, errors.New("error looking up history events: history is empty") - } - - return events, nil -} - -func FirstHistoryEvent(ctx context.Context, cc cadencesdk_client.Client, exec *cadencesdk_gen_shared.WorkflowExecution) (event *cadencesdk_gen_shared.HistoryEvent, err error) { - const polling = false - iter := cc.GetWorkflowHistory(ctx, exec.GetWorkflowId(), exec.GetRunId(), polling, cadencesdk_gen_shared.HistoryEventFilterTypeAllEvent) - - for iter.HasNext() { - event, err = iter.Next() - if err != nil { - return nil, fmt.Errorf("error looking up history events: %w", err) - } else { - break - } - } - - return event, nil -} diff --git a/internal/collection/bulk_workflow.go b/internal/collection/bulk_workflow.go index 4d73e947..02d217b0 100644 --- a/internal/collection/bulk_workflow.go +++ b/internal/collection/bulk_workflow.go @@ -2,17 +2,14 @@ package collection import ( "context" - "errors" "fmt" - "strings" "sync" "time" "github.com/oklog/run" - cadencesdk_gen_shared "go.uber.org/cadence/.gen/go/shared" - cadencesdk_activity "go.uber.org/cadence/activity" - cadencesdk_workflow "go.uber.org/cadence/workflow" - "go.uber.org/yarpc/yarpcerrors" + temporalsdk_activity "go.temporal.io/sdk/activity" + temporalsdk_temporal "go.temporal.io/sdk/temporal" + temporalsdk_workflow "go.temporal.io/sdk/workflow" "github.com/artefactual-labs/enduro/internal/api/gen/collection" ) @@ -50,16 +47,18 @@ type BulkWorkflowInput struct { Size uint } -// BulkWorkflow is a Cadence workflow that performs bulk operations. -func BulkWorkflow(ctx cadencesdk_workflow.Context, params BulkWorkflowInput) error { - opts := cadencesdk_workflow.WithActivityOptions(ctx, cadencesdk_workflow.ActivityOptions{ - ScheduleToStartTimeout: time.Hour * 24 * 365, - StartToCloseTimeout: time.Hour * 24 * 365, - WaitForCancellation: true, - HeartbeatTimeout: time.Second * 5, +// BulkWorkflow is a Temporal workflow that performs bulk operations. +func BulkWorkflow(ctx temporalsdk_workflow.Context, params BulkWorkflowInput) error { + opts := temporalsdk_workflow.WithActivityOptions(ctx, temporalsdk_workflow.ActivityOptions{ + StartToCloseTimeout: time.Hour * 24 * 365, + WaitForCancellation: true, + HeartbeatTimeout: time.Second * 5, + RetryPolicy: &temporalsdk_temporal.RetryPolicy{ + MaximumAttempts: 1, + }, }) - return cadencesdk_workflow.ExecuteActivity(opts, BulkActivityName, params).Get(opts, nil) + return temporalsdk_workflow.ExecuteActivity(opts, BulkActivityName, params).Get(opts, nil) } type BulkActivity struct { @@ -98,7 +97,7 @@ func (a *BulkActivity) Execute(ctx context.Context, params BulkWorkflowInput) er cp := progress mu.RUnlock() - cadencesdk_activity.RecordHeartbeat(ctx, cp) + temporalsdk_activity.RecordHeartbeat(ctx, cp) } } }, @@ -181,27 +180,12 @@ func (a *BulkActivity) Retry(ctx context.Context, ID uint) error { err := a.colsvc.Goa().Retry(ctx, &collection.RetryPayload{ID: ID}) // User may have already started it manually. - var werr *cadencesdk_gen_shared.WorkflowExecutionAlreadyStartedError - if errors.As(err, &werr) { + if temporalsdk_temporal.IsWorkflowExecutionAlreadyStartedError(err) { return nil } - // Cadence seems to retry on cases where we'd rather give up right away, - // e.g. when the history is unavailable. - var yarpcerr *yarpcerrors.Status - if errors.As(err, &yarpcerr) { - switch yarpcerr.Code() { - case yarpcerrors.CodeInternal: - if strings.Contains(yarpcerr.Message(), "requested workflow history does not exist") { - return nil - } - case yarpcerrors.CodeDeadlineExceeded: - // At some point I'm seeing the timeout to be exceeded while the - // underlying error (presumably history does not exist) is not - // visible. - return nil - } - } + // TODO: ignore the error returned when the workflow history does not exist, + // which is something that we used to do in Temporal. return err } diff --git a/internal/collection/collection.go b/internal/collection/collection.go index 5600b4fe..e8c84178 100644 --- a/internal/collection/collection.go +++ b/internal/collection/collection.go @@ -9,7 +9,7 @@ import ( "github.com/go-logr/logr" "github.com/jmoiron/sqlx" - cadencesdk_client "go.uber.org/cadence/client" + temporalsdk_client "go.temporal.io/sdk/client" goahttp "goa.design/goa/v3/http" goacollection "github.com/artefactual-labs/enduro/internal/api/gen/collection" @@ -36,9 +36,10 @@ type Service interface { } type collectionImpl struct { - logger logr.Logger - db *sqlx.DB - cc cadencesdk_client.Client + logger logr.Logger + db *sqlx.DB + cc temporalsdk_client.Client + taskQueue string registry *pipeline.Registry @@ -51,11 +52,12 @@ type collectionImpl struct { var _ Service = (*collectionImpl)(nil) -func NewService(logger logr.Logger, db *sql.DB, cc cadencesdk_client.Client, registry *pipeline.Registry) *collectionImpl { +func NewService(logger logr.Logger, db *sql.DB, cc temporalsdk_client.Client, taskQueue string, registry *pipeline.Registry) *collectionImpl { return &collectionImpl{ logger: logger, db: sqlx.NewDb(db, "mysql"), cc: cc, + taskQueue: taskQueue, registry: registry, downloadProxy: newDownloadReverseProxy(logger), events: NewEventService(), diff --git a/internal/collection/goa.go b/internal/collection/goa.go index 2247b0a9..93780b74 100644 --- a/internal/collection/goa.go +++ b/internal/collection/goa.go @@ -1,7 +1,6 @@ package collection import ( - "bytes" "context" "database/sql" "encoding/json" @@ -11,11 +10,13 @@ import ( "strings" "time" - cadencesdk_gen_shared "go.uber.org/cadence/.gen/go/shared" - cadencesdk_client "go.uber.org/cadence/client" + temporalapi_common "go.temporal.io/api/common/v1" + temporalapi_enums "go.temporal.io/api/enums/v1" + temporalapi_serviceerror "go.temporal.io/api/serviceerror" + temporalsdk_client "go.temporal.io/sdk/client" goacollection "github.com/artefactual-labs/enduro/internal/api/gen/collection" - "github.com/artefactual-labs/enduro/internal/cadence" + "github.com/artefactual-labs/enduro/internal/temporal" ) var ErrBulkStatusUnavailable = errors.New("bulk status unavailable") @@ -214,13 +215,7 @@ func (w *goaWrapper) Cancel(ctx context.Context, payload *goacollection.CancelPa } if err := w.cc.CancelWorkflow(ctx, *goacol.WorkflowID, *goacol.RunID); err != nil { - switch err.(type) { - case *cadencesdk_gen_shared.InternalServiceError: - case *cadencesdk_gen_shared.BadRequestError: - case *cadencesdk_gen_shared.EntityNotExistsError: - case *cadencesdk_gen_shared.WorkflowExecutionAlreadyCompletedError: - // TODO: return custom errors - } + // TODO: return custom errors return err } @@ -231,7 +226,7 @@ func (w *goaWrapper) Cancel(ctx context.Context, payload *goacollection.CancelPa // Retry collection processing by ID. It implements goacollection.Service. // -// TODO: conceptually Cadence workflows should handle retries, i.e. retry could be part of workflow code too (e.g. signals, children, etc). +// TODO: conceptually Temporal workflows should handle retries, i.e. retry could be part of workflow code too (e.g. signals, children, etc). func (w *goaWrapper) Retry(ctx context.Context, payload *goacollection.RetryPayload) error { var err error var goacol *goacollection.EnduroStoredCollection @@ -239,31 +234,35 @@ func (w *goaWrapper) Retry(ctx context.Context, payload *goacollection.RetryPayl return err } - execution := &cadencesdk_gen_shared.WorkflowExecution{ - WorkflowId: goacol.WorkflowID, - RunId: goacol.RunID, + execution := &temporalapi_common.WorkflowExecution{ + WorkflowId: *goacol.WorkflowID, + RunId: *goacol.RunID, } - historyEvent, err := cadence.FirstHistoryEvent(ctx, w.cc, execution) + historyEvent, err := temporal.FirstHistoryEvent(ctx, w.cc, execution) if err != nil { return fmt.Errorf("error loading history of the previous workflow run: %w", err) } - if historyEvent.GetEventType() != cadencesdk_gen_shared.EventTypeWorkflowExecutionStarted { + if historyEvent.GetEventType() != temporalapi_enums.EVENT_TYPE_WORKFLOW_EXECUTION_STARTED { return fmt.Errorf("error loading history of the previous workflow run: initiator state not found") } - input := historyEvent.WorkflowExecutionStartedEventAttributes.Input - attrs := bytes.Split(input, []byte("\n")) - req := &ProcessingWorkflowRequest{} + input := historyEvent.GetWorkflowExecutionStartedEventAttributes().Input + if len(input.Payloads) == 0 { + return errors.New("error loading state of the previous workflow run") + } + eventPayload := input.Payloads[0] + eventAttrs := eventPayload.GetData() - if err := json.Unmarshal(attrs[0], req); err != nil { + req := &ProcessingWorkflowRequest{} + if err := json.Unmarshal(eventAttrs, req); err != nil { return fmt.Errorf("error loading state of the previous workflow run: %w", err) } req.WorkflowID = *goacol.WorkflowID req.CollectionID = goacol.ID - if err := InitProcessingWorkflow(ctx, w.cc, req); err != nil { + if err := InitProcessingWorkflow(ctx, w.cc, w.taskQueue, req); err != nil { return fmt.Errorf("error starting the new workflow instance: %w", err) } @@ -285,7 +284,7 @@ func (w *goaWrapper) Workflow(ctx context.Context, payload *goacollection.Workfl we, err := w.cc.DescribeWorkflowExecution(ctx, *goacol.WorkflowID, *goacol.RunID) if err != nil { switch err.(type) { - case *cadencesdk_gen_shared.EntityNotExistsError: + case *temporalapi_serviceerror.NotFound: return nil, &goacollection.CollectionNotfound{Message: "not_found"} default: return nil, fmt.Errorf("error looking up history: %v", err) @@ -293,19 +292,19 @@ func (w *goaWrapper) Workflow(ctx context.Context, payload *goacollection.Workfl } status := "ACTIVE" - if we.WorkflowExecutionInfo.CloseStatus != nil { - status = we.WorkflowExecutionInfo.CloseStatus.String() + if we.WorkflowExecutionInfo.Status != temporalapi_enums.WORKFLOW_EXECUTION_STATUS_RUNNING { + status = we.WorkflowExecutionInfo.Status.String() } resp.Status = &status - iter := w.cc.GetWorkflowHistory(ctx, *goacol.WorkflowID, *goacol.RunID, false, cadencesdk_gen_shared.HistoryEventFilterTypeAllEvent) + iter := w.cc.GetWorkflowHistory(ctx, *goacol.WorkflowID, *goacol.RunID, false, temporalapi_enums.HISTORY_EVENT_FILTER_TYPE_ALL_EVENT) for iter.HasNext() { event, err := iter.Next() if err != nil { return nil, fmt.Errorf("error looking up history events: %v", err) } - eventID := uint(*event.EventId) + eventID := uint(event.EventId) eventType := event.EventType.String() resp.History = append(resp.History, &goacollection.EnduroCollectionWorkflowHistory{ ID: &eventID, @@ -362,20 +361,19 @@ func (w *goaWrapper) Bulk(ctx context.Context, payload *goacollection.BulkPayloa Size: payload.Size, } - opts := cadencesdk_client.StartWorkflowOptions{ - ID: BulkWorkflowID, - WorkflowIDReusePolicy: cadencesdk_client.WorkflowIDReusePolicyAllowDuplicate, - TaskList: cadence.GlobalTaskListName, - DecisionTaskStartToCloseTimeout: time.Second * 10, - ExecutionStartToCloseTimeout: time.Hour, + opts := temporalsdk_client.StartWorkflowOptions{ + ID: BulkWorkflowID, + WorkflowIDReusePolicy: temporalapi_enums.WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE, + TaskQueue: w.collectionImpl.taskQueue, + WorkflowExecutionTimeout: time.Hour, } - exec, err := w.cc.StartWorkflow(ctx, opts, BulkWorkflowName, input) + exec, err := w.cc.ExecuteWorkflow(ctx, opts, BulkWorkflowName, input) if err != nil { switch err := err.(type) { - case *cadencesdk_gen_shared.WorkflowExecutionAlreadyStartedError: + case *temporalapi_serviceerror.NotFound: return nil, goacollection.MakeNotAvailable( - fmt.Errorf("error starting bulk - operation is already in progress (workflowID=%s runID=%s)", - BulkWorkflowID, *err.RunId)) + fmt.Errorf("error starting bulk - operation is already in progress (workflowID=%s)", BulkWorkflowID), + ) default: w.logger.Info("error starting bulk", "err", err) return nil, fmt.Errorf("error starting bulk") @@ -383,8 +381,8 @@ func (w *goaWrapper) Bulk(ctx context.Context, payload *goacollection.BulkPayloa } return &goacollection.BulkResult{ - WorkflowID: exec.ID, - RunID: exec.RunID, + WorkflowID: exec.GetID(), + RunID: exec.GetRunID(), }, nil } @@ -394,7 +392,7 @@ func (w *goaWrapper) BulkStatus(ctx context.Context) (*goacollection.BulkStatusR resp, err := w.cc.DescribeWorkflowExecution(ctx, BulkWorkflowID, "") if err != nil { switch err := err.(type) { - case *cadencesdk_gen_shared.EntityNotExistsError: + case *temporalapi_serviceerror.NotFound: // We've never seen a workflow run before. return result, nil default: @@ -408,22 +406,22 @@ func (w *goaWrapper) BulkStatus(ctx context.Context) (*goacollection.BulkStatusR return nil, ErrBulkStatusUnavailable } - result.WorkflowID = resp.WorkflowExecutionInfo.Execution.WorkflowId - result.RunID = resp.WorkflowExecutionInfo.Execution.RunId + result.WorkflowID = &resp.WorkflowExecutionInfo.Execution.WorkflowId + result.RunID = &resp.WorkflowExecutionInfo.Execution.RunId if resp.WorkflowExecutionInfo.StartTime != nil { - t := time.Unix(0, *resp.WorkflowExecutionInfo.StartTime).Format(time.RFC3339) + t := resp.WorkflowExecutionInfo.StartTime.Format(time.RFC3339) result.StartedAt = &t } if resp.WorkflowExecutionInfo.CloseTime != nil { - t := time.Unix(0, *resp.WorkflowExecutionInfo.CloseTime).Format(time.RFC3339) + t := resp.WorkflowExecutionInfo.CloseTime.Format(time.RFC3339) result.ClosedAt = &t } // Workflow is not running! - if resp.WorkflowExecutionInfo.CloseStatus != nil { - st := strings.ToLower(resp.WorkflowExecutionInfo.CloseStatus.String()) + if resp.WorkflowExecutionInfo.Status != temporalapi_enums.WORKFLOW_EXECUTION_STATUS_RUNNING { + st := strings.ToLower(resp.WorkflowExecutionInfo.Status.String()) result.Status = &st return result, nil @@ -436,7 +434,8 @@ func (w *goaWrapper) BulkStatus(ctx context.Context) (*goacollection.BulkStatusR if length > 0 { latest := resp.PendingActivities[length-1] progress := &BulkProgress{} - if err := json.Unmarshal(latest.HeartbeatDetails, progress); err == nil { + details := latest.HeartbeatDetails.String() + if err := json.Unmarshal([]byte(details), progress); err == nil { status := fmt.Sprintf("Processing collection %d (done: %d)", progress.CurrentID, progress.Count) result.Status = &status } diff --git a/internal/collection/workflow.go b/internal/collection/workflow.go index f853039f..8492ba9d 100644 --- a/internal/collection/workflow.go +++ b/internal/collection/workflow.go @@ -6,21 +6,14 @@ import ( "time" "github.com/google/uuid" - cadencesdk_client "go.uber.org/cadence/client" + temporalsdk_api_enums "go.temporal.io/api/enums/v1" + temporalsdk_client "go.temporal.io/sdk/client" - "github.com/artefactual-labs/enduro/internal/cadence" "github.com/artefactual-labs/enduro/internal/validation" ) -const ( - // Name of the collection processing workflow. - ProcessingWorkflowName = "processing-workflow" - - // Maximum duration of the processing workflow. Cadence does not support - // workflows with infinite duration for now, but high values are fine. - // Ten years is the timeout we also use in activities (policies.go). - ProcessingWorkflowStartToCloseTimeout = time.Hour * 24 * 365 * 10 -) +// Name of the collection processing workflow. +const ProcessingWorkflowName = "processing-workflow" type ProcessingWorkflowRequest struct { WorkflowID string `json:"-"` @@ -64,7 +57,7 @@ type ProcessingWorkflowRequest struct { ProcessingConfig string } -func InitProcessingWorkflow(ctx context.Context, c cadencesdk_client.Client, req *ProcessingWorkflowRequest) error { +func InitProcessingWorkflow(ctx context.Context, c temporalsdk_client.Client, taskQueue string, req *ProcessingWorkflowRequest) error { if req.WorkflowID == "" { req.WorkflowID = fmt.Sprintf("processing-workflow-%s", uuid.New().String()) } @@ -72,13 +65,12 @@ func InitProcessingWorkflow(ctx context.Context, c cadencesdk_client.Client, req ctx, cancel := context.WithTimeout(ctx, time.Second*5) defer cancel() - opts := cadencesdk_client.StartWorkflowOptions{ - ID: req.WorkflowID, - TaskList: cadence.GlobalTaskListName, - ExecutionStartToCloseTimeout: ProcessingWorkflowStartToCloseTimeout, - WorkflowIDReusePolicy: cadencesdk_client.WorkflowIDReusePolicyAllowDuplicate, + opts := temporalsdk_client.StartWorkflowOptions{ + ID: req.WorkflowID, + TaskQueue: taskQueue, + WorkflowIDReusePolicy: temporalsdk_api_enums.WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE, } - _, err := c.StartWorkflow(ctx, opts, ProcessingWorkflowName, req) + _, err := c.ExecuteWorkflow(ctx, opts, ProcessingWorkflowName, req) return err } diff --git a/internal/nha/activities/hari.go b/internal/nha/activities/hari.go index 51123cb1..b99bb1d9 100644 --- a/internal/nha/activities/hari.go +++ b/internal/nha/activities/hari.go @@ -17,7 +17,7 @@ import ( "time" "github.com/artefactual-labs/enduro/internal/nha" - wferrors "github.com/artefactual-labs/enduro/internal/workflow/errors" + "github.com/artefactual-labs/enduro/internal/temporal" "github.com/artefactual-labs/enduro/internal/workflow/manager" ) @@ -56,7 +56,7 @@ func (a UpdateHARIActivity) Execute(ctx context.Context, params *UpdateHARIActiv apiURL, err := a.url() if err != nil { - return wferrors.NonRetryableError(fmt.Errorf("error in URL construction: %v", err)) + return temporal.NewNonRetryableError(fmt.Errorf("error in URL construction: %v", err)) } mock, _ := manager.HookAttrBool(a.manager.Hooks, "hari", "mock") @@ -68,7 +68,7 @@ func (a UpdateHARIActivity) Execute(ctx context.Context, params *UpdateHARIActiv path := a.avlxml(params.FullPath, params.NameInfo.Type) if path == "" { - return wferrors.NonRetryableError(fmt.Errorf("error reading AVLXML file: not found")) + return temporal.NewNonRetryableError(fmt.Errorf("error reading AVLXML file: not found")) } f, err := os.Open(path) @@ -85,7 +85,7 @@ func (a UpdateHARIActivity) Execute(ctx context.Context, params *UpdateHARIActiv blob, err = io.ReadAll(f) } if err != nil { - return wferrors.NonRetryableError(fmt.Errorf("error reading AVLXML file: %v", err)) + return temporal.NewNonRetryableError(fmt.Errorf("error reading AVLXML file: %v", err)) } } @@ -95,7 +95,7 @@ func (a UpdateHARIActivity) Execute(ctx context.Context, params *UpdateHARIActiv const idtype = "avleveringsidentifikator" parentID, err = readIdentifier(params.FullPath, params.NameInfo.Type.String()+"/journal/avlxml.xml", idtype) if err != nil { - return wferrors.NonRetryableError(fmt.Errorf("error looking up avleveringsidentifikator: %v", err)) + return temporal.NewNonRetryableError(fmt.Errorf("error looking up avleveringsidentifikator: %v", err)) } } } diff --git a/internal/nha/activities/hari_test.go b/internal/nha/activities/hari_test.go index 288fadf4..2c41d4c1 100644 --- a/internal/nha/activities/hari_test.go +++ b/internal/nha/activities/hari_test.go @@ -3,6 +3,7 @@ package activities import ( "context" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -12,13 +13,13 @@ import ( "github.com/go-logr/logr" "github.com/golang/mock/gomock" + temporalsdk_temporal "go.temporal.io/sdk/temporal" "gotest.tools/v3/assert" "gotest.tools/v3/fs" collectionfake "github.com/artefactual-labs/enduro/internal/collection/fake" "github.com/artefactual-labs/enduro/internal/nha" "github.com/artefactual-labs/enduro/internal/pipeline" - "github.com/artefactual-labs/enduro/internal/testutil" watcherfake "github.com/artefactual-labs/enduro/internal/watcher/fake" "github.com/artefactual-labs/enduro/internal/workflow/manager" ) @@ -56,8 +57,8 @@ func TestHARIActivity(t *testing.T) { // handler of the fake HTTP server. wantResponse *serverResponse - // Expected error: see activityError for more. - wantErr testutil.ActivityError + wantNonRetryableError bool + wantErr string }{ "Receipt is delivered successfully (DPJ)": { params: UpdateHARIActivityParams{ @@ -322,9 +323,8 @@ func TestHARIActivity(t *testing.T) { fs.WithDir("DPJ/journal"), fs.WithFile("DPJ/journal/avlxml.xml", ""), }, - wantErr: testutil.ActivityError{ - NRE: true, - }, + wantNonRetryableError: true, + wantErr: "error looking up avleveringsidentifikator: error reading identifier", }, "Failure when identifier cannot be found (DPJ/EPJ/OTHER)": { params: UpdateHARIActivityParams{ @@ -349,10 +349,8 @@ func TestHARIActivity(t *testing.T) { }] }]`), }, - wantErr: testutil.ActivityError{ - Message: "error looking up avleveringsidentifikator: error reading identifier: not found", - NRE: true, - }, + wantNonRetryableError: true, + wantErr: "error looking up avleveringsidentifikator: error reading identifier: not found", }, "Failure when HARI returns a server error": { params: UpdateHARIActivityParams{ @@ -386,10 +384,7 @@ func TestHARIActivity(t *testing.T) { Parent: "12345", XML: []byte(""), }, - wantErr: testutil.ActivityError{ - Message: "error sending request: (unexpected response status: 500 Internal Server Error) - Backend server not available, try again later.\n", - NRE: false, - }, + wantErr: "error sending request: (unexpected response status: 500 Internal Server Error) - Backend server not available, try again later.\n", }, "Unexisten AVLXML file causes error": { params: UpdateHARIActivityParams{ @@ -405,10 +400,8 @@ func TestHARIActivity(t *testing.T) { fs.WithDir("DPJ/journal"), fs.WithFile("DPJ/journal/_____other_name_____.xml", ""), }, - wantErr: testutil.ActivityError{ - Message: "error reading AVLXML file: not found", - NRE: true, - }, + wantErr: "error reading AVLXML file: not found", + wantNonRetryableError: true, }, "Unparseable baseURL is rejected": { params: UpdateHARIActivityParams{ @@ -424,9 +417,8 @@ func TestHARIActivity(t *testing.T) { fs.WithDir("DPJ/journal"), fs.WithFile("DPJ/journal/avlxml.xml", ""), }, - wantErr: testutil.ActivityError{ - NRE: true, - }, + wantErr: "error in URL construction: error looking up baseURL configuration attribute", + wantNonRetryableError: true, }, } @@ -481,11 +473,30 @@ func TestHARIActivity(t *testing.T) { err := act.Execute(context.Background(), &tc.params) - tc.wantErr.Assert(t, err) + testError(t, err, tc.wantErr, tc.wantNonRetryableError) }) } } +func testError(t *testing.T, err error, wantErr string, wantNonRetryable bool) { + t.Helper() + + if wantErr == "" { + assert.NilError(t, err) + return + } + + assert.ErrorContains(t, err, wantErr) + + if !wantNonRetryable { + return + } + var appError *temporalsdk_temporal.ApplicationError + if errors.As(err, &appError) && !appError.NonRetryable() { + t.Fatal("error is not non-retryable") + } +} + func createHariActivity(t *testing.T, hariConfig map[string]interface{}) *UpdateHARIActivity { t.Helper() diff --git a/internal/nha/activities/prod.go b/internal/nha/activities/prod.go index 865dd0ef..193580ad 100644 --- a/internal/nha/activities/prod.go +++ b/internal/nha/activities/prod.go @@ -10,7 +10,7 @@ import ( "time" "github.com/artefactual-labs/enduro/internal/nha" - wferrors "github.com/artefactual-labs/enduro/internal/workflow/errors" + "github.com/artefactual-labs/enduro/internal/temporal" "github.com/artefactual-labs/enduro/internal/workflow/manager" ) @@ -43,7 +43,7 @@ func (a *UpdateProductionSystemActivity) Execute(ctx context.Context, params *Up receiptPath, err := manager.HookAttrString(a.manager.Hooks, "prod", "receiptPath") if err != nil { - return wferrors.NonRetryableError(fmt.Errorf("error looking up receiptPath configuration attribute: %v", err)) + return temporal.NewNonRetryableError(fmt.Errorf("error looking up receiptPath configuration attribute: %v", err)) } basename := filepath.Join(receiptPath, fmt.Sprintf("Receipt_%s_%s", params.NameInfo.Identifier, params.StoredAt.Format(rfc3339forFilename))) @@ -53,7 +53,7 @@ func (a *UpdateProductionSystemActivity) Execute(ctx context.Context, params *Up // Create and open receipt file. file, err := os.OpenFile(jsonPath, os.O_RDWR|os.O_CREATE, os.FileMode(0o644)) if err != nil { - return wferrors.NonRetryableError(fmt.Errorf("error creating receipt file: %v", err)) + return temporal.NewNonRetryableError(fmt.Errorf("error creating receipt file: %v", err)) } var parentID string @@ -62,26 +62,26 @@ func (a *UpdateProductionSystemActivity) Execute(ctx context.Context, params *Up const idtype = "avleveringsidentifikator" parentID, err = readIdentifier(params.FullPath, params.NameInfo.Type.String()+"/journal/avlxml.xml", idtype) if err != nil { - return wferrors.NonRetryableError(fmt.Errorf("error looking up avleveringsidentifikator: %v", err)) + return temporal.NewNonRetryableError(fmt.Errorf("error looking up avleveringsidentifikator: %v", err)) } } } // Write receipt contents. if err := a.generateReceipt(params, file, parentID); err != nil { - return wferrors.NonRetryableError(fmt.Errorf("error writing receipt file: %v", err)) + return temporal.NewNonRetryableError(fmt.Errorf("error writing receipt file: %v", err)) } // Seek to the beginning of the file. if _, err = file.Seek(0, io.SeekStart); err != nil { - return wferrors.NonRetryableError(fmt.Errorf("error resetting receipt file cursor: %v", err)) + return temporal.NewNonRetryableError(fmt.Errorf("error resetting receipt file cursor: %v", err)) } _ = file.Close() // Final rename. if err := os.Rename(jsonPath, mftPath); err != nil { - return wferrors.NonRetryableError(fmt.Errorf("error renaming receipt (json » mft): %v", err)) + return temporal.NewNonRetryableError(fmt.Errorf("error renaming receipt (json » mft): %v", err)) } return nil diff --git a/internal/nha/activities/prod_test.go b/internal/nha/activities/prod_test.go index 0f4884fd..6e2ce5ab 100644 --- a/internal/nha/activities/prod_test.go +++ b/internal/nha/activities/prod_test.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "os" - "path/filepath" "testing" "time" @@ -16,7 +15,6 @@ import ( collectionfake "github.com/artefactual-labs/enduro/internal/collection/fake" "github.com/artefactual-labs/enduro/internal/nha" "github.com/artefactual-labs/enduro/internal/pipeline" - "github.com/artefactual-labs/enduro/internal/testutil" watcherfake "github.com/artefactual-labs/enduro/internal/watcher/fake" "github.com/artefactual-labs/enduro/internal/workflow/manager" ) @@ -29,11 +27,12 @@ func TestProdActivity(t *testing.T) { defer os.RemoveAll(tmpdir) tests := map[string]struct { - params UpdateProductionSystemActivityParams - hookConfig *map[string]interface{} - dirOpts []fs.PathOp - wantContent string - wantErr testutil.ActivityError + params UpdateProductionSystemActivityParams + hookConfig *map[string]interface{} + dirOpts []fs.PathOp + wantContent string + wantNonRetryableError bool + wantErr string }{ "Receipt is generated successfully with status 'done'": { params: UpdateProductionSystemActivityParams{ @@ -97,11 +96,9 @@ func TestProdActivity(t *testing.T) { Type: nha.TransferTypeDPJ, }, }, - hookConfig: &map[string]interface{}{}, - wantErr: testutil.ActivityError{ - Message: "error looking up receiptPath configuration attribute: error accessing \"prod:receiptPath\"", - NRE: true, - }, + hookConfig: &map[string]interface{}{}, + wantErr: "error looking up receiptPath configuration attribute: error accessing \"prod:receiptPath\"", + wantNonRetryableError: true, }, "Unexistent receiptPath is rejected": { params: UpdateProductionSystemActivityParams{ @@ -115,11 +112,8 @@ func TestProdActivity(t *testing.T) { hookConfig: &map[string]interface{}{ "receiptPath": tmpdir, }, - wantErr: testutil.ActivityError{ - Message: fmt.Sprintf("error creating receipt file: open %s: no such file or directory", filepath.Join(tmpdir, "Receipt_aa1df25d-1477-4085-8be3-a17fed20f843_20091110.230000.json")), - MessageWindows: fmt.Sprintf("error creating receipt file: open %s: The system cannot find the path specified.", filepath.Join(tmpdir, "Receipt_aa1df25d-1477-4085-8be3-a17fed20f843_20091110.230000.json")), - NRE: true, - }, + wantErr: "error creating receipt file", + wantNonRetryableError: true, }, } @@ -143,10 +137,10 @@ func TestProdActivity(t *testing.T) { err := act.Execute(context.Background(), &tc.params) - tc.wantErr.Assert(t, err) + testError(t, err, tc.wantErr, tc.wantNonRetryableError) // Stop here if we were expecting the activity to fail. - if !tc.wantErr.IsZero() { + if tc.wantErr != "" { return } diff --git a/internal/temporal/config.go b/internal/temporal/config.go new file mode 100644 index 00000000..8a396cc5 --- /dev/null +++ b/internal/temporal/config.go @@ -0,0 +1,15 @@ +package temporal + +import "github.com/spf13/viper" + +type Config struct { + Address string + Namespace string + TaskQueue string +} + +func SetDefaults(v *viper.Viper) { + v.SetDefault("temporal.address", "127.0.0.1:7233") + v.SetDefault("temporal.namespace", "default") + v.SetDefault("temporal.taskQueue", "global") +} diff --git a/internal/temporal/errors.go b/internal/temporal/errors.go new file mode 100644 index 00000000..177f66ac --- /dev/null +++ b/internal/temporal/errors.go @@ -0,0 +1,19 @@ +package temporal + +import ( + "errors" + + temporalsdk_temporal "go.temporal.io/sdk/temporal" +) + +func NewNonRetryableError(err error) error { + return temporalsdk_temporal.NewNonRetryableApplicationError(err.Error(), "", nil, nil) +} + +func NonRetryableError(err error) bool { + applicationError := &temporalsdk_temporal.ApplicationError{} + if !errors.As(err, &applicationError) { + return false + } + return applicationError.NonRetryable() +} diff --git a/internal/temporal/history.go b/internal/temporal/history.go new file mode 100644 index 00000000..b6e91f35 --- /dev/null +++ b/internal/temporal/history.go @@ -0,0 +1,47 @@ +package temporal + +import ( + "context" + "errors" + "fmt" + + temporalapi_common "go.temporal.io/api/common/v1" + temporalapi_enums "go.temporal.io/api/enums/v1" + temporalapi_history "go.temporal.io/api/history/v1" + temporalsdk_client "go.temporal.io/sdk/client" +) + +func HistoryEvents(ctx context.Context, cc temporalsdk_client.Client, exec *temporalapi_common.WorkflowExecution, poll bool) ([]*temporalapi_history.HistoryEvent, error) { + iter := cc.GetWorkflowHistory(ctx, exec.GetWorkflowId(), exec.GetRunId(), poll, temporalapi_enums.HISTORY_EVENT_FILTER_TYPE_ALL_EVENT) + var events []*temporalapi_history.HistoryEvent + for iter.HasNext() { + event, err := iter.Next() + if err != nil { + return nil, fmt.Errorf("error looking up history events: %w", err) + } + + events = append(events, event) + } + + if len(events) == 0 { + return nil, errors.New("error looking up history events: history is empty") + } + + return events, nil +} + +func FirstHistoryEvent(ctx context.Context, cc temporalsdk_client.Client, exec *temporalapi_common.WorkflowExecution) (event *temporalapi_history.HistoryEvent, err error) { + const polling = false + iter := cc.GetWorkflowHistory(ctx, exec.GetWorkflowId(), exec.GetRunId(), polling, temporalapi_enums.HISTORY_EVENT_FILTER_TYPE_ALL_EVENT) + + for iter.HasNext() { + event, err = iter.Next() + if err != nil { + return nil, fmt.Errorf("error looking up history events: %w", err) + } else { + break + } + } + + return event, nil +} diff --git a/internal/temporal/logging.go b/internal/temporal/logging.go new file mode 100644 index 00000000..f3cf3080 --- /dev/null +++ b/internal/temporal/logging.go @@ -0,0 +1,94 @@ +package temporal + +import ( + "context" + "errors" + + "github.com/go-logr/logr" + "go.temporal.io/sdk/activity" + "go.temporal.io/sdk/interceptor" + "go.temporal.io/sdk/log" +) + +// logrWrapper implements the Temporal logger interface wrapping a logr.Logger. +type logrWrapper struct { + logger logr.Logger +} + +var _ log.Logger = (*logrWrapper)(nil) + +// Logger returns a logger for the Temporal Go SDK. +func Logger(logger logr.Logger) log.Logger { + return logrWrapper{logger.WithCallDepth(1)} +} + +func (l logrWrapper) Debug(msg string, keyvals ...interface{}) { + l.logger.V(1).WithValues("level", "debug").Info(msg, keyvals...) +} + +func (l logrWrapper) Info(msg string, keyvals ...interface{}) { + l.logger.WithValues("level", "info").Info(msg, keyvals...) +} + +func (l logrWrapper) Warn(msg string, keyvals ...interface{}) { + l.logger.WithValues("level", "warn").Info(msg, keyvals...) +} + +func (l logrWrapper) Error(msg string, keyvals ...interface{}) { + l.logger.Error(errors.New(msg), "error", keyvals...) +} + +type workerInterceptor struct { + interceptor.WorkerInterceptorBase + logger logr.Logger +} + +var _ interceptor.WorkerInterceptor = (*workerInterceptor)(nil) + +// NewWorkerInterceptor returns an interceptor that makes the application logger +// available to activities via context. +func NewLoggerInterceptor(logger logr.Logger) *workerInterceptor { + return &workerInterceptor{ + logger: logger, + } +} + +func (w *workerInterceptor) InterceptActivity(ctx context.Context, next interceptor.ActivityInboundInterceptor) interceptor.ActivityInboundInterceptor { + i := &activityInboundInterceptor{ + root: w, + logger: w.logger, + } + i.Next = next + return i +} + +type activityInboundInterceptor struct { + interceptor.ActivityInboundInterceptorBase + root *workerInterceptor + logger logr.Logger +} + +type contextKey struct{} + +var loggerContextKey = contextKey{} + +func (a *activityInboundInterceptor) ExecuteActivity(ctx context.Context, in *interceptor.ExecuteActivityInput) (interface{}, error) { + ctx = context.WithValue(ctx, loggerContextKey, a.logger) + return a.Next.ExecuteActivity(ctx, in) +} + +func GetLogger(ctx context.Context) logr.Logger { + v := ctx.Value(loggerContextKey) + if v == nil { + return logr.Discard() + } + + logger := v.(logr.Logger) + + info := activity.GetInfo(ctx) + + return logger.WithValues( + "ActivityID", info.ActivityID, + "ActivityType", info.ActivityType.Name, + ) +} diff --git a/internal/testutil/activity.go b/internal/testutil/activity.go deleted file mode 100644 index 44619030..00000000 --- a/internal/testutil/activity.go +++ /dev/null @@ -1,93 +0,0 @@ -package testutil - -import ( - "fmt" - "runtime" - "testing" - - cadencesdk "go.uber.org/cadence" - "gotest.tools/v3/assert" - - wferrors "github.com/artefactual-labs/enduro/internal/workflow/errors" -) - -// ActivityError describes an error assertion, where its zero value is a -// non-error. Its Assert method is used to assert against a given error value. -type ActivityError struct { - Message string // Text message. - MessageWindows string // Test message specific to the Windows platform. - NRE bool // Process as a NRE error. -} - -func (ae ActivityError) IsZero() bool { - return ae == ActivityError{} -} - -func (ae ActivityError) Assert(t *testing.T, err error) { - t.Helper() - - // Test for a nil error. - if ae.IsZero() { - ae.AssertNilError(t, err) - return - } - - // Test for a non-retryable error. - if ae.NRE { - ae.assertNonRetryableError(t, err) - return - } - - // Test for a regular error. - assert.Error(t, err, ae.message()) -} - -func (ae ActivityError) message() string { - message := ae.Message - - if runtime.GOOS == "windows" && ae.MessageWindows != "" { - message = ae.MessageWindows - } - - return message -} - -func (ae ActivityError) AssertNilError(t *testing.T, err error) { - t.Helper() - - details := func(err error) string { - if err == nil { - return "" - } - - perr, ok := err.(*cadencesdk.CustomError) - if !ok { - return err.Error() - } - - var result string - if err := perr.Details(&result); err != nil { - return fmt.Sprintf("cannot extract details: %v", err) - } - - return result - } - - assert.NilError(t, err, fmt.Sprintf("error is not nil: %s", details(err))) -} - -func (ae ActivityError) assertNonRetryableError(t *testing.T, err error) { - t.Helper() - - assert.ErrorType(t, err, &cadencesdk.CustomError{}) - assert.Error(t, err, wferrors.NRE) - - // cadence.CustomError has a details field where our test message goes. - var result string - perr := err.(*cadencesdk.CustomError) - assert.NilError(t, perr.Details(&result)) - - if ae.message() != "" { - assert.Equal(t, result, ae.message()) - } -} diff --git a/internal/watcher/event.go b/internal/watcher/event.go index 7300fcee..f818e398 100644 --- a/internal/watcher/event.go +++ b/internal/watcher/event.go @@ -8,7 +8,7 @@ import ( // BlobEvent is a serializable event that describes a blob. // // BlobEvent can be sent over the wire, i.e. they're serializable. Receivers, -// typicially Cadence activities, can download the blob via the service +// typicially Temporal activities, can download the blob via the service // implementation in this package. // // TODO: use signed URLs to simplify access to buckets? diff --git a/internal/workflow/activities/acquire_pipeline.go b/internal/workflow/activities/acquire_pipeline.go index dae7b2c3..3510dd6a 100644 --- a/internal/workflow/activities/acquire_pipeline.go +++ b/internal/workflow/activities/acquire_pipeline.go @@ -6,26 +6,26 @@ import ( "time" "github.com/cenkalti/backoff/v4" - cadencesdk_activity "go.uber.org/cadence/activity" + temporalsdk_activity "go.temporal.io/sdk/activity" - wferrors "github.com/artefactual-labs/enduro/internal/workflow/errors" - "github.com/artefactual-labs/enduro/internal/workflow/manager" + "github.com/artefactual-labs/enduro/internal/pipeline" + "github.com/artefactual-labs/enduro/internal/temporal" ) // AcquirePipelineActivity acquires a lock in the weighted semaphore associated // to a particular pipeline. type AcquirePipelineActivity struct { - manager *manager.Manager + pipelineRegistry *pipeline.Registry } -func NewAcquirePipelineActivity(m *manager.Manager) *AcquirePipelineActivity { - return &AcquirePipelineActivity{manager: m} +func NewAcquirePipelineActivity(pipelineRegistry *pipeline.Registry) *AcquirePipelineActivity { + return &AcquirePipelineActivity{pipelineRegistry: pipelineRegistry} } func (a *AcquirePipelineActivity) Execute(ctx context.Context, pipelineName string) error { - p, err := a.manager.Pipelines.ByName(pipelineName) + p, err := a.pipelineRegistry.ByName(pipelineName) if err != nil { - return wferrors.NonRetryableError(err) + return temporal.NewNonRetryableError(err) } errAcquirePipeline := fmt.Errorf("error acquring semaphore: busy") @@ -41,7 +41,7 @@ func (a *AcquirePipelineActivity) Execute(ctx context.Context, pipelineName stri }, backoff.WithContext(backoff.NewConstantBackOff(time.Second*5), ctx), func(err error, duration time.Duration) { - cadencesdk_activity.RecordHeartbeat(ctx) + temporalsdk_activity.RecordHeartbeat(ctx) }, ) diff --git a/internal/workflow/activities/bundle.go b/internal/workflow/activities/bundle.go index 68746207..4d2578b8 100644 --- a/internal/workflow/activities/bundle.go +++ b/internal/workflow/activities/bundle.go @@ -14,8 +14,8 @@ import ( "github.com/artefactual-labs/enduro/internal/amclient/bundler" "github.com/artefactual-labs/enduro/internal/bagit" + "github.com/artefactual-labs/enduro/internal/temporal" "github.com/artefactual-labs/enduro/internal/watcher" - wferrors "github.com/artefactual-labs/enduro/internal/workflow/errors" "github.com/artefactual-labs/enduro/internal/workflow/manager" ) @@ -51,7 +51,7 @@ func (a *BundleActivity) Execute(ctx context.Context, params *BundleActivityPara defer func() { if err != nil { - err = wferrors.NonRetryableError(err) + err = temporal.NewNonRetryableError(err) } }() @@ -59,7 +59,7 @@ func (a *BundleActivity) Execute(ctx context.Context, params *BundleActivityPara var batchDirIsInTransferDir bool batchDirIsInTransferDir, err = isSubPath(params.TransferDir, params.BatchDir) if err != nil { - return nil, wferrors.NonRetryableError(err) + return nil, temporal.NewNonRetryableError(err) } if batchDirIsInTransferDir { res.FullPath = filepath.Join(params.BatchDir, params.Key) @@ -88,12 +88,12 @@ func (a *BundleActivity) Execute(ctx context.Context, params *BundleActivityPara } } if err != nil { - return nil, wferrors.NonRetryableError(err) + return nil, temporal.NewNonRetryableError(err) } err = unbag(res.FullPath) if err != nil { - return nil, wferrors.NonRetryableError(err) + return nil, temporal.NewNonRetryableError(err) } res.RelPath, err = filepath.Rel(params.TransferDir, res.FullPath) diff --git a/internal/workflow/activities/download.go b/internal/workflow/activities/download.go index 8767d701..73f4ff04 100644 --- a/internal/workflow/activities/download.go +++ b/internal/workflow/activities/download.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - wferrors "github.com/artefactual-labs/enduro/internal/workflow/errors" + "github.com/artefactual-labs/enduro/internal/temporal" "github.com/artefactual-labs/enduro/internal/workflow/manager" ) @@ -20,17 +20,17 @@ func NewDownloadActivity(m *manager.Manager) *DownloadActivity { func (a *DownloadActivity) Execute(ctx context.Context, pipelineName, watcherName, key string) (string, error) { p, err := a.manager.Pipelines.ByName(pipelineName) if err != nil { - return "", wferrors.NonRetryableError(err) + return "", temporal.NewNonRetryableError(err) } file, err := p.TempFile("blob-*") if err != nil { - return "", wferrors.NonRetryableError(fmt.Errorf("error creating temporary file in processing directory: %v", err)) + return "", temporal.NewNonRetryableError(fmt.Errorf("error creating temporary file in processing directory: %v", err)) } defer file.Close() if err := a.manager.Watcher.Download(ctx, file, watcherName, key); err != nil { - return "", wferrors.NonRetryableError(fmt.Errorf("error downloading blob: %v", err)) + return "", temporal.NewNonRetryableError(fmt.Errorf("error downloading blob: %v", err)) } return file.Name(), nil diff --git a/internal/workflow/activities/hide_package.go b/internal/workflow/activities/hide_package.go index 8729e621..6a73dcc9 100644 --- a/internal/workflow/activities/hide_package.go +++ b/internal/workflow/activities/hide_package.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - wferrors "github.com/artefactual-labs/enduro/internal/workflow/errors" + "github.com/artefactual-labs/enduro/internal/temporal" "github.com/artefactual-labs/enduro/internal/workflow/manager" ) @@ -19,12 +19,12 @@ func NewHidePackageActivity(m *manager.Manager) *HidePackageActivity { func (a *HidePackageActivity) Execute(ctx context.Context, unitID, unitType, pipelineName string) error { p, err := a.manager.Pipelines.ByName(pipelineName) if err != nil { - return wferrors.NonRetryableError(err) + return temporal.NewNonRetryableError(err) } amc := p.Client() if unitType != "transfer" && unitType != "ingest" { - return wferrors.NonRetryableError(fmt.Errorf("unexpected unit type: %s", unitType)) + return temporal.NewNonRetryableError(fmt.Errorf("unexpected unit type: %s", unitType)) } if unitType == "transfer" { diff --git a/internal/workflow/activities/poll_ingest.go b/internal/workflow/activities/poll_ingest.go index b21c5275..10195325 100644 --- a/internal/workflow/activities/poll_ingest.go +++ b/internal/workflow/activities/poll_ingest.go @@ -6,20 +6,18 @@ import ( "time" "github.com/cenkalti/backoff/v4" - cadencesdk_activity "go.uber.org/cadence/activity" - "go.uber.org/zap" + temporalsdk_activity "go.temporal.io/sdk/activity" "github.com/artefactual-labs/enduro/internal/pipeline" - wferrors "github.com/artefactual-labs/enduro/internal/workflow/errors" - "github.com/artefactual-labs/enduro/internal/workflow/manager" + "github.com/artefactual-labs/enduro/internal/temporal" ) type PollIngestActivity struct { - manager *manager.Manager + pipelineRegistry *pipeline.Registry } -func NewPollIngestActivity(m *manager.Manager) *PollIngestActivity { - return &PollIngestActivity{manager: m} +func NewPollIngestActivity(pipelineRegistry *pipeline.Registry) *PollIngestActivity { + return &PollIngestActivity{pipelineRegistry: pipelineRegistry} } type PollIngestActivityParams struct { @@ -28,11 +26,11 @@ type PollIngestActivityParams struct { } func (a *PollIngestActivity) Execute(ctx context.Context, params *PollIngestActivityParams) (time.Time, error) { - logger := cadencesdk_activity.GetLogger(ctx) + logger := temporalsdk_activity.GetLogger(ctx) - p, err := a.manager.Pipelines.ByName(params.PipelineName) + p, err := a.pipelineRegistry.ByName(params.PipelineName) if err != nil { - return time.Time{}, wferrors.NonRetryableError(err) + return time.Time{}, temporal.NewNonRetryableError(err) } amc := p.Client() @@ -53,7 +51,7 @@ func (a *PollIngestActivity) Execute(ctx context.Context, params *PollIngestActi // Abandon when we see a non-retryable error. if errors.Is(err, pipeline.ErrStatusNonRetryable) { - return backoff.Permanent(wferrors.NonRetryableError(err)) + return backoff.Permanent(temporal.NewNonRetryableError(err)) } // Looking good, keep polling. @@ -63,21 +61,21 @@ func (a *PollIngestActivity) Execute(ctx context.Context, params *PollIngestActi } if err != nil { - logger.Error("Failed to look up Ingest status.", zap.Error(err)) + logger.Error("Failed to look up Ingest status.", "error", err) } // Retry unless the deadline was exceeded. if lastRetryableError.IsZero() { lastRetryableError = clock.Now() } else if clock.Since(lastRetryableError) > deadline { - return backoff.Permanent(wferrors.NonRetryableError(err)) + return backoff.Permanent(temporal.NewNonRetryableError(err)) } return err }, backoffStrategy, func(err error, duration time.Duration) { - cadencesdk_activity.RecordHeartbeat(ctx, err.Error()) + temporalsdk_activity.RecordHeartbeat(ctx, err.Error()) }, ) diff --git a/internal/workflow/activities/poll_ingest_test.go b/internal/workflow/activities/poll_ingest_test.go index b3a9c8af..f1c44682 100644 --- a/internal/workflow/activities/poll_ingest_test.go +++ b/internal/workflow/activities/poll_ingest_test.go @@ -8,47 +8,47 @@ import ( "github.com/go-logr/logr" "github.com/jonboulle/clockwork" - cadencesdk_testsuite "go.uber.org/cadence/testsuite" - cadencesdk_worker "go.uber.org/cadence/worker" + temporalsdk_testsuite "go.temporal.io/sdk/testsuite" + temporalsdk_worker "go.temporal.io/sdk/worker" "gotest.tools/v3/assert" - is "gotest.tools/v3/assert/cmp" "github.com/artefactual-labs/enduro/internal/pipeline" + "github.com/artefactual-labs/enduro/internal/temporal" ) func TestPollIngestActivity(t *testing.T) { t.Run("Fails when the pipeline isn't found", func(t *testing.T) { - manager := newManager(t, nil) - activity := NewPollIngestActivity(manager) - manager.Pipelines, _ = pipeline.NewPipelineRegistry(logr.Discard(), []pipeline.Config{}) + pipelineRegistry, _ := pipeline.NewPipelineRegistry(logr.Discard(), []pipeline.Config{}) + activity := NewPollIngestActivity(pipelineRegistry) - s := cadencesdk_testsuite.WorkflowTestSuite{} + s := temporalsdk_testsuite.WorkflowTestSuite{} env := s.NewTestActivityEnvironment() env.RegisterActivity(activity.Execute) future, err := env.ExecuteActivity(activity.Execute, &PollIngestActivityParams{}) - assert.Assert(t, is.Nil(future)) - assert.Error(t, err, "non retryable error") + assert.Assert(t, future == nil) + assert.ErrorContains(t, err, "unknown pipeline") + assert.Assert(t, temporal.NonRetryableError(err) == true) }) t.Run("Identifies packages that completed processing successfully", func(t *testing.T) { ctx := context.Background() now := time.Now() clock = clockwork.NewFakeClockAt(now) - manager := newManager(t, func(w http.ResponseWriter, r *http.Request) { + pipelineRegistry := newPipelineRegistry(t, func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte(`{ "sip_uuid": "734abbaf-4e2f-4a68-938c-c8ff6420e525", "status": "COMPLETE" }`)) }) - activity := NewPollIngestActivity(manager) + activity := NewPollIngestActivity(pipelineRegistry) - s := cadencesdk_testsuite.WorkflowTestSuite{} + s := temporalsdk_testsuite.WorkflowTestSuite{} env := s.NewTestActivityEnvironment() env.RegisterActivity(activity.Execute) - env.SetWorkerOptions(cadencesdk_worker.Options{BackgroundActivityContext: ctx}) + env.SetWorkerOptions(temporalsdk_worker.Options{BackgroundActivityContext: ctx}) var storedAt time.Time future, err := env.ExecuteActivity(activity.Execute, &PollIngestActivityParams{ @@ -63,30 +63,31 @@ func TestPollIngestActivity(t *testing.T) { t.Run("Abandons when a non-retryable error is detected", func(t *testing.T) { ctx := context.Background() - manager := newManager(t, func(w http.ResponseWriter, r *http.Request) { + pipelineRegistry := newPipelineRegistry(t, func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusUnauthorized) }) - activity := NewPollIngestActivity(manager) + activity := NewPollIngestActivity(pipelineRegistry) - s := cadencesdk_testsuite.WorkflowTestSuite{} + s := temporalsdk_testsuite.WorkflowTestSuite{} env := s.NewTestActivityEnvironment() env.RegisterActivity(activity.Execute) - env.SetWorkerOptions(cadencesdk_worker.Options{BackgroundActivityContext: ctx}) + env.SetWorkerOptions(temporalsdk_worker.Options{BackgroundActivityContext: ctx}) future, err := env.ExecuteActivity(activity.Execute, &PollIngestActivityParams{ PipelineName: "am", SIPID: "cbc4b312-b076-4ff7-b67b-b6850f2b4486", }) - assert.Assert(t, is.Nil(future)) - assert.Error(t, err, "non retryable error") + assert.Assert(t, future == nil) + assert.ErrorContains(t, err, "error checking ingest status: server error") + assert.Assert(t, temporal.NonRetryableError(err) == true) }) t.Run("Polls until processing completes", func(t *testing.T) { ctx := context.Background() backoffStrategy = &ZeroBackOff{} attempts := 0 - manager := newManager(t, func(w http.ResponseWriter, r *http.Request) { + pipelineRegistry := newPipelineRegistry(t, func(w http.ResponseWriter, r *http.Request) { attempts++ if attempts > 3 { w.WriteHeader(http.StatusOK) @@ -102,12 +103,12 @@ func TestPollIngestActivity(t *testing.T) { "status": "PROCESSING" }`)) }) - activity := NewPollIngestActivity(manager) + activity := NewPollIngestActivity(pipelineRegistry) - s := cadencesdk_testsuite.WorkflowTestSuite{} + s := temporalsdk_testsuite.WorkflowTestSuite{} env := s.NewTestActivityEnvironment() env.RegisterActivity(activity.Execute) - env.SetWorkerOptions(cadencesdk_worker.Options{BackgroundActivityContext: ctx}) + env.SetWorkerOptions(temporalsdk_worker.Options{BackgroundActivityContext: ctx}) _, err := env.ExecuteActivity(activity.Execute, &PollIngestActivityParams{ PipelineName: "am", @@ -123,25 +124,26 @@ func TestPollIngestActivity(t *testing.T) { backoffStrategy = &ZeroBackOff{} clock = clockwork.NewFakeClock() attempts := 0 - manager := newManager(t, func(w http.ResponseWriter, r *http.Request) { + pipelineRegistry := newPipelineRegistry(t, func(w http.ResponseWriter, r *http.Request) { attempts++ clock.(clockwork.FakeClock).Advance(time.Minute) w.WriteHeader(http.StatusBadGateway) }) - activity := NewPollIngestActivity(manager) + activity := NewPollIngestActivity(pipelineRegistry) - s := cadencesdk_testsuite.WorkflowTestSuite{} + s := temporalsdk_testsuite.WorkflowTestSuite{} env := s.NewTestActivityEnvironment() env.RegisterActivity(activity.Execute) - env.SetWorkerOptions(cadencesdk_worker.Options{BackgroundActivityContext: ctx}) + env.SetWorkerOptions(temporalsdk_worker.Options{BackgroundActivityContext: ctx}) future, err := env.ExecuteActivity(activity.Execute, &PollIngestActivityParams{ PipelineName: "am", SIPID: "734abbaf-4e2f-4a68-938c-c8ff6420e525", }) - assert.Assert(t, is.Nil(future)) - assert.Error(t, err, "non retryable error") + assert.Assert(t, future == nil) + assert.Assert(t, temporal.NonRetryableError(err) == true) + assert.ErrorContains(t, err, "error checking ingest status") assert.Equal(t, backoffStrategy.(*ZeroBackOff).hits, 6) }) } diff --git a/internal/workflow/activities/poll_test.go b/internal/workflow/activities/poll_test.go index 46448a54..fa91e828 100644 --- a/internal/workflow/activities/poll_test.go +++ b/internal/workflow/activities/poll_test.go @@ -11,7 +11,6 @@ import ( "gotest.tools/v3/assert" "github.com/artefactual-labs/enduro/internal/pipeline" - "github.com/artefactual-labs/enduro/internal/workflow/manager" ) type ZeroBackOff struct { @@ -25,8 +24,9 @@ func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 } -func newManager(t *testing.T, h http.HandlerFunc) *manager.Manager { +func newPipelineRegistry(t *testing.T, h http.HandlerFunc) *pipeline.Registry { t.Helper() + logger := logr.Discard() mux := http.NewServeMux() @@ -39,7 +39,7 @@ func newManager(t *testing.T, h http.HandlerFunc) *manager.Manager { retryDeadline := time.Duration(time.Minute * 5) pipelineURL, _ := url.Parse(server.URL) - pipelines, err := pipeline.NewPipelineRegistry(logger, []pipeline.Config{ + pipelineRegistry, err := pipeline.NewPipelineRegistry(logger, []pipeline.Config{ { ID: "75ed5f0a-792e-4ce9-aeb7-e2e832d2a4fa", Name: "am", @@ -49,8 +49,5 @@ func newManager(t *testing.T, h http.HandlerFunc) *manager.Manager { }) assert.NilError(t, err) - return &manager.Manager{ - Logger: logger, - Pipelines: pipelines, - } + return pipelineRegistry } diff --git a/internal/workflow/activities/poll_transfer.go b/internal/workflow/activities/poll_transfer.go index a346b30d..8ac5b8ce 100644 --- a/internal/workflow/activities/poll_transfer.go +++ b/internal/workflow/activities/poll_transfer.go @@ -6,12 +6,10 @@ import ( "time" "github.com/cenkalti/backoff/v4" - cadencesdk_activity "go.uber.org/cadence/activity" - "go.uber.org/zap" + temporalsdk_activity "go.temporal.io/sdk/activity" "github.com/artefactual-labs/enduro/internal/pipeline" - wferrors "github.com/artefactual-labs/enduro/internal/workflow/errors" - "github.com/artefactual-labs/enduro/internal/workflow/manager" + "github.com/artefactual-labs/enduro/internal/temporal" ) // PollTransferActivity polls the Transfer Status API repeatedly until @@ -19,11 +17,11 @@ import ( // // It is expected to deliver at least on heartbeat per minute. type PollTransferActivity struct { - manager *manager.Manager + pipelineRegistry *pipeline.Registry } -func NewPollTransferActivity(m *manager.Manager) *PollTransferActivity { - return &PollTransferActivity{manager: m} +func NewPollTransferActivity(pipelineRegistry *pipeline.Registry) *PollTransferActivity { + return &PollTransferActivity{pipelineRegistry: pipelineRegistry} } type PollTransferActivityParams struct { @@ -32,11 +30,11 @@ type PollTransferActivityParams struct { } func (a *PollTransferActivity) Execute(ctx context.Context, params *PollTransferActivityParams) (string, error) { - logger := cadencesdk_activity.GetLogger(ctx) + logger := temporalsdk_activity.GetLogger(ctx) - p, err := a.manager.Pipelines.ByName(params.PipelineName) + p, err := a.pipelineRegistry.ByName(params.PipelineName) if err != nil { - return "", wferrors.NonRetryableError(err) + return "", temporal.NewNonRetryableError(err) } amc := p.Client() @@ -58,7 +56,7 @@ func (a *PollTransferActivity) Execute(ctx context.Context, params *PollTransfer // Abandon when we see a non-retryable error. if errors.Is(err, pipeline.ErrStatusNonRetryable) { - return backoff.Permanent(wferrors.NonRetryableError(err)) + return backoff.Permanent(temporal.NewNonRetryableError(err)) } // Looking good, keep polling. @@ -68,21 +66,21 @@ func (a *PollTransferActivity) Execute(ctx context.Context, params *PollTransfer } if err != nil { - logger.Error("Failed to look up Transfer status.", zap.Error(err)) + logger.Error("Failed to look up Transfer status.", "error", err) } // Retry unless the deadline was exceeded. if lastRetryableError.IsZero() { lastRetryableError = clock.Now() } else if clock.Since(lastRetryableError) > deadline { - return backoff.Permanent(wferrors.NonRetryableError(err)) + return backoff.Permanent(temporal.NewNonRetryableError(err)) } return err }, backoffStrategy, func(err error, duration time.Duration) { - cadencesdk_activity.RecordHeartbeat(ctx, err.Error()) + temporalsdk_activity.RecordHeartbeat(ctx, err.Error()) }, ) diff --git a/internal/workflow/activities/poll_transfer_test.go b/internal/workflow/activities/poll_transfer_test.go index d5440281..26c6a849 100644 --- a/internal/workflow/activities/poll_transfer_test.go +++ b/internal/workflow/activities/poll_transfer_test.go @@ -8,45 +8,45 @@ import ( "github.com/go-logr/logr" "github.com/jonboulle/clockwork" - cadencesdk_testsuite "go.uber.org/cadence/testsuite" - cadencesdk_worker "go.uber.org/cadence/worker" + temporalsdk_testsuite "go.temporal.io/sdk/testsuite" + temporalsdk_worker "go.temporal.io/sdk/worker" "gotest.tools/v3/assert" - is "gotest.tools/v3/assert/cmp" "github.com/artefactual-labs/enduro/internal/pipeline" + "github.com/artefactual-labs/enduro/internal/temporal" ) func TestPollTransferActivity(t *testing.T) { t.Run("Fails when the pipeline isn't found", func(t *testing.T) { - manager := newManager(t, nil) - activity := NewPollTransferActivity(manager) - manager.Pipelines, _ = pipeline.NewPipelineRegistry(logr.Discard(), []pipeline.Config{}) + pipelineRegistry, _ := pipeline.NewPipelineRegistry(logr.Discard(), []pipeline.Config{}) + activity := NewPollTransferActivity(pipelineRegistry) - s := cadencesdk_testsuite.WorkflowTestSuite{} + s := temporalsdk_testsuite.WorkflowTestSuite{} env := s.NewTestActivityEnvironment() env.RegisterActivity(activity.Execute) future, err := env.ExecuteActivity(activity.Execute, &PollTransferActivityParams{}) - assert.Assert(t, is.Nil(future)) - assert.Error(t, err, "non retryable error") + assert.Assert(t, future == nil) + assert.Assert(t, temporal.NonRetryableError(err) == true) + assert.ErrorContains(t, err, "unknown pipeline") }) t.Run("Identifies packages that completed processing successfully", func(t *testing.T) { ctx := context.Background() - manager := newManager(t, func(w http.ResponseWriter, r *http.Request) { + pipelineRegistry := newPipelineRegistry(t, func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte(`{ "sip_uuid": "734abbaf-4e2f-4a68-938c-c8ff6420e525", "status": "COMPLETE" }`)) }) - activity := NewPollTransferActivity(manager) + activity := NewPollTransferActivity(pipelineRegistry) - s := cadencesdk_testsuite.WorkflowTestSuite{} + s := temporalsdk_testsuite.WorkflowTestSuite{} env := s.NewTestActivityEnvironment() env.RegisterActivity(activity.Execute) - env.SetWorkerOptions(cadencesdk_worker.Options{BackgroundActivityContext: ctx}) + env.SetWorkerOptions(temporalsdk_worker.Options{BackgroundActivityContext: ctx}) var sipID string future, err := env.ExecuteActivity(activity.Execute, &PollTransferActivityParams{ @@ -61,30 +61,31 @@ func TestPollTransferActivity(t *testing.T) { t.Run("Abandons when a non-retryable error is detected", func(t *testing.T) { ctx := context.Background() - manager := newManager(t, func(w http.ResponseWriter, r *http.Request) { + pipelineRegistry := newPipelineRegistry(t, func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusUnauthorized) }) - activity := NewPollTransferActivity(manager) + activity := NewPollTransferActivity(pipelineRegistry) - s := cadencesdk_testsuite.WorkflowTestSuite{} + s := temporalsdk_testsuite.WorkflowTestSuite{} env := s.NewTestActivityEnvironment() env.RegisterActivity(activity.Execute) - env.SetWorkerOptions(cadencesdk_worker.Options{BackgroundActivityContext: ctx}) + env.SetWorkerOptions(temporalsdk_worker.Options{BackgroundActivityContext: ctx}) future, err := env.ExecuteActivity(activity.Execute, &PollTransferActivityParams{ PipelineName: "am", TransferID: "cbc4b312-b076-4ff7-b67b-b6850f2b4486", }) - assert.Assert(t, is.Nil(future)) - assert.Error(t, err, "non retryable error") + assert.Assert(t, future == nil) + assert.Assert(t, temporal.NonRetryableError(err) == true) + assert.ErrorContains(t, err, "error checking transfer status: server error") }) t.Run("Polls until processing completes", func(t *testing.T) { ctx := context.Background() backoffStrategy = &ZeroBackOff{} attempts := 0 - manager := newManager(t, func(w http.ResponseWriter, r *http.Request) { + pipelineRegistry := newPipelineRegistry(t, func(w http.ResponseWriter, r *http.Request) { attempts++ if attempts > 3 { w.WriteHeader(http.StatusOK) @@ -100,12 +101,12 @@ func TestPollTransferActivity(t *testing.T) { "status": "PROCESSING" }`)) }) - activity := NewPollTransferActivity(manager) + activity := NewPollTransferActivity(pipelineRegistry) - s := cadencesdk_testsuite.WorkflowTestSuite{} + s := temporalsdk_testsuite.WorkflowTestSuite{} env := s.NewTestActivityEnvironment() env.RegisterActivity(activity.Execute) - env.SetWorkerOptions(cadencesdk_worker.Options{BackgroundActivityContext: ctx}) + env.SetWorkerOptions(temporalsdk_worker.Options{BackgroundActivityContext: ctx}) var sipID string future, err := env.ExecuteActivity(activity.Execute, &PollTransferActivityParams{ @@ -124,25 +125,26 @@ func TestPollTransferActivity(t *testing.T) { backoffStrategy = &ZeroBackOff{} clock = clockwork.NewFakeClock() attempts := 0 - manager := newManager(t, func(w http.ResponseWriter, r *http.Request) { + pipelineRegistry := newPipelineRegistry(t, func(w http.ResponseWriter, r *http.Request) { attempts++ clock.(clockwork.FakeClock).Advance(time.Minute) w.WriteHeader(http.StatusBadGateway) }) - activity := NewPollTransferActivity(manager) + activity := NewPollTransferActivity(pipelineRegistry) - s := cadencesdk_testsuite.WorkflowTestSuite{} + s := temporalsdk_testsuite.WorkflowTestSuite{} env := s.NewTestActivityEnvironment() env.RegisterActivity(activity.Execute) - env.SetWorkerOptions(cadencesdk_worker.Options{BackgroundActivityContext: ctx}) + env.SetWorkerOptions(temporalsdk_worker.Options{BackgroundActivityContext: ctx}) future, err := env.ExecuteActivity(activity.Execute, &PollTransferActivityParams{ PipelineName: "am", TransferID: "cbc4b312-b076-4ff7-b67b-b6850f2b4486", }) - assert.Assert(t, is.Nil(future)) - assert.Error(t, err, "non retryable error") + assert.Assert(t, future == nil) + assert.Assert(t, temporal.NonRetryableError(err) == true) + assert.ErrorContains(t, err, "error checking transfer status") assert.Equal(t, backoffStrategy.(*ZeroBackOff).hits, 6) }) } diff --git a/internal/workflow/activities/transfer.go b/internal/workflow/activities/transfer.go index aef18f28..c332d577 100644 --- a/internal/workflow/activities/transfer.go +++ b/internal/workflow/activities/transfer.go @@ -6,7 +6,7 @@ import ( "net/http" "github.com/artefactual-labs/enduro/internal/amclient" - wferrors "github.com/artefactual-labs/enduro/internal/workflow/errors" + "github.com/artefactual-labs/enduro/internal/temporal" "github.com/artefactual-labs/enduro/internal/workflow/manager" ) @@ -39,7 +39,7 @@ type TransferActivityResponse struct { func (a *TransferActivity) Execute(ctx context.Context, params *TransferActivityParams) (*TransferActivityResponse, error) { p, err := a.manager.Pipelines.ByName(params.PipelineName) if err != nil { - return nil, wferrors.NonRetryableError(err) + return nil, temporal.NewNonRetryableError(err) } amc := p.Client() @@ -59,7 +59,7 @@ func (a *TransferActivity) Execute(ctx context.Context, params *TransferActivity if httpResp != nil { switch { case httpResp.StatusCode == http.StatusForbidden: - return nil, wferrors.NonRetryableError(fmt.Errorf("authentication error: %v", err)) + return nil, temporal.NewNonRetryableError(fmt.Errorf("authentication error: %v", err)) } } return nil, err diff --git a/internal/workflow/async.go b/internal/workflow/async.go index eeef4be9..fe41570c 100644 --- a/internal/workflow/async.go +++ b/internal/workflow/async.go @@ -6,12 +6,11 @@ import ( "fmt" "time" - cadencesdk "go.uber.org/cadence" - cadencesdk_activity "go.uber.org/cadence/activity" - cadencesdk_workflow "go.uber.org/cadence/workflow" + temporalsdk_activity "go.temporal.io/sdk/activity" + temporalsdk_temporal "go.temporal.io/sdk/temporal" + temporalsdk_workflow "go.temporal.io/sdk/workflow" "github.com/artefactual-labs/enduro/internal/collection" - "github.com/artefactual-labs/enduro/internal/workflow/manager" ) type asyncDecision string @@ -32,10 +31,10 @@ var ErrAsyncCompletionAbandoned = errors.New("user abandoned") // // TODO: state changes in collection could be performed via hook functions, // generalize and convert into a struct. -func executeActivityWithAsyncErrorHandling(ctx cadencesdk_workflow.Context, colsvc collection.Service, colID uint, opts cadencesdk_workflow.ActivityOptions, act interface{}, args ...interface{}) cadencesdk_workflow.Future { - future, settable := cadencesdk_workflow.NewFuture(ctx) +func executeActivityWithAsyncErrorHandling(ctx temporalsdk_workflow.Context, colsvc collection.Service, colID uint, opts temporalsdk_workflow.ActivityOptions, act interface{}, args ...interface{}) temporalsdk_workflow.Future { + future, settable := temporalsdk_workflow.NewFuture(ctx) - cadencesdk_workflow.Go(ctx, func(ctx cadencesdk_workflow.Context) { + temporalsdk_workflow.Go(ctx, func(ctx temporalsdk_workflow.Context) { retryWithPolicy := true retryPolicy := opts.RetryPolicy var attempts uint @@ -51,12 +50,12 @@ func executeActivityWithAsyncErrorHandling(ctx cadencesdk_workflow.Context, cols // Set in-progress status on new attempts - presumably coming from "pending". if attempts > 0 { - _ = cadencesdk_workflow.ExecuteLocalActivity(ctx, setStatusInProgressLocalActivity, colsvc, colID, time.Time{}).Get(ctx, nil) + _ = temporalsdk_workflow.ExecuteLocalActivity(ctx, setStatusInProgressLocalActivity, colsvc, colID, time.Time{}).Get(ctx, nil) } // Execute the activity that we're wrapping. - activityOpts := cadencesdk_workflow.WithActivityOptions(ctx, opts) - err := cadencesdk_workflow.ExecuteActivity(activityOpts, act, args...).Get(activityOpts, nil) + activityOpts := temporalsdk_workflow.WithActivityOptions(ctx, opts) + err := temporalsdk_workflow.ExecuteActivity(activityOpts, act, args...).Get(activityOpts, nil) // We're done here if the activity did not fail. if err == nil { @@ -67,11 +66,11 @@ func executeActivityWithAsyncErrorHandling(ctx cadencesdk_workflow.Context, cols // Execute the activity that performs asynchronous completion. var decision asyncDecision activityOpts = withActivityOptsForAsyncCompletion(ctx) - err = cadencesdk_workflow.ExecuteActivity(activityOpts, AsyncCompletionActivityName, colID).Get(activityOpts, &decision) + err = temporalsdk_workflow.ExecuteActivity(activityOpts, AsyncCompletionActivityName, colID).Get(activityOpts, &decision) // Asynchronous completion failed. if err != nil { - if cadencesdk.IsTimeoutError(err) { + if temporalsdk_temporal.IsTimeoutError(err) { decision = abandon } else { settable.Set(nil, err) @@ -90,7 +89,7 @@ func executeActivityWithAsyncErrorHandling(ctx cadencesdk_workflow.Context, cols settable.Set(nil, ErrAsyncCompletionAbandoned) return default: - settable.Set(nil, cadencesdk.NewCustomError("received decision is unknown")) + settable.Set(nil, temporalsdk_temporal.NewApplicationError("received decision is unknown", "")) return } } @@ -102,19 +101,19 @@ func executeActivityWithAsyncErrorHandling(ctx cadencesdk_workflow.Context, cols var AsyncCompletionActivityName = "async-completion-activity" type AsyncCompletionActivity struct { - manager *manager.Manager + colsvc collection.Service } -func NewAsyncCompletionActivity(m *manager.Manager) *AsyncCompletionActivity { - return &AsyncCompletionActivity{manager: m} +func NewAsyncCompletionActivity(colsvc collection.Service) *AsyncCompletionActivity { + return &AsyncCompletionActivity{colsvc: colsvc} } func (a *AsyncCompletionActivity) Execute(ctx context.Context, colID uint) (string, error) { - info := cadencesdk_activity.GetInfo(ctx) + info := temporalsdk_activity.GetInfo(ctx) - if err := a.manager.Collection.SetStatusPending(ctx, colID, info.TaskToken); err != nil { + if err := a.colsvc.SetStatusPending(ctx, colID, info.TaskToken); err != nil { return "", fmt.Errorf("error saving task token: %v", err) } - return "", cadencesdk_activity.ErrResultPending + return "", temporalsdk_activity.ErrResultPending } diff --git a/internal/workflow/errors/errors.go b/internal/workflow/errors/errors.go deleted file mode 100644 index 532aae97..00000000 --- a/internal/workflow/errors/errors.go +++ /dev/null @@ -1,31 +0,0 @@ -package errors - -import ( - cadencesdk "go.uber.org/cadence" - cadencesdk_gen_shared "go.uber.org/cadence/.gen/go/shared" - cadencesdk_workflow "go.uber.org/cadence/workflow" -) - -const NRE = "non retryable error" - -func NonRetryableError(err error) error { - return cadencesdk.NewCustomError(NRE, err.Error()) -} - -// HeartbeatTimeoutError determines if a given error is a heartbeat error. -func HeartbeatTimeoutError(err error, details interface{}) bool { - timeoutErr, ok := err.(*cadencesdk_workflow.TimeoutError) - if !ok { - return false - } - - if timeoutErr.TimeoutType() != cadencesdk_gen_shared.TimeoutTypeHeartbeat { - return false - } - - if timeoutErr.HasDetails() { - _ = timeoutErr.Details(&details) - } - - return true -} diff --git a/internal/workflow/local_activities.go b/internal/workflow/local_activities.go index 8d6a0818..ef87184e 100644 --- a/internal/workflow/local_activities.go +++ b/internal/workflow/local_activities.go @@ -5,7 +5,7 @@ import ( "time" "github.com/go-logr/logr" - cadencesdk_activity "go.uber.org/cadence/activity" + temporalsdk_activity "go.temporal.io/sdk/activity" "github.com/artefactual-labs/enduro/internal/collection" "github.com/artefactual-labs/enduro/internal/workflow/manager" @@ -17,7 +17,7 @@ type createPackageLocalActivityParams struct { } func createPackageLocalActivity(ctx context.Context, logger logr.Logger, colsvc collection.Service, params *createPackageLocalActivityParams) (uint, error) { - info := cadencesdk_activity.GetInfo(ctx) + info := temporalsdk_activity.GetInfo(ctx) col := &collection.Collection{ Name: params.Key, @@ -45,7 +45,7 @@ type updatePackageLocalActivityParams struct { } func updatePackageLocalActivity(ctx context.Context, logger logr.Logger, colsvc collection.Service, params *updatePackageLocalActivityParams) error { - info := cadencesdk_activity.GetInfo(ctx) + info := temporalsdk_activity.GetInfo(ctx) err := colsvc.UpdateWorkflowStatus( ctx, params.CollectionID, params.Key, info.WorkflowExecution.ID, diff --git a/internal/workflow/policies.go b/internal/workflow/policies.go index 7b11fc12..2ad914c3 100644 --- a/internal/workflow/policies.go +++ b/internal/workflow/policies.go @@ -3,31 +3,25 @@ package workflow import ( "time" - cadencesdk "go.uber.org/cadence" - cadencesdk_workflow "go.uber.org/cadence/workflow" - - wferrors "github.com/artefactual-labs/enduro/internal/workflow/errors" + temporalsdk_temporal "go.temporal.io/sdk/temporal" + temporalsdk_workflow "go.temporal.io/sdk/workflow" ) -// Cadence doesn't seem to have a concept of unlimited duration. We use this -// constant to represent a long period of time (10 years). +// We use this constant to represent a long period of time (10 years). const forever = time.Hour * 24 * 365 * 10 // withActivityOptsForLongLivedRequest returns a workflow context with activity // options suited for long-running activities without heartbeats -func withActivityOptsForLongLivedRequest(ctx cadencesdk_workflow.Context) cadencesdk_workflow.Context { - return cadencesdk_workflow.WithActivityOptions(ctx, cadencesdk_workflow.ActivityOptions{ - ScheduleToStartTimeout: forever, - StartToCloseTimeout: time.Hour * 2, - RetryPolicy: &cadencesdk.RetryPolicy{ +func withActivityOptsForLongLivedRequest(ctx temporalsdk_workflow.Context) temporalsdk_workflow.Context { + return temporalsdk_workflow.WithActivityOptions(ctx, temporalsdk_workflow.ActivityOptions{ + StartToCloseTimeout: time.Hour * 2, + RetryPolicy: &temporalsdk_temporal.RetryPolicy{ InitialInterval: time.Second, BackoffCoefficient: 2, MaximumInterval: time.Minute * 10, - ExpirationInterval: time.Minute * 10, MaximumAttempts: 5, - NonRetriableErrorReasons: []string{ - wferrors.NRE, - "cadenceInternal:Timeout START_TO_CLOSE", + NonRetryableErrorTypes: []string{ + "TemporalTimeout:StartToClose", }, }, }) @@ -36,39 +30,33 @@ func withActivityOptsForLongLivedRequest(ctx cadencesdk_workflow.Context) cadenc // withActivityOptsForHeartbeatedRequest returns a workflow context with // activity options suited for long-lived activities implementing heartbeats. // -// Remember that Cadence passes the cancellation signal to these activities. +// Remember that Temporal passes the cancellation signal to these activities. // The activity should not ignore cancellation signals! // -// The activity is responsible for returning a NRE error. Otherwise it will be -// retried "forever". -func withActivityOptsForHeartbeatedRequest(ctx cadencesdk_workflow.Context, heartbeatTimeout time.Duration) cadencesdk_workflow.Context { - return cadencesdk_workflow.WithActivityOptions(ctx, cadencesdk_workflow.ActivityOptions{ - ScheduleToStartTimeout: forever, - StartToCloseTimeout: forever, // Real cap is workflow.ExecutionStartToCloseTimeout. +// The activity is responsible for returning a NRE error. +func withActivityOptsForHeartbeatedRequest(ctx temporalsdk_workflow.Context, heartbeatTimeout time.Duration) temporalsdk_workflow.Context { + return temporalsdk_workflow.WithActivityOptions(ctx, temporalsdk_workflow.ActivityOptions{ + ScheduleToCloseTimeout: forever, HeartbeatTimeout: heartbeatTimeout, - RetryPolicy: &cadencesdk.RetryPolicy{ - InitialInterval: time.Second, - BackoffCoefficient: 2, - MaximumInterval: time.Second * 10, - ExpirationInterval: forever, - NonRetriableErrorReasons: []string{wferrors.NRE}, + RetryPolicy: &temporalsdk_temporal.RetryPolicy{ + InitialInterval: time.Second, + BackoffCoefficient: 2, + MaximumInterval: time.Second * 10, }, }) } // withActivityOptsForRequest returns a workflow context with activity options // suited for short-lived requests that may require multiple attempts. -func withActivityOptsForRequest(ctx cadencesdk_workflow.Context) cadencesdk_workflow.Context { - return cadencesdk_workflow.WithActivityOptions(ctx, cadencesdk_workflow.ActivityOptions{ - ScheduleToStartTimeout: forever, +func withActivityOptsForRequest(ctx temporalsdk_workflow.Context) temporalsdk_workflow.Context { + return temporalsdk_workflow.WithActivityOptions(ctx, temporalsdk_workflow.ActivityOptions{ StartToCloseTimeout: time.Second * 10, - RetryPolicy: &cadencesdk.RetryPolicy{ - InitialInterval: time.Second, - BackoffCoefficient: 2, - MaximumInterval: time.Minute * 5, - ExpirationInterval: time.Minute * 5, - MaximumAttempts: 20, - NonRetriableErrorReasons: []string{wferrors.NRE}, + ScheduleToCloseTimeout: time.Minute * 5, + RetryPolicy: &temporalsdk_temporal.RetryPolicy{ + InitialInterval: time.Second, + BackoffCoefficient: 2, + MaximumInterval: time.Minute, + MaximumAttempts: 20, }, }) } @@ -76,53 +64,48 @@ func withActivityOptsForRequest(ctx cadencesdk_workflow.Context) cadencesdk_work // withActivityOptsForLocalAction returns a workflow context with activity // options suited for local activities like disk operations that should not // require a retry policy attached. -func withActivityOptsForLocalAction(ctx cadencesdk_workflow.Context) cadencesdk_workflow.Context { - return cadencesdk_workflow.WithActivityOptions(ctx, cadencesdk_workflow.ActivityOptions{ - ScheduleToStartTimeout: forever, - StartToCloseTimeout: time.Hour, - }) -} - -// withActivityOptionsForNoOp returns a workflow context with activity options -// suited for no-op activities. -// -//nolint:deadcode,unused -func withActivityOptsForNoOp(ctx cadencesdk_workflow.Context) cadencesdk_workflow.Context { - return cadencesdk_workflow.WithActivityOptions(ctx, cadencesdk_workflow.ActivityOptions{ - ScheduleToStartTimeout: forever, - StartToCloseTimeout: time.Second * 10, +func withActivityOptsForLocalAction(ctx temporalsdk_workflow.Context) temporalsdk_workflow.Context { + return temporalsdk_workflow.WithActivityOptions(ctx, temporalsdk_workflow.ActivityOptions{ + StartToCloseTimeout: time.Hour, + RetryPolicy: &temporalsdk_temporal.RetryPolicy{ + MaximumAttempts: 1, + }, }) } // withLocalActivityOpts returns a workflow context with activity options suited // for local and short-lived activities with a few retries. -func withLocalActivityOpts(ctx cadencesdk_workflow.Context) cadencesdk_workflow.Context { - return cadencesdk_workflow.WithLocalActivityOptions(ctx, cadencesdk_workflow.LocalActivityOptions{ +func withLocalActivityOpts(ctx temporalsdk_workflow.Context) temporalsdk_workflow.Context { + return temporalsdk_workflow.WithLocalActivityOptions(ctx, temporalsdk_workflow.LocalActivityOptions{ ScheduleToCloseTimeout: 5 * time.Second, - RetryPolicy: &cadencesdk.RetryPolicy{ - InitialInterval: time.Second, - BackoffCoefficient: 2, - MaximumInterval: time.Minute, - MaximumAttempts: 3, - NonRetriableErrorReasons: []string{wferrors.NRE}, + RetryPolicy: &temporalsdk_temporal.RetryPolicy{ + InitialInterval: time.Second, + BackoffCoefficient: 2, + MaximumInterval: time.Minute, + MaximumAttempts: 3, }, }) } // withActivityOptsForAsyncCompletion returns a workflow context with activity // options for local and short-lived activities that don't deserve retries. -func withLocalActivityWithoutRetriesOpts(ctx cadencesdk_workflow.Context) cadencesdk_workflow.Context { - return cadencesdk_workflow.WithLocalActivityOptions(ctx, cadencesdk_workflow.LocalActivityOptions{ +func withLocalActivityWithoutRetriesOpts(ctx temporalsdk_workflow.Context) temporalsdk_workflow.Context { + return temporalsdk_workflow.WithLocalActivityOptions(ctx, temporalsdk_workflow.LocalActivityOptions{ ScheduleToCloseTimeout: 5 * time.Second, + RetryPolicy: &temporalsdk_temporal.RetryPolicy{ + MaximumAttempts: 1, + }, }) } // withActivityOptsForAsyncCompletion returns a workflow context with activity // options suited for asynchronous completion, embracing the fact that users // can be away from keyboard for long periods (weekends, holidays...). -func withActivityOptsForAsyncCompletion(ctx cadencesdk_workflow.Context) cadencesdk_workflow.Context { - return cadencesdk_workflow.WithActivityOptions(ctx, cadencesdk_workflow.ActivityOptions{ - ScheduleToStartTimeout: forever, - StartToCloseTimeout: time.Hour * 24 * 7, +func withActivityOptsForAsyncCompletion(ctx temporalsdk_workflow.Context) temporalsdk_workflow.Context { + return temporalsdk_workflow.WithActivityOptions(ctx, temporalsdk_workflow.ActivityOptions{ + StartToCloseTimeout: time.Hour * 24 * 7, + RetryPolicy: &temporalsdk_temporal.RetryPolicy{ + MaximumAttempts: 1, + }, }) } diff --git a/internal/workflow/processing.go b/internal/workflow/processing.go index f4a1513f..f7319c8f 100644 --- a/internal/workflow/processing.go +++ b/internal/workflow/processing.go @@ -11,9 +11,8 @@ import ( "math/rand" "time" - cadencesdk "go.uber.org/cadence" - cadencesdk_workflow "go.uber.org/cadence/workflow" - "go.uber.org/zap" + temporalsdk_temporal "go.temporal.io/sdk/temporal" + temporalsdk_workflow "go.temporal.io/sdk/workflow" "github.com/artefactual-labs/enduro/internal/collection" "github.com/artefactual-labs/enduro/internal/nha" @@ -154,9 +153,9 @@ func (tinfo TransferInfo) ProcessingConfiguration() string { // Retrying this workflow would result in a new Archivematica transfer. We do // not have a retry policy in place. The user could trigger a new instance via // the API. -func (w *ProcessingWorkflow) Execute(ctx cadencesdk_workflow.Context, req *collection.ProcessingWorkflowRequest) error { +func (w *ProcessingWorkflow) Execute(ctx temporalsdk_workflow.Context, req *collection.ProcessingWorkflowRequest) error { var ( - logger = cadencesdk_workflow.GetLogger(ctx) + logger = temporalsdk_workflow.GetLogger(ctx) tinfo = &TransferInfo{ CollectionID: req.CollectionID, @@ -183,13 +182,13 @@ func (w *ProcessingWorkflow) Execute(ctx cadencesdk_workflow.Context, req *colle var err error if req.CollectionID == 0 { - err = cadencesdk_workflow.ExecuteLocalActivity(activityOpts, createPackageLocalActivity, w.manager.Logger, w.manager.Collection, &createPackageLocalActivityParams{ + err = temporalsdk_workflow.ExecuteLocalActivity(activityOpts, createPackageLocalActivity, w.manager.Logger, w.manager.Collection, &createPackageLocalActivityParams{ Key: req.Key, Status: status, }).Get(activityOpts, &tinfo.CollectionID) } else { // TODO: investigate better way to reset the collection. - err = cadencesdk_workflow.ExecuteLocalActivity(activityOpts, updatePackageLocalActivity, w.manager.Logger, w.manager.Collection, &updatePackageLocalActivityParams{ + err = temporalsdk_workflow.ExecuteLocalActivity(activityOpts, updatePackageLocalActivity, w.manager.Logger, w.manager.Collection, &updatePackageLocalActivityParams{ CollectionID: req.CollectionID, Key: req.Key, PipelineID: "", @@ -214,9 +213,9 @@ func (w *ProcessingWorkflow) Execute(ctx cadencesdk_workflow.Context, req *colle } // Use disconnected context so it also runs after cancellation. - dctx, _ := cadencesdk_workflow.NewDisconnectedContext(ctx) + dctx, _ := temporalsdk_workflow.NewDisconnectedContext(ctx) activityOpts := withLocalActivityOpts(dctx) - _ = cadencesdk_workflow.ExecuteLocalActivity(activityOpts, updatePackageLocalActivity, w.manager.Logger, w.manager.Collection, &updatePackageLocalActivityParams{ + _ = temporalsdk_workflow.ExecuteLocalActivity(activityOpts, updatePackageLocalActivity, w.manager.Logger, w.manager.Collection, &updatePackageLocalActivityParams{ CollectionID: tinfo.CollectionID, Key: tinfo.Key, PipelineID: tinfo.PipelineID, @@ -230,7 +229,7 @@ func (w *ProcessingWorkflow) Execute(ctx cadencesdk_workflow.Context, req *colle // Extract details from transfer name. { activityOpts := withLocalActivityWithoutRetriesOpts(ctx) - err := cadencesdk_workflow.ExecuteLocalActivity(activityOpts, nha_activities.ParseNameLocalActivity, tinfo.Key).Get(activityOpts, &nameInfo) + err := temporalsdk_workflow.ExecuteLocalActivity(activityOpts, nha_activities.ParseNameLocalActivity, tinfo.Key).Get(activityOpts, &nameInfo) // An error should only stop the workflow if hari/prod activities are enabled. hariDisabled, _ := manager.HookAttrBool(w.manager.Hooks, "hari", "disabled") @@ -241,7 +240,7 @@ func (w *ProcessingWorkflow) Execute(ctx cadencesdk_workflow.Context, req *colle if nameInfo.Identifier != "" { activityOpts = withLocalActivityOpts(ctx) - _ = cadencesdk_workflow.ExecuteLocalActivity(activityOpts, setOriginalIDLocalActivity, w.manager.Collection, tinfo.CollectionID, nameInfo.Identifier).Get(activityOpts, nil) + _ = temporalsdk_workflow.ExecuteLocalActivity(activityOpts, setOriginalIDLocalActivity, w.manager.Collection, tinfo.CollectionID, nameInfo.Identifier).Get(activityOpts, nil) } } @@ -249,7 +248,7 @@ func (w *ProcessingWorkflow) Execute(ctx cadencesdk_workflow.Context, req *colle // list is empty then choose one from the list of all configured pipelines. { var pick string - if err := cadencesdk_workflow.SideEffect(ctx, func(ctx cadencesdk_workflow.Context) interface{} { + if err := temporalsdk_workflow.SideEffect(ctx, func(ctx temporalsdk_workflow.Context) interface{} { names := req.PipelineNames if len(names) < 1 { names = w.manager.Pipelines.Names() @@ -270,7 +269,7 @@ func (w *ProcessingWorkflow) Execute(ctx cadencesdk_workflow.Context, req *colle // Load pipeline configuration and hooks. { activityOpts := withLocalActivityWithoutRetriesOpts(ctx) - err := cadencesdk_workflow.ExecuteLocalActivity(activityOpts, loadConfigLocalActivity, w.manager, tinfo.PipelineName, tinfo).Get(activityOpts, &tinfo) + err := temporalsdk_workflow.ExecuteLocalActivity(activityOpts, loadConfigLocalActivity, w.manager, tinfo.PipelineName, tinfo).Get(activityOpts, &tinfo) if err != nil { return fmt.Errorf("error loading configuration: %v", err) } @@ -282,11 +281,11 @@ func (w *ProcessingWorkflow) Execute(ctx cadencesdk_workflow.Context, req *colle maxAttempts := 5 for attempt := 1; attempt <= maxAttempts; attempt++ { - activityOpts := cadencesdk_workflow.WithActivityOptions(ctx, cadencesdk_workflow.ActivityOptions{ + activityOpts := temporalsdk_workflow.WithActivityOptions(ctx, temporalsdk_workflow.ActivityOptions{ ScheduleToStartTimeout: forever, StartToCloseTimeout: time.Minute, }) - sessCtx, err := cadencesdk_workflow.CreateSession(activityOpts, &cadencesdk_workflow.SessionOptions{ + sessCtx, err := temporalsdk_workflow.CreateSession(activityOpts, &temporalsdk_workflow.SessionOptions{ CreationTimeout: forever, ExecutionTimeout: forever, }) @@ -305,23 +304,23 @@ func (w *ProcessingWorkflow) Execute(ctx cadencesdk_workflow.Context, req *colle // of losing the worker but not otherwise. This scenario seems to be // identifiable when we have an error but the root context has not // been canceled. - if sessErr != nil && (errors.Is(sessErr, cadencesdk_workflow.ErrSessionFailed) || cadencesdk.IsCanceledError(sessErr)) { + if sessErr != nil && (errors.Is(sessErr, temporalsdk_workflow.ErrSessionFailed) || temporalsdk_temporal.IsCanceledError(sessErr)) { // Root context canceled, hence workflow canceled. - if ctx.Err() == cadencesdk_workflow.ErrCanceled { + if ctx.Err() == temporalsdk_workflow.ErrCanceled { return nil } // We're done if the transfer deadline was exceeded. - if cadencesdk.IsCanceledError(sessErr) && timer.Exceeded() { + if temporalsdk_temporal.IsCanceledError(sessErr) && timer.Exceeded() { return fmt.Errorf("transfer deadline (%s) exceeded", tinfo.PipelineConfig.TransferDeadline) } logger.Error("Session failed, will retry shortly (10s)...", - zap.NamedError("rootCtx", ctx.Err()), - zap.Int("attemptFailed", attempt), - zap.Int("attemptsLeft", maxAttempts-attempt)) + "rootCtx", ctx.Err(), + "attemptFailed", attempt, + "attemptsLeft", maxAttempts-attempt) - _ = cadencesdk_workflow.Sleep(ctx, time.Second*10) + _ = temporalsdk_workflow.Sleep(ctx, time.Second*10) continue } @@ -344,10 +343,10 @@ func (w *ProcessingWorkflow) Execute(ctx cadencesdk_workflow.Context, req *colle // Hide packages from Archivematica Dashboard. { if status == collection.StatusDone { - futures := []cadencesdk_workflow.Future{} + futures := []temporalsdk_workflow.Future{} activityOpts := withActivityOptsForRequest(ctx) - futures = append(futures, cadencesdk_workflow.ExecuteActivity(activityOpts, activities.HidePackageActivityName, tinfo.TransferID, "transfer", tinfo.PipelineName)) - futures = append(futures, cadencesdk_workflow.ExecuteActivity(activityOpts, activities.HidePackageActivityName, tinfo.SIPID, "ingest", tinfo.PipelineName)) + futures = append(futures, temporalsdk_workflow.ExecuteActivity(activityOpts, activities.HidePackageActivityName, tinfo.TransferID, "transfer", tinfo.PipelineName)) + futures = append(futures, temporalsdk_workflow.ExecuteActivity(activityOpts, activities.HidePackageActivityName, tinfo.SIPID, "ingest", tinfo.PipelineName)) for _, f := range futures { _ = f.Get(activityOpts, nil) } @@ -358,16 +357,16 @@ func (w *ProcessingWorkflow) Execute(ctx cadencesdk_workflow.Context, req *colle { if status == collection.StatusDone { if tinfo.RetentionPeriod != nil { - err := cadencesdk_workflow.NewTimer(ctx, *tinfo.RetentionPeriod).Get(ctx, nil) + err := temporalsdk_workflow.NewTimer(ctx, *tinfo.RetentionPeriod).Get(ctx, nil) if err != nil { - logger.Warn("Retention policy timer failed", zap.Error(err)) + logger.Warn("Retention policy timer failed", "error", err) } else { activityOpts := withActivityOptsForRequest(ctx) - _ = cadencesdk_workflow.ExecuteActivity(activityOpts, activities.DeleteOriginalActivityName, tinfo.WatcherName, tinfo.BatchDir, tinfo.Key).Get(activityOpts, nil) + _ = temporalsdk_workflow.ExecuteActivity(activityOpts, activities.DeleteOriginalActivityName, tinfo.WatcherName, tinfo.BatchDir, tinfo.Key).Get(activityOpts, nil) } } else if tinfo.CompletedDir != "" { activityOpts := withActivityOptsForLocalAction(ctx) - err := cadencesdk_workflow.ExecuteActivity(activityOpts, activities.DisposeOriginalActivityName, tinfo.WatcherName, tinfo.CompletedDir, tinfo.BatchDir, tinfo.Key).Get(activityOpts, nil) + err := temporalsdk_workflow.ExecuteActivity(activityOpts, activities.DisposeOriginalActivityName, tinfo.WatcherName, tinfo.CompletedDir, tinfo.BatchDir, tinfo.Key).Get(activityOpts, nil) if err != nil { return err } @@ -377,20 +376,20 @@ func (w *ProcessingWorkflow) Execute(ctx cadencesdk_workflow.Context, req *colle logger.Info( "Workflow completed successfully!", - zap.Uint("collectionID", tinfo.CollectionID), - zap.String("pipeline", tinfo.PipelineName), - zap.String("watcher", tinfo.WatcherName), - zap.String("batchDir", tinfo.BatchDir), - zap.String("key", tinfo.Key), - zap.String("status", status.String()), + "collectionID", tinfo.CollectionID, + "pipeline", tinfo.PipelineName, + "watcher", tinfo.WatcherName, + "batchDir", tinfo.BatchDir, + "key", tinfo.Key, + "status", status.String(), ) return nil } // SessionHandler runs activities that belong to the same session. -func (w *ProcessingWorkflow) SessionHandler(sessCtx cadencesdk_workflow.Context, attempt int, tinfo *TransferInfo, nameInfo nha.NameInfo, validationConfig validation.Config, timer *Timer) error { - defer cadencesdk_workflow.CompleteSession(sessCtx) +func (w *ProcessingWorkflow) SessionHandler(sessCtx temporalsdk_workflow.Context, attempt int, tinfo *TransferInfo, nameInfo nha.NameInfo, validationConfig validation.Config, timer *Timer) error { + defer temporalsdk_workflow.CompleteSession(sessCtx) var release releaser @@ -399,10 +398,10 @@ func (w *ProcessingWorkflow) SessionHandler(sessCtx cadencesdk_workflow.Context, { var acquired bool var err error - acquired, release, err = acquirePipeline(sessCtx, w.manager, tinfo.PipelineName, tinfo.CollectionID) + acquired, release, err = acquirePipeline(sessCtx, w.manager.Collection, w.manager.Pipelines, tinfo.PipelineName, tinfo.CollectionID) if acquired { defer func() { - _ = release(sessCtx, w.manager, tinfo.PipelineName) + _ = release(sessCtx) }() } if err != nil { @@ -419,7 +418,7 @@ func (w *ProcessingWorkflow) SessionHandler(sessCtx cadencesdk_workflow.Context, // case, the activity whould be executed again. if tinfo.TempFile == "" { activityOpts := withActivityOptsForLongLivedRequest(sessCtx) - err := cadencesdk_workflow.ExecuteActivity(activityOpts, activities.DownloadActivityName, tinfo.PipelineName, tinfo.WatcherName, tinfo.Key).Get(activityOpts, &tinfo.TempFile) + err := temporalsdk_workflow.ExecuteActivity(activityOpts, activities.DownloadActivityName, tinfo.PipelineName, tinfo.WatcherName, tinfo.Key).Get(activityOpts, &tinfo.TempFile) if err != nil { return err } @@ -431,7 +430,7 @@ func (w *ProcessingWorkflow) SessionHandler(sessCtx cadencesdk_workflow.Context, { if tinfo.Bundle == (activities.BundleActivityResult{}) { activityOpts := withActivityOptsForLongLivedRequest(sessCtx) - err := cadencesdk_workflow.ExecuteActivity(activityOpts, activities.BundleActivityName, &activities.BundleActivityParams{ + err := temporalsdk_workflow.ExecuteActivity(activityOpts, activities.BundleActivityName, &activities.BundleActivityParams{ WatcherName: tinfo.WatcherName, TransferDir: tinfo.PipelineConfig.TransferDir, Key: tinfo.Key, @@ -450,7 +449,7 @@ func (w *ProcessingWorkflow) SessionHandler(sessCtx cadencesdk_workflow.Context, defer func() { if tinfo.Bundle.FullPathBeforeStrip != "" { activityOpts := withActivityOptsForRequest(sessCtx) - _ = cadencesdk_workflow.ExecuteActivity(activityOpts, activities.CleanUpActivityName, &activities.CleanUpActivityParams{ + _ = temporalsdk_workflow.ExecuteActivity(activityOpts, activities.CleanUpActivityName, &activities.CleanUpActivityParams{ FullPath: tinfo.Bundle.FullPathBeforeStrip, }).Get(activityOpts, nil) } @@ -459,11 +458,11 @@ func (w *ProcessingWorkflow) SessionHandler(sessCtx cadencesdk_workflow.Context, // Validate transfer. { if validationConfig.IsEnabled() && tinfo.Bundle != (activities.BundleActivityResult{}) { - activityOpts := cadencesdk_workflow.WithActivityOptions(sessCtx, cadencesdk_workflow.ActivityOptions{ + activityOpts := temporalsdk_workflow.WithActivityOptions(sessCtx, temporalsdk_workflow.ActivityOptions{ ScheduleToStartTimeout: forever, StartToCloseTimeout: time.Minute * 5, }) - err := cadencesdk_workflow.ExecuteActivity(activityOpts, activities.ValidateTransferActivityName, &activities.ValidateTransferActivityParams{ + err := temporalsdk_workflow.ExecuteActivity(activityOpts, activities.ValidateTransferActivityName, &activities.ValidateTransferActivityParams{ Config: validationConfig, Path: tinfo.Bundle.FullPath, }).Get(activityOpts, nil) @@ -478,7 +477,7 @@ func (w *ProcessingWorkflow) SessionHandler(sessCtx cadencesdk_workflow.Context, // Use our timed context if this transfer has a deadline set. duration := tinfo.PipelineConfig.TransferDeadline if duration != nil { - var cancel cadencesdk_workflow.CancelFunc + var cancel temporalsdk_workflow.CancelFunc sessCtx, cancel = timer.WithTimeout(sessCtx, *duration) defer cancel() } @@ -491,7 +490,7 @@ func (w *ProcessingWorkflow) SessionHandler(sessCtx cadencesdk_workflow.Context, // We can release now. Other activities will re-use the session but will not // need the pipeline. - _ = release(sessCtx, w.manager, tinfo.PipelineName) + _ = release(sessCtx) // Deliver receipts. { @@ -511,14 +510,14 @@ func (w *ProcessingWorkflow) SessionHandler(sessCtx cadencesdk_workflow.Context, return nil } -func (w *ProcessingWorkflow) transfer(sessCtx cadencesdk_workflow.Context, tinfo *TransferInfo) error { +func (w *ProcessingWorkflow) transfer(sessCtx temporalsdk_workflow.Context, tinfo *TransferInfo) error { // Transfer. { if tinfo.TransferID == "" { transferResponse := activities.TransferActivityResponse{} activityOpts := withActivityOptsForRequest(sessCtx) - err := cadencesdk_workflow.ExecuteActivity(activityOpts, activities.TransferActivityName, &activities.TransferActivityParams{ + err := temporalsdk_workflow.ExecuteActivity(activityOpts, activities.TransferActivityName, &activities.TransferActivityParams{ PipelineName: tinfo.PipelineName, TransferLocationID: tinfo.PipelineConfig.TransferLocationID, RelPath: tinfo.Bundle.RelPath, @@ -537,7 +536,7 @@ func (w *ProcessingWorkflow) transfer(sessCtx cadencesdk_workflow.Context, tinfo // Persist TransferID + PipelineID. { activityOpts := withLocalActivityOpts(sessCtx) - _ = cadencesdk_workflow.ExecuteLocalActivity(activityOpts, updatePackageLocalActivity, w.manager.Logger, w.manager.Collection, &updatePackageLocalActivityParams{ + _ = temporalsdk_workflow.ExecuteLocalActivity(activityOpts, updatePackageLocalActivity, w.manager.Logger, w.manager.Collection, &updatePackageLocalActivityParams{ CollectionID: tinfo.CollectionID, Key: tinfo.Key, Status: collection.StatusInProgress, @@ -550,7 +549,7 @@ func (w *ProcessingWorkflow) transfer(sessCtx cadencesdk_workflow.Context, tinfo { if tinfo.SIPID == "" { activityOpts := withActivityOptsForHeartbeatedRequest(sessCtx, time.Minute) - err := cadencesdk_workflow.ExecuteActivity(activityOpts, activities.PollTransferActivityName, &activities.PollTransferActivityParams{ + err := temporalsdk_workflow.ExecuteActivity(activityOpts, activities.PollTransferActivityName, &activities.PollTransferActivityParams{ PipelineName: tinfo.PipelineName, TransferID: tinfo.TransferID, }).Get(activityOpts, &tinfo.SIPID) @@ -563,7 +562,7 @@ func (w *ProcessingWorkflow) transfer(sessCtx cadencesdk_workflow.Context, tinfo // Persist SIPID. { activityOpts := withLocalActivityOpts(sessCtx) - _ = cadencesdk_workflow.ExecuteLocalActivity(activityOpts, updatePackageLocalActivity, w.manager.Logger, w.manager.Collection, &updatePackageLocalActivityParams{ + _ = temporalsdk_workflow.ExecuteLocalActivity(activityOpts, updatePackageLocalActivity, w.manager.Logger, w.manager.Collection, &updatePackageLocalActivityParams{ CollectionID: tinfo.CollectionID, Key: tinfo.Key, TransferID: tinfo.TransferID, @@ -577,7 +576,7 @@ func (w *ProcessingWorkflow) transfer(sessCtx cadencesdk_workflow.Context, tinfo { if tinfo.StoredAt.IsZero() { activityOpts := withActivityOptsForHeartbeatedRequest(sessCtx, time.Minute) - err := cadencesdk_workflow.ExecuteActivity(activityOpts, activities.PollIngestActivityName, &activities.PollIngestActivityParams{ + err := temporalsdk_workflow.ExecuteActivity(activityOpts, activities.PollIngestActivityName, &activities.PollIngestActivityParams{ PipelineName: tinfo.PipelineName, SIPID: tinfo.SIPID, }).Get(activityOpts, &tinfo.StoredAt) diff --git a/internal/workflow/processing_test.go b/internal/workflow/processing_test.go index 8ee1ab0e..251eaa2d 100644 --- a/internal/workflow/processing_test.go +++ b/internal/workflow/processing_test.go @@ -9,8 +9,7 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" - cadencesdk "go.uber.org/cadence" - cadencesdk_testsuite "go.uber.org/cadence/testsuite" + temporalsdk_testsuite "go.temporal.io/sdk/testsuite" "github.com/artefactual-labs/enduro/internal/collection" collectionfake "github.com/artefactual-labs/enduro/internal/collection/fake" @@ -22,9 +21,9 @@ import ( type ProcessingWorkflowTestSuite struct { suite.Suite - cadencesdk_testsuite.WorkflowTestSuite + temporalsdk_testsuite.WorkflowTestSuite - env *cadencesdk_testsuite.TestWorkflowEnvironment + env *temporalsdk_testsuite.TestWorkflowEnvironment manager *manager.Manager @@ -78,7 +77,7 @@ func (s *ProcessingWorkflowTestSuite) TestParseErrorIsIgnored() { }) s.True(s.env.IsWorkflowCompleted()) - s.EqualError(s.env.GetWorkflowError(), "error loading configuration: pipeline is unavailable") + s.ErrorContains(s.env.GetWorkflowError(), "pipeline is unavailable") } // Workflow does not ignore an error in parseName when NHA hooks are enabled. @@ -114,7 +113,7 @@ func (s *ProcessingWorkflowTestSuite) TestParseError() { }) s.True(s.env.IsWorkflowCompleted()) - s.EqualError(s.env.GetWorkflowError(), "error parsing transfer name: parse error") + s.ErrorContains(s.env.GetWorkflowError(), "parse error") } func TestProcessingWorkflow(t *testing.T) { @@ -136,22 +135,6 @@ func buildManager(t *testing.T, ctrl *gomock.Controller) *manager.Manager { ) } -func assertNilWorkflowError(t *testing.T, err error) { - t.Helper() - - if err == nil { - return - } - - if perr, ok := err.(*cadencesdk.CustomError); ok { - var details string - perr.Details(&details) - t.Fatal(details) - } else { - t.Fatal(err.Error()) - } -} - func TestTransferInfoProcessingConfiguration(t *testing.T) { t.Parallel() diff --git a/internal/workflow/receipts.go b/internal/workflow/receipts.go index 3cf25eef..cf271c23 100644 --- a/internal/workflow/receipts.go +++ b/internal/workflow/receipts.go @@ -4,7 +4,8 @@ import ( "fmt" "time" - cadencesdk_workflow "go.uber.org/cadence/workflow" + temporalsdk_temporal "go.temporal.io/sdk/temporal" + temporalsdk_workflow "go.temporal.io/sdk/workflow" "github.com/artefactual-labs/enduro/internal/nha" nha_activities "github.com/artefactual-labs/enduro/internal/nha/activities" @@ -20,11 +21,13 @@ type sendReceiptsParams struct { CollectionID uint } -func (w *ProcessingWorkflow) sendReceipts(ctx cadencesdk_workflow.Context, params *sendReceiptsParams) error { +func (w *ProcessingWorkflow) sendReceipts(ctx temporalsdk_workflow.Context, params *sendReceiptsParams) error { if disabled, _ := manager.HookAttrBool(w.manager.Hooks, "hari", "disabled"); !disabled { - opts := cadencesdk_workflow.ActivityOptions{ - ScheduleToStartTimeout: forever, - StartToCloseTimeout: time.Minute * 20, + opts := temporalsdk_workflow.ActivityOptions{ + StartToCloseTimeout: time.Minute * 20, + RetryPolicy: &temporalsdk_temporal.RetryPolicy{ + MaximumAttempts: 1, + }, } err := executeActivityWithAsyncErrorHandling(ctx, w.manager.Collection, params.CollectionID, opts, nha_activities.UpdateHARIActivityName, &nha_activities.UpdateHARIActivityParams{ SIPID: params.SIPID, @@ -39,9 +42,11 @@ func (w *ProcessingWorkflow) sendReceipts(ctx cadencesdk_workflow.Context, param } if disabled, _ := manager.HookAttrBool(w.manager.Hooks, "prod", "disabled"); !disabled { - opts := cadencesdk_workflow.ActivityOptions{ - ScheduleToStartTimeout: forever, - StartToCloseTimeout: time.Second * 10, + opts := temporalsdk_workflow.ActivityOptions{ + StartToCloseTimeout: time.Second * 10, + RetryPolicy: &temporalsdk_temporal.RetryPolicy{ + MaximumAttempts: 1, + }, } err := executeActivityWithAsyncErrorHandling(ctx, w.manager.Collection, params.CollectionID, opts, nha_activities.UpdateProductionSystemActivityName, &nha_activities.UpdateProductionSystemActivityParams{ StoredAt: params.StoredAt, diff --git a/internal/workflow/receipts_test.go b/internal/workflow/receipts_test.go index 3b9d8854..521086dc 100644 --- a/internal/workflow/receipts_test.go +++ b/internal/workflow/receipts_test.go @@ -8,10 +8,10 @@ import ( "github.com/golang/mock/gomock" "github.com/google/uuid" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" - cadencesdk_activity "go.uber.org/cadence/activity" - cadencesdk_testsuite "go.uber.org/cadence/testsuite" + temporalsdk_activity "go.temporal.io/sdk/activity" + temporalsdk_testsuite "go.temporal.io/sdk/testsuite" + "gotest.tools/v3/assert" "github.com/artefactual-labs/enduro/internal/nha" nha_activities "github.com/artefactual-labs/enduro/internal/nha/activities" @@ -20,15 +20,15 @@ import ( // sendReceipts exits immediately after an activity error, ensuring that // receipt delivery is halted once one delivery has failed. func TestSendReceiptsSequentialBehavior(t *testing.T) { - wts := cadencesdk_testsuite.WorkflowTestSuite{} + wts := temporalsdk_testsuite.WorkflowTestSuite{} env := wts.NewTestWorkflowEnvironment() m := buildManager(t, gomock.NewController(t)) - AsyncCompletionActivityName = uuid.New().String() - cadencesdk_activity.RegisterWithOptions(NewAsyncCompletionActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: AsyncCompletionActivityName}) + AsyncCompletionActivityName = uuid.New().String() + "-async-completion" + env.RegisterActivityWithOptions(NewAsyncCompletionActivity(m.Collection).Execute, temporalsdk_activity.RegisterOptions{Name: AsyncCompletionActivityName}) - nha_activities.UpdateHARIActivityName = uuid.New().String() - cadencesdk_activity.RegisterWithOptions(nha_activities.NewUpdateHARIActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: nha_activities.UpdateHARIActivityName}) + nha_activities.UpdateHARIActivityName = uuid.New().String() + "-update-hary" + env.RegisterActivityWithOptions(nha_activities.NewUpdateHARIActivity(m).Execute, temporalsdk_activity.RegisterOptions{Name: nha_activities.UpdateHARIActivityName}) params := sendReceiptsParams{ SIPID: "91e3ed2f-b798-4f4e-9133-74193f0d6a4f", @@ -60,21 +60,21 @@ func TestSendReceiptsSequentialBehavior(t *testing.T) { env.ExecuteWorkflow(NewProcessingWorkflow(m).sendReceipts, ¶ms) - assert.True(t, env.IsWorkflowCompleted()) - assert.Equal(t, "error sending hari receipt: user abandoned", env.GetWorkflowError().Error()) + assert.Equal(t, env.IsWorkflowCompleted(), true) + assert.ErrorContains(t, env.GetWorkflowError(), "error sending hari receipt: user abandoned") env.AssertExpectations(t) } func TestSendReceipts(t *testing.T) { - wts := cadencesdk_testsuite.WorkflowTestSuite{} + wts := temporalsdk_testsuite.WorkflowTestSuite{} env := wts.NewTestWorkflowEnvironment() m := buildManager(t, gomock.NewController(t)) nha_activities.UpdateHARIActivityName = uuid.New().String() - cadencesdk_activity.RegisterWithOptions(nha_activities.NewUpdateHARIActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: nha_activities.UpdateHARIActivityName}) + env.RegisterActivityWithOptions(nha_activities.NewUpdateHARIActivity(m).Execute, temporalsdk_activity.RegisterOptions{Name: nha_activities.UpdateHARIActivityName}) nha_activities.UpdateProductionSystemActivityName = uuid.New().String() - cadencesdk_activity.RegisterWithOptions(nha_activities.NewUpdateProductionSystemActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: nha_activities.UpdateProductionSystemActivityName}) + env.RegisterActivityWithOptions(nha_activities.NewUpdateProductionSystemActivity(m).Execute, temporalsdk_activity.RegisterOptions{Name: nha_activities.UpdateProductionSystemActivityName}) params := sendReceiptsParams{ SIPID: "91e3ed2f-b798-4f4e-9133-74193f0d6a4f", @@ -110,7 +110,7 @@ func TestSendReceipts(t *testing.T) { env.ExecuteWorkflow(NewProcessingWorkflow(m).sendReceipts, ¶ms) - assert.True(t, env.IsWorkflowCompleted()) - assertNilWorkflowError(t, env.GetWorkflowError()) + assert.Equal(t, env.IsWorkflowCompleted(), true) + assert.NilError(t, env.GetWorkflowError()) env.AssertExpectations(t) } diff --git a/internal/workflow/semaphore.go b/internal/workflow/semaphore.go index 25e1150b..f8f37e70 100644 --- a/internal/workflow/semaphore.go +++ b/internal/workflow/semaphore.go @@ -6,35 +6,42 @@ import ( "sync" "time" - "github.com/go-logr/logr" - cadencesdk_workflow "go.uber.org/cadence/workflow" + temporalsdk_temporal "go.temporal.io/sdk/temporal" + temporalsdk_workflow "go.temporal.io/sdk/workflow" + "github.com/artefactual-labs/enduro/internal/collection" "github.com/artefactual-labs/enduro/internal/pipeline" + "github.com/artefactual-labs/enduro/internal/temporal" "github.com/artefactual-labs/enduro/internal/workflow/activities" - wferrors "github.com/artefactual-labs/enduro/internal/workflow/errors" - "github.com/artefactual-labs/enduro/internal/workflow/manager" ) -type releaser func(ctx cadencesdk_workflow.Context, m *manager.Manager, pipelineName string) error +type releaser func(ctx temporalsdk_workflow.Context) error + +var noopReleaser = releaser(func(ctx temporalsdk_workflow.Context) error { + return nil +}) // acquirePipeline acquires the pipeline semaphore. It returns a releaser that // users should execute. It's safe to execute more than once or when the acquire // operation failed (no-op). -func acquirePipeline(ctx cadencesdk_workflow.Context, m *manager.Manager, pipelineName string, colID uint) (bool, releaser, error) { +func acquirePipeline(ctx temporalsdk_workflow.Context, colsvc collection.Service, pipelineRegistry *pipeline.Registry, pipelineName string, colID uint) (bool, releaser, error) { var acquired bool // The releaser defaults to a no-op operation, a nil value would panic. - var relfn releaser = func(ctx cadencesdk_workflow.Context, m *manager.Manager, pipelineName string) error { return nil } + relfn := noopReleaser // Acquire the pipeline semaphore. { - ctx := cadencesdk_workflow.WithActivityOptions(ctx, cadencesdk_workflow.ActivityOptions{ - ScheduleToStartTimeout: forever, - StartToCloseTimeout: forever, + ctx := temporalsdk_workflow.WithActivityOptions(ctx, temporalsdk_workflow.ActivityOptions{ HeartbeatTimeout: time.Minute, WaitForCancellation: false, + ScheduleToStartTimeout: forever, + StartToCloseTimeout: forever, + RetryPolicy: &temporalsdk_temporal.RetryPolicy{ + MaximumAttempts: 1, + }, }) - if err := cadencesdk_workflow.ExecuteActivity(ctx, activities.AcquirePipelineActivityName, pipelineName).Get(ctx, nil); err != nil { + if err := temporalsdk_workflow.ExecuteActivity(ctx, activities.AcquirePipelineActivityName, pipelineName).Get(ctx, nil); err != nil { return acquired, relfn, fmt.Errorf("error acquiring pipeline: %w", err) } @@ -43,15 +50,15 @@ func acquirePipeline(ctx cadencesdk_workflow.Context, m *manager.Manager, pipeli // Create the function that releases the pipeline that we've just acquired. var once sync.Once - relfn = func(ctx cadencesdk_workflow.Context, m *manager.Manager, pipelineName string) error { + relfn = func(ctx temporalsdk_workflow.Context) error { if !acquired { return nil } var err error once.Do(func() { ctx = withLocalActivityWithoutRetriesOpts(ctx) - ctx, _ = cadencesdk_workflow.NewDisconnectedContext(ctx) - err = cadencesdk_workflow.ExecuteLocalActivity(ctx, releasePipelineLocalActivity, m.Logger, m.Pipelines, pipelineName).Get(ctx, nil) + ctx, _ = temporalsdk_workflow.NewDisconnectedContext(ctx) + err = temporalsdk_workflow.ExecuteLocalActivity(ctx, releasePipelineLocalActivity, pipelineRegistry, pipelineName).Get(ctx, nil) if err != nil { err = fmt.Errorf("error releasing pipeline semaphore: %w", err) } @@ -62,7 +69,7 @@ func acquirePipeline(ctx cadencesdk_workflow.Context, m *manager.Manager, pipeli // Set in-progress status. { ctx := withLocalActivityOpts(ctx) - err := cadencesdk_workflow.ExecuteLocalActivity(ctx, setStatusInProgressLocalActivity, m.Collection, colID, time.Now().UTC()).Get(ctx, nil) + err := temporalsdk_workflow.ExecuteLocalActivity(ctx, setStatusInProgressLocalActivity, colsvc, colID, time.Now().UTC()).Get(ctx, nil) if err != nil { return acquired, relfn, fmt.Errorf("error updating collection status: %w", err) } @@ -71,10 +78,10 @@ func acquirePipeline(ctx cadencesdk_workflow.Context, m *manager.Manager, pipeli return acquired, relfn, nil } -func releasePipelineLocalActivity(ctx context.Context, logger logr.Logger, registry *pipeline.Registry, pipelineName string) error { +func releasePipelineLocalActivity(ctx context.Context, registry *pipeline.Registry, pipelineName string) error { p, err := registry.ByName(pipelineName) if err != nil { - return wferrors.NonRetryableError(err) + return temporal.NewNonRetryableError(err) } p.Release() diff --git a/internal/workflow/semaphore_test.go b/internal/workflow/semaphore_test.go index 6cb0ca9e..5759b4c7 100644 --- a/internal/workflow/semaphore_test.go +++ b/internal/workflow/semaphore_test.go @@ -6,21 +6,20 @@ import ( "github.com/go-logr/logr" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" - cadencesdk_activity "go.uber.org/cadence/activity" - cadencesdk_testsuite "go.uber.org/cadence/testsuite" - cadencesdk_workflow "go.uber.org/cadence/workflow" + temporalsdk_activity "go.temporal.io/sdk/activity" + temporalsdk_testsuite "go.temporal.io/sdk/testsuite" + temporalsdk_workflow "go.temporal.io/sdk/workflow" collectionfake "github.com/artefactual-labs/enduro/internal/collection/fake" "github.com/artefactual-labs/enduro/internal/pipeline" "github.com/artefactual-labs/enduro/internal/workflow/activities" - "github.com/artefactual-labs/enduro/internal/workflow/manager" ) func TestSemaphoreAcquireRelease(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - wts := cadencesdk_testsuite.WorkflowTestSuite{} + wts := temporalsdk_testsuite.WorkflowTestSuite{} env := wts.NewTestWorkflowEnvironment() colsvc := collectionfake.NewMockService(ctrl) @@ -33,38 +32,33 @@ func TestSemaphoreAcquireRelease(t *testing.T) { {Name: "am1", Capacity: 1}, } registry, _ := pipeline.NewPipelineRegistry(logr.Discard(), config) - m := &manager.Manager{ - Pipelines: registry, - Collection: colsvc, - } - - a := activities.NewAcquirePipelineActivity(m) + a := activities.NewAcquirePipelineActivity(registry) env.RegisterActivityWithOptions( a.Execute, - cadencesdk_activity.RegisterOptions{ + temporalsdk_activity.RegisterOptions{ Name: activities.AcquirePipelineActivityName, }, ) env.RegisterWorkflowWithOptions( - func(ctx cadencesdk_workflow.Context) error { - acquired, release, err := acquirePipeline(ctx, m, "am1", 12345) + func(ctx temporalsdk_workflow.Context) error { + acquired, release, err := acquirePipeline(ctx, colsvc, registry, "am1", 12345) assert.Nil(t, err) assert.Equal(t, acquired, true) - p, _ := m.Pipelines.ByName("am1") + p, _ := registry.ByName("am1") size, cur := p.Capacity() assert.Equal(t, size, int64(1)) assert.Equal(t, cur, int64(1)) - release(ctx, m, "am1") + release(ctx) size, cur = p.Capacity() assert.Equal(t, size, int64(1)) assert.Equal(t, cur, int64(0)) return nil }, - cadencesdk_workflow.RegisterOptions{ + temporalsdk_workflow.RegisterOptions{ Name: "workflow", }, ) diff --git a/internal/workflow/timer.go b/internal/workflow/timer.go index 01c1a840..245485d5 100644 --- a/internal/workflow/timer.go +++ b/internal/workflow/timer.go @@ -4,9 +4,8 @@ import ( "sync" "time" - cadencesdk "go.uber.org/cadence" - cadencesdk_workflow "go.uber.org/cadence/workflow" - "go.uber.org/zap" + temporalsdk_temporal "go.temporal.io/sdk/temporal" + temporalsdk_workflow "go.temporal.io/sdk/workflow" ) type Timer struct { @@ -18,14 +17,14 @@ func NewTimer() *Timer { return &Timer{} } -func (t *Timer) WithTimeout(ctx cadencesdk_workflow.Context, d time.Duration) (cadencesdk_workflow.Context, cadencesdk_workflow.CancelFunc) { - logger := cadencesdk_workflow.GetLogger(ctx) +func (t *Timer) WithTimeout(ctx temporalsdk_workflow.Context, d time.Duration) (temporalsdk_workflow.Context, temporalsdk_workflow.CancelFunc) { + logger := temporalsdk_workflow.GetLogger(ctx) - timedCtx, cancelHandler := cadencesdk_workflow.WithCancel(ctx) - cadencesdk_workflow.Go(ctx, func(ctx cadencesdk_workflow.Context) { - if err := cadencesdk_workflow.NewTimer(ctx, d).Get(ctx, nil); err != nil { - if !cadencesdk.IsCanceledError(err) { - logger.Warn("Timer failed", zap.Error(err)) + timedCtx, cancelHandler := temporalsdk_workflow.WithCancel(ctx) + temporalsdk_workflow.Go(ctx, func(ctx temporalsdk_workflow.Context) { + if err := temporalsdk_workflow.NewTimer(ctx, d).Get(ctx, nil); err != nil { + if !temporalsdk_temporal.IsCanceledError(err) { + logger.Warn("Timer failed", "err", err.Error()) } } diff --git a/internal/workflow/timer_test.go b/internal/workflow/timer_test.go index e2aa9b7b..523873c3 100644 --- a/internal/workflow/timer_test.go +++ b/internal/workflow/timer_test.go @@ -6,17 +6,17 @@ import ( "testing" "time" - "github.com/stretchr/testify/assert" - cadencesdk "go.uber.org/cadence" - cadencesdk_activity "go.uber.org/cadence/activity" - cadencesdk_testsuite "go.uber.org/cadence/testsuite" - cadencesdk_workflow "go.uber.org/cadence/workflow" + temporalsdk_activity "go.temporal.io/sdk/activity" + temporalsdk_temporal "go.temporal.io/sdk/temporal" + temporalsdk_testsuite "go.temporal.io/sdk/testsuite" + temporalsdk_workflow "go.temporal.io/sdk/workflow" + "gotest.tools/v3/assert" "github.com/artefactual-labs/enduro/internal/workflow" ) func TestTimer(t *testing.T) { - wts := cadencesdk_testsuite.WorkflowTestSuite{} + wts := temporalsdk_testsuite.WorkflowTestSuite{} env := wts.NewTestWorkflowEnvironment() env.RegisterActivityWithOptions( @@ -24,13 +24,13 @@ func TestTimer(t *testing.T) { time.Sleep(time.Minute) return nil }, - cadencesdk_activity.RegisterOptions{ + temporalsdk_activity.RegisterOptions{ Name: "activity", }, ) env.RegisterWorkflowWithOptions( - func(ctx cadencesdk_workflow.Context, duration time.Duration) error { + func(ctx temporalsdk_workflow.Context, duration time.Duration) error { // Our timer implements a workflow goroutine that cancels the // context when the timeout is exceeded. As a result, the activity // should return a CanceledError. @@ -38,22 +38,25 @@ func TestTimer(t *testing.T) { ctx, cancel := timer.WithTimeout(ctx, duration) defer cancel() - future := cadencesdk_workflow.ExecuteActivity( - cadencesdk_workflow.WithActivityOptions(ctx, cadencesdk_workflow.ActivityOptions{ + future := temporalsdk_workflow.ExecuteActivity( + temporalsdk_workflow.WithActivityOptions(ctx, temporalsdk_workflow.ActivityOptions{ ScheduleToStartTimeout: time.Hour, StartToCloseTimeout: time.Hour, + RetryPolicy: &temporalsdk_temporal.RetryPolicy{ + MaximumAttempts: 1, + }, }), "activity", ) err := future.Get(ctx, nil) - if cadencesdk.IsCanceledError(err) && timer.Exceeded() { + if temporalsdk_temporal.IsCanceledError(err) && timer.Exceeded() { return fmt.Errorf("deadline exceeded: %s", duration) } return err }, - cadencesdk_workflow.RegisterOptions{ + temporalsdk_workflow.RegisterOptions{ Name: "workflow", }, ) @@ -62,6 +65,6 @@ func TestTimer(t *testing.T) { env.ExecuteWorkflow("workflow", deadline) // Workflow should end with an error: deadline exceeded. - assert.True(t, env.IsWorkflowCompleted()) - assert.Equal(t, fmt.Sprintf("deadline exceeded: %s", deadline), env.GetWorkflowError().Error()) + assert.Equal(t, env.IsWorkflowCompleted(), true) + assert.ErrorContains(t, env.GetWorkflowError(), fmt.Sprintf("deadline exceeded: %s", deadline)) } diff --git a/main.go b/main.go index ff9999e2..57daf91c 100644 --- a/main.go +++ b/main.go @@ -13,24 +13,23 @@ import ( "syscall" "time" - "github.com/go-logr/logr" "github.com/oklog/run" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/spf13/pflag" "github.com/spf13/viper" "go.artefactual.dev/tools/log" - cadencesdk_activity "go.uber.org/cadence/activity" - cadencesdk_client "go.uber.org/cadence/client" - cadencesdk_workflow "go.uber.org/cadence/workflow" - "go.uber.org/zap" + temporalsdk_activity "go.temporal.io/sdk/activity" + temporalsdk_client "go.temporal.io/sdk/client" + temporalsdk_worker "go.temporal.io/sdk/worker" + temporalsdk_workflow "go.temporal.io/sdk/workflow" "github.com/artefactual-labs/enduro/internal/api" "github.com/artefactual-labs/enduro/internal/batch" - "github.com/artefactual-labs/enduro/internal/cadence" "github.com/artefactual-labs/enduro/internal/collection" "github.com/artefactual-labs/enduro/internal/db" nha_activities "github.com/artefactual-labs/enduro/internal/nha/activities" "github.com/artefactual-labs/enduro/internal/pipeline" + "github.com/artefactual-labs/enduro/internal/temporal" "github.com/artefactual-labs/enduro/internal/validation" "github.com/artefactual-labs/enduro/internal/watcher" "github.com/artefactual-labs/enduro/internal/workflow" @@ -75,20 +74,8 @@ func main() { } // Logging configuration. - var logger logr.Logger - var zlogger *zap.Logger - { - logger = log.New(os.Stderr, log.WithName(appName), log.WithDebug(config.Debug)) - - var ok bool - zlogger, ok = log.Underlying(logger) - if !ok { - fmt.Println("Failed to configure logger.") - os.Exit(1) - } - - defer log.Sync(logger) - } + logger := log.New(os.Stderr, log.WithName(appName), log.WithDebug(config.Debug)) + defer log.Sync(logger) logger.Info("Starting...", "version", version, "pid", os.Getpid()) @@ -108,13 +95,14 @@ func main() { } _ = database.Ping() - var workflowClient cadencesdk_client.Client - { - workflowClient, err = cadence.NewWorkflowClient(zlogger.Named("cadence-client"), appName, config.Cadence) - if err != nil { - logger.Error(err, "Cadence workflow client creation failed.") - os.Exit(1) - } + temporalClient, err := temporalsdk_client.Dial(temporalsdk_client.Options{ + Namespace: config.Temporal.Namespace, + HostPort: config.Temporal.Address, + Logger: temporal.Logger(logger.WithName("temporal-client")), + }) + if err != nil { + logger.Error(err, "Error creating Temporal client.") + os.Exit(1) } // Set up the pipeline registry. @@ -133,13 +121,13 @@ func main() { // Set up the batch service. var batchsvc batch.Service { - batchsvc = batch.NewService(logger.WithName("batch"), workflowClient, config.Watcher.CompletedDirs()) + batchsvc = batch.NewService(logger.WithName("batch"), temporalClient, config.Temporal.TaskQueue, config.Watcher.CompletedDirs()) } // Set up the collection service. var colsvc collection.Service { - colsvc = collection.NewService(logger.WithName("collection"), database, workflowClient, pipelineRegistry) + colsvc = collection.NewService(logger.WithName("collection"), database, temporalClient, config.Temporal.TaskQueue, pipelineRegistry) } // Set up the watcher service. @@ -202,7 +190,7 @@ func main() { IsDir: event.IsDir, ValidationConfig: config.Validation, } - if err := collection.InitProcessingWorkflow(ctx, workflowClient, &req); err != nil { + if err := collection.InitProcessingWorkflow(ctx, temporalClient, config.Temporal.TaskQueue, &req); err != nil { logger.Error(err, "Error initializing processing workflow.") } }() @@ -216,8 +204,7 @@ func main() { } } - // Create workflow workers which manage workflow and activity executions. - // This section could be executed as a different process and have replicas. + // Workflow and activity worker. { // TODO: this is a temporary workaround for dependency injection until we // figure out what's the depdencency tree is going to look like after POC. @@ -225,34 +212,37 @@ func main() { m := manager.NewManager(logger, colsvc, wsvc, pipelineRegistry, config.Hooks) done := make(chan struct{}) - w, err := cadence.NewWorker(zlogger.Named("cadence-worker"), appName, config.Cadence) + w := temporalsdk_worker.New(temporalClient, config.Temporal.TaskQueue, temporalsdk_worker.Options{ + EnableSessionWorker: true, + MaxConcurrentSessionExecutionSize: 5000, + }) if err != nil { - logger.Error(err, "Error creating Cadence worker.") + logger.Error(err, "Error creating Temporal worker.") os.Exit(1) } - w.RegisterWorkflowWithOptions(workflow.NewProcessingWorkflow(m).Execute, cadencesdk_workflow.RegisterOptions{Name: collection.ProcessingWorkflowName}) - w.RegisterActivityWithOptions(activities.NewAcquirePipelineActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: activities.AcquirePipelineActivityName}) - w.RegisterActivityWithOptions(activities.NewDownloadActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: activities.DownloadActivityName}) - w.RegisterActivityWithOptions(activities.NewBundleActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: activities.BundleActivityName}) - w.RegisterActivityWithOptions(activities.NewValidateTransferActivity().Execute, cadencesdk_activity.RegisterOptions{Name: activities.ValidateTransferActivityName}) - w.RegisterActivityWithOptions(activities.NewTransferActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: activities.TransferActivityName}) - w.RegisterActivityWithOptions(activities.NewPollTransferActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: activities.PollTransferActivityName}) - w.RegisterActivityWithOptions(activities.NewPollIngestActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: activities.PollIngestActivityName}) - w.RegisterActivityWithOptions(activities.NewCleanUpActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: activities.CleanUpActivityName}) - w.RegisterActivityWithOptions(activities.NewHidePackageActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: activities.HidePackageActivityName}) - w.RegisterActivityWithOptions(activities.NewDeleteOriginalActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: activities.DeleteOriginalActivityName}) - w.RegisterActivityWithOptions(activities.NewDisposeOriginalActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: activities.DisposeOriginalActivityName}) - - w.RegisterActivityWithOptions(workflow.NewAsyncCompletionActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: workflow.AsyncCompletionActivityName}) - w.RegisterActivityWithOptions(nha_activities.NewUpdateHARIActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: nha_activities.UpdateHARIActivityName}) - w.RegisterActivityWithOptions(nha_activities.NewUpdateProductionSystemActivity(m).Execute, cadencesdk_activity.RegisterOptions{Name: nha_activities.UpdateProductionSystemActivityName}) - - w.RegisterWorkflowWithOptions(collection.BulkWorkflow, cadencesdk_workflow.RegisterOptions{Name: collection.BulkWorkflowName}) - w.RegisterActivityWithOptions(collection.NewBulkActivity(colsvc).Execute, cadencesdk_activity.RegisterOptions{Name: collection.BulkActivityName}) - - w.RegisterWorkflowWithOptions(batch.BatchWorkflow, cadencesdk_workflow.RegisterOptions{Name: batch.BatchWorkflowName}) - w.RegisterActivityWithOptions(batch.NewBatchActivity(batchsvc).Execute, cadencesdk_activity.RegisterOptions{Name: batch.BatchActivityName}) + w.RegisterWorkflowWithOptions(workflow.NewProcessingWorkflow(m).Execute, temporalsdk_workflow.RegisterOptions{Name: collection.ProcessingWorkflowName}) + w.RegisterActivityWithOptions(activities.NewAcquirePipelineActivity(pipelineRegistry).Execute, temporalsdk_activity.RegisterOptions{Name: activities.AcquirePipelineActivityName}) + w.RegisterActivityWithOptions(activities.NewDownloadActivity(m).Execute, temporalsdk_activity.RegisterOptions{Name: activities.DownloadActivityName}) + w.RegisterActivityWithOptions(activities.NewBundleActivity(m).Execute, temporalsdk_activity.RegisterOptions{Name: activities.BundleActivityName}) + w.RegisterActivityWithOptions(activities.NewValidateTransferActivity().Execute, temporalsdk_activity.RegisterOptions{Name: activities.ValidateTransferActivityName}) + w.RegisterActivityWithOptions(activities.NewTransferActivity(m).Execute, temporalsdk_activity.RegisterOptions{Name: activities.TransferActivityName}) + w.RegisterActivityWithOptions(activities.NewPollTransferActivity(pipelineRegistry).Execute, temporalsdk_activity.RegisterOptions{Name: activities.PollTransferActivityName}) + w.RegisterActivityWithOptions(activities.NewPollIngestActivity(pipelineRegistry).Execute, temporalsdk_activity.RegisterOptions{Name: activities.PollIngestActivityName}) + w.RegisterActivityWithOptions(activities.NewCleanUpActivity(m).Execute, temporalsdk_activity.RegisterOptions{Name: activities.CleanUpActivityName}) + w.RegisterActivityWithOptions(activities.NewHidePackageActivity(m).Execute, temporalsdk_activity.RegisterOptions{Name: activities.HidePackageActivityName}) + w.RegisterActivityWithOptions(activities.NewDeleteOriginalActivity(m).Execute, temporalsdk_activity.RegisterOptions{Name: activities.DeleteOriginalActivityName}) + w.RegisterActivityWithOptions(activities.NewDisposeOriginalActivity(m).Execute, temporalsdk_activity.RegisterOptions{Name: activities.DisposeOriginalActivityName}) + + w.RegisterActivityWithOptions(workflow.NewAsyncCompletionActivity(colsvc).Execute, temporalsdk_activity.RegisterOptions{Name: workflow.AsyncCompletionActivityName}) + w.RegisterActivityWithOptions(nha_activities.NewUpdateHARIActivity(m).Execute, temporalsdk_activity.RegisterOptions{Name: nha_activities.UpdateHARIActivityName}) + w.RegisterActivityWithOptions(nha_activities.NewUpdateProductionSystemActivity(m).Execute, temporalsdk_activity.RegisterOptions{Name: nha_activities.UpdateProductionSystemActivityName}) + + w.RegisterWorkflowWithOptions(collection.BulkWorkflow, temporalsdk_workflow.RegisterOptions{Name: collection.BulkWorkflowName}) + w.RegisterActivityWithOptions(collection.NewBulkActivity(colsvc).Execute, temporalsdk_activity.RegisterOptions{Name: collection.BulkActivityName}) + + w.RegisterWorkflowWithOptions(batch.BatchWorkflow, temporalsdk_workflow.RegisterOptions{Name: batch.BatchWorkflowName}) + w.RegisterActivityWithOptions(batch.NewBatchActivity(batchsvc).Execute, temporalsdk_activity.RegisterOptions{Name: batch.BatchActivityName}) g.Add( func() error { @@ -269,6 +259,7 @@ func main() { ) } + // Observability server. { ln, err := net.Listen("tcp", config.DebugListen) if err != nil { @@ -340,7 +331,7 @@ type configuration struct { DebugListen string API api.Config Database db.Config - Cadence cadence.Config + Temporal temporal.Config Watcher watcher.Config Pipeline []pipeline.Config Validation validation.Config @@ -361,8 +352,9 @@ func configureViper(v *viper.Viper) { v.SetConfigName(appName) v.SetDefault("debugListen", "127.0.0.1:9001") v.SetDefault("api.listen", "127.0.0.1:9000") - v.SetDefault("cadence.address", ":7933") v.Set("api.appVersion", version) + + temporal.SetDefaults(v) } func readConfig(v *viper.Viper, config *configuration, configFile string) (found bool, err error) { diff --git a/ui/src/openapi-generator/models/EnduroCollectionWorkflowHistoryResponseBody.ts b/ui/src/openapi-generator/models/EnduroCollectionWorkflowHistoryResponseBody.ts index 8df48ed3..6262282d 100644 --- a/ui/src/openapi-generator/models/EnduroCollectionWorkflowHistoryResponseBody.ts +++ b/ui/src/openapi-generator/models/EnduroCollectionWorkflowHistoryResponseBody.ts @@ -14,7 +14,7 @@ import { exists, mapValues } from '../runtime'; /** - * WorkflowHistoryEvent describes a history event in Cadence. (default view) + * WorkflowHistoryEvent describes a history event in Temporal. (default view) * @export * @interface EnduroCollectionWorkflowHistoryResponseBody */ diff --git a/ui/src/views/CollectionShowWorkflow.vue b/ui/src/views/CollectionShowWorkflow.vue index 596d9b78..f927e0a7 100644 --- a/ui/src/views/CollectionShowWorkflow.vue +++ b/ui/src/views/CollectionShowWorkflow.vue @@ -34,13 +34,13 @@ @@ -52,7 +52,7 @@ {{ item.name }} {{ item.name }} (local activity) - {{ item.started | formatEpoch }} + {{ item.started | formatDateTimeString }} {{ item.replayed | formatDateTimeString }} {{ item.duration }}s ({{ item.attempts }} attempts) @@ -67,8 +67,8 @@ #{{ item.id }} {{ item.type }}
- {{ item.details.timestamp | formatEpoch }} -
+ {{ item.details.event_time | formatDateTimeString }} +
@@ -125,12 +125,15 @@ export default class CollectionShowWorkflow extends Vue { return EnduroCollectionClient.collectionWorkflow({id: +this.$route.params.id}).then((response: api.CollectionWorkflowResponseBody) => { this.history = response; this.processHistory(); - }).catch((response) => { + }).catch((err) => { this.error = true; + + // tslint:disable-next-line:no-console + console.log(err); }); } - private parseEncodedField(input: string): string { + private parseEncodedField(input: string): any { const value = window.atob(input); try { return JSON.parse(value); @@ -147,22 +150,24 @@ export default class CollectionShowWorkflow extends Vue { for (const event of this.history.history) { const details = event.details; if (event.type === 'MarkerRecorded') { - const attrs = details.markerRecordedEventAttributes; - if (attrs.markerName === 'LocalActivity') { - const innerDetails = JSON.parse(window.atob(attrs.details)); - this.activities[event.id] = { - local: true, - name: innerDetails.activityType, - attempts: 0, - replayed: innerDetails.replayTime, - }; - if (innerDetails.hasOwnProperty('resultJson')) { - // JSON.parse(innerDetails.resultJson); - } + const attrs = details.Attributes.marker_recorded_event_attributes; + if (attrs.marker_name !== 'LocalActivity') { + continue; } + const dataPayloads = attrs.details.data.payloads; + if (!dataPayloads.length) { + continue; + } + const innerDetails = this.parseEncodedField(dataPayloads[0].data); + this.activities[event.id] = { + local: true, + name: innerDetails.ActivityType, + attempts: innerDetails.Attempt, + replayed: innerDetails.ReplayTime, + }; } else if (event.type === 'ActivityTaskScheduled') { - const attrs = details.activityTaskScheduledEventAttributes; - const name = attrs.activityType.name; + const attrs = details.Attributes.activity_task_scheduled_event_attributes; + const name = attrs.activity_type.name; if (ignoredActivities.includes(name)) { continue; } @@ -171,59 +176,74 @@ export default class CollectionShowWorkflow extends Vue { name, status: 'in progress', attempts: 0, - started: details.timestamp, + started: details.event_time, }; } else if (event.type === 'ActivityTaskStarted') { - const attrs = details.activityTaskStartedEventAttributes; - if (attrs.scheduledEventId in this.activities) { - const item = this.activities[attrs.scheduledEventId]; - item.attempts = attrs.attempt + 1; + const attrs = details.Attributes.activity_task_started_event_attributes; + if (attrs.scheduled_event_id in this.activities) { + const item = this.activities[attrs.scheduled_event_id]; + item.attempts = attrs.attempt; } } else if (event.type === 'ActivityTaskFailed') { - const attrs = details.activityTaskFailedEventAttributes; + const attrs = details.Attributes.activity_task_failed_event_attributes; this.activityError = true; - if (attrs.scheduledEventId in this.activities) { - const item = this.activities[attrs.scheduledEventId]; + if (attrs.scheduled_event_id in this.activities) { + const item = this.activities[attrs.scheduled_event_id]; item.status = 'error'; - item.details = window.atob(attrs.details); - item.completed = details.timestamp; - item.duration = (item.completed - item.started) / 1000000000; - item.duration = item.duration.toFixed(2); + item.details = 'Message: ' + attrs.failure.message; + item.completed = details.event_time; + item.duration = this.duration(item.started, item.completed); } } else if (event.type === 'ActivityTaskCompleted') { - const attrs = details.activityTaskCompletedEventAttributes; - if (attrs.scheduledEventId in this.activities) { - const item = this.activities[attrs.scheduledEventId]; + const attrs = details.Attributes.activity_task_completed_event_attributes; + if (attrs.scheduled_event_id in this.activities) { + const item = this.activities[attrs.scheduled_event_id]; item.status = 'done'; - item.completed = details.timestamp; - item.duration = (item.completed - item.started) / 1000000000; - item.duration = item.duration.toFixed(2); + item.completed = details.event_time; + item.duration = this.duration(item.started, item.completed); if (item.name === 'async-completion-activity' && attrs.result) { item.details = 'User selection: ' + window.atob(attrs.result) + '.'; } } } else if (event.type === 'ActivityTaskTimedOut') { - const attrs = details.activityTaskTimedOutEventAttributes; - if (attrs.scheduledEventId in this.activities) { - const item = this.activities[attrs.scheduledEventId]; + const attrs = details.Attributes.activity_task_timed_out_event_attributes; + if (attrs.scheduled_event_id in this.activities) { + const item = this.activities[attrs.scheduled_event_id]; item.status = 'timed out'; - item.details = 'Timeout ' + attrs.timeoutType + '.'; + item.details = 'Timeout ' + attrs.timeout_type + '.'; } } else if (event.type === 'WorkflowExecutionStarted') { - this.startedAt = details.timestamp; + this.startedAt = details.event_time; } else if (event.type === 'WorkflowExecutionCompleted') { - this.completedAt = details.timestamp; + this.completedAt = details.event_time; } else if (event.type === 'WorkflowExecutionFailed') { - const attrs = details.workflowExecutionFailedEventAttributes; - const reason = attrs.reason; - const info = this.parseEncodedField(attrs.details); - this.workflowError = reason + ' - ' + info; - this.completedAt = details.timestamp; + const attrs = details.Attributes.workflow_execution_failed_event_attributes; + this.workflowError = this.workflowErrorDescription(attrs.failure); + this.completedAt = details.event_time; } } } - private renderDetails(event: api.EnduroCollectionWorkflowHistoryResponseBody): string { + private workflowErrorDescription(failure: any): string { + let desc = ''; + if (failure.hasOwnProperty('message')) { + desc = failure.message; + } + if (failure.hasOwnProperty('cause') && failure.cause.hasOwnProperty('message')) { + if (desc.length) desc += ': '; + desc += failure.cause.message; + } + return desc + } + + private duration(startedAt: string, completedAt: string): string { + const started = new Date(startedAt); + const completed = new Date(completedAt); + const took = (completed.getTime() - started.getTime()) / 1000; + return took.toLocaleString(); + } + + private historyEventDescription(event: api.EnduroCollectionWorkflowHistoryResponseBody): string { let ret = ''; if (!event || !event.type) { @@ -231,17 +251,21 @@ export default class CollectionShowWorkflow extends Vue { } const attrs: any = event.details; + if (event.type === 'ActivityTaskScheduled') { - ret = 'Activity: ' + attrs.activityTaskScheduledEventAttributes.activityType.name; + ret = 'Activity: ' + attrs.Attributes.activity_task_scheduled_event_attributes.activity_type.name; } else if (event.type === 'ActivityTaskFailed') { - ret = 'Error: ' + window.atob(attrs.activityTaskFailedEventAttributes.details); + const body = attrs.Attributes.activity_task_failed_event_attributes; + ret = JSON.stringify(body, null, 2); } else if (event.type === 'DecisionTaskScheduled') { const attempt: number = parseInt(attrs.decisionTaskScheduledEventAttributes.attempt, 10) + 1; ret = 'Attempts: ' + attempt; } else if (event.type === 'WorkflowExecutionFailed') { - const reason = attrs.workflowExecutionFailedEventAttributes.reason; - const info = this.parseEncodedField(attrs.workflowExecutionFailedEventAttributes.details); - ret = reason + ' - ' + info; + const body = attrs.Attributes.workflow_execution_failed_event_attributes; + ret = JSON.stringify(body, null, 2); + } else if (event.type == 'WorkflowExecutionStarted') { + const body = attrs.Attributes.workflow_execution_started_event_attributes; + ret = JSON.stringify(body, null, 2); } if (ret.length) { diff --git a/website/content/en/docs/development/environment.md b/website/content/en/docs/development/environment.md index d48179a3..f86c80b2 100644 --- a/website/content/en/docs/development/environment.md +++ b/website/content/en/docs/development/environment.md @@ -18,10 +18,10 @@ makes thing much simpler during development. There are some dependencies that need to be installed: -* [Go][go], -* [Docker Compose][docker-compose], -* [Node.js][nodejs], and -* [GNU Make][make] +- [Go][go], +- [Docker Engine][docker-engine] (includes Docker Compose), +- [Node.js][nodejs], and +- [GNU Make][make] This guide may not work for you if you manage Docker with `sudo`, see [issue #118][issue-118] for more. It is possible to manage Docker as a non-root @@ -31,17 +31,7 @@ user with some [extra configuration steps][docker-non-root]. Spin up the environment with the following command: - docker-compose up --detach - -Cadence will crash right away because the database has not been set up properly. -Run the following command to introduce the MySQL tables needed by Cadence: - - make cadence-seed - -In a minute or less, Cadence should be up again. Since Cadence is a multitenant -service, we need to create a Cadence domain for Enduro: - - make cadence-domain + docker compose up --detach Now we need to build some Go tools we're going to use during development: @@ -66,8 +56,8 @@ MinIO is one of the services installed automatically with Docker Compose. You should be able to access the web file browser via http://127.0.0.1:7460 using the following credentials: -* Access key: `minio` -* Secret key: `minio123` +- Access key: `minio` +- Secret key: `minio123` Alternatively, you can [install][mc] the MinIO command-line client (mc) and register the local instance with: @@ -102,8 +92,8 @@ since the event is buffered by Redis. make run -Additionally, you can visualize workflows and activities from Cadence Web. Try -opening the following link: http://127.0.0.1:7440/domain/enduro/workflows/. +Additionally, you can visualize workflows and activities from Temporal UI. Try +opening the following link: http://127.0.0.1:7440/namespaces/default/workflows. ## Development workflow @@ -129,13 +119,12 @@ You can enable it in Visual Studio Code as follows: ```json { - "go.lintTool": "golangci-lint", - "go.lintFlags": ["--fast"] + "go.lintTool": "golangci-lint", + "go.lintFlags": ["--fast"] } ``` - -[docker-compose]: https://docs.docker.com/compose/install/ +[docker-engine]: https://docs.docker.com/engine/install/ [mc]: https://docs.min.io/docs/minio-client-quickstart-guide.html [go]: https://golang.org/doc/install [gopls]: https://github.com/golang/tools/blob/master/gopls/README.md diff --git a/website/content/en/docs/installation/_index.md b/website/content/en/docs/installation/_index.md index 9cd13d6c..8c3006dd 100644 --- a/website/content/en/docs/installation/_index.md +++ b/website/content/en/docs/installation/_index.md @@ -13,7 +13,7 @@ Enduro is still at its early stages. **Use with caution!** ## Introduction This is a work-in-progress document that we expect to extend as we refine the -design of Enduro and we learn more about Cadence. You may prefer to use our +design of Enduro and we learn more about Temporal. You may prefer to use our [development environment][enduro-devenv] if you only came here for evaluating purposes. @@ -21,87 +21,21 @@ The instructions below are not specific to a particular environment. ## Dependencies -Enduro's two main dependencies are MySQL and Cadence. +Enduro's two main dependencies are MySQL and Temporal. ### MySQL -We use MySQL 5.7. MySQL 8.x has not been tested yet but there is at least one -known incompatibility in Cadence. +We use MySQL 8, which serves as the data store for Enduro and Temporal. -It is recommendable to change the default character settings of the server. For -example, it can be added to the `[mysqld]` configuration: +### Temporal -```ini -[mysqld] -character-set-server=utf8mb4 -collation-server=utf8mb4_general_ci -``` - -### Cadence - -Cadence is the orchestration engine. Currently, Cadence is only distributed as a -Docker image. It is possible to extract the static binaries from the image using -the following commands: - - mkdir -p $HOME/cadence - cd $HOME/cadence - ctid=$(docker create ubercadence/server:0.9.4) - docker cp ${ctid}:/usr/local/bin/cadence . - docker cp ${ctid}:/usr/local/bin/cadence-server . - docker cp ${ctid}:/usr/local/bin/cadence-sql-tool . - docker cp ${ctid}:/etc/cadence/schema/mysql/v57/cadence/versioned ./cadence-migrations - docker cp ${ctid}:/etc/cadence/schema/mysql/v57/visibility/versioned ./visibility-migrations - -A detailed description of what we are extracting from the Docker image: - -* `cadence` is the [Cadence CLI management tool][cadence-cli]. It is the most - important tool for Cadence administrators. -* `cadence-server` is the server binary. -* `cadence-sql-tool` is the database migration tool which we're going to use - later in this document to apply migrations. The `cadence-migrations` and - `visibility-migrations` directories contain the actual SQL migrations. - -#### Running Cadence - -This is an example on how to run the Cadence server: - - cadence-server \ - --root=/etc/cadence \ - --env=demo \ - --services=frontend,matching,history,worker \ - start - -The previous command will read config from `/etc/cadence/config/demo.yaml`. -Unfortunately, the configuration is not documented properly. Please use our -[development config][development-config] as a reference. - -The `--services` flag is telling Cadence which subsystems to load. It allows -administrators to set up complex distributed deployments. It is safe to start -with a simpler configuration with the four main services together. - -Off all the services that make up Cadence, `frontend` is the one we need to -connect. By default, it listens on `127.0.0.1:7933` but our development -environment uses `127.0.0.1:7400` instead. - -#### Database setup - -Cadence needs two MySQL databases set up properly before starting the daemon -(`cadence` and `cadence_visibility`). Enduro needs its own MySQL database -(`enduro`). The following snippet provisions the databases as needed: - -```mysql -CREATE USER 'enduro'@'%' IDENTIFIED BY 'enduro123'; -CREATE DATABASE IF NOT EXISTS cadence CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -GRANT ALL PRIVILEGES ON cadence.* TO 'enduro'@'%'; -CREATE DATABASE IF NOT EXISTS cadence_visibility CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -GRANT ALL PRIVILEGES ON cadence_visibility.* TO 'enduro'@'%'; -CREATE DATABASE IF NOT EXISTS enduro CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -GRANT ALL PRIVILEGES ON enduro.* TO 'enduro'@'%'; -``` +Temporal is the orchestration engine. There are [multiple ways to run a Temporal +Cluster](temporal-clusters). Our standard configuration uses an [Ansible +role](temporal-ansible-role) to deploy both Enduro and Temporal on a remote +server. -Another required step is to apply the SQL migrations using `cadence-sql-tool`. -We do similarly in the development environment via [`seed.sh`][cadence-dbseed] -which can be used as a reference. +More on this topic can be found at the official [Temporal Cluster deployment +guide](temporal-deployment). ### Other dependencies @@ -109,31 +43,20 @@ which can be used as a reference. Enduro can consume objects uploaded to MinIO by listening to [MinIO events via Redis][minio-redis-access]. MinIO and Redis can be considered dependencies only -when Enduro is set up with at least one ``watcher.minio`` entry. +when Enduro is set up with at least one `watcher.minio` entry. -#### Cadence Web +#### Temporal Web UI -Cadence provides a web interface that offers some visibility of workflows and +Temporal provides a web interface that offers great visibility of workflows and activities. Compared to the command-line interface, it does not provide as much control and granularity, but it is useful in simpler use cases. -It is distributed as a Docker image but it can also be installed via Node -package managers such npm or Yarn. With Docker installed, you can run it with: - - docker run \ - --env=CADENCE_WEB_PORT=10000 \ - --env=CADENCE_TCHANNEL_PEERS=127.0.0.1:7933 \ - ubercadence/web:3.4.1 - -If you're deploying with Docker, use `--restart=always` or similar to apply a -[restart policy][docker-restart-policy] to the container. At the moment, the -process ignores system signals. Use `docker container kill` if you want to stop -the container. +Visit [Temporal Web UI](temporal-web-ui) to know more. #### Prometheus Though not a dependency per se, Prometheus can be used to pull metrics from -both Cadence (be prepared for an extensive set of metrics here) and Enduro. +both Temporal (be prepared for an extensive set of metrics here) and Enduro. In Enduro, the `debugListen` configuration parameter determines the address of the HTTP server from which the metrics are served. E.g. use @@ -146,16 +69,6 @@ Enduro binaries can be found at the [release page][enduro-release-page]. Learn more about the configuration details [here]({{< relref "/docs/user-manual/configuration" >}}). -### Domain creation - -Enduro is set up to employ a specific [Cadence domain][cadence-domain] which -needs to be created beforehand with Cadence's CLI tool. The following is an -example that creates the `enduro` domain assuming that Cadence's `frontend` is -listening on `127.0.0.1:7933`. - - docker run -it --network=host --rm \ - ubercadence/cli:master --address=127.0.0.1:7933 --domain=enduro domain register - ### API server The configuration attribute `api.listen` determines the address where Enduro @@ -194,13 +107,12 @@ the API via cURL is `curl -Ls 127.0.0.1:9000/collection | jq`: ] ``` - -[cadence-deployment]: https://github.com/uber/cadence/tree/master/docker -[cadence-dbseed]: https://github.com/artefactual-labs/enduro/blob/main/hack/cadence/seed.sh -[cadence-cli]: https://cadenceworkflow.io/docs/08_cli -[cadence-domain]: https://cadenceworkflow.io/docs/04_glossary#domain -[development-config]: https://github.com/artefactual-labs/enduro/blob/main/hack/cadence/config.yml +[temporal-clusters]: https://docs.temporal.io/kb/all-the-ways-to-run-a-cluster +[temporal-ansible-role]: https://github.com/artefactual-labs/ansible-enduro-temporal +[temporal-deployment]: https://docs.temporal.io/cluster-deployment-guide +[temporal-web-ui]: https://docs.temporal.io/web-ui [minio-redis-access]: https://docs.min.io/docs/minio-bucket-notification-guide.html#Redis [docker-restart-policy]: https://docs.docker.com/config/containers/start-containers-automatically/#use-a-restart-policy [enduro-release-page]: https://github.com/artefactual-labs/enduro/releases + [enduro-devenv]: {{< ref "/docs/development/environment" >}} diff --git a/website/content/en/docs/overview/cadence.md b/website/content/en/docs/overview/cadence.md deleted file mode 100644 index ef1c9fb1..00000000 --- a/website/content/en/docs/overview/cadence.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: "Cadence" -linkTitle: "Cadence" -weight: 3 -description: > - How we use Cadence to build Enduro. ---- - -Enduro is based on [Cadence][cadence-website], an [open-source][cadence-repo] -orchestration engine developed at Uber Engineering and led by the designers of -off-premises solutions like [Amazon Simple Workflow Service (SWF)][aws-swf] and -[Azure Durable Functions][azure-durable-functions]. - -Cadence is being used by some well-known companies, such as: Uber, HashiCorp, -Coinbase, LinkedIn or Banzai Cloud: - -* Banzai Cloud shared a [series of blog posts][banzai-cloud-posts] on how they - are using Cadence to implement complex workflows that manage the entire - life-cycle of Kubernetes clusters. -* HashiCorp has recently shared details of [HashiCorp Consul Service][hcs], a - managed Consul service built in partnership with Microsoft. Their control - plane uses Cadence - see [the presentation][hcs-presentation] for more - details. - -[cadence-website]: https://cadenceworkflow.io/ -[cadence-repo]: https://github.com/uber/cadence -[banzai-cloud-posts]: https://banzaicloud.com/tags/cadence/ -[aws-swf]: https://aws.amazon.com/swf/ -[azure-durable-functions]: https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-overview -[hcs]: https://www.hashicorp.com/resources/making-multi-environment-service-networking-on-microsoft-azure-easy-with-consul -[hcs-presentation]: https://youtu.be/kDlrM6sgk2k?t=970 diff --git a/website/content/en/docs/overview/howitworks.md b/website/content/en/docs/overview/howitworks.md index 676cd249..009f7b36 100644 --- a/website/content/en/docs/overview/howitworks.md +++ b/website/content/en/docs/overview/howitworks.md @@ -10,7 +10,7 @@ sources an event tells Enduro to start a **processing workflow** for the file. The processing workflow consists of many activities (see the -*activity* definition in Cadence's [glossary]) which are orchestrated +_activity_ definition in Temporal's [glossary]) which are orchestrated by Enduro. This is how the activity summary looks in the user interface when you @@ -19,74 +19,74 @@ check the workflow of a successful transfer: ![Activity summary](/activity-summary.jpg) 1. **createPackageLocalActivity** creates the Enduro collection giving -it an identifier and naming it after the original file. + it an identifier and naming it after the original file. 1. **ParseNameLocalActivity** is an NHA specific activity which -validates the name of the source file according to their -rules. Enduro's default configuration makes this activity a -[NOP](https://en.wikipedia.org/wiki/NOP_(code)). + validates the name of the source file according to their + rules. Enduro's default configuration makes this activity a + [NOP](). 1. **loadConfigLocalActivity** loads the pipeline -configuration. Things like its transfer and processing directories, -credentials for contacting it, how many concurrent transfers can -handle (its capacity), etc. + configuration. Things like its transfer and processing directories, + credentials for contacting it, how many concurrent transfers can + handle (its capacity), etc. 1. **acquire-pipeline-activity** checks the capacity of the pipeline -to decide if we can send a new one. + to decide if we can send a new one. 1. **setStatusInProgressLocalActivity** updates the collection marking -it as "in progress". + it as "in progress". 1. **download-activity** copies the original file from the watched -source into a temporary file in the pipeline's processing directory. + source into a temporary file in the pipeline's processing directory. 1. **bundle-activity** prepares the temporary file in the pipeline's -processing directory: if it's a compressed file it extracts it and it -creates the objects and metadata directory expected by -Archivematica. Then it copies the prepared directory into the -pipeline's transfer source location. + processing directory: if it's a compressed file it extracts it and it + creates the objects and metadata directory expected by + Archivematica. Then it copies the prepared directory into the + pipeline's transfer source location. 1. **transfer-activity** submits the transfer to Archivematica and -stores its UUID. + stores its UUID. 1. **updatePackageLocalActivity** updates the Enduro collection with -the transfer UUID. + the transfer UUID. 1. **poll-transfer-activity** checks the transfer status (think of -looking at the Transfer tab in the Archivematica dashboard) + looking at the Transfer tab in the Archivematica dashboard) 1. **updatePackageLocalActivity** updates the Enduro collection with -the SIP UUID once the transfer finishes. + the SIP UUID once the transfer finishes. 1. **poll-ingest-activity** checks the SIP status (think of looking at -the Ingest tab in the Archivematica dashboard) + the Ingest tab in the Archivematica dashboard) 1. **clean-up-activity** removes the directory that Enduro created in -the pipeline's transfer source location. + the pipeline's transfer source location. 1. **releasePipelineLocalActivity** updates the pipeline capacity -saying we're done using it. + saying we're done using it. 1. **hide-package-activity** is executed twice to hide the transfer -from the Transfer and Ingest tabs in the Dashboard. + from the Transfer and Ingest tabs in the Dashboard. 1. **delete-original-activity** schedules a time when the original -file has to be removed from the watched source. + file has to be removed from the watched source. 1. **updatePackageLocalActivity** updates the final status of the -Enduro collection. + Enduro collection. ## Local and "non local" activities Notice that some of these activities are marked as **(local activity)** which means they're supposed to run in the same host that -is running the processing workflow (see the *local activity* -definition in Cadence's [glossary]). +is running the processing workflow (see the _local activity_ +definition in Temporal's [glossary]). The other type of activities (non local) can theoretically be run in a separate host (which can provide better performance, more resilience, etc), but in practice we're [running them all in the same host at the moment][issue-37]. -[glossary]: https://cadenceworkflow.io/GLOSSARY.html#glossary +[glossary]: https://docs.temporal.io/glossary [issue-37]: https://github.com/artefactual-labs/enduro/issues/37 diff --git a/website/content/en/docs/user-manual/configuration.md b/website/content/en/docs/user-manual/configuration.md index ed388e3f..785f9041 100644 --- a/website/content/en/docs/user-manual/configuration.md +++ b/website/content/en/docs/user-manual/configuration.md @@ -8,7 +8,7 @@ description: > ## Configuration -Enduro is configured via the ``enduro.toml`` configuration file which uses TOML, +Enduro is configured via the `enduro.toml` configuration file which uses TOML, a well-known file format for configuration files. The default search paths are `/etc/enduro.toml`, `$HOME/.config/enduro.toml`, @@ -37,19 +37,19 @@ data. E.g.: `"127.0.0.1:9001"` -### `[cadence]` +### `[temporal]` -Connection details with the Cadence server. +Connection details with the Temporal server. -#### `domain` (String) +#### `namespace` (String) -Name of the Cadence domain used by this application. +Name of the Temporal namespace used by this application. E.g.: `"enduro"` #### `address` (String) -Address of the Cadence front-end server. +Address of the Temporal front-end server. E.g.: `"127.0.0.1:7400"` @@ -343,6 +343,4 @@ Source: https://github.com/artefactual-labs/enduro/blob/main/enduro.toml. {{< config >}} [Data Source Name format]: https://github.com/go-sql-driver/mysql#dsn-data-source-name - - [RE2 syntax]: https://github.com/google/re2/wiki/Syntax