diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cda372..0e94a7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.8.0] - 2026-06-05 + +### Added + +- `workflows`: Added `TaskExecutor`, `PollingTaskRunner`, and `client.NewPollingTaskRunner` for custom task execution backends that need to use the Tilebox task polling protocol directly. + +### Changed + +- `workflows`: Changed `TaskRunner.RunForever` and `TaskRunner.RunAll` to return errors from the polling loop. + ## [0.7.1] - 2026-05-22 ### Fixed @@ -118,7 +128,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added support for Tilebox Observability, including logging and tracing helpers. - Added examples for using the library. -[Unreleased]: https://github.com/tilebox/tilebox-go/compare/v0.7.1...HEAD +[Unreleased]: https://github.com/tilebox/tilebox-go/compare/v0.8.0...HEAD +[0.8.0]: https://github.com/tilebox/tilebox-go/compare/v0.7.1...v0.8.0 [0.7.1]: https://github.com/tilebox/tilebox-go/compare/v0.7.0...v0.7.1 [0.7.0]: https://github.com/tilebox/tilebox-go/compare/v0.6.0...v0.7.0 [0.6.0]: https://github.com/tilebox/tilebox-go/compare/v0.5.0...v0.6.0 diff --git a/README.md b/README.md index 80fd07b..410f960 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,9 @@ func main() { return } - runner.RunForever(ctx) + if err := runner.RunForever(ctx); err != nil { + slog.ErrorContext(ctx, "task runner stopped", slog.Any("error", err)) + } } ``` diff --git a/examples/workflows/helloworld/main.go b/examples/workflows/helloworld/main.go index 3f8aa5f..150588e 100644 --- a/examples/workflows/helloworld/main.go +++ b/examples/workflows/helloworld/main.go @@ -47,5 +47,7 @@ func main() { return } - runner.RunForever(ctx) + if err := runner.RunForever(ctx); err != nil { + slog.ErrorContext(ctx, "task runner stopped", slog.Any("error", err)) + } } diff --git a/examples/workflows/mapreduce/main.go b/examples/workflows/mapreduce/main.go index 69aae08..e8e4c6d 100644 --- a/examples/workflows/mapreduce/main.go +++ b/examples/workflows/mapreduce/main.go @@ -106,5 +106,7 @@ func main() { return } - runner.RunForever(ctx) + if err := runner.RunForever(ctx); err != nil { + slog.ErrorContext(ctx, "task runner stopped", slog.Any("error", err)) + } } diff --git a/examples/workflows/observability/axiom/main.go b/examples/workflows/observability/axiom/main.go index a57490e..1a15269 100644 --- a/examples/workflows/observability/axiom/main.go +++ b/examples/workflows/observability/axiom/main.go @@ -81,5 +81,7 @@ func main() { return } - taskRunner.RunForever(ctx) + if err := taskRunner.RunForever(ctx); err != nil { + slog.ErrorContext(ctx, "task runner stopped", slog.Any("error", err)) + } } diff --git a/examples/workflows/observability/opentelemetry/main.go b/examples/workflows/observability/opentelemetry/main.go index 6a49e4e..ac9110d 100644 --- a/examples/workflows/observability/opentelemetry/main.go +++ b/examples/workflows/observability/opentelemetry/main.go @@ -91,5 +91,7 @@ func main() { return } - taskRunner.RunForever(ctx) + if err := taskRunner.RunForever(ctx); err != nil { + slog.ErrorContext(ctx, "task runner stopped", slog.Any("error", err)) + } } diff --git a/examples/workflows/progress/main.go b/examples/workflows/progress/main.go index 0dba852..16faf0b 100644 --- a/examples/workflows/progress/main.go +++ b/examples/workflows/progress/main.go @@ -70,7 +70,10 @@ func main() { return } - runner.RunAll(ctx) + if err := runner.RunAll(ctx); err != nil { + slog.ErrorContext(ctx, "failed to run tasks", slog.Any("error", err)) + return + } job, err = client.Jobs.Get(ctx, job.ID) // fetch up-to-date job progress if err != nil { diff --git a/examples/workflows/protobuf-task/main.go b/examples/workflows/protobuf-task/main.go index 8c062be..d319123 100644 --- a/examples/workflows/protobuf-task/main.go +++ b/examples/workflows/protobuf-task/main.go @@ -97,5 +97,7 @@ func main() { return } - taskRunner.RunForever(ctx) + if err := taskRunner.RunForever(ctx); err != nil { + slog.ErrorContext(ctx, "task runner stopped", slog.Any("error", err)) + } } diff --git a/go.mod b/go.mod index 4297636..5093f5b 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,7 @@ go 1.25.0 require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20260415201107-50325440f8f2.1 - connectrpc.com/connect v1.19.2 - github.com/avast/retry-go/v4 v4.7.0 + connectrpc.com/connect v1.20.0 github.com/cespare/xxhash/v2 v2.3.0 github.com/deckarep/golang-set/v2 v2.9.0 github.com/google/uuid v1.6.0 @@ -15,16 +14,16 @@ require ( github.com/samber/lo v1.53.0 github.com/samber/slog-multi v1.8.0 github.com/stretchr/testify v1.11.1 - go.opentelemetry.io/contrib/bridges/otelslog v0.18.0 - go.opentelemetry.io/otel v1.43.0 - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 - go.opentelemetry.io/otel/metric v1.43.0 - go.opentelemetry.io/otel/sdk v1.43.0 - go.opentelemetry.io/otel/sdk/log v0.19.0 - go.opentelemetry.io/otel/trace v1.43.0 + go.opentelemetry.io/contrib/bridges/otelslog v0.19.0 + go.opentelemetry.io/otel v1.44.0 + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.20.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.44.0 + go.opentelemetry.io/otel/metric v1.44.0 + go.opentelemetry.io/otel/sdk v1.44.0 + go.opentelemetry.io/otel/sdk/log v0.20.0 + go.opentelemetry.io/otel/trace v1.44.0 go.opentelemetry.io/proto/otlp v1.10.0 - google.golang.org/grpc v1.81.0 + google.golang.org/grpc v1.81.1 google.golang.org/protobuf v1.36.11 pgregory.net/rapid v1.3.0 ) @@ -42,12 +41,12 @@ require ( github.com/samber/slog-common v0.22.0 // indirect go.mongodb.org/mongo-driver v1.17.9 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect - go.opentelemetry.io/otel/log v0.19.0 // indirect - golang.org/x/net v0.54.0 // indirect - golang.org/x/sys v0.44.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0 // indirect + go.opentelemetry.io/otel/log v0.20.0 // indirect + golang.org/x/net v0.55.0 // indirect + golang.org/x/sys v0.45.0 // indirect golang.org/x/text v0.37.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260504160031-60b97b32f348 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index cb1e7f5..73a8b52 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,7 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20260415201107-50325440f8f2.1 h1:s6hzCXtND/ICdGPTMGk7C+/BFlr2Jg5GyH0NKf4XGXg= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20260415201107-50325440f8f2.1/go.mod h1:tvtbpgaVXZX4g6Pn+AnzFycuRK3MOz5HJfEGeEllXYM= -connectrpc.com/connect v1.19.2 h1:McQ83FGdzL+t60peksi0gXC7MQ/iLKgLduAnThbM0mo= -connectrpc.com/connect v1.19.2/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w= -github.com/avast/retry-go/v4 v4.7.0 h1:yjDs35SlGvKwRNSykujfjdMxMhMQQM0TnIjJaHB+Zio= -github.com/avast/retry-go/v4 v4.7.0/go.mod h1:ZMPDa3sY2bKgpLtap9JRUgk2yTAba7cgiFhqxY2Sg6Q= +connectrpc.com/connect v1.20.0 h1:6TNDAB+WeNd2uolWNlYczB5E0KNNaVMNUEx8JEUsPmQ= +connectrpc.com/connect v1.20.0/go.mod h1:A2ygJrukXwWy32vkCAAHNVguZrqZ+jeZ9rGRnGR4dN4= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -61,48 +59,48 @@ go.mongodb.org/mongo-driver v1.17.9 h1:IexDdCuuNJ3BHrELgBlyaH9p60JXAvdzWR128q+U5 go.mongodb.org/mongo-driver v1.17.9/go.mod h1:LlOhpH5NUEfhxcAwG0UEkMqwYcc4JU18gtCdGudk/tQ= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/bridges/otelslog v0.18.0 h1:hhPGP3zvvy1xWT9RTy970wlniSxFttBIsAK1gvMguJM= -go.opentelemetry.io/contrib/bridges/otelslog v0.18.0/go.mod h1:twJF7inoMza6kxMcF8JOdL3mPmtOZu7GEr34CUNE6Dg= -go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= -go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 h1:HIBTQ3VO5aupLKjC90JgMqpezVXwFuq6Ryjn0/izoag= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0/go.mod h1:ji9vId85hMxqfvICA0Jt8JqEdrXaAkcpkI9HPXya0ro= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= -go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= -go.opentelemetry.io/otel/log v0.19.0/go.mod h1:5DQYeGmxVIr4n0/BcJvF4upsraHjg6vudJJpnkL6Ipk= -go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= -go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= -go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= -go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= -go.opentelemetry.io/otel/sdk/log v0.19.0 h1:scYVLqT22D2gqXItnWiocLUKGH9yvkkeql5dBDiXyko= -go.opentelemetry.io/otel/sdk/log v0.19.0/go.mod h1:vFBowwXGLlW9AvpuF7bMgnNI95LiW10szrOdvzBHlAg= -go.opentelemetry.io/otel/sdk/log/logtest v0.19.0 h1:BEbF7ZBB6qQloV/Ub1+3NQoOUnVtcGkU3XX4Ws3GQfk= -go.opentelemetry.io/otel/sdk/log/logtest v0.19.0/go.mod h1:Lua81/3yM0wOmoHTokLj9y9ADeA02v1naRrVrkAZuKk= -go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= -go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= -go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= -go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +go.opentelemetry.io/contrib/bridges/otelslog v0.19.0 h1:5RgvxieNq9tS3ewrV1vnODvbHPfKUIJcYtF9Cvz+6aQ= +go.opentelemetry.io/contrib/bridges/otelslog v0.19.0/go.mod h1:iTBIdNwx/xmUhfgJs6+84S4dIK059811cO1eUBjKcHY= +go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= +go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.20.0 h1:owlhcJ3QO3X0YTDTCcDZ4V+6aVDkWbNmBoQ5NUp7Oww= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.20.0/go.mod h1:MP4eemTiI9zC8fgg+DYynhYDYf3ba72S376TvP+Ye0Q= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0 h1:4YsVu3B8+3qtWYYrsUYgn0OG78pN0rnNPRGX4SbokQI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0/go.mod h1:+wnlSn0mD1ADVMe3v9Z/WIaiz6q6gL2J/ejaAmdmv80= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.44.0 h1:lgh3PiVrRUWMLOVSkQicxzZll5NjF1r+AtsX1XRIHw0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.44.0/go.mod h1:5Cnhth3m/AgOeTgE3ex12pPmiu/gGtZit03kSzx9X7s= +go.opentelemetry.io/otel/log v0.20.0 h1:/5i0vuHxCLWUfChWG41K9wkM0jafruPw9NU1/RCJirs= +go.opentelemetry.io/otel/log v0.20.0/go.mod h1:wOcMcjsZpG8x7Bak7IhSi/lg8wscV2C1VdrKCLPlt0E= +go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= +go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= +go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= +go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= +go.opentelemetry.io/otel/sdk/log v0.20.0 h1:vM3xI7TQgKPiSghe6urZtAkyFY7SodrSpC83CffDFuY= +go.opentelemetry.io/otel/sdk/log v0.20.0/go.mod h1:Knej2nmsTUzN79T2eeXdRsjjPcoxoq2pUyUHz9TFyyU= +go.opentelemetry.io/otel/sdk/log/logtest v0.20.0 h1:OqdRZ1guyzamK3M6LlRsmGqRrjkHWw6WZOKKli5ELpg= +go.opentelemetry.io/otel/sdk/log/logtest v0.20.0/go.mod h1:PuMIlm7zAt7c3z8zfOI5ox4iT1Z87We+PF6YoINux/M= +go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= +go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= +go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= +go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= -golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= -golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= -golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= +golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= +golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= +golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/genproto/googleapis/api v0.0.0-20260504160031-60b97b32f348 h1:U8orV30l6KpDsi9dxU0CoJZGbjS8EEpw+6ba+XwGPQA= -google.golang.org/genproto/googleapis/api v0.0.0-20260504160031-60b97b32f348/go.mod h1:Yzdzr5OOZFgSsEV2D/Xi9NL3bszpXFAg0hFJiRohcD8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348 h1:pfIbyB44sWzHiCpRqIen67ZQnVXSfIxWrqUMk1qwODE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.81.0 h1:W3G9N3KQf3BU+YuCtGKJk0CmxQNbAISICD/9AORxLIw= -google.golang.org/grpc v1.81.0/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= +google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= +google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ= +google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/protogen/workflows/v1/core.pb.go b/protogen/workflows/v1/core.pb.go index a00be94..ed79332 100644 --- a/protogen/workflows/v1/core.pb.go +++ b/protogen/workflows/v1/core.pb.go @@ -206,95 +206,6 @@ func (x TaskState) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } -// A cluster is a grouping of tasks that are related. -type Cluster struct { - state protoimpl.MessageState `protogen:"opaque.v1"` - xxx_hidden_Slug string `protobuf:"bytes,2,opt,name=slug"` - xxx_hidden_DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName"` - xxx_hidden_Deletable bool `protobuf:"varint,4,opt,name=deletable"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Cluster) Reset() { - *x = Cluster{} - mi := &file_workflows_v1_core_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Cluster) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Cluster) ProtoMessage() {} - -func (x *Cluster) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_core_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -func (x *Cluster) GetSlug() string { - if x != nil { - return x.xxx_hidden_Slug - } - return "" -} - -func (x *Cluster) GetDisplayName() string { - if x != nil { - return x.xxx_hidden_DisplayName - } - return "" -} - -func (x *Cluster) GetDeletable() bool { - if x != nil { - return x.xxx_hidden_Deletable - } - return false -} - -func (x *Cluster) SetSlug(v string) { - x.xxx_hidden_Slug = v -} - -func (x *Cluster) SetDisplayName(v string) { - x.xxx_hidden_DisplayName = v -} - -func (x *Cluster) SetDeletable(v bool) { - x.xxx_hidden_Deletable = v -} - -type Cluster_builder struct { - _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - - // The unique slug of the cluster within the namespace. - Slug string - // The display name of the cluster. - DisplayName string - // Where the cluster is deletable - Deletable bool -} - -func (b0 Cluster_builder) Build() *Cluster { - m0 := &Cluster{} - b, x := &b0, m0 - _, _ = b, x - x.xxx_hidden_Slug = b.Slug - x.xxx_hidden_DisplayName = b.DisplayName - x.xxx_hidden_Deletable = b.Deletable - return m0 -} - // A job is a logical grouping of tasks that are related. type Job struct { state protoimpl.MessageState `protogen:"opaque.v1"` @@ -316,7 +227,7 @@ type Job struct { func (x *Job) Reset() { *x = Job{} - mi := &file_workflows_v1_core_proto_msgTypes[1] + mi := &file_workflows_v1_core_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -328,7 +239,7 @@ func (x *Job) String() string { func (*Job) ProtoMessage() {} func (x *Job) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_core_proto_msgTypes[1] + mi := &file_workflows_v1_core_proto_msgTypes[0] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -605,7 +516,7 @@ type ExecutionStats struct { func (x *ExecutionStats) Reset() { *x = ExecutionStats{} - mi := &file_workflows_v1_core_proto_msgTypes[2] + mi := &file_workflows_v1_core_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -617,7 +528,7 @@ func (x *ExecutionStats) String() string { func (*ExecutionStats) ProtoMessage() {} func (x *ExecutionStats) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_core_proto_msgTypes[2] + mi := &file_workflows_v1_core_proto_msgTypes[1] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -795,7 +706,7 @@ type TaskStateCount struct { func (x *TaskStateCount) Reset() { *x = TaskStateCount{} - mi := &file_workflows_v1_core_proto_msgTypes[3] + mi := &file_workflows_v1_core_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -807,7 +718,7 @@ func (x *TaskStateCount) String() string { func (*TaskStateCount) ProtoMessage() {} func (x *TaskStateCount) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_core_proto_msgTypes[3] + mi := &file_workflows_v1_core_proto_msgTypes[2] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -871,7 +782,7 @@ type TaskSummary struct { func (x *TaskSummary) Reset() { *x = TaskSummary{} - mi := &file_workflows_v1_core_proto_msgTypes[4] + mi := &file_workflows_v1_core_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -883,7 +794,7 @@ func (x *TaskSummary) String() string { func (*TaskSummary) ProtoMessage() {} func (x *TaskSummary) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_core_proto_msgTypes[4] + mi := &file_workflows_v1_core_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1040,7 +951,7 @@ type Progress struct { func (x *Progress) Reset() { *x = Progress{} - mi := &file_workflows_v1_core_proto_msgTypes[5] + mi := &file_workflows_v1_core_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1052,7 +963,7 @@ func (x *Progress) String() string { func (*Progress) ProtoMessage() {} func (x *Progress) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_core_proto_msgTypes[5] + mi := &file_workflows_v1_core_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1138,7 +1049,7 @@ type Task struct { func (x *Task) Reset() { *x = Task{} - mi := &file_workflows_v1_core_proto_msgTypes[6] + mi := &file_workflows_v1_core_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1150,7 +1061,7 @@ func (x *Task) String() string { func (*Task) ProtoMessage() {} func (x *Task) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_core_proto_msgTypes[6] + mi := &file_workflows_v1_core_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1419,7 +1330,7 @@ type TaskIdentifier struct { func (x *TaskIdentifier) Reset() { *x = TaskIdentifier{} - mi := &file_workflows_v1_core_proto_msgTypes[7] + mi := &file_workflows_v1_core_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1431,7 +1342,7 @@ func (x *TaskIdentifier) String() string { func (*TaskIdentifier) ProtoMessage() {} func (x *TaskIdentifier) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_core_proto_msgTypes[7] + mi := &file_workflows_v1_core_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1482,6 +1393,66 @@ func (b0 TaskIdentifier_builder) Build() *TaskIdentifier { return m0 } +// A list of task identifiers. +type TaskIdentifiers struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Identifiers *[]*TaskIdentifier `protobuf:"bytes,1,rep,name=identifiers"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TaskIdentifiers) Reset() { + *x = TaskIdentifiers{} + mi := &file_workflows_v1_core_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TaskIdentifiers) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TaskIdentifiers) ProtoMessage() {} + +func (x *TaskIdentifiers) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_core_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *TaskIdentifiers) GetIdentifiers() []*TaskIdentifier { + if x != nil { + if x.xxx_hidden_Identifiers != nil { + return *x.xxx_hidden_Identifiers + } + } + return nil +} + +func (x *TaskIdentifiers) SetIdentifiers(v []*TaskIdentifier) { + x.xxx_hidden_Identifiers = &v +} + +type TaskIdentifiers_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Identifiers []*TaskIdentifier +} + +func (b0 TaskIdentifiers_builder) Build() *TaskIdentifiers { + m0 := &TaskIdentifiers{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Identifiers = &b.Identifiers + return m0 +} + // A list of tasks. type Tasks struct { state protoimpl.MessageState `protogen:"opaque.v1"` @@ -2062,11 +2033,7 @@ var File_workflows_v1_core_proto protoreflect.FileDescriptor const file_workflows_v1_core_proto_rawDesc = "" + "\n" + - "\x17workflows/v1/core.proto\x12\fworkflows.v1\x1a\x1bbuf/validate/validate.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x13tilebox/v1/id.proto\"d\n" + - "\aCluster\x12\x12\n" + - "\x04slug\x18\x02 \x01(\tR\x04slug\x12!\n" + - "\fdisplay_name\x18\x03 \x01(\tR\vdisplayName\x12\x1c\n" + - "\tdeletable\x18\x04 \x01(\bR\tdeletableJ\x04\b\x01\x10\x02\"\xe5\x04\n" + + "\x17workflows/v1/core.proto\x12\fworkflows.v1\x1a\x1bbuf/validate/validate.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x13tilebox/v1/id.proto\"\xe5\x04\n" + "\x03Job\x12\x1e\n" + "\x02id\x18\x01 \x01(\v2\x0e.tilebox.v1.IDR\x02id\x12\x12\n" + "\x04name\x18\x02 \x01(\tR\x04name\x12!\n" + @@ -2126,7 +2093,9 @@ const file_workflows_v1_core_proto_rawDesc = "" + "\x0eTaskIdentifier\x12\x1e\n" + "\x04name\x18\x01 \x01(\tB\n" + "\xbaH\ar\x05 \x01(\x80\x02R\x04name\x122\n" + - "\aversion\x18\x02 \x01(\tB\x18\xbaH\x15r\x13 \x012\x0f^v(\\d+)\\.(\\d+)$R\aversion\"1\n" + + "\aversion\x18\x02 \x01(\tB\x18\xbaH\x15r\x13 \x012\x0f^v(\\d+)\\.(\\d+)$R\aversion\"Q\n" + + "\x0fTaskIdentifiers\x12>\n" + + "\videntifiers\x18\x01 \x03(\v2\x1c.workflows.v1.TaskIdentifierR\videntifiers\"1\n" + "\x05Tasks\x12(\n" + "\x05tasks\x18\x01 \x03(\v2\x12.workflows.v1.TaskR\x05tasks\"\x98\x02\n" + "\x14SingleTaskSubmission\x12!\n" + @@ -2191,14 +2160,14 @@ var file_workflows_v1_core_proto_goTypes = []any{ (LegacyJobState)(0), // 0: workflows.v1.LegacyJobState (JobState)(0), // 1: workflows.v1.JobState (TaskState)(0), // 2: workflows.v1.TaskState - (*Cluster)(nil), // 3: workflows.v1.Cluster - (*Job)(nil), // 4: workflows.v1.Job - (*ExecutionStats)(nil), // 5: workflows.v1.ExecutionStats - (*TaskStateCount)(nil), // 6: workflows.v1.TaskStateCount - (*TaskSummary)(nil), // 7: workflows.v1.TaskSummary - (*Progress)(nil), // 8: workflows.v1.Progress - (*Task)(nil), // 9: workflows.v1.Task - (*TaskIdentifier)(nil), // 10: workflows.v1.TaskIdentifier + (*Job)(nil), // 3: workflows.v1.Job + (*ExecutionStats)(nil), // 4: workflows.v1.ExecutionStats + (*TaskStateCount)(nil), // 5: workflows.v1.TaskStateCount + (*TaskSummary)(nil), // 6: workflows.v1.TaskSummary + (*Progress)(nil), // 7: workflows.v1.Progress + (*Task)(nil), // 8: workflows.v1.Task + (*TaskIdentifier)(nil), // 9: workflows.v1.TaskIdentifier + (*TaskIdentifiers)(nil), // 10: workflows.v1.TaskIdentifiers (*Tasks)(nil), // 11: workflows.v1.Tasks (*SingleTaskSubmission)(nil), // 12: workflows.v1.SingleTaskSubmission (*TaskSubmissions)(nil), // 13: workflows.v1.TaskSubmissions @@ -2213,16 +2182,16 @@ var file_workflows_v1_core_proto_depIdxs = []int32{ 0, // 1: workflows.v1.Job.legacy_state:type_name -> workflows.v1.LegacyJobState 17, // 2: workflows.v1.Job.submitted_at:type_name -> google.protobuf.Timestamp 17, // 3: workflows.v1.Job.started_at:type_name -> google.protobuf.Timestamp - 7, // 4: workflows.v1.Job.task_summaries:type_name -> workflows.v1.TaskSummary + 6, // 4: workflows.v1.Job.task_summaries:type_name -> workflows.v1.TaskSummary 16, // 5: workflows.v1.Job.automation_id:type_name -> tilebox.v1.ID - 8, // 6: workflows.v1.Job.progress:type_name -> workflows.v1.Progress + 7, // 6: workflows.v1.Job.progress:type_name -> workflows.v1.Progress 1, // 7: workflows.v1.Job.state:type_name -> workflows.v1.JobState - 5, // 8: workflows.v1.Job.execution_stats:type_name -> workflows.v1.ExecutionStats + 4, // 8: workflows.v1.Job.execution_stats:type_name -> workflows.v1.ExecutionStats 17, // 9: workflows.v1.ExecutionStats.first_task_started_at:type_name -> google.protobuf.Timestamp 17, // 10: workflows.v1.ExecutionStats.last_task_stopped_at:type_name -> google.protobuf.Timestamp 18, // 11: workflows.v1.ExecutionStats.compute_time:type_name -> google.protobuf.Duration 18, // 12: workflows.v1.ExecutionStats.elapsed_time:type_name -> google.protobuf.Duration - 6, // 13: workflows.v1.ExecutionStats.tasks_by_state:type_name -> workflows.v1.TaskStateCount + 5, // 13: workflows.v1.ExecutionStats.tasks_by_state:type_name -> workflows.v1.TaskStateCount 2, // 14: workflows.v1.TaskStateCount.state:type_name -> workflows.v1.TaskState 16, // 15: workflows.v1.TaskSummary.id:type_name -> tilebox.v1.ID 2, // 16: workflows.v1.TaskSummary.state:type_name -> workflows.v1.TaskState @@ -2230,23 +2199,24 @@ var file_workflows_v1_core_proto_depIdxs = []int32{ 17, // 18: workflows.v1.TaskSummary.started_at:type_name -> google.protobuf.Timestamp 17, // 19: workflows.v1.TaskSummary.stopped_at:type_name -> google.protobuf.Timestamp 16, // 20: workflows.v1.Task.id:type_name -> tilebox.v1.ID - 10, // 21: workflows.v1.Task.identifier:type_name -> workflows.v1.TaskIdentifier + 9, // 21: workflows.v1.Task.identifier:type_name -> workflows.v1.TaskIdentifier 2, // 22: workflows.v1.Task.state:type_name -> workflows.v1.TaskState - 4, // 23: workflows.v1.Task.job:type_name -> workflows.v1.Job + 3, // 23: workflows.v1.Task.job:type_name -> workflows.v1.Job 16, // 24: workflows.v1.Task.parent_id:type_name -> tilebox.v1.ID 16, // 25: workflows.v1.Task.depends_on:type_name -> tilebox.v1.ID 15, // 26: workflows.v1.Task.lease:type_name -> workflows.v1.TaskLease - 9, // 27: workflows.v1.Tasks.tasks:type_name -> workflows.v1.Task - 10, // 28: workflows.v1.SingleTaskSubmission.identifier:type_name -> workflows.v1.TaskIdentifier - 14, // 29: workflows.v1.TaskSubmissions.task_groups:type_name -> workflows.v1.TaskSubmissionGroup - 10, // 30: workflows.v1.TaskSubmissions.identifier_lookup:type_name -> workflows.v1.TaskIdentifier - 18, // 31: workflows.v1.TaskLease.lease:type_name -> google.protobuf.Duration - 18, // 32: workflows.v1.TaskLease.recommended_wait_until_next_extension:type_name -> google.protobuf.Duration - 33, // [33:33] is the sub-list for method output_type - 33, // [33:33] is the sub-list for method input_type - 33, // [33:33] is the sub-list for extension type_name - 33, // [33:33] is the sub-list for extension extendee - 0, // [0:33] is the sub-list for field type_name + 9, // 27: workflows.v1.TaskIdentifiers.identifiers:type_name -> workflows.v1.TaskIdentifier + 8, // 28: workflows.v1.Tasks.tasks:type_name -> workflows.v1.Task + 9, // 29: workflows.v1.SingleTaskSubmission.identifier:type_name -> workflows.v1.TaskIdentifier + 14, // 30: workflows.v1.TaskSubmissions.task_groups:type_name -> workflows.v1.TaskSubmissionGroup + 9, // 31: workflows.v1.TaskSubmissions.identifier_lookup:type_name -> workflows.v1.TaskIdentifier + 18, // 32: workflows.v1.TaskLease.lease:type_name -> google.protobuf.Duration + 18, // 33: workflows.v1.TaskLease.recommended_wait_until_next_extension:type_name -> google.protobuf.Duration + 34, // [34:34] is the sub-list for method output_type + 34, // [34:34] is the sub-list for method input_type + 34, // [34:34] is the sub-list for extension type_name + 34, // [34:34] is the sub-list for extension extendee + 0, // [0:34] is the sub-list for field type_name } func init() { file_workflows_v1_core_proto_init() } diff --git a/protogen/workflows/v1/task_release.pb.go b/protogen/workflows/v1/task_release.pb.go deleted file mode 100644 index 81fb605..0000000 --- a/protogen/workflows/v1/task_release.pb.go +++ /dev/null @@ -1,1100 +0,0 @@ -// The externally facing API allowing users to publish and deploy workflow task releases. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.11 -// protoc (unknown) -// source: workflows/v1/task_release.proto - -package workflowsv1 - -import ( - _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" - v1 "github.com/tilebox/tilebox-go/protogen/tilebox/v1" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// PublishReleaseRequest publishes immutable release metadata for a release task set. -type PublishReleaseRequest struct { - state protoimpl.MessageState `protogen:"opaque.v1"` - xxx_hidden_Tasks *[]*TaskIdentifier `protobuf:"bytes,1,rep,name=tasks"` - xxx_hidden_ArtifactUri string `protobuf:"bytes,2,opt,name=artifact_uri,json=artifactUri"` - xxx_hidden_ArtifactDigest string `protobuf:"bytes,3,opt,name=artifact_digest,json=artifactDigest"` - xxx_hidden_RuntimeKind string `protobuf:"bytes,4,opt,name=runtime_kind,json=runtimeKind"` - xxx_hidden_EnvironmentDigest string `protobuf:"bytes,5,opt,name=environment_digest,json=environmentDigest"` - xxx_hidden_MetadataJson []byte `protobuf:"bytes,6,opt,name=metadata_json,json=metadataJson"` - XXX_raceDetectHookData protoimpl.RaceDetectHookData - XXX_presence [1]uint32 - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *PublishReleaseRequest) Reset() { - *x = PublishReleaseRequest{} - mi := &file_workflows_v1_task_release_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *PublishReleaseRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PublishReleaseRequest) ProtoMessage() {} - -func (x *PublishReleaseRequest) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_task_release_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -func (x *PublishReleaseRequest) GetTasks() []*TaskIdentifier { - if x != nil { - if x.xxx_hidden_Tasks != nil { - return *x.xxx_hidden_Tasks - } - } - return nil -} - -func (x *PublishReleaseRequest) GetArtifactUri() string { - if x != nil { - return x.xxx_hidden_ArtifactUri - } - return "" -} - -func (x *PublishReleaseRequest) GetArtifactDigest() string { - if x != nil { - return x.xxx_hidden_ArtifactDigest - } - return "" -} - -func (x *PublishReleaseRequest) GetRuntimeKind() string { - if x != nil { - return x.xxx_hidden_RuntimeKind - } - return "" -} - -func (x *PublishReleaseRequest) GetEnvironmentDigest() string { - if x != nil { - return x.xxx_hidden_EnvironmentDigest - } - return "" -} - -func (x *PublishReleaseRequest) GetMetadataJson() []byte { - if x != nil { - return x.xxx_hidden_MetadataJson - } - return nil -} - -func (x *PublishReleaseRequest) SetTasks(v []*TaskIdentifier) { - x.xxx_hidden_Tasks = &v -} - -func (x *PublishReleaseRequest) SetArtifactUri(v string) { - x.xxx_hidden_ArtifactUri = v -} - -func (x *PublishReleaseRequest) SetArtifactDigest(v string) { - x.xxx_hidden_ArtifactDigest = v -} - -func (x *PublishReleaseRequest) SetRuntimeKind(v string) { - x.xxx_hidden_RuntimeKind = v -} - -func (x *PublishReleaseRequest) SetEnvironmentDigest(v string) { - x.xxx_hidden_EnvironmentDigest = v -} - -func (x *PublishReleaseRequest) SetMetadataJson(v []byte) { - if v == nil { - v = []byte{} - } - x.xxx_hidden_MetadataJson = v - protoimpl.X.SetPresent(&(x.XXX_presence[0]), 5, 6) -} - -func (x *PublishReleaseRequest) HasMetadataJson() bool { - if x == nil { - return false - } - return protoimpl.X.Present(&(x.XXX_presence[0]), 5) -} - -func (x *PublishReleaseRequest) ClearMetadataJson() { - protoimpl.X.ClearPresent(&(x.XXX_presence[0]), 5) - x.xxx_hidden_MetadataJson = nil -} - -type PublishReleaseRequest_builder struct { - _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - - // Task identifiers included in this release. - Tasks []*TaskIdentifier - // URI pointing to the release artifact. - ArtifactUri string - // Canonical artifact digest in format sha256:. - ArtifactDigest string - // Runtime kind for this release, currently python_uv in phase 1. - RuntimeKind string - // Canonical environment digest in format sha256:. - EnvironmentDigest string - // Optional UTF-8 JSON metadata payload. - MetadataJson []byte -} - -func (b0 PublishReleaseRequest_builder) Build() *PublishReleaseRequest { - m0 := &PublishReleaseRequest{} - b, x := &b0, m0 - _, _ = b, x - x.xxx_hidden_Tasks = &b.Tasks - x.xxx_hidden_ArtifactUri = b.ArtifactUri - x.xxx_hidden_ArtifactDigest = b.ArtifactDigest - x.xxx_hidden_RuntimeKind = b.RuntimeKind - x.xxx_hidden_EnvironmentDigest = b.EnvironmentDigest - if b.MetadataJson != nil { - protoimpl.X.SetPresentNonAtomic(&(x.XXX_presence[0]), 5, 6) - x.xxx_hidden_MetadataJson = b.MetadataJson - } - return m0 -} - -// PublishReleaseResponse is the publish API response. -type PublishReleaseResponse struct { - state protoimpl.MessageState `protogen:"opaque.v1"` - xxx_hidden_ReleaseId *v1.ID `protobuf:"bytes,1,opt,name=release_id,json=releaseId"` - xxx_hidden_Created bool `protobuf:"varint,2,opt,name=created"` - xxx_hidden_Changes *PublishReleaseChanges `protobuf:"bytes,4,opt,name=changes"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *PublishReleaseResponse) Reset() { - *x = PublishReleaseResponse{} - mi := &file_workflows_v1_task_release_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *PublishReleaseResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PublishReleaseResponse) ProtoMessage() {} - -func (x *PublishReleaseResponse) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_task_release_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -func (x *PublishReleaseResponse) GetReleaseId() *v1.ID { - if x != nil { - return x.xxx_hidden_ReleaseId - } - return nil -} - -func (x *PublishReleaseResponse) GetCreated() bool { - if x != nil { - return x.xxx_hidden_Created - } - return false -} - -func (x *PublishReleaseResponse) GetChanges() *PublishReleaseChanges { - if x != nil { - return x.xxx_hidden_Changes - } - return nil -} - -func (x *PublishReleaseResponse) SetReleaseId(v *v1.ID) { - x.xxx_hidden_ReleaseId = v -} - -func (x *PublishReleaseResponse) SetCreated(v bool) { - x.xxx_hidden_Created = v -} - -func (x *PublishReleaseResponse) SetChanges(v *PublishReleaseChanges) { - x.xxx_hidden_Changes = v -} - -func (x *PublishReleaseResponse) HasReleaseId() bool { - if x == nil { - return false - } - return x.xxx_hidden_ReleaseId != nil -} - -func (x *PublishReleaseResponse) HasChanges() bool { - if x == nil { - return false - } - return x.xxx_hidden_Changes != nil -} - -func (x *PublishReleaseResponse) ClearReleaseId() { - x.xxx_hidden_ReleaseId = nil -} - -func (x *PublishReleaseResponse) ClearChanges() { - x.xxx_hidden_Changes = nil -} - -type PublishReleaseResponse_builder struct { - _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - - // Immutable release id. - ReleaseId *v1.ID - // True when this call created a new release row. - Created bool - // Explicit payload changes compared to the latest comparable release. - Changes *PublishReleaseChanges -} - -func (b0 PublishReleaseResponse_builder) Build() *PublishReleaseResponse { - m0 := &PublishReleaseResponse{} - b, x := &b0, m0 - _, _ = b, x - x.xxx_hidden_ReleaseId = b.ReleaseId - x.xxx_hidden_Created = b.Created - x.xxx_hidden_Changes = b.Changes - return m0 -} - -// PublishReleaseChanges captures which release surfaces changed. -type PublishReleaseChanges struct { - state protoimpl.MessageState `protogen:"opaque.v1"` - xxx_hidden_Tasks bool `protobuf:"varint,1,opt,name=tasks"` - xxx_hidden_Artifact bool `protobuf:"varint,2,opt,name=artifact"` - xxx_hidden_Environment bool `protobuf:"varint,3,opt,name=environment"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *PublishReleaseChanges) Reset() { - *x = PublishReleaseChanges{} - mi := &file_workflows_v1_task_release_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *PublishReleaseChanges) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PublishReleaseChanges) ProtoMessage() {} - -func (x *PublishReleaseChanges) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_task_release_proto_msgTypes[2] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -func (x *PublishReleaseChanges) GetTasks() bool { - if x != nil { - return x.xxx_hidden_Tasks - } - return false -} - -func (x *PublishReleaseChanges) GetArtifact() bool { - if x != nil { - return x.xxx_hidden_Artifact - } - return false -} - -func (x *PublishReleaseChanges) GetEnvironment() bool { - if x != nil { - return x.xxx_hidden_Environment - } - return false -} - -func (x *PublishReleaseChanges) SetTasks(v bool) { - x.xxx_hidden_Tasks = v -} - -func (x *PublishReleaseChanges) SetArtifact(v bool) { - x.xxx_hidden_Artifact = v -} - -func (x *PublishReleaseChanges) SetEnvironment(v bool) { - x.xxx_hidden_Environment = v -} - -type PublishReleaseChanges_builder struct { - _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - - // True when the task set (including versions) changed. - Tasks bool - // True when the artifact content changed. - Artifact bool - // True when the runtime environment changed. - Environment bool -} - -func (b0 PublishReleaseChanges_builder) Build() *PublishReleaseChanges { - m0 := &PublishReleaseChanges{} - b, x := &b0, m0 - _, _ = b, x - x.xxx_hidden_Tasks = b.Tasks - x.xxx_hidden_Artifact = b.Artifact - x.xxx_hidden_Environment = b.Environment - return m0 -} - -// DeployReleaseRequest updates the cluster deployment pointer for a release. -type DeployReleaseRequest struct { - state protoimpl.MessageState `protogen:"opaque.v1"` - xxx_hidden_ClusterSlug string `protobuf:"bytes,1,opt,name=cluster_slug,json=clusterSlug"` - xxx_hidden_ReleaseId *v1.ID `protobuf:"bytes,2,opt,name=release_id,json=releaseId"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *DeployReleaseRequest) Reset() { - *x = DeployReleaseRequest{} - mi := &file_workflows_v1_task_release_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *DeployReleaseRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DeployReleaseRequest) ProtoMessage() {} - -func (x *DeployReleaseRequest) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_task_release_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -func (x *DeployReleaseRequest) GetClusterSlug() string { - if x != nil { - return x.xxx_hidden_ClusterSlug - } - return "" -} - -func (x *DeployReleaseRequest) GetReleaseId() *v1.ID { - if x != nil { - return x.xxx_hidden_ReleaseId - } - return nil -} - -func (x *DeployReleaseRequest) SetClusterSlug(v string) { - x.xxx_hidden_ClusterSlug = v -} - -func (x *DeployReleaseRequest) SetReleaseId(v *v1.ID) { - x.xxx_hidden_ReleaseId = v -} - -func (x *DeployReleaseRequest) HasReleaseId() bool { - if x == nil { - return false - } - return x.xxx_hidden_ReleaseId != nil -} - -func (x *DeployReleaseRequest) ClearReleaseId() { - x.xxx_hidden_ReleaseId = nil -} - -type DeployReleaseRequest_builder struct { - _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - - // Target cluster slug. - ClusterSlug string - // Immutable release id. - ReleaseId *v1.ID -} - -func (b0 DeployReleaseRequest_builder) Build() *DeployReleaseRequest { - m0 := &DeployReleaseRequest{} - b, x := &b0, m0 - _, _ = b, x - x.xxx_hidden_ClusterSlug = b.ClusterSlug - x.xxx_hidden_ReleaseId = b.ReleaseId - return m0 -} - -// DeployReleaseResponse is the deploy API response. -type DeployReleaseResponse struct { - state protoimpl.MessageState `protogen:"opaque.v1"` - xxx_hidden_ClusterSlug string `protobuf:"bytes,1,opt,name=cluster_slug,json=clusterSlug"` - xxx_hidden_ReleaseId *v1.ID `protobuf:"bytes,2,opt,name=release_id,json=releaseId"` - xxx_hidden_ManifestRevision uint64 `protobuf:"varint,3,opt,name=manifest_revision,json=manifestRevision"` - xxx_hidden_Changed bool `protobuf:"varint,4,opt,name=changed"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *DeployReleaseResponse) Reset() { - *x = DeployReleaseResponse{} - mi := &file_workflows_v1_task_release_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *DeployReleaseResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DeployReleaseResponse) ProtoMessage() {} - -func (x *DeployReleaseResponse) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_task_release_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -func (x *DeployReleaseResponse) GetClusterSlug() string { - if x != nil { - return x.xxx_hidden_ClusterSlug - } - return "" -} - -func (x *DeployReleaseResponse) GetReleaseId() *v1.ID { - if x != nil { - return x.xxx_hidden_ReleaseId - } - return nil -} - -func (x *DeployReleaseResponse) GetManifestRevision() uint64 { - if x != nil { - return x.xxx_hidden_ManifestRevision - } - return 0 -} - -func (x *DeployReleaseResponse) GetChanged() bool { - if x != nil { - return x.xxx_hidden_Changed - } - return false -} - -func (x *DeployReleaseResponse) SetClusterSlug(v string) { - x.xxx_hidden_ClusterSlug = v -} - -func (x *DeployReleaseResponse) SetReleaseId(v *v1.ID) { - x.xxx_hidden_ReleaseId = v -} - -func (x *DeployReleaseResponse) SetManifestRevision(v uint64) { - x.xxx_hidden_ManifestRevision = v -} - -func (x *DeployReleaseResponse) SetChanged(v bool) { - x.xxx_hidden_Changed = v -} - -func (x *DeployReleaseResponse) HasReleaseId() bool { - if x == nil { - return false - } - return x.xxx_hidden_ReleaseId != nil -} - -func (x *DeployReleaseResponse) ClearReleaseId() { - x.xxx_hidden_ReleaseId = nil -} - -type DeployReleaseResponse_builder struct { - _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - - // Target cluster slug. - ClusterSlug string - // Deployed release id. - ReleaseId *v1.ID - // Latest cluster manifest revision after the request. - ManifestRevision uint64 - // Whether this request changed the deployment pointer. - Changed bool -} - -func (b0 DeployReleaseResponse_builder) Build() *DeployReleaseResponse { - m0 := &DeployReleaseResponse{} - b, x := &b0, m0 - _, _ = b, x - x.xxx_hidden_ClusterSlug = b.ClusterSlug - x.xxx_hidden_ReleaseId = b.ReleaseId - x.xxx_hidden_ManifestRevision = b.ManifestRevision - x.xxx_hidden_Changed = b.Changed - return m0 -} - -// GetClusterDeploymentManifestRequest requests the active desired state for a cluster. -type GetClusterDeploymentManifestRequest struct { - state protoimpl.MessageState `protogen:"opaque.v1"` - xxx_hidden_ClusterSlug string `protobuf:"bytes,1,opt,name=cluster_slug,json=clusterSlug"` - xxx_hidden_SinceRevision uint64 `protobuf:"varint,2,opt,name=since_revision,json=sinceRevision"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetClusterDeploymentManifestRequest) Reset() { - *x = GetClusterDeploymentManifestRequest{} - mi := &file_workflows_v1_task_release_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetClusterDeploymentManifestRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetClusterDeploymentManifestRequest) ProtoMessage() {} - -func (x *GetClusterDeploymentManifestRequest) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_task_release_proto_msgTypes[5] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -func (x *GetClusterDeploymentManifestRequest) GetClusterSlug() string { - if x != nil { - return x.xxx_hidden_ClusterSlug - } - return "" -} - -func (x *GetClusterDeploymentManifestRequest) GetSinceRevision() uint64 { - if x != nil { - return x.xxx_hidden_SinceRevision - } - return 0 -} - -func (x *GetClusterDeploymentManifestRequest) SetClusterSlug(v string) { - x.xxx_hidden_ClusterSlug = v -} - -func (x *GetClusterDeploymentManifestRequest) SetSinceRevision(v uint64) { - x.xxx_hidden_SinceRevision = v -} - -type GetClusterDeploymentManifestRequest_builder struct { - _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - - // Target cluster slug. - ClusterSlug string - // Optional revision cursor. 0 requests a full snapshot. - SinceRevision uint64 -} - -func (b0 GetClusterDeploymentManifestRequest_builder) Build() *GetClusterDeploymentManifestRequest { - m0 := &GetClusterDeploymentManifestRequest{} - b, x := &b0, m0 - _, _ = b, x - x.xxx_hidden_ClusterSlug = b.ClusterSlug - x.xxx_hidden_SinceRevision = b.SinceRevision - return m0 -} - -// DeployedRelease describes the currently deployed release in the manifest response. -type DeployedRelease struct { - state protoimpl.MessageState `protogen:"opaque.v1"` - xxx_hidden_ReleaseId *v1.ID `protobuf:"bytes,1,opt,name=release_id,json=releaseId"` - xxx_hidden_ArtifactUri string `protobuf:"bytes,2,opt,name=artifact_uri,json=artifactUri"` - xxx_hidden_ArtifactDigest string `protobuf:"bytes,3,opt,name=artifact_digest,json=artifactDigest"` - xxx_hidden_RuntimeKind string `protobuf:"bytes,4,opt,name=runtime_kind,json=runtimeKind"` - xxx_hidden_EnvironmentDigest string `protobuf:"bytes,5,opt,name=environment_digest,json=environmentDigest"` - xxx_hidden_MetadataJson []byte `protobuf:"bytes,6,opt,name=metadata_json,json=metadataJson"` - xxx_hidden_ChangeRevision uint64 `protobuf:"varint,7,opt,name=change_revision,json=changeRevision"` - xxx_hidden_Tasks *[]*TaskIdentifier `protobuf:"bytes,8,rep,name=tasks"` - xxx_hidden_DeployedAt *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=deployed_at,json=deployedAt"` - XXX_raceDetectHookData protoimpl.RaceDetectHookData - XXX_presence [1]uint32 - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *DeployedRelease) Reset() { - *x = DeployedRelease{} - mi := &file_workflows_v1_task_release_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *DeployedRelease) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DeployedRelease) ProtoMessage() {} - -func (x *DeployedRelease) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_task_release_proto_msgTypes[6] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -func (x *DeployedRelease) GetReleaseId() *v1.ID { - if x != nil { - return x.xxx_hidden_ReleaseId - } - return nil -} - -func (x *DeployedRelease) GetArtifactUri() string { - if x != nil { - return x.xxx_hidden_ArtifactUri - } - return "" -} - -func (x *DeployedRelease) GetArtifactDigest() string { - if x != nil { - return x.xxx_hidden_ArtifactDigest - } - return "" -} - -func (x *DeployedRelease) GetRuntimeKind() string { - if x != nil { - return x.xxx_hidden_RuntimeKind - } - return "" -} - -func (x *DeployedRelease) GetEnvironmentDigest() string { - if x != nil { - return x.xxx_hidden_EnvironmentDigest - } - return "" -} - -func (x *DeployedRelease) GetMetadataJson() []byte { - if x != nil { - return x.xxx_hidden_MetadataJson - } - return nil -} - -func (x *DeployedRelease) GetChangeRevision() uint64 { - if x != nil { - return x.xxx_hidden_ChangeRevision - } - return 0 -} - -func (x *DeployedRelease) GetTasks() []*TaskIdentifier { - if x != nil { - if x.xxx_hidden_Tasks != nil { - return *x.xxx_hidden_Tasks - } - } - return nil -} - -func (x *DeployedRelease) GetDeployedAt() *timestamppb.Timestamp { - if x != nil { - return x.xxx_hidden_DeployedAt - } - return nil -} - -func (x *DeployedRelease) SetReleaseId(v *v1.ID) { - x.xxx_hidden_ReleaseId = v -} - -func (x *DeployedRelease) SetArtifactUri(v string) { - x.xxx_hidden_ArtifactUri = v -} - -func (x *DeployedRelease) SetArtifactDigest(v string) { - x.xxx_hidden_ArtifactDigest = v -} - -func (x *DeployedRelease) SetRuntimeKind(v string) { - x.xxx_hidden_RuntimeKind = v -} - -func (x *DeployedRelease) SetEnvironmentDigest(v string) { - x.xxx_hidden_EnvironmentDigest = v -} - -func (x *DeployedRelease) SetMetadataJson(v []byte) { - if v == nil { - v = []byte{} - } - x.xxx_hidden_MetadataJson = v - protoimpl.X.SetPresent(&(x.XXX_presence[0]), 5, 9) -} - -func (x *DeployedRelease) SetChangeRevision(v uint64) { - x.xxx_hidden_ChangeRevision = v -} - -func (x *DeployedRelease) SetTasks(v []*TaskIdentifier) { - x.xxx_hidden_Tasks = &v -} - -func (x *DeployedRelease) SetDeployedAt(v *timestamppb.Timestamp) { - x.xxx_hidden_DeployedAt = v -} - -func (x *DeployedRelease) HasReleaseId() bool { - if x == nil { - return false - } - return x.xxx_hidden_ReleaseId != nil -} - -func (x *DeployedRelease) HasMetadataJson() bool { - if x == nil { - return false - } - return protoimpl.X.Present(&(x.XXX_presence[0]), 5) -} - -func (x *DeployedRelease) HasDeployedAt() bool { - if x == nil { - return false - } - return x.xxx_hidden_DeployedAt != nil -} - -func (x *DeployedRelease) ClearReleaseId() { - x.xxx_hidden_ReleaseId = nil -} - -func (x *DeployedRelease) ClearMetadataJson() { - protoimpl.X.ClearPresent(&(x.XXX_presence[0]), 5) - x.xxx_hidden_MetadataJson = nil -} - -func (x *DeployedRelease) ClearDeployedAt() { - x.xxx_hidden_DeployedAt = nil -} - -type DeployedRelease_builder struct { - _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - - // Immutable release id. - ReleaseId *v1.ID - // URI pointing to the release artifact. - ArtifactUri string - // Canonical artifact digest. - ArtifactDigest string - // Runtime kind. - RuntimeKind string - // Canonical environment digest. - EnvironmentDigest string - // Optional UTF-8 JSON metadata payload. - MetadataJson []byte - // Deployment revision at which this release pointer changed. - ChangeRevision uint64 - // Task identifiers included in the deployed release. - Tasks []*TaskIdentifier - // Timestamp when this release pointer was deployed. - DeployedAt *timestamppb.Timestamp -} - -func (b0 DeployedRelease_builder) Build() *DeployedRelease { - m0 := &DeployedRelease{} - b, x := &b0, m0 - _, _ = b, x - x.xxx_hidden_ReleaseId = b.ReleaseId - x.xxx_hidden_ArtifactUri = b.ArtifactUri - x.xxx_hidden_ArtifactDigest = b.ArtifactDigest - x.xxx_hidden_RuntimeKind = b.RuntimeKind - x.xxx_hidden_EnvironmentDigest = b.EnvironmentDigest - if b.MetadataJson != nil { - protoimpl.X.SetPresentNonAtomic(&(x.XXX_presence[0]), 5, 9) - x.xxx_hidden_MetadataJson = b.MetadataJson - } - x.xxx_hidden_ChangeRevision = b.ChangeRevision - x.xxx_hidden_Tasks = &b.Tasks - x.xxx_hidden_DeployedAt = b.DeployedAt - return m0 -} - -// GetClusterDeploymentManifestResponse returns desired deployment state for a cluster. -type GetClusterDeploymentManifestResponse struct { - state protoimpl.MessageState `protogen:"opaque.v1"` - xxx_hidden_ClusterSlug string `protobuf:"bytes,1,opt,name=cluster_slug,json=clusterSlug"` - xxx_hidden_ManifestRevision uint64 `protobuf:"varint,2,opt,name=manifest_revision,json=manifestRevision"` - xxx_hidden_Release *DeployedRelease `protobuf:"bytes,3,opt,name=release"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetClusterDeploymentManifestResponse) Reset() { - *x = GetClusterDeploymentManifestResponse{} - mi := &file_workflows_v1_task_release_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetClusterDeploymentManifestResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetClusterDeploymentManifestResponse) ProtoMessage() {} - -func (x *GetClusterDeploymentManifestResponse) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_task_release_proto_msgTypes[7] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -func (x *GetClusterDeploymentManifestResponse) GetClusterSlug() string { - if x != nil { - return x.xxx_hidden_ClusterSlug - } - return "" -} - -func (x *GetClusterDeploymentManifestResponse) GetManifestRevision() uint64 { - if x != nil { - return x.xxx_hidden_ManifestRevision - } - return 0 -} - -func (x *GetClusterDeploymentManifestResponse) GetRelease() *DeployedRelease { - if x != nil { - return x.xxx_hidden_Release - } - return nil -} - -func (x *GetClusterDeploymentManifestResponse) SetClusterSlug(v string) { - x.xxx_hidden_ClusterSlug = v -} - -func (x *GetClusterDeploymentManifestResponse) SetManifestRevision(v uint64) { - x.xxx_hidden_ManifestRevision = v -} - -func (x *GetClusterDeploymentManifestResponse) SetRelease(v *DeployedRelease) { - x.xxx_hidden_Release = v -} - -func (x *GetClusterDeploymentManifestResponse) HasRelease() bool { - if x == nil { - return false - } - return x.xxx_hidden_Release != nil -} - -func (x *GetClusterDeploymentManifestResponse) ClearRelease() { - x.xxx_hidden_Release = nil -} - -type GetClusterDeploymentManifestResponse_builder struct { - _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - - // Target cluster slug. - ClusterSlug string - // Latest cluster manifest revision. - ManifestRevision uint64 - // Active deployed release. Empty when nothing is deployed or when unchanged since since_revision. - Release *DeployedRelease -} - -func (b0 GetClusterDeploymentManifestResponse_builder) Build() *GetClusterDeploymentManifestResponse { - m0 := &GetClusterDeploymentManifestResponse{} - b, x := &b0, m0 - _, _ = b, x - x.xxx_hidden_ClusterSlug = b.ClusterSlug - x.xxx_hidden_ManifestRevision = b.ManifestRevision - x.xxx_hidden_Release = b.Release - return m0 -} - -var File_workflows_v1_task_release_proto protoreflect.FileDescriptor - -const file_workflows_v1_task_release_proto_rawDesc = "" + - "\n" + - "\x1fworkflows/v1/task_release.proto\x12\fworkflows.v1\x1a\x1bbuf/validate/validate.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x13tilebox/v1/id.proto\x1a\x17workflows/v1/core.proto\"\xed\x02\n" + - "\x15PublishReleaseRequest\x12<\n" + - "\x05tasks\x18\x01 \x03(\v2\x1c.workflows.v1.TaskIdentifierB\b\xbaH\x05\x92\x01\x02\b\x01R\x05tasks\x12*\n" + - "\fartifact_uri\x18\x02 \x01(\tB\a\xbaH\x04r\x02\x10\x01R\vartifactUri\x12E\n" + - "\x0fartifact_digest\x18\x03 \x01(\tB\x1c\xbaH\x19r\x172\x15^sha256:[a-f0-9]{64}$R\x0eartifactDigest\x12*\n" + - "\fruntime_kind\x18\x04 \x01(\tB\a\xbaH\x04r\x02\x10\x01R\vruntimeKind\x12K\n" + - "\x12environment_digest\x18\x05 \x01(\tB\x1c\xbaH\x19r\x172\x15^sha256:[a-f0-9]{64}$R\x11environmentDigest\x12*\n" + - "\rmetadata_json\x18\x06 \x01(\fB\x05\xaa\x01\x02\b\x01R\fmetadataJson\"\xb2\x01\n" + - "\x16PublishReleaseResponse\x12-\n" + - "\n" + - "release_id\x18\x01 \x01(\v2\x0e.tilebox.v1.IDR\treleaseId\x12\x18\n" + - "\acreated\x18\x02 \x01(\bR\acreated\x12=\n" + - "\achanges\x18\x04 \x01(\v2#.workflows.v1.PublishReleaseChangesR\achangesJ\x04\b\x03\x10\x04R\n" + - "idempotent\"k\n" + - "\x15PublishReleaseChanges\x12\x14\n" + - "\x05tasks\x18\x01 \x01(\bR\x05tasks\x12\x1a\n" + - "\bartifact\x18\x02 \x01(\bR\bartifact\x12 \n" + - "\venvironment\x18\x03 \x01(\bR\venvironment\"y\n" + - "\x14DeployReleaseRequest\x12*\n" + - "\fcluster_slug\x18\x01 \x01(\tB\a\xbaH\x04r\x02\x10\x01R\vclusterSlug\x125\n" + - "\n" + - "release_id\x18\x02 \x01(\v2\x0e.tilebox.v1.IDB\x06\xbaH\x03\xc8\x01\x01R\treleaseId\"\xb0\x01\n" + - "\x15DeployReleaseResponse\x12!\n" + - "\fcluster_slug\x18\x01 \x01(\tR\vclusterSlug\x12-\n" + - "\n" + - "release_id\x18\x02 \x01(\v2\x0e.tilebox.v1.IDR\treleaseId\x12+\n" + - "\x11manifest_revision\x18\x03 \x01(\x04R\x10manifestRevision\x12\x18\n" + - "\achanged\x18\x04 \x01(\bR\achanged\"x\n" + - "#GetClusterDeploymentManifestRequest\x12*\n" + - "\fcluster_slug\x18\x01 \x01(\tB\a\xbaH\x04r\x02\x10\x01R\vclusterSlug\x12%\n" + - "\x0esince_revision\x18\x02 \x01(\x04R\rsinceRevision\"\xa4\x03\n" + - "\x0fDeployedRelease\x12-\n" + - "\n" + - "release_id\x18\x01 \x01(\v2\x0e.tilebox.v1.IDR\treleaseId\x12!\n" + - "\fartifact_uri\x18\x02 \x01(\tR\vartifactUri\x12'\n" + - "\x0fartifact_digest\x18\x03 \x01(\tR\x0eartifactDigest\x12!\n" + - "\fruntime_kind\x18\x04 \x01(\tR\vruntimeKind\x12-\n" + - "\x12environment_digest\x18\x05 \x01(\tR\x11environmentDigest\x12*\n" + - "\rmetadata_json\x18\x06 \x01(\fB\x05\xaa\x01\x02\b\x01R\fmetadataJson\x12'\n" + - "\x0fchange_revision\x18\a \x01(\x04R\x0echangeRevision\x122\n" + - "\x05tasks\x18\b \x03(\v2\x1c.workflows.v1.TaskIdentifierR\x05tasks\x12;\n" + - "\vdeployed_at\x18\t \x01(\v2\x1a.google.protobuf.TimestampR\n" + - "deployedAt\"\xaf\x01\n" + - "$GetClusterDeploymentManifestResponse\x12!\n" + - "\fcluster_slug\x18\x01 \x01(\tR\vclusterSlug\x12+\n" + - "\x11manifest_revision\x18\x02 \x01(\x04R\x10manifestRevision\x127\n" + - "\arelease\x18\x03 \x01(\v2\x1d.workflows.v1.DeployedReleaseR\arelease2\xd3\x02\n" + - "\x12TaskReleaseService\x12[\n" + - "\x0ePublishRelease\x12#.workflows.v1.PublishReleaseRequest\x1a$.workflows.v1.PublishReleaseResponse\x12X\n" + - "\rDeployRelease\x12\".workflows.v1.DeployReleaseRequest\x1a#.workflows.v1.DeployReleaseResponse\x12\x85\x01\n" + - "\x1cGetClusterDeploymentManifest\x121.workflows.v1.GetClusterDeploymentManifestRequest\x1a2.workflows.v1.GetClusterDeploymentManifestResponseB\xbb\x01\n" + - "\x10com.workflows.v1B\x10TaskReleaseProtoP\x01Z?github.com/tilebox/tilebox-go/protogen/workflows/v1;workflowsv1\xa2\x02\x03WXX\xaa\x02\fWorkflows.V1\xca\x02\fWorkflows\\V1\xe2\x02\x18Workflows\\V1\\GPBMetadata\xea\x02\rWorkflows::V1\x92\x03\x02\b\x02b\beditionsp\xe8\a" - -var file_workflows_v1_task_release_proto_msgTypes = make([]protoimpl.MessageInfo, 8) -var file_workflows_v1_task_release_proto_goTypes = []any{ - (*PublishReleaseRequest)(nil), // 0: workflows.v1.PublishReleaseRequest - (*PublishReleaseResponse)(nil), // 1: workflows.v1.PublishReleaseResponse - (*PublishReleaseChanges)(nil), // 2: workflows.v1.PublishReleaseChanges - (*DeployReleaseRequest)(nil), // 3: workflows.v1.DeployReleaseRequest - (*DeployReleaseResponse)(nil), // 4: workflows.v1.DeployReleaseResponse - (*GetClusterDeploymentManifestRequest)(nil), // 5: workflows.v1.GetClusterDeploymentManifestRequest - (*DeployedRelease)(nil), // 6: workflows.v1.DeployedRelease - (*GetClusterDeploymentManifestResponse)(nil), // 7: workflows.v1.GetClusterDeploymentManifestResponse - (*TaskIdentifier)(nil), // 8: workflows.v1.TaskIdentifier - (*v1.ID)(nil), // 9: tilebox.v1.ID - (*timestamppb.Timestamp)(nil), // 10: google.protobuf.Timestamp -} -var file_workflows_v1_task_release_proto_depIdxs = []int32{ - 8, // 0: workflows.v1.PublishReleaseRequest.tasks:type_name -> workflows.v1.TaskIdentifier - 9, // 1: workflows.v1.PublishReleaseResponse.release_id:type_name -> tilebox.v1.ID - 2, // 2: workflows.v1.PublishReleaseResponse.changes:type_name -> workflows.v1.PublishReleaseChanges - 9, // 3: workflows.v1.DeployReleaseRequest.release_id:type_name -> tilebox.v1.ID - 9, // 4: workflows.v1.DeployReleaseResponse.release_id:type_name -> tilebox.v1.ID - 9, // 5: workflows.v1.DeployedRelease.release_id:type_name -> tilebox.v1.ID - 8, // 6: workflows.v1.DeployedRelease.tasks:type_name -> workflows.v1.TaskIdentifier - 10, // 7: workflows.v1.DeployedRelease.deployed_at:type_name -> google.protobuf.Timestamp - 6, // 8: workflows.v1.GetClusterDeploymentManifestResponse.release:type_name -> workflows.v1.DeployedRelease - 0, // 9: workflows.v1.TaskReleaseService.PublishRelease:input_type -> workflows.v1.PublishReleaseRequest - 3, // 10: workflows.v1.TaskReleaseService.DeployRelease:input_type -> workflows.v1.DeployReleaseRequest - 5, // 11: workflows.v1.TaskReleaseService.GetClusterDeploymentManifest:input_type -> workflows.v1.GetClusterDeploymentManifestRequest - 1, // 12: workflows.v1.TaskReleaseService.PublishRelease:output_type -> workflows.v1.PublishReleaseResponse - 4, // 13: workflows.v1.TaskReleaseService.DeployRelease:output_type -> workflows.v1.DeployReleaseResponse - 7, // 14: workflows.v1.TaskReleaseService.GetClusterDeploymentManifest:output_type -> workflows.v1.GetClusterDeploymentManifestResponse - 12, // [12:15] is the sub-list for method output_type - 9, // [9:12] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name -} - -func init() { file_workflows_v1_task_release_proto_init() } -func file_workflows_v1_task_release_proto_init() { - if File_workflows_v1_task_release_proto != nil { - return - } - file_workflows_v1_core_proto_init() - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_workflows_v1_task_release_proto_rawDesc), len(file_workflows_v1_task_release_proto_rawDesc)), - NumEnums: 0, - NumMessages: 8, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_workflows_v1_task_release_proto_goTypes, - DependencyIndexes: file_workflows_v1_task_release_proto_depIdxs, - MessageInfos: file_workflows_v1_task_release_proto_msgTypes, - }.Build() - File_workflows_v1_task_release_proto = out.File - file_workflows_v1_task_release_proto_goTypes = nil - file_workflows_v1_task_release_proto_depIdxs = nil -} diff --git a/protogen/workflows/v1/task_release_grpc.pb.go b/protogen/workflows/v1/task_release_grpc.pb.go deleted file mode 100644 index 4eb7976..0000000 --- a/protogen/workflows/v1/task_release_grpc.pb.go +++ /dev/null @@ -1,203 +0,0 @@ -// The externally facing API allowing users to publish and deploy workflow task releases. - -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.6.2 -// - protoc (unknown) -// source: workflows/v1/task_release.proto - -package workflowsv1 - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -const ( - TaskReleaseService_PublishRelease_FullMethodName = "/workflows.v1.TaskReleaseService/PublishRelease" - TaskReleaseService_DeployRelease_FullMethodName = "/workflows.v1.TaskReleaseService/DeployRelease" - TaskReleaseService_GetClusterDeploymentManifest_FullMethodName = "/workflows.v1.TaskReleaseService/GetClusterDeploymentManifest" -) - -// TaskReleaseServiceClient is the client API for TaskReleaseService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -// -// A service for managing workflows. -type TaskReleaseServiceClient interface { - PublishRelease(ctx context.Context, in *PublishReleaseRequest, opts ...grpc.CallOption) (*PublishReleaseResponse, error) - DeployRelease(ctx context.Context, in *DeployReleaseRequest, opts ...grpc.CallOption) (*DeployReleaseResponse, error) - GetClusterDeploymentManifest(ctx context.Context, in *GetClusterDeploymentManifestRequest, opts ...grpc.CallOption) (*GetClusterDeploymentManifestResponse, error) -} - -type taskReleaseServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewTaskReleaseServiceClient(cc grpc.ClientConnInterface) TaskReleaseServiceClient { - return &taskReleaseServiceClient{cc} -} - -func (c *taskReleaseServiceClient) PublishRelease(ctx context.Context, in *PublishReleaseRequest, opts ...grpc.CallOption) (*PublishReleaseResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(PublishReleaseResponse) - err := c.cc.Invoke(ctx, TaskReleaseService_PublishRelease_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *taskReleaseServiceClient) DeployRelease(ctx context.Context, in *DeployReleaseRequest, opts ...grpc.CallOption) (*DeployReleaseResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(DeployReleaseResponse) - err := c.cc.Invoke(ctx, TaskReleaseService_DeployRelease_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *taskReleaseServiceClient) GetClusterDeploymentManifest(ctx context.Context, in *GetClusterDeploymentManifestRequest, opts ...grpc.CallOption) (*GetClusterDeploymentManifestResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetClusterDeploymentManifestResponse) - err := c.cc.Invoke(ctx, TaskReleaseService_GetClusterDeploymentManifest_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -// TaskReleaseServiceServer is the server API for TaskReleaseService service. -// All implementations must embed UnimplementedTaskReleaseServiceServer -// for forward compatibility. -// -// A service for managing workflows. -type TaskReleaseServiceServer interface { - PublishRelease(context.Context, *PublishReleaseRequest) (*PublishReleaseResponse, error) - DeployRelease(context.Context, *DeployReleaseRequest) (*DeployReleaseResponse, error) - GetClusterDeploymentManifest(context.Context, *GetClusterDeploymentManifestRequest) (*GetClusterDeploymentManifestResponse, error) - mustEmbedUnimplementedTaskReleaseServiceServer() -} - -// UnimplementedTaskReleaseServiceServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedTaskReleaseServiceServer struct{} - -func (UnimplementedTaskReleaseServiceServer) PublishRelease(context.Context, *PublishReleaseRequest) (*PublishReleaseResponse, error) { - return nil, status.Error(codes.Unimplemented, "method PublishRelease not implemented") -} -func (UnimplementedTaskReleaseServiceServer) DeployRelease(context.Context, *DeployReleaseRequest) (*DeployReleaseResponse, error) { - return nil, status.Error(codes.Unimplemented, "method DeployRelease not implemented") -} -func (UnimplementedTaskReleaseServiceServer) GetClusterDeploymentManifest(context.Context, *GetClusterDeploymentManifestRequest) (*GetClusterDeploymentManifestResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetClusterDeploymentManifest not implemented") -} -func (UnimplementedTaskReleaseServiceServer) mustEmbedUnimplementedTaskReleaseServiceServer() {} -func (UnimplementedTaskReleaseServiceServer) testEmbeddedByValue() {} - -// UnsafeTaskReleaseServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to TaskReleaseServiceServer will -// result in compilation errors. -type UnsafeTaskReleaseServiceServer interface { - mustEmbedUnimplementedTaskReleaseServiceServer() -} - -func RegisterTaskReleaseServiceServer(s grpc.ServiceRegistrar, srv TaskReleaseServiceServer) { - // If the following call panics, it indicates UnimplementedTaskReleaseServiceServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&TaskReleaseService_ServiceDesc, srv) -} - -func _TaskReleaseService_PublishRelease_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(PublishReleaseRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(TaskReleaseServiceServer).PublishRelease(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: TaskReleaseService_PublishRelease_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TaskReleaseServiceServer).PublishRelease(ctx, req.(*PublishReleaseRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _TaskReleaseService_DeployRelease_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DeployReleaseRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(TaskReleaseServiceServer).DeployRelease(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: TaskReleaseService_DeployRelease_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TaskReleaseServiceServer).DeployRelease(ctx, req.(*DeployReleaseRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _TaskReleaseService_GetClusterDeploymentManifest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetClusterDeploymentManifestRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(TaskReleaseServiceServer).GetClusterDeploymentManifest(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: TaskReleaseService_GetClusterDeploymentManifest_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TaskReleaseServiceServer).GetClusterDeploymentManifest(ctx, req.(*GetClusterDeploymentManifestRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// TaskReleaseService_ServiceDesc is the grpc.ServiceDesc for TaskReleaseService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var TaskReleaseService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "workflows.v1.TaskReleaseService", - HandlerType: (*TaskReleaseServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "PublishRelease", - Handler: _TaskReleaseService_PublishRelease_Handler, - }, - { - MethodName: "DeployRelease", - Handler: _TaskReleaseService_DeployRelease_Handler, - }, - { - MethodName: "GetClusterDeploymentManifest", - Handler: _TaskReleaseService_GetClusterDeploymentManifest_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "workflows/v1/task_release.proto", -} diff --git a/protogen/workflows/v1/worker.pb.go b/protogen/workflows/v1/worker.pb.go new file mode 100644 index 0000000..17d6a2f --- /dev/null +++ b/protogen/workflows/v1/worker.pb.go @@ -0,0 +1,562 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: workflows/v1/worker.proto + +package workflowsv1 + +import ( + _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" + v1 "github.com/tilebox/tilebox-go/protogen/tilebox/v1" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + emptypb "google.golang.org/protobuf/types/known/emptypb" + reflect "reflect" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// InitializeRunnerRequest is sent by the runner to a worker runtime to discover its capabilities. +type InitializeRunnerRequest struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_RunnerId *v1.ID `protobuf:"bytes,1,opt,name=runner_id,json=runnerId"` + xxx_hidden_TraceParent *string `protobuf:"bytes,2,opt,name=trace_parent,json=traceParent"` + xxx_hidden_Cluster *Cluster `protobuf:"bytes,3,opt,name=cluster"` + xxx_hidden_Workflow *Workflow `protobuf:"bytes,4,opt,name=workflow"` + xxx_hidden_ApiConnection *TileboxAPIConnection `protobuf:"bytes,5,opt,name=api_connection,json=apiConnection"` + XXX_raceDetectHookData protoimpl.RaceDetectHookData + XXX_presence [1]uint32 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InitializeRunnerRequest) Reset() { + *x = InitializeRunnerRequest{} + mi := &file_workflows_v1_worker_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InitializeRunnerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InitializeRunnerRequest) ProtoMessage() {} + +func (x *InitializeRunnerRequest) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_worker_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *InitializeRunnerRequest) GetRunnerId() *v1.ID { + if x != nil { + return x.xxx_hidden_RunnerId + } + return nil +} + +func (x *InitializeRunnerRequest) GetTraceParent() string { + if x != nil { + if x.xxx_hidden_TraceParent != nil { + return *x.xxx_hidden_TraceParent + } + return "" + } + return "" +} + +func (x *InitializeRunnerRequest) GetCluster() *Cluster { + if x != nil { + return x.xxx_hidden_Cluster + } + return nil +} + +func (x *InitializeRunnerRequest) GetWorkflow() *Workflow { + if x != nil { + return x.xxx_hidden_Workflow + } + return nil +} + +func (x *InitializeRunnerRequest) GetApiConnection() *TileboxAPIConnection { + if x != nil { + return x.xxx_hidden_ApiConnection + } + return nil +} + +func (x *InitializeRunnerRequest) SetRunnerId(v *v1.ID) { + x.xxx_hidden_RunnerId = v +} + +func (x *InitializeRunnerRequest) SetTraceParent(v string) { + x.xxx_hidden_TraceParent = &v + protoimpl.X.SetPresent(&(x.XXX_presence[0]), 1, 5) +} + +func (x *InitializeRunnerRequest) SetCluster(v *Cluster) { + x.xxx_hidden_Cluster = v +} + +func (x *InitializeRunnerRequest) SetWorkflow(v *Workflow) { + x.xxx_hidden_Workflow = v +} + +func (x *InitializeRunnerRequest) SetApiConnection(v *TileboxAPIConnection) { + x.xxx_hidden_ApiConnection = v +} + +func (x *InitializeRunnerRequest) HasRunnerId() bool { + if x == nil { + return false + } + return x.xxx_hidden_RunnerId != nil +} + +func (x *InitializeRunnerRequest) HasTraceParent() bool { + if x == nil { + return false + } + return protoimpl.X.Present(&(x.XXX_presence[0]), 1) +} + +func (x *InitializeRunnerRequest) HasCluster() bool { + if x == nil { + return false + } + return x.xxx_hidden_Cluster != nil +} + +func (x *InitializeRunnerRequest) HasWorkflow() bool { + if x == nil { + return false + } + return x.xxx_hidden_Workflow != nil +} + +func (x *InitializeRunnerRequest) HasApiConnection() bool { + if x == nil { + return false + } + return x.xxx_hidden_ApiConnection != nil +} + +func (x *InitializeRunnerRequest) ClearRunnerId() { + x.xxx_hidden_RunnerId = nil +} + +func (x *InitializeRunnerRequest) ClearTraceParent() { + protoimpl.X.ClearPresent(&(x.XXX_presence[0]), 1) + x.xxx_hidden_TraceParent = nil +} + +func (x *InitializeRunnerRequest) ClearCluster() { + x.xxx_hidden_Cluster = nil +} + +func (x *InitializeRunnerRequest) ClearWorkflow() { + x.xxx_hidden_Workflow = nil +} + +func (x *InitializeRunnerRequest) ClearApiConnection() { + x.xxx_hidden_ApiConnection = nil +} + +type InitializeRunnerRequest_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The id of the runner that this worker runtime is connected to. + RunnerId *v1.ID + // The trace_parent that should be used for any traces emitted by this worker runtime (outside of task execution, + // which has its own trace_parent propagation from jobs). This allows us to correlate any logs and traces emitted + // by the worker runtime with the runner that it's connected to. + TraceParent *string + // The cluster that the worker runtime is running on. + Cluster *Cluster + // The workflow (and the release) that this worker was created from. + Workflow *Workflow + // The storage locations that the worker runtime can access, for triggered automations. + ApiConnection *TileboxAPIConnection +} + +func (b0 InitializeRunnerRequest_builder) Build() *InitializeRunnerRequest { + m0 := &InitializeRunnerRequest{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_RunnerId = b.RunnerId + if b.TraceParent != nil { + protoimpl.X.SetPresentNonAtomic(&(x.XXX_presence[0]), 1, 5) + x.xxx_hidden_TraceParent = b.TraceParent + } + x.xxx_hidden_Cluster = b.Cluster + x.xxx_hidden_Workflow = b.Workflow + x.xxx_hidden_ApiConnection = b.ApiConnection + return m0 +} + +// TileboxAPIConnection is a message containing the information needed for a worker runtime to connect to the Tilebox +// API, to e.g. export observability data to (logs and traces). It's the credentials that the tilebox-cli locally +// uses to connect to the Tilebox API, and is passed down to the worker runtimes so that they can also connect to the +// Tilebox API in the same way. Since this only is done on a local machine, via a unix socket, and not in a shared +// environment or over the internet, this is safe to do. +type TileboxAPIConnection struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Url *string `protobuf:"bytes,1,opt,name=url"` + xxx_hidden_Token *string `protobuf:"bytes,2,opt,name=token"` + XXX_raceDetectHookData protoimpl.RaceDetectHookData + XXX_presence [1]uint32 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TileboxAPIConnection) Reset() { + *x = TileboxAPIConnection{} + mi := &file_workflows_v1_worker_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TileboxAPIConnection) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TileboxAPIConnection) ProtoMessage() {} + +func (x *TileboxAPIConnection) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_worker_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *TileboxAPIConnection) GetUrl() string { + if x != nil { + if x.xxx_hidden_Url != nil { + return *x.xxx_hidden_Url + } + return "" + } + return "" +} + +func (x *TileboxAPIConnection) GetToken() string { + if x != nil { + if x.xxx_hidden_Token != nil { + return *x.xxx_hidden_Token + } + return "" + } + return "" +} + +func (x *TileboxAPIConnection) SetUrl(v string) { + x.xxx_hidden_Url = &v + protoimpl.X.SetPresent(&(x.XXX_presence[0]), 0, 2) +} + +func (x *TileboxAPIConnection) SetToken(v string) { + x.xxx_hidden_Token = &v + protoimpl.X.SetPresent(&(x.XXX_presence[0]), 1, 2) +} + +func (x *TileboxAPIConnection) HasUrl() bool { + if x == nil { + return false + } + return protoimpl.X.Present(&(x.XXX_presence[0]), 0) +} + +func (x *TileboxAPIConnection) HasToken() bool { + if x == nil { + return false + } + return protoimpl.X.Present(&(x.XXX_presence[0]), 1) +} + +func (x *TileboxAPIConnection) ClearUrl() { + protoimpl.X.ClearPresent(&(x.XXX_presence[0]), 0) + x.xxx_hidden_Url = nil +} + +func (x *TileboxAPIConnection) ClearToken() { + protoimpl.X.ClearPresent(&(x.XXX_presence[0]), 1) + x.xxx_hidden_Token = nil +} + +type TileboxAPIConnection_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The API url to which the worker runtime can connect, to e.g. export observability data to (logs and traces). + Url *string + // The token to use for authenticating to the API. + Token *string +} + +func (b0 TileboxAPIConnection_builder) Build() *TileboxAPIConnection { + m0 := &TileboxAPIConnection{} + b, x := &b0, m0 + _, _ = b, x + if b.Url != nil { + protoimpl.X.SetPresentNonAtomic(&(x.XXX_presence[0]), 0, 2) + x.xxx_hidden_Url = b.Url + } + if b.Token != nil { + protoimpl.X.SetPresentNonAtomic(&(x.XXX_presence[0]), 1, 2) + x.xxx_hidden_Token = b.Token + } + return m0 +} + +// HandshakeResponse is the response to a handshake request, containing the task identifiers that the worker can execute. +type InitializeRunnerResponse struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InitializeRunnerResponse) Reset() { + *x = InitializeRunnerResponse{} + mi := &file_workflows_v1_worker_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InitializeRunnerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InitializeRunnerResponse) ProtoMessage() {} + +func (x *InitializeRunnerResponse) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_worker_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +type InitializeRunnerResponse_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + +} + +func (b0 InitializeRunnerResponse_builder) Build() *InitializeRunnerResponse { + m0 := &InitializeRunnerResponse{} + b, x := &b0, m0 + _, _ = b, x + return m0 +} + +// ExecuteTaskResponse is the response of a worker runtime to a request to execute a task, after the task has +// been executed. +type ExecuteTaskResponse struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_ComputedTask *ComputedTask `protobuf:"bytes,1,opt,name=computed_task,json=computedTask"` + xxx_hidden_FailedTask *TaskFailedRequest `protobuf:"bytes,2,opt,name=failed_task,json=failedTask"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExecuteTaskResponse) Reset() { + *x = ExecuteTaskResponse{} + mi := &file_workflows_v1_worker_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExecuteTaskResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecuteTaskResponse) ProtoMessage() {} + +func (x *ExecuteTaskResponse) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_worker_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ExecuteTaskResponse) GetComputedTask() *ComputedTask { + if x != nil { + return x.xxx_hidden_ComputedTask + } + return nil +} + +func (x *ExecuteTaskResponse) GetFailedTask() *TaskFailedRequest { + if x != nil { + return x.xxx_hidden_FailedTask + } + return nil +} + +func (x *ExecuteTaskResponse) SetComputedTask(v *ComputedTask) { + x.xxx_hidden_ComputedTask = v +} + +func (x *ExecuteTaskResponse) SetFailedTask(v *TaskFailedRequest) { + x.xxx_hidden_FailedTask = v +} + +func (x *ExecuteTaskResponse) HasComputedTask() bool { + if x == nil { + return false + } + return x.xxx_hidden_ComputedTask != nil +} + +func (x *ExecuteTaskResponse) HasFailedTask() bool { + if x == nil { + return false + } + return x.xxx_hidden_FailedTask != nil +} + +func (x *ExecuteTaskResponse) ClearComputedTask() { + x.xxx_hidden_ComputedTask = nil +} + +func (x *ExecuteTaskResponse) ClearFailedTask() { + x.xxx_hidden_FailedTask = nil +} + +type ExecuteTaskResponse_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // If the task execution succeeded, this field will be set with the computed task result. + ComputedTask *ComputedTask + // If the task execution failed, this field will be set with details about the failure. + FailedTask *TaskFailedRequest +} + +func (b0 ExecuteTaskResponse_builder) Build() *ExecuteTaskResponse { + m0 := &ExecuteTaskResponse{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_ComputedTask = b.ComputedTask + x.xxx_hidden_FailedTask = b.FailedTask + return m0 +} + +var File_workflows_v1_worker_proto protoreflect.FileDescriptor + +const file_workflows_v1_worker_proto_rawDesc = "" + + "\n" + + "\x19workflows/v1/worker.proto\x12\fworkflows.v1\x1a\x1bbuf/validate/validate.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x13tilebox/v1/id.proto\x1a\x1dworkflows/v1/automation.proto\x1a\x17workflows/v1/core.proto\x1a\x17workflows/v1/task.proto\x1a\x1cworkflows/v1/workflows.proto\"\x99\x02\n" + + "\x17InitializeRunnerRequest\x12+\n" + + "\trunner_id\x18\x01 \x01(\v2\x0e.tilebox.v1.IDR\brunnerId\x12!\n" + + "\ftrace_parent\x18\x02 \x01(\tR\vtraceParent\x12/\n" + + "\acluster\x18\x03 \x01(\v2\x15.workflows.v1.ClusterR\acluster\x122\n" + + "\bworkflow\x18\x04 \x01(\v2\x16.workflows.v1.WorkflowR\bworkflow\x12I\n" + + "\x0eapi_connection\x18\x05 \x01(\v2\".workflows.v1.TileboxAPIConnectionR\rapiConnection\">\n" + + "\x14TileboxAPIConnection\x12\x10\n" + + "\x03url\x18\x01 \x01(\tR\x03url\x12\x14\n" + + "\x05token\x18\x02 \x01(\tR\x05token\"\x1a\n" + + "\x18InitializeRunnerResponse\"\xbb\x01\n" + + "\x13ExecuteTaskResponse\x12?\n" + + "\rcomputed_task\x18\x01 \x01(\v2\x1a.workflows.v1.ComputedTaskR\fcomputedTask\x12@\n" + + "\vfailed_task\x18\x02 \x01(\v2\x1f.workflows.v1.TaskFailedRequestR\n" + + "failedTask:!\xbaH\x1e\"\x1c\n" + + "\rcomputed_task\n" + + "\vfailed_task2\xce\x02\n" + + "\rWorkerService\x12L\n" + + "\x13ListRegisteredTasks\x12\x16.google.protobuf.Empty\x1a\x1d.workflows.v1.TaskIdentifiers\x12c\n" + + "\x10InitializeWorker\x12%.workflows.v1.InitializeRunnerRequest\x1a&.workflows.v1.InitializeRunnerResponse\"\x00\x12F\n" + + "\vExecuteTask\x12\x12.workflows.v1.Task\x1a!.workflows.v1.ExecuteTaskResponse\"\x00\x12B\n" + + "\x0eShutdownWorker\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\"\x00B\xb1\x01\n" + + "\x10com.workflows.v1B\vWorkerProtoP\x01Z?github.com/tilebox/tilebox-go/protogen/workflows/v1;workflowsv1\xa2\x02\x03WXX\xaa\x02\fWorkflows.V1\xca\x02\fWorkflows\\V1\xe2\x02\x18Workflows\\V1\\GPBMetadata\xea\x02\rWorkflows::V1b\beditionsp\xe8\a" + +var file_workflows_v1_worker_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_workflows_v1_worker_proto_goTypes = []any{ + (*InitializeRunnerRequest)(nil), // 0: workflows.v1.InitializeRunnerRequest + (*TileboxAPIConnection)(nil), // 1: workflows.v1.TileboxAPIConnection + (*InitializeRunnerResponse)(nil), // 2: workflows.v1.InitializeRunnerResponse + (*ExecuteTaskResponse)(nil), // 3: workflows.v1.ExecuteTaskResponse + (*v1.ID)(nil), // 4: tilebox.v1.ID + (*Cluster)(nil), // 5: workflows.v1.Cluster + (*Workflow)(nil), // 6: workflows.v1.Workflow + (*ComputedTask)(nil), // 7: workflows.v1.ComputedTask + (*TaskFailedRequest)(nil), // 8: workflows.v1.TaskFailedRequest + (*emptypb.Empty)(nil), // 9: google.protobuf.Empty + (*Task)(nil), // 10: workflows.v1.Task + (*TaskIdentifiers)(nil), // 11: workflows.v1.TaskIdentifiers +} +var file_workflows_v1_worker_proto_depIdxs = []int32{ + 4, // 0: workflows.v1.InitializeRunnerRequest.runner_id:type_name -> tilebox.v1.ID + 5, // 1: workflows.v1.InitializeRunnerRequest.cluster:type_name -> workflows.v1.Cluster + 6, // 2: workflows.v1.InitializeRunnerRequest.workflow:type_name -> workflows.v1.Workflow + 1, // 3: workflows.v1.InitializeRunnerRequest.api_connection:type_name -> workflows.v1.TileboxAPIConnection + 7, // 4: workflows.v1.ExecuteTaskResponse.computed_task:type_name -> workflows.v1.ComputedTask + 8, // 5: workflows.v1.ExecuteTaskResponse.failed_task:type_name -> workflows.v1.TaskFailedRequest + 9, // 6: workflows.v1.WorkerService.ListRegisteredTasks:input_type -> google.protobuf.Empty + 0, // 7: workflows.v1.WorkerService.InitializeWorker:input_type -> workflows.v1.InitializeRunnerRequest + 10, // 8: workflows.v1.WorkerService.ExecuteTask:input_type -> workflows.v1.Task + 9, // 9: workflows.v1.WorkerService.ShutdownWorker:input_type -> google.protobuf.Empty + 11, // 10: workflows.v1.WorkerService.ListRegisteredTasks:output_type -> workflows.v1.TaskIdentifiers + 2, // 11: workflows.v1.WorkerService.InitializeWorker:output_type -> workflows.v1.InitializeRunnerResponse + 3, // 12: workflows.v1.WorkerService.ExecuteTask:output_type -> workflows.v1.ExecuteTaskResponse + 9, // 13: workflows.v1.WorkerService.ShutdownWorker:output_type -> google.protobuf.Empty + 10, // [10:14] is the sub-list for method output_type + 6, // [6:10] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name +} + +func init() { file_workflows_v1_worker_proto_init() } +func file_workflows_v1_worker_proto_init() { + if File_workflows_v1_worker_proto != nil { + return + } + file_workflows_v1_automation_proto_init() + file_workflows_v1_core_proto_init() + file_workflows_v1_task_proto_init() + file_workflows_v1_workflows_proto_init() + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_workflows_v1_worker_proto_rawDesc), len(file_workflows_v1_worker_proto_rawDesc)), + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_workflows_v1_worker_proto_goTypes, + DependencyIndexes: file_workflows_v1_worker_proto_depIdxs, + MessageInfos: file_workflows_v1_worker_proto_msgTypes, + }.Build() + File_workflows_v1_worker_proto = out.File + file_workflows_v1_worker_proto_goTypes = nil + file_workflows_v1_worker_proto_depIdxs = nil +} diff --git a/protogen/workflows/v1/worker_grpc.pb.go b/protogen/workflows/v1/worker_grpc.pb.go new file mode 100644 index 0000000..1cd9790 --- /dev/null +++ b/protogen/workflows/v1/worker_grpc.pb.go @@ -0,0 +1,258 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.2 +// - protoc (unknown) +// source: workflows/v1/worker.proto + +package workflowsv1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + emptypb "google.golang.org/protobuf/types/known/emptypb" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + WorkerService_ListRegisteredTasks_FullMethodName = "/workflows.v1.WorkerService/ListRegisteredTasks" + WorkerService_InitializeWorker_FullMethodName = "/workflows.v1.WorkerService/InitializeWorker" + WorkerService_ExecuteTask_FullMethodName = "/workflows.v1.WorkerService/ExecuteTask" + WorkerService_ShutdownWorker_FullMethodName = "/workflows.v1.WorkerService/ShutdownWorker" +) + +// WorkerServiceClient is the client API for WorkerService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// WorkerService defines the RPC interface between a runner and a a worker runtime that can execute workflow tasks. +type WorkerServiceClient interface { + // ListRegisteredTasks is called by the runner to discover the task identifiers that a worker runtime can execute. + ListRegisteredTasks(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*TaskIdentifiers, error) + // InitializeWorker is called by the runner to initialize a worker runtime with some known metadata about the + // runner. This allows us to add those metadata to any logs and traces emitted by the worker. + InitializeWorker(ctx context.Context, in *InitializeRunnerRequest, opts ...grpc.CallOption) (*InitializeRunnerResponse, error) + // ExecuteTask is called by the runner to execute a task on the worker runtime. The worker runtime will execute the + // task, and then respond with the result of the task execution, which can either be a computed task, or a failed + // task. If the worker runtime crashes or becomes unreachable during task execution, the runner will treat the task + // as failed with an unknown error. + ExecuteTask(ctx context.Context, in *Task, opts ...grpc.CallOption) (*ExecuteTaskResponse, error) + // Gracefully shuts down the worker runtime. After receiving this request, the worker runtime will + // cleanly shut down. + ShutdownWorker(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) +} + +type workerServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewWorkerServiceClient(cc grpc.ClientConnInterface) WorkerServiceClient { + return &workerServiceClient{cc} +} + +func (c *workerServiceClient) ListRegisteredTasks(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*TaskIdentifiers, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(TaskIdentifiers) + err := c.cc.Invoke(ctx, WorkerService_ListRegisteredTasks_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *workerServiceClient) InitializeWorker(ctx context.Context, in *InitializeRunnerRequest, opts ...grpc.CallOption) (*InitializeRunnerResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(InitializeRunnerResponse) + err := c.cc.Invoke(ctx, WorkerService_InitializeWorker_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *workerServiceClient) ExecuteTask(ctx context.Context, in *Task, opts ...grpc.CallOption) (*ExecuteTaskResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ExecuteTaskResponse) + err := c.cc.Invoke(ctx, WorkerService_ExecuteTask_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *workerServiceClient) ShutdownWorker(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, WorkerService_ShutdownWorker_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// WorkerServiceServer is the server API for WorkerService service. +// All implementations must embed UnimplementedWorkerServiceServer +// for forward compatibility. +// +// WorkerService defines the RPC interface between a runner and a a worker runtime that can execute workflow tasks. +type WorkerServiceServer interface { + // ListRegisteredTasks is called by the runner to discover the task identifiers that a worker runtime can execute. + ListRegisteredTasks(context.Context, *emptypb.Empty) (*TaskIdentifiers, error) + // InitializeWorker is called by the runner to initialize a worker runtime with some known metadata about the + // runner. This allows us to add those metadata to any logs and traces emitted by the worker. + InitializeWorker(context.Context, *InitializeRunnerRequest) (*InitializeRunnerResponse, error) + // ExecuteTask is called by the runner to execute a task on the worker runtime. The worker runtime will execute the + // task, and then respond with the result of the task execution, which can either be a computed task, or a failed + // task. If the worker runtime crashes or becomes unreachable during task execution, the runner will treat the task + // as failed with an unknown error. + ExecuteTask(context.Context, *Task) (*ExecuteTaskResponse, error) + // Gracefully shuts down the worker runtime. After receiving this request, the worker runtime will + // cleanly shut down. + ShutdownWorker(context.Context, *emptypb.Empty) (*emptypb.Empty, error) + mustEmbedUnimplementedWorkerServiceServer() +} + +// UnimplementedWorkerServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedWorkerServiceServer struct{} + +func (UnimplementedWorkerServiceServer) ListRegisteredTasks(context.Context, *emptypb.Empty) (*TaskIdentifiers, error) { + return nil, status.Error(codes.Unimplemented, "method ListRegisteredTasks not implemented") +} +func (UnimplementedWorkerServiceServer) InitializeWorker(context.Context, *InitializeRunnerRequest) (*InitializeRunnerResponse, error) { + return nil, status.Error(codes.Unimplemented, "method InitializeWorker not implemented") +} +func (UnimplementedWorkerServiceServer) ExecuteTask(context.Context, *Task) (*ExecuteTaskResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ExecuteTask not implemented") +} +func (UnimplementedWorkerServiceServer) ShutdownWorker(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { + return nil, status.Error(codes.Unimplemented, "method ShutdownWorker not implemented") +} +func (UnimplementedWorkerServiceServer) mustEmbedUnimplementedWorkerServiceServer() {} +func (UnimplementedWorkerServiceServer) testEmbeddedByValue() {} + +// UnsafeWorkerServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to WorkerServiceServer will +// result in compilation errors. +type UnsafeWorkerServiceServer interface { + mustEmbedUnimplementedWorkerServiceServer() +} + +func RegisterWorkerServiceServer(s grpc.ServiceRegistrar, srv WorkerServiceServer) { + // If the following call panics, it indicates UnimplementedWorkerServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&WorkerService_ServiceDesc, srv) +} + +func _WorkerService_ListRegisteredTasks_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WorkerServiceServer).ListRegisteredTasks(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WorkerService_ListRegisteredTasks_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WorkerServiceServer).ListRegisteredTasks(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _WorkerService_InitializeWorker_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InitializeRunnerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WorkerServiceServer).InitializeWorker(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WorkerService_InitializeWorker_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WorkerServiceServer).InitializeWorker(ctx, req.(*InitializeRunnerRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WorkerService_ExecuteTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Task) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WorkerServiceServer).ExecuteTask(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WorkerService_ExecuteTask_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WorkerServiceServer).ExecuteTask(ctx, req.(*Task)) + } + return interceptor(ctx, in, info, handler) +} + +func _WorkerService_ShutdownWorker_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WorkerServiceServer).ShutdownWorker(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WorkerService_ShutdownWorker_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WorkerServiceServer).ShutdownWorker(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +// WorkerService_ServiceDesc is the grpc.ServiceDesc for WorkerService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var WorkerService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "workflows.v1.WorkerService", + HandlerType: (*WorkerServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ListRegisteredTasks", + Handler: _WorkerService_ListRegisteredTasks_Handler, + }, + { + MethodName: "InitializeWorker", + Handler: _WorkerService_InitializeWorker_Handler, + }, + { + MethodName: "ExecuteTask", + Handler: _WorkerService_ExecuteTask_Handler, + }, + { + MethodName: "ShutdownWorker", + Handler: _WorkerService_ShutdownWorker_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "workflows/v1/worker.proto", +} diff --git a/protogen/workflows/v1/workflows.pb.go b/protogen/workflows/v1/workflows.pb.go index 7b4252d..e6bdb21 100644 --- a/protogen/workflows/v1/workflows.pb.go +++ b/protogen/workflows/v1/workflows.pb.go @@ -10,8 +10,11 @@ package workflowsv1 import ( _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" + v1 "github.com/tilebox/tilebox-go/protogen/tilebox/v1" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + _ "google.golang.org/protobuf/types/known/emptypb" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" unsafe "unsafe" ) @@ -23,6 +26,113 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +// A cluster is a grouping of tasks that are related. +type Cluster struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Slug string `protobuf:"bytes,2,opt,name=slug"` + xxx_hidden_DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName"` + xxx_hidden_Deletable bool `protobuf:"varint,4,opt,name=deletable"` + xxx_hidden_DeployedReleases *[]*Workflow `protobuf:"bytes,5,rep,name=deployed_releases,json=deployedReleases"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Cluster) Reset() { + *x = Cluster{} + mi := &file_workflows_v1_workflows_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Cluster) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Cluster) ProtoMessage() {} + +func (x *Cluster) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_workflows_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Cluster) GetSlug() string { + if x != nil { + return x.xxx_hidden_Slug + } + return "" +} + +func (x *Cluster) GetDisplayName() string { + if x != nil { + return x.xxx_hidden_DisplayName + } + return "" +} + +func (x *Cluster) GetDeletable() bool { + if x != nil { + return x.xxx_hidden_Deletable + } + return false +} + +func (x *Cluster) GetDeployedReleases() []*Workflow { + if x != nil { + if x.xxx_hidden_DeployedReleases != nil { + return *x.xxx_hidden_DeployedReleases + } + } + return nil +} + +func (x *Cluster) SetSlug(v string) { + x.xxx_hidden_Slug = v +} + +func (x *Cluster) SetDisplayName(v string) { + x.xxx_hidden_DisplayName = v +} + +func (x *Cluster) SetDeletable(v bool) { + x.xxx_hidden_Deletable = v +} + +func (x *Cluster) SetDeployedReleases(v []*Workflow) { + x.xxx_hidden_DeployedReleases = &v +} + +type Cluster_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The unique slug of the cluster within the namespace. + Slug string + // The display name of the cluster. + DisplayName string + // Where the cluster is deletable + Deletable bool + // The workflows that are currently deployed to this cluster. Each workflow will only contain one release, + // which is the currently deployed release for that workflow on this cluster. + DeployedReleases []*Workflow +} + +func (b0 Cluster_builder) Build() *Cluster { + m0 := &Cluster{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Slug = b.Slug + x.xxx_hidden_DisplayName = b.DisplayName + x.xxx_hidden_Deletable = b.Deletable + x.xxx_hidden_DeployedReleases = &b.DeployedReleases + return m0 +} + // CreateClusterRequest creates a new cluster. type CreateClusterRequest struct { state protoimpl.MessageState `protogen:"opaque.v1"` @@ -33,7 +143,7 @@ type CreateClusterRequest struct { func (x *CreateClusterRequest) Reset() { *x = CreateClusterRequest{} - mi := &file_workflows_v1_workflows_proto_msgTypes[0] + mi := &file_workflows_v1_workflows_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -45,7 +155,7 @@ func (x *CreateClusterRequest) String() string { func (*CreateClusterRequest) ProtoMessage() {} func (x *CreateClusterRequest) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_workflows_proto_msgTypes[0] + mi := &file_workflows_v1_workflows_proto_msgTypes[1] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -92,7 +202,7 @@ type GetClusterRequest struct { func (x *GetClusterRequest) Reset() { *x = GetClusterRequest{} - mi := &file_workflows_v1_workflows_proto_msgTypes[1] + mi := &file_workflows_v1_workflows_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -104,7 +214,7 @@ func (x *GetClusterRequest) String() string { func (*GetClusterRequest) ProtoMessage() {} func (x *GetClusterRequest) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_workflows_proto_msgTypes[1] + mi := &file_workflows_v1_workflows_proto_msgTypes[2] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -129,7 +239,7 @@ func (x *GetClusterRequest) SetClusterSlug(v string) { type GetClusterRequest_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. - // The slug of the cluster to get details for. + // The slug of the cluster to get details for. Empty string requests the default cluster. ClusterSlug string } @@ -151,7 +261,7 @@ type DeleteClusterRequest struct { func (x *DeleteClusterRequest) Reset() { *x = DeleteClusterRequest{} - mi := &file_workflows_v1_workflows_proto_msgTypes[2] + mi := &file_workflows_v1_workflows_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -163,7 +273,7 @@ func (x *DeleteClusterRequest) String() string { func (*DeleteClusterRequest) ProtoMessage() {} func (x *DeleteClusterRequest) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_workflows_proto_msgTypes[2] + mi := &file_workflows_v1_workflows_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -209,7 +319,7 @@ type DeleteClusterResponse struct { func (x *DeleteClusterResponse) Reset() { *x = DeleteClusterResponse{} - mi := &file_workflows_v1_workflows_proto_msgTypes[3] + mi := &file_workflows_v1_workflows_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -221,7 +331,7 @@ func (x *DeleteClusterResponse) String() string { func (*DeleteClusterResponse) ProtoMessage() {} func (x *DeleteClusterResponse) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_workflows_proto_msgTypes[3] + mi := &file_workflows_v1_workflows_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -253,7 +363,7 @@ type ListClustersRequest struct { func (x *ListClustersRequest) Reset() { *x = ListClustersRequest{} - mi := &file_workflows_v1_workflows_proto_msgTypes[4] + mi := &file_workflows_v1_workflows_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -265,7 +375,7 @@ func (x *ListClustersRequest) String() string { func (*ListClustersRequest) ProtoMessage() {} func (x *ListClustersRequest) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_workflows_proto_msgTypes[4] + mi := &file_workflows_v1_workflows_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -298,7 +408,7 @@ type ListClustersResponse struct { func (x *ListClustersResponse) Reset() { *x = ListClustersResponse{} - mi := &file_workflows_v1_workflows_proto_msgTypes[5] + mi := &file_workflows_v1_workflows_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -310,7 +420,7 @@ func (x *ListClustersResponse) String() string { func (*ListClustersResponse) ProtoMessage() {} func (x *ListClustersResponse) ProtoReflect() protoreflect.Message { - mi := &file_workflows_v1_workflows_proto_msgTypes[5] + mi := &file_workflows_v1_workflows_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -349,54 +459,1425 @@ func (b0 ListClustersResponse_builder) Build() *ListClustersResponse { return m0 } -var File_workflows_v1_workflows_proto protoreflect.FileDescriptor +// GetWorkflowRequest requests details for a workflow. +type GetWorkflowRequest struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_WorkflowSlug string `protobuf:"bytes,1,opt,name=workflow_slug,json=workflowSlug"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} -const file_workflows_v1_workflows_proto_rawDesc = "" + - "\n" + - "\x1cworkflows/v1/workflows.proto\x12\fworkflows.v1\x1a\x1bbuf/validate/validate.proto\x1a\x17workflows/v1/core.proto\"3\n" + - "\x14CreateClusterRequest\x12\x1b\n" + - "\x04name\x18\x01 \x01(\tB\a\xbaH\x04r\x02\x10\x01R\x04name\"6\n" + - "\x11GetClusterRequest\x12!\n" + - "\fcluster_slug\x18\x01 \x01(\tR\vclusterSlug\"B\n" + - "\x14DeleteClusterRequest\x12*\n" + - "\fcluster_slug\x18\x01 \x01(\tB\a\xbaH\x04r\x02\x10\x01R\vclusterSlug\"\x17\n" + - "\x15DeleteClusterResponse\"\x15\n" + - "\x13ListClustersRequest\"I\n" + - "\x14ListClustersResponse\x121\n" + - "\bclusters\x18\x01 \x03(\v2\x15.workflows.v1.ClusterR\bclusters2\xd5\x02\n" + +func (x *GetWorkflowRequest) Reset() { + *x = GetWorkflowRequest{} + mi := &file_workflows_v1_workflows_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetWorkflowRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetWorkflowRequest) ProtoMessage() {} + +func (x *GetWorkflowRequest) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_workflows_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *GetWorkflowRequest) GetWorkflowSlug() string { + if x != nil { + return x.xxx_hidden_WorkflowSlug + } + return "" +} + +func (x *GetWorkflowRequest) SetWorkflowSlug(v string) { + x.xxx_hidden_WorkflowSlug = v +} + +type GetWorkflowRequest_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The slug of the workflow to get details for. + WorkflowSlug string +} + +func (b0 GetWorkflowRequest_builder) Build() *GetWorkflowRequest { + m0 := &GetWorkflowRequest{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_WorkflowSlug = b.WorkflowSlug + return m0 +} + +// PublishWorkflowReleaseRequest publishes a new workflow release artifact, and associates it with a workflow. +type PublishWorkflowReleaseRequest struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_WorkflowSlug string `protobuf:"bytes,1,opt,name=workflow_slug,json=workflowSlug"` + xxx_hidden_ArtifactId *v1.ID `protobuf:"bytes,2,opt,name=artifact_id,json=artifactId"` + xxx_hidden_Content *ReleaseContent `protobuf:"bytes,3,opt,name=content"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PublishWorkflowReleaseRequest) Reset() { + *x = PublishWorkflowReleaseRequest{} + mi := &file_workflows_v1_workflows_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PublishWorkflowReleaseRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PublishWorkflowReleaseRequest) ProtoMessage() {} + +func (x *PublishWorkflowReleaseRequest) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_workflows_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *PublishWorkflowReleaseRequest) GetWorkflowSlug() string { + if x != nil { + return x.xxx_hidden_WorkflowSlug + } + return "" +} + +func (x *PublishWorkflowReleaseRequest) GetArtifactId() *v1.ID { + if x != nil { + return x.xxx_hidden_ArtifactId + } + return nil +} + +func (x *PublishWorkflowReleaseRequest) GetContent() *ReleaseContent { + if x != nil { + return x.xxx_hidden_Content + } + return nil +} + +func (x *PublishWorkflowReleaseRequest) SetWorkflowSlug(v string) { + x.xxx_hidden_WorkflowSlug = v +} + +func (x *PublishWorkflowReleaseRequest) SetArtifactId(v *v1.ID) { + x.xxx_hidden_ArtifactId = v +} + +func (x *PublishWorkflowReleaseRequest) SetContent(v *ReleaseContent) { + x.xxx_hidden_Content = v +} + +func (x *PublishWorkflowReleaseRequest) HasArtifactId() bool { + if x == nil { + return false + } + return x.xxx_hidden_ArtifactId != nil +} + +func (x *PublishWorkflowReleaseRequest) HasContent() bool { + if x == nil { + return false + } + return x.xxx_hidden_Content != nil +} + +func (x *PublishWorkflowReleaseRequest) ClearArtifactId() { + x.xxx_hidden_ArtifactId = nil +} + +func (x *PublishWorkflowReleaseRequest) ClearContent() { + x.xxx_hidden_Content = nil +} + +type PublishWorkflowReleaseRequest_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + WorkflowSlug string + ArtifactId *v1.ID + Content *ReleaseContent +} + +func (b0 PublishWorkflowReleaseRequest_builder) Build() *PublishWorkflowReleaseRequest { + m0 := &PublishWorkflowReleaseRequest{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_WorkflowSlug = b.WorkflowSlug + x.xxx_hidden_ArtifactId = b.ArtifactId + x.xxx_hidden_Content = b.Content + return m0 +} + +// ListWorkflowsRequest lists all workflows. +type ListWorkflowsRequest struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListWorkflowsRequest) Reset() { + *x = ListWorkflowsRequest{} + mi := &file_workflows_v1_workflows_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListWorkflowsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListWorkflowsRequest) ProtoMessage() {} + +func (x *ListWorkflowsRequest) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_workflows_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +type ListWorkflowsRequest_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + +} + +func (b0 ListWorkflowsRequest_builder) Build() *ListWorkflowsRequest { + m0 := &ListWorkflowsRequest{} + b, x := &b0, m0 + _, _ = b, x + return m0 +} + +// ListWorkflowsResponse is the response to ListWorkflowsRequest. +type ListWorkflowsResponse struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Workflows *[]*Workflow `protobuf:"bytes,1,rep,name=workflows"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListWorkflowsResponse) Reset() { + *x = ListWorkflowsResponse{} + mi := &file_workflows_v1_workflows_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListWorkflowsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListWorkflowsResponse) ProtoMessage() {} + +func (x *ListWorkflowsResponse) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_workflows_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ListWorkflowsResponse) GetWorkflows() []*Workflow { + if x != nil { + if x.xxx_hidden_Workflows != nil { + return *x.xxx_hidden_Workflows + } + } + return nil +} + +func (x *ListWorkflowsResponse) SetWorkflows(v []*Workflow) { + x.xxx_hidden_Workflows = &v +} + +type ListWorkflowsResponse_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Workflows []*Workflow +} + +func (b0 ListWorkflowsResponse_builder) Build() *ListWorkflowsResponse { + m0 := &ListWorkflowsResponse{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Workflows = &b.Workflows + return m0 +} + +// CreateWorkflowRequest creates a new workflow, with a name and an optional description. +// A workflow slug will be generated based on the name. +type CreateWorkflowRequest struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Name string `protobuf:"bytes,1,opt,name=name"` + xxx_hidden_Description string `protobuf:"bytes,2,opt,name=description"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateWorkflowRequest) Reset() { + *x = CreateWorkflowRequest{} + mi := &file_workflows_v1_workflows_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateWorkflowRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateWorkflowRequest) ProtoMessage() {} + +func (x *CreateWorkflowRequest) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_workflows_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *CreateWorkflowRequest) GetName() string { + if x != nil { + return x.xxx_hidden_Name + } + return "" +} + +func (x *CreateWorkflowRequest) GetDescription() string { + if x != nil { + return x.xxx_hidden_Description + } + return "" +} + +func (x *CreateWorkflowRequest) SetName(v string) { + x.xxx_hidden_Name = v +} + +func (x *CreateWorkflowRequest) SetDescription(v string) { + x.xxx_hidden_Description = v +} + +type CreateWorkflowRequest_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Name string + Description string +} + +func (b0 CreateWorkflowRequest_builder) Build() *CreateWorkflowRequest { + m0 := &CreateWorkflowRequest{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Name = b.Name + x.xxx_hidden_Description = b.Description + return m0 +} + +// Workflow represents a logical grouping for a set of tasks. It can have multiple releases, each comprising a different +// set of tasks. +type Workflow struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Slug string `protobuf:"bytes,2,opt,name=slug"` + xxx_hidden_Name string `protobuf:"bytes,3,opt,name=name"` + xxx_hidden_Description string `protobuf:"bytes,4,opt,name=description"` + xxx_hidden_Releases *[]*WorkflowRelease `protobuf:"bytes,5,rep,name=releases"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Workflow) Reset() { + *x = Workflow{} + mi := &file_workflows_v1_workflows_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Workflow) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Workflow) ProtoMessage() {} + +func (x *Workflow) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_workflows_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Workflow) GetSlug() string { + if x != nil { + return x.xxx_hidden_Slug + } + return "" +} + +func (x *Workflow) GetName() string { + if x != nil { + return x.xxx_hidden_Name + } + return "" +} + +func (x *Workflow) GetDescription() string { + if x != nil { + return x.xxx_hidden_Description + } + return "" +} + +func (x *Workflow) GetReleases() []*WorkflowRelease { + if x != nil { + if x.xxx_hidden_Releases != nil { + return *x.xxx_hidden_Releases + } + } + return nil +} + +func (x *Workflow) SetSlug(v string) { + x.xxx_hidden_Slug = v +} + +func (x *Workflow) SetName(v string) { + x.xxx_hidden_Name = v +} + +func (x *Workflow) SetDescription(v string) { + x.xxx_hidden_Description = v +} + +func (x *Workflow) SetReleases(v []*WorkflowRelease) { + x.xxx_hidden_Releases = &v +} + +type Workflow_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Slug string + Name string + Description string + Releases []*WorkflowRelease +} + +func (b0 Workflow_builder) Build() *Workflow { + m0 := &Workflow{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Slug = b.Slug + x.xxx_hidden_Name = b.Name + x.xxx_hidden_Description = b.Description + x.xxx_hidden_Releases = &b.Releases + return m0 +} + +// WorkflowRelease represents an immutable release of a workflow, which includes a set of tasks and an artifact. +type WorkflowRelease struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Id *v1.ID `protobuf:"bytes,1,opt,name=id"` + xxx_hidden_Artifact *Artifact `protobuf:"bytes,2,opt,name=artifact"` + xxx_hidden_Content *ReleaseContent `protobuf:"bytes,3,opt,name=content"` + xxx_hidden_CreatedAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=created_at,json=createdAt"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WorkflowRelease) Reset() { + *x = WorkflowRelease{} + mi := &file_workflows_v1_workflows_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WorkflowRelease) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WorkflowRelease) ProtoMessage() {} + +func (x *WorkflowRelease) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_workflows_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *WorkflowRelease) GetId() *v1.ID { + if x != nil { + return x.xxx_hidden_Id + } + return nil +} + +func (x *WorkflowRelease) GetArtifact() *Artifact { + if x != nil { + return x.xxx_hidden_Artifact + } + return nil +} + +func (x *WorkflowRelease) GetContent() *ReleaseContent { + if x != nil { + return x.xxx_hidden_Content + } + return nil +} + +func (x *WorkflowRelease) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.xxx_hidden_CreatedAt + } + return nil +} + +func (x *WorkflowRelease) SetId(v *v1.ID) { + x.xxx_hidden_Id = v +} + +func (x *WorkflowRelease) SetArtifact(v *Artifact) { + x.xxx_hidden_Artifact = v +} + +func (x *WorkflowRelease) SetContent(v *ReleaseContent) { + x.xxx_hidden_Content = v +} + +func (x *WorkflowRelease) SetCreatedAt(v *timestamppb.Timestamp) { + x.xxx_hidden_CreatedAt = v +} + +func (x *WorkflowRelease) HasId() bool { + if x == nil { + return false + } + return x.xxx_hidden_Id != nil +} + +func (x *WorkflowRelease) HasArtifact() bool { + if x == nil { + return false + } + return x.xxx_hidden_Artifact != nil +} + +func (x *WorkflowRelease) HasContent() bool { + if x == nil { + return false + } + return x.xxx_hidden_Content != nil +} + +func (x *WorkflowRelease) HasCreatedAt() bool { + if x == nil { + return false + } + return x.xxx_hidden_CreatedAt != nil +} + +func (x *WorkflowRelease) ClearId() { + x.xxx_hidden_Id = nil +} + +func (x *WorkflowRelease) ClearArtifact() { + x.xxx_hidden_Artifact = nil +} + +func (x *WorkflowRelease) ClearContent() { + x.xxx_hidden_Content = nil +} + +func (x *WorkflowRelease) ClearCreatedAt() { + x.xxx_hidden_CreatedAt = nil +} + +type WorkflowRelease_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Id *v1.ID + Artifact *Artifact + Content *ReleaseContent + CreatedAt *timestamppb.Timestamp +} + +func (b0 WorkflowRelease_builder) Build() *WorkflowRelease { + m0 := &WorkflowRelease{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Id = b.Id + x.xxx_hidden_Artifact = b.Artifact + x.xxx_hidden_Content = b.Content + x.xxx_hidden_CreatedAt = b.CreatedAt + return m0 +} + +// Artifact represents the artifact associated with a workflow release, +// which is the file that contains the code and dependencies needed to execute the tasks in the release. +type Artifact struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Id *v1.ID `protobuf:"bytes,1,opt,name=id"` + xxx_hidden_Digest string `protobuf:"bytes,2,opt,name=digest"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Artifact) Reset() { + *x = Artifact{} + mi := &file_workflows_v1_workflows_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Artifact) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Artifact) ProtoMessage() {} + +func (x *Artifact) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_workflows_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Artifact) GetId() *v1.ID { + if x != nil { + return x.xxx_hidden_Id + } + return nil +} + +func (x *Artifact) GetDigest() string { + if x != nil { + return x.xxx_hidden_Digest + } + return "" +} + +func (x *Artifact) SetId(v *v1.ID) { + x.xxx_hidden_Id = v +} + +func (x *Artifact) SetDigest(v string) { + x.xxx_hidden_Digest = v +} + +func (x *Artifact) HasId() bool { + if x == nil { + return false + } + return x.xxx_hidden_Id != nil +} + +func (x *Artifact) ClearId() { + x.xxx_hidden_Id = nil +} + +type Artifact_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Id *v1.ID + Digest string +} + +func (b0 Artifact_builder) Build() *Artifact { + m0 := &Artifact{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Id = b.Id + x.xxx_hidden_Digest = b.Digest + return m0 +} + +// ReleaseContent represents the content of a workflow release, which is the set of files that are included, +// the list of task identifiers, and the command to start a worker runtime for executing the tasks in the release. +// The fingerprint is a hash of the release content. +type ReleaseContent struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Fingerprint string `protobuf:"bytes,1,opt,name=fingerprint"` + xxx_hidden_Tasks *[]*TaskIdentifier `protobuf:"bytes,2,rep,name=tasks"` + xxx_hidden_Files *[]*Path `protobuf:"bytes,3,rep,name=files"` + xxx_hidden_RunnerObjectPath string `protobuf:"bytes,4,opt,name=runner_object_path,json=runnerObjectPath"` + xxx_hidden_CommandOverride []string `protobuf:"bytes,5,rep,name=command_override,json=commandOverride"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ReleaseContent) Reset() { + *x = ReleaseContent{} + mi := &file_workflows_v1_workflows_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ReleaseContent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReleaseContent) ProtoMessage() {} + +func (x *ReleaseContent) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_workflows_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ReleaseContent) GetFingerprint() string { + if x != nil { + return x.xxx_hidden_Fingerprint + } + return "" +} + +func (x *ReleaseContent) GetTasks() []*TaskIdentifier { + if x != nil { + if x.xxx_hidden_Tasks != nil { + return *x.xxx_hidden_Tasks + } + } + return nil +} + +func (x *ReleaseContent) GetFiles() []*Path { + if x != nil { + if x.xxx_hidden_Files != nil { + return *x.xxx_hidden_Files + } + } + return nil +} + +func (x *ReleaseContent) GetRunnerObjectPath() string { + if x != nil { + return x.xxx_hidden_RunnerObjectPath + } + return "" +} + +func (x *ReleaseContent) GetCommandOverride() []string { + if x != nil { + return x.xxx_hidden_CommandOverride + } + return nil +} + +func (x *ReleaseContent) SetFingerprint(v string) { + x.xxx_hidden_Fingerprint = v +} + +func (x *ReleaseContent) SetTasks(v []*TaskIdentifier) { + x.xxx_hidden_Tasks = &v +} + +func (x *ReleaseContent) SetFiles(v []*Path) { + x.xxx_hidden_Files = &v +} + +func (x *ReleaseContent) SetRunnerObjectPath(v string) { + x.xxx_hidden_RunnerObjectPath = v +} + +func (x *ReleaseContent) SetCommandOverride(v []string) { + x.xxx_hidden_CommandOverride = v +} + +type ReleaseContent_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // A fingerprint of the release content, which is a hash of the task identifiers, files, runner object path, + // and command override. Used to determine if two releases have the same content, for idempotent builds. + Fingerprint string + // List of task identifiers included in the release artifact. + Tasks []*TaskIdentifier + // List of files/directories included in the release artifact. + Files []*Path + // The python module/object path to the runner instance, e.g. "my_module.my_runner:runner". + RunnerObjectPath string + // A custom command override for starting a worker runtime. This is optional, and if not set defaults to + // "uv run python -m tilebox.workflows.runner ". This allows users to specify a custom command + // for starting the worker runtime, e.g. to set environment variables or use a different entrypoint. + CommandOverride []string +} + +func (b0 ReleaseContent_builder) Build() *ReleaseContent { + m0 := &ReleaseContent{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Fingerprint = b.Fingerprint + x.xxx_hidden_Tasks = &b.Tasks + x.xxx_hidden_Files = &b.Files + x.xxx_hidden_RunnerObjectPath = b.RunnerObjectPath + x.xxx_hidden_CommandOverride = b.CommandOverride + return m0 +} + +// Path represents a file or directory path in the release content. If it is a directory, it can have child paths. +type Path struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Path string `protobuf:"bytes,1,opt,name=path"` + xxx_hidden_Directory bool `protobuf:"varint,2,opt,name=directory"` + xxx_hidden_Children *[]*Path `protobuf:"bytes,3,rep,name=children"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Path) Reset() { + *x = Path{} + mi := &file_workflows_v1_workflows_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Path) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Path) ProtoMessage() {} + +func (x *Path) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_workflows_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Path) GetPath() string { + if x != nil { + return x.xxx_hidden_Path + } + return "" +} + +func (x *Path) GetDirectory() bool { + if x != nil { + return x.xxx_hidden_Directory + } + return false +} + +func (x *Path) GetChildren() []*Path { + if x != nil { + if x.xxx_hidden_Children != nil { + return *x.xxx_hidden_Children + } + } + return nil +} + +func (x *Path) SetPath(v string) { + x.xxx_hidden_Path = v +} + +func (x *Path) SetDirectory(v bool) { + x.xxx_hidden_Directory = v +} + +func (x *Path) SetChildren(v []*Path) { + x.xxx_hidden_Children = &v +} + +type Path_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Path string + Directory bool + Children []*Path +} + +func (b0 Path_builder) Build() *Path { + m0 := &Path{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Path = b.Path + x.xxx_hidden_Directory = b.Directory + x.xxx_hidden_Children = &b.Children + return m0 +} + +// DeployWorkflowReleaseRequest deploys a workflow release to a set of clusters, making the tasks available for +// execution on those clusters. +type DeployWorkflowReleaseRequest struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_WorkflowSlug string `protobuf:"bytes,1,opt,name=workflow_slug,json=workflowSlug"` + xxx_hidden_ReleaseId *v1.ID `protobuf:"bytes,2,opt,name=release_id,json=releaseId"` + xxx_hidden_ClusterSlugs []string `protobuf:"bytes,3,rep,name=cluster_slugs,json=clusterSlugs"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeployWorkflowReleaseRequest) Reset() { + *x = DeployWorkflowReleaseRequest{} + mi := &file_workflows_v1_workflows_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeployWorkflowReleaseRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeployWorkflowReleaseRequest) ProtoMessage() {} + +func (x *DeployWorkflowReleaseRequest) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_workflows_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *DeployWorkflowReleaseRequest) GetWorkflowSlug() string { + if x != nil { + return x.xxx_hidden_WorkflowSlug + } + return "" +} + +func (x *DeployWorkflowReleaseRequest) GetReleaseId() *v1.ID { + if x != nil { + return x.xxx_hidden_ReleaseId + } + return nil +} + +func (x *DeployWorkflowReleaseRequest) GetClusterSlugs() []string { + if x != nil { + return x.xxx_hidden_ClusterSlugs + } + return nil +} + +func (x *DeployWorkflowReleaseRequest) SetWorkflowSlug(v string) { + x.xxx_hidden_WorkflowSlug = v +} + +func (x *DeployWorkflowReleaseRequest) SetReleaseId(v *v1.ID) { + x.xxx_hidden_ReleaseId = v +} + +func (x *DeployWorkflowReleaseRequest) SetClusterSlugs(v []string) { + x.xxx_hidden_ClusterSlugs = v +} + +func (x *DeployWorkflowReleaseRequest) HasReleaseId() bool { + if x == nil { + return false + } + return x.xxx_hidden_ReleaseId != nil +} + +func (x *DeployWorkflowReleaseRequest) ClearReleaseId() { + x.xxx_hidden_ReleaseId = nil +} + +type DeployWorkflowReleaseRequest_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + WorkflowSlug string + ReleaseId *v1.ID + ClusterSlugs []string +} + +func (b0 DeployWorkflowReleaseRequest_builder) Build() *DeployWorkflowReleaseRequest { + m0 := &DeployWorkflowReleaseRequest{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_WorkflowSlug = b.WorkflowSlug + x.xxx_hidden_ReleaseId = b.ReleaseId + x.xxx_hidden_ClusterSlugs = b.ClusterSlugs + return m0 +} + +// DeployWorkflowReleaseResponse is the response to DeployWorkflowReleaseRequest, +// containing the deployed release and the new state of all the clusters it was deployed to. +type DeployWorkflowReleaseResponse struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Release *WorkflowRelease `protobuf:"bytes,1,opt,name=release"` + xxx_hidden_Clusters *[]*Cluster `protobuf:"bytes,2,rep,name=clusters"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeployWorkflowReleaseResponse) Reset() { + *x = DeployWorkflowReleaseResponse{} + mi := &file_workflows_v1_workflows_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeployWorkflowReleaseResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeployWorkflowReleaseResponse) ProtoMessage() {} + +func (x *DeployWorkflowReleaseResponse) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_workflows_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *DeployWorkflowReleaseResponse) GetRelease() *WorkflowRelease { + if x != nil { + return x.xxx_hidden_Release + } + return nil +} + +func (x *DeployWorkflowReleaseResponse) GetClusters() []*Cluster { + if x != nil { + if x.xxx_hidden_Clusters != nil { + return *x.xxx_hidden_Clusters + } + } + return nil +} + +func (x *DeployWorkflowReleaseResponse) SetRelease(v *WorkflowRelease) { + x.xxx_hidden_Release = v +} + +func (x *DeployWorkflowReleaseResponse) SetClusters(v []*Cluster) { + x.xxx_hidden_Clusters = &v +} + +func (x *DeployWorkflowReleaseResponse) HasRelease() bool { + if x == nil { + return false + } + return x.xxx_hidden_Release != nil +} + +func (x *DeployWorkflowReleaseResponse) ClearRelease() { + x.xxx_hidden_Release = nil +} + +type DeployWorkflowReleaseResponse_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Release *WorkflowRelease + Clusters []*Cluster +} + +func (b0 DeployWorkflowReleaseResponse_builder) Build() *DeployWorkflowReleaseResponse { + m0 := &DeployWorkflowReleaseResponse{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Release = b.Release + x.xxx_hidden_Clusters = &b.Clusters + return m0 +} + +// UndeployWorkflowReleaseRequest undeploys a workflow release from a set of clusters, making them no longer available +// for execution on those clusters. +type UndeployWorkflowReleaseRequest struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_WorkflowSlug string `protobuf:"bytes,1,opt,name=workflow_slug,json=workflowSlug"` + xxx_hidden_ReleaseId *v1.ID `protobuf:"bytes,2,opt,name=release_id,json=releaseId"` + xxx_hidden_ClusterSlugs []string `protobuf:"bytes,3,rep,name=cluster_slugs,json=clusterSlugs"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UndeployWorkflowReleaseRequest) Reset() { + *x = UndeployWorkflowReleaseRequest{} + mi := &file_workflows_v1_workflows_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UndeployWorkflowReleaseRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UndeployWorkflowReleaseRequest) ProtoMessage() {} + +func (x *UndeployWorkflowReleaseRequest) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_workflows_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *UndeployWorkflowReleaseRequest) GetWorkflowSlug() string { + if x != nil { + return x.xxx_hidden_WorkflowSlug + } + return "" +} + +func (x *UndeployWorkflowReleaseRequest) GetReleaseId() *v1.ID { + if x != nil { + return x.xxx_hidden_ReleaseId + } + return nil +} + +func (x *UndeployWorkflowReleaseRequest) GetClusterSlugs() []string { + if x != nil { + return x.xxx_hidden_ClusterSlugs + } + return nil +} + +func (x *UndeployWorkflowReleaseRequest) SetWorkflowSlug(v string) { + x.xxx_hidden_WorkflowSlug = v +} + +func (x *UndeployWorkflowReleaseRequest) SetReleaseId(v *v1.ID) { + x.xxx_hidden_ReleaseId = v +} + +func (x *UndeployWorkflowReleaseRequest) SetClusterSlugs(v []string) { + x.xxx_hidden_ClusterSlugs = v +} + +func (x *UndeployWorkflowReleaseRequest) HasReleaseId() bool { + if x == nil { + return false + } + return x.xxx_hidden_ReleaseId != nil +} + +func (x *UndeployWorkflowReleaseRequest) ClearReleaseId() { + x.xxx_hidden_ReleaseId = nil +} + +type UndeployWorkflowReleaseRequest_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + WorkflowSlug string + ReleaseId *v1.ID + ClusterSlugs []string +} + +func (b0 UndeployWorkflowReleaseRequest_builder) Build() *UndeployWorkflowReleaseRequest { + m0 := &UndeployWorkflowReleaseRequest{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_WorkflowSlug = b.WorkflowSlug + x.xxx_hidden_ReleaseId = b.ReleaseId + x.xxx_hidden_ClusterSlugs = b.ClusterSlugs + return m0 +} + +// UndeployWorkflowReleaseResponse is the response to UndeployWorkflowReleaseRequest, +// containing the undeployed release and the new state of all the clusters it was undeployed from. +type UndeployWorkflowReleaseResponse struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Release *WorkflowRelease `protobuf:"bytes,1,opt,name=release"` + xxx_hidden_Clusters *[]*Cluster `protobuf:"bytes,2,rep,name=clusters"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UndeployWorkflowReleaseResponse) Reset() { + *x = UndeployWorkflowReleaseResponse{} + mi := &file_workflows_v1_workflows_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UndeployWorkflowReleaseResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UndeployWorkflowReleaseResponse) ProtoMessage() {} + +func (x *UndeployWorkflowReleaseResponse) ProtoReflect() protoreflect.Message { + mi := &file_workflows_v1_workflows_proto_msgTypes[20] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *UndeployWorkflowReleaseResponse) GetRelease() *WorkflowRelease { + if x != nil { + return x.xxx_hidden_Release + } + return nil +} + +func (x *UndeployWorkflowReleaseResponse) GetClusters() []*Cluster { + if x != nil { + if x.xxx_hidden_Clusters != nil { + return *x.xxx_hidden_Clusters + } + } + return nil +} + +func (x *UndeployWorkflowReleaseResponse) SetRelease(v *WorkflowRelease) { + x.xxx_hidden_Release = v +} + +func (x *UndeployWorkflowReleaseResponse) SetClusters(v []*Cluster) { + x.xxx_hidden_Clusters = &v +} + +func (x *UndeployWorkflowReleaseResponse) HasRelease() bool { + if x == nil { + return false + } + return x.xxx_hidden_Release != nil +} + +func (x *UndeployWorkflowReleaseResponse) ClearRelease() { + x.xxx_hidden_Release = nil +} + +type UndeployWorkflowReleaseResponse_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Release *WorkflowRelease + Clusters []*Cluster +} + +func (b0 UndeployWorkflowReleaseResponse_builder) Build() *UndeployWorkflowReleaseResponse { + m0 := &UndeployWorkflowReleaseResponse{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Release = b.Release + x.xxx_hidden_Clusters = &b.Clusters + return m0 +} + +var File_workflows_v1_workflows_proto protoreflect.FileDescriptor + +const file_workflows_v1_workflows_proto_rawDesc = "" + + "\n" + + "\x1cworkflows/v1/workflows.proto\x12\fworkflows.v1\x1a\x1bbuf/validate/validate.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x13tilebox/v1/id.proto\x1a\x17workflows/v1/core.proto\"\xa9\x01\n" + + "\aCluster\x12\x12\n" + + "\x04slug\x18\x02 \x01(\tR\x04slug\x12!\n" + + "\fdisplay_name\x18\x03 \x01(\tR\vdisplayName\x12\x1c\n" + + "\tdeletable\x18\x04 \x01(\bR\tdeletable\x12C\n" + + "\x11deployed_releases\x18\x05 \x03(\v2\x16.workflows.v1.WorkflowR\x10deployedReleasesJ\x04\b\x01\x10\x02\"3\n" + + "\x14CreateClusterRequest\x12\x1b\n" + + "\x04name\x18\x01 \x01(\tB\a\xbaH\x04r\x02\x10\x01R\x04name\"6\n" + + "\x11GetClusterRequest\x12!\n" + + "\fcluster_slug\x18\x01 \x01(\tR\vclusterSlug\"B\n" + + "\x14DeleteClusterRequest\x12*\n" + + "\fcluster_slug\x18\x01 \x01(\tB\a\xbaH\x04r\x02\x10\x01R\vclusterSlug\"\x17\n" + + "\x15DeleteClusterResponse\"\x15\n" + + "\x13ListClustersRequest\"I\n" + + "\x14ListClustersResponse\x121\n" + + "\bclusters\x18\x01 \x03(\v2\x15.workflows.v1.ClusterR\bclusters\"B\n" + + "\x12GetWorkflowRequest\x12,\n" + + "\rworkflow_slug\x18\x01 \x01(\tB\a\xbaH\x04r\x02\x10\x01R\fworkflowSlug\"\xc6\x01\n" + + "\x1dPublishWorkflowReleaseRequest\x12,\n" + + "\rworkflow_slug\x18\x01 \x01(\tB\a\xbaH\x04r\x02\x10\x01R\fworkflowSlug\x127\n" + + "\vartifact_id\x18\x02 \x01(\v2\x0e.tilebox.v1.IDB\x06\xbaH\x03\xc8\x01\x01R\n" + + "artifactId\x12>\n" + + "\acontent\x18\x03 \x01(\v2\x1c.workflows.v1.ReleaseContentB\x06\xbaH\x03\xc8\x01\x01R\acontent\"\x16\n" + + "\x14ListWorkflowsRequest\"M\n" + + "\x15ListWorkflowsResponse\x124\n" + + "\tworkflows\x18\x01 \x03(\v2\x16.workflows.v1.WorkflowR\tworkflows\"V\n" + + "\x15CreateWorkflowRequest\x12\x1b\n" + + "\x04name\x18\x01 \x01(\tB\a\xbaH\x04r\x02\x10\x01R\x04name\x12 \n" + + "\vdescription\x18\x02 \x01(\tR\vdescription\"\x95\x01\n" + + "\bWorkflow\x12\x12\n" + + "\x04slug\x18\x02 \x01(\tR\x04slug\x12\x12\n" + + "\x04name\x18\x03 \x01(\tR\x04name\x12 \n" + + "\vdescription\x18\x04 \x01(\tR\vdescription\x129\n" + + "\breleases\x18\x05 \x03(\v2\x1d.workflows.v1.WorkflowReleaseR\breleasesJ\x04\b\x01\x10\x02\"\xd8\x01\n" + + "\x0fWorkflowRelease\x12\x1e\n" + + "\x02id\x18\x01 \x01(\v2\x0e.tilebox.v1.IDR\x02id\x122\n" + + "\bartifact\x18\x02 \x01(\v2\x16.workflows.v1.ArtifactR\bartifact\x126\n" + + "\acontent\x18\x03 \x01(\v2\x1c.workflows.v1.ReleaseContentR\acontent\x129\n" + + "\n" + + "created_at\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\"Y\n" + + "\bArtifact\x12\x1e\n" + + "\x02id\x18\x01 \x01(\v2\x0e.tilebox.v1.IDR\x02id\x12-\n" + + "\x06digest\x18\x02 \x01(\tB\x15\xbaH\x12r\x102\x0e^[a-f0-9]{64}$R\x06digest\"\x8a\x02\n" + + "\x0eReleaseContent\x127\n" + + "\vfingerprint\x18\x01 \x01(\tB\x15\xbaH\x12r\x102\x0e^[a-f0-9]{64}$R\vfingerprint\x12<\n" + + "\x05tasks\x18\x02 \x03(\v2\x1c.workflows.v1.TaskIdentifierB\b\xbaH\x05\x92\x01\x02\b\x01R\x05tasks\x12(\n" + + "\x05files\x18\x03 \x03(\v2\x12.workflows.v1.PathR\x05files\x12,\n" + + "\x12runner_object_path\x18\x04 \x01(\tR\x10runnerObjectPath\x12)\n" + + "\x10command_override\x18\x05 \x03(\tR\x0fcommandOverride\"h\n" + + "\x04Path\x12\x12\n" + + "\x04path\x18\x01 \x01(\tR\x04path\x12\x1c\n" + + "\tdirectory\x18\x02 \x01(\bR\tdirectory\x12.\n" + + "\bchildren\x18\x03 \x03(\v2\x12.workflows.v1.PathR\bchildren\"\xb0\x01\n" + + "\x1cDeployWorkflowReleaseRequest\x12,\n" + + "\rworkflow_slug\x18\x01 \x01(\tB\a\xbaH\x04r\x02\x10\x01R\fworkflowSlug\x12-\n" + + "\n" + + "release_id\x18\x02 \x01(\v2\x0e.tilebox.v1.IDR\treleaseId\x123\n" + + "\rcluster_slugs\x18\x03 \x03(\tB\x0e\xbaH\v\x92\x01\b\b\x00\"\x04r\x02 \x01R\fclusterSlugs\"\x8b\x01\n" + + "\x1dDeployWorkflowReleaseResponse\x127\n" + + "\arelease\x18\x01 \x01(\v2\x1d.workflows.v1.WorkflowReleaseR\arelease\x121\n" + + "\bclusters\x18\x02 \x03(\v2\x15.workflows.v1.ClusterR\bclusters\"\xb2\x01\n" + + "\x1eUndeployWorkflowReleaseRequest\x12,\n" + + "\rworkflow_slug\x18\x01 \x01(\tB\a\xbaH\x04r\x02\x10\x01R\fworkflowSlug\x12-\n" + + "\n" + + "release_id\x18\x02 \x01(\v2\x0e.tilebox.v1.IDR\treleaseId\x123\n" + + "\rcluster_slugs\x18\x03 \x03(\tB\x0e\xbaH\v\x92\x01\b\b\x01\"\x04r\x02 \x01R\fclusterSlugs\"\x8d\x01\n" + + "\x1fUndeployWorkflowReleaseResponse\x127\n" + + "\arelease\x18\x01 \x01(\v2\x1d.workflows.v1.WorkflowReleaseR\arelease\x121\n" + + "\bclusters\x18\x02 \x03(\v2\x15.workflows.v1.ClusterR\bclusters2\x97\a\n" + "\x10WorkflowsService\x12J\n" + "\rCreateCluster\x12\".workflows.v1.CreateClusterRequest\x1a\x15.workflows.v1.Cluster\x12D\n" + "\n" + "GetCluster\x12\x1f.workflows.v1.GetClusterRequest\x1a\x15.workflows.v1.Cluster\x12X\n" + "\rDeleteCluster\x12\".workflows.v1.DeleteClusterRequest\x1a#.workflows.v1.DeleteClusterResponse\x12U\n" + - "\fListClusters\x12!.workflows.v1.ListClustersRequest\x1a\".workflows.v1.ListClustersResponseB\xb9\x01\n" + + "\fListClusters\x12!.workflows.v1.ListClustersRequest\x1a\".workflows.v1.ListClustersResponse\x12M\n" + + "\x0eCreateWorkflow\x12#.workflows.v1.CreateWorkflowRequest\x1a\x16.workflows.v1.Workflow\x12X\n" + + "\rListWorkflows\x12\".workflows.v1.ListWorkflowsRequest\x1a#.workflows.v1.ListWorkflowsResponse\x12G\n" + + "\vGetWorkflow\x12 .workflows.v1.GetWorkflowRequest\x1a\x16.workflows.v1.Workflow\x12d\n" + + "\x16PublishWorkflowRelease\x12+.workflows.v1.PublishWorkflowReleaseRequest\x1a\x1d.workflows.v1.WorkflowRelease\x12p\n" + + "\x15DeployWorkflowRelease\x12*.workflows.v1.DeployWorkflowReleaseRequest\x1a+.workflows.v1.DeployWorkflowReleaseResponse\x12v\n" + + "\x17UndeployWorkflowRelease\x12,.workflows.v1.UndeployWorkflowReleaseRequest\x1a-.workflows.v1.UndeployWorkflowReleaseResponseB\xb9\x01\n" + "\x10com.workflows.v1B\x0eWorkflowsProtoP\x01Z?github.com/tilebox/tilebox-go/protogen/workflows/v1;workflowsv1\xa2\x02\x03WXX\xaa\x02\fWorkflows.V1\xca\x02\fWorkflows\\V1\xe2\x02\x18Workflows\\V1\\GPBMetadata\xea\x02\rWorkflows::V1\x92\x03\x02\b\x02b\beditionsp\xe8\a" -var file_workflows_v1_workflows_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_workflows_v1_workflows_proto_msgTypes = make([]protoimpl.MessageInfo, 21) var file_workflows_v1_workflows_proto_goTypes = []any{ - (*CreateClusterRequest)(nil), // 0: workflows.v1.CreateClusterRequest - (*GetClusterRequest)(nil), // 1: workflows.v1.GetClusterRequest - (*DeleteClusterRequest)(nil), // 2: workflows.v1.DeleteClusterRequest - (*DeleteClusterResponse)(nil), // 3: workflows.v1.DeleteClusterResponse - (*ListClustersRequest)(nil), // 4: workflows.v1.ListClustersRequest - (*ListClustersResponse)(nil), // 5: workflows.v1.ListClustersResponse - (*Cluster)(nil), // 6: workflows.v1.Cluster + (*Cluster)(nil), // 0: workflows.v1.Cluster + (*CreateClusterRequest)(nil), // 1: workflows.v1.CreateClusterRequest + (*GetClusterRequest)(nil), // 2: workflows.v1.GetClusterRequest + (*DeleteClusterRequest)(nil), // 3: workflows.v1.DeleteClusterRequest + (*DeleteClusterResponse)(nil), // 4: workflows.v1.DeleteClusterResponse + (*ListClustersRequest)(nil), // 5: workflows.v1.ListClustersRequest + (*ListClustersResponse)(nil), // 6: workflows.v1.ListClustersResponse + (*GetWorkflowRequest)(nil), // 7: workflows.v1.GetWorkflowRequest + (*PublishWorkflowReleaseRequest)(nil), // 8: workflows.v1.PublishWorkflowReleaseRequest + (*ListWorkflowsRequest)(nil), // 9: workflows.v1.ListWorkflowsRequest + (*ListWorkflowsResponse)(nil), // 10: workflows.v1.ListWorkflowsResponse + (*CreateWorkflowRequest)(nil), // 11: workflows.v1.CreateWorkflowRequest + (*Workflow)(nil), // 12: workflows.v1.Workflow + (*WorkflowRelease)(nil), // 13: workflows.v1.WorkflowRelease + (*Artifact)(nil), // 14: workflows.v1.Artifact + (*ReleaseContent)(nil), // 15: workflows.v1.ReleaseContent + (*Path)(nil), // 16: workflows.v1.Path + (*DeployWorkflowReleaseRequest)(nil), // 17: workflows.v1.DeployWorkflowReleaseRequest + (*DeployWorkflowReleaseResponse)(nil), // 18: workflows.v1.DeployWorkflowReleaseResponse + (*UndeployWorkflowReleaseRequest)(nil), // 19: workflows.v1.UndeployWorkflowReleaseRequest + (*UndeployWorkflowReleaseResponse)(nil), // 20: workflows.v1.UndeployWorkflowReleaseResponse + (*v1.ID)(nil), // 21: tilebox.v1.ID + (*timestamppb.Timestamp)(nil), // 22: google.protobuf.Timestamp + (*TaskIdentifier)(nil), // 23: workflows.v1.TaskIdentifier } var file_workflows_v1_workflows_proto_depIdxs = []int32{ - 6, // 0: workflows.v1.ListClustersResponse.clusters:type_name -> workflows.v1.Cluster - 0, // 1: workflows.v1.WorkflowsService.CreateCluster:input_type -> workflows.v1.CreateClusterRequest - 1, // 2: workflows.v1.WorkflowsService.GetCluster:input_type -> workflows.v1.GetClusterRequest - 2, // 3: workflows.v1.WorkflowsService.DeleteCluster:input_type -> workflows.v1.DeleteClusterRequest - 4, // 4: workflows.v1.WorkflowsService.ListClusters:input_type -> workflows.v1.ListClustersRequest - 6, // 5: workflows.v1.WorkflowsService.CreateCluster:output_type -> workflows.v1.Cluster - 6, // 6: workflows.v1.WorkflowsService.GetCluster:output_type -> workflows.v1.Cluster - 3, // 7: workflows.v1.WorkflowsService.DeleteCluster:output_type -> workflows.v1.DeleteClusterResponse - 5, // 8: workflows.v1.WorkflowsService.ListClusters:output_type -> workflows.v1.ListClustersResponse - 5, // [5:9] is the sub-list for method output_type - 1, // [1:5] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name + 12, // 0: workflows.v1.Cluster.deployed_releases:type_name -> workflows.v1.Workflow + 0, // 1: workflows.v1.ListClustersResponse.clusters:type_name -> workflows.v1.Cluster + 21, // 2: workflows.v1.PublishWorkflowReleaseRequest.artifact_id:type_name -> tilebox.v1.ID + 15, // 3: workflows.v1.PublishWorkflowReleaseRequest.content:type_name -> workflows.v1.ReleaseContent + 12, // 4: workflows.v1.ListWorkflowsResponse.workflows:type_name -> workflows.v1.Workflow + 13, // 5: workflows.v1.Workflow.releases:type_name -> workflows.v1.WorkflowRelease + 21, // 6: workflows.v1.WorkflowRelease.id:type_name -> tilebox.v1.ID + 14, // 7: workflows.v1.WorkflowRelease.artifact:type_name -> workflows.v1.Artifact + 15, // 8: workflows.v1.WorkflowRelease.content:type_name -> workflows.v1.ReleaseContent + 22, // 9: workflows.v1.WorkflowRelease.created_at:type_name -> google.protobuf.Timestamp + 21, // 10: workflows.v1.Artifact.id:type_name -> tilebox.v1.ID + 23, // 11: workflows.v1.ReleaseContent.tasks:type_name -> workflows.v1.TaskIdentifier + 16, // 12: workflows.v1.ReleaseContent.files:type_name -> workflows.v1.Path + 16, // 13: workflows.v1.Path.children:type_name -> workflows.v1.Path + 21, // 14: workflows.v1.DeployWorkflowReleaseRequest.release_id:type_name -> tilebox.v1.ID + 13, // 15: workflows.v1.DeployWorkflowReleaseResponse.release:type_name -> workflows.v1.WorkflowRelease + 0, // 16: workflows.v1.DeployWorkflowReleaseResponse.clusters:type_name -> workflows.v1.Cluster + 21, // 17: workflows.v1.UndeployWorkflowReleaseRequest.release_id:type_name -> tilebox.v1.ID + 13, // 18: workflows.v1.UndeployWorkflowReleaseResponse.release:type_name -> workflows.v1.WorkflowRelease + 0, // 19: workflows.v1.UndeployWorkflowReleaseResponse.clusters:type_name -> workflows.v1.Cluster + 1, // 20: workflows.v1.WorkflowsService.CreateCluster:input_type -> workflows.v1.CreateClusterRequest + 2, // 21: workflows.v1.WorkflowsService.GetCluster:input_type -> workflows.v1.GetClusterRequest + 3, // 22: workflows.v1.WorkflowsService.DeleteCluster:input_type -> workflows.v1.DeleteClusterRequest + 5, // 23: workflows.v1.WorkflowsService.ListClusters:input_type -> workflows.v1.ListClustersRequest + 11, // 24: workflows.v1.WorkflowsService.CreateWorkflow:input_type -> workflows.v1.CreateWorkflowRequest + 9, // 25: workflows.v1.WorkflowsService.ListWorkflows:input_type -> workflows.v1.ListWorkflowsRequest + 7, // 26: workflows.v1.WorkflowsService.GetWorkflow:input_type -> workflows.v1.GetWorkflowRequest + 8, // 27: workflows.v1.WorkflowsService.PublishWorkflowRelease:input_type -> workflows.v1.PublishWorkflowReleaseRequest + 17, // 28: workflows.v1.WorkflowsService.DeployWorkflowRelease:input_type -> workflows.v1.DeployWorkflowReleaseRequest + 19, // 29: workflows.v1.WorkflowsService.UndeployWorkflowRelease:input_type -> workflows.v1.UndeployWorkflowReleaseRequest + 0, // 30: workflows.v1.WorkflowsService.CreateCluster:output_type -> workflows.v1.Cluster + 0, // 31: workflows.v1.WorkflowsService.GetCluster:output_type -> workflows.v1.Cluster + 4, // 32: workflows.v1.WorkflowsService.DeleteCluster:output_type -> workflows.v1.DeleteClusterResponse + 6, // 33: workflows.v1.WorkflowsService.ListClusters:output_type -> workflows.v1.ListClustersResponse + 12, // 34: workflows.v1.WorkflowsService.CreateWorkflow:output_type -> workflows.v1.Workflow + 10, // 35: workflows.v1.WorkflowsService.ListWorkflows:output_type -> workflows.v1.ListWorkflowsResponse + 12, // 36: workflows.v1.WorkflowsService.GetWorkflow:output_type -> workflows.v1.Workflow + 13, // 37: workflows.v1.WorkflowsService.PublishWorkflowRelease:output_type -> workflows.v1.WorkflowRelease + 18, // 38: workflows.v1.WorkflowsService.DeployWorkflowRelease:output_type -> workflows.v1.DeployWorkflowReleaseResponse + 20, // 39: workflows.v1.WorkflowsService.UndeployWorkflowRelease:output_type -> workflows.v1.UndeployWorkflowReleaseResponse + 30, // [30:40] is the sub-list for method output_type + 20, // [20:30] is the sub-list for method input_type + 20, // [20:20] is the sub-list for extension type_name + 20, // [20:20] is the sub-list for extension extendee + 0, // [0:20] is the sub-list for field type_name } func init() { file_workflows_v1_workflows_proto_init() } @@ -411,7 +1892,7 @@ func file_workflows_v1_workflows_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_workflows_v1_workflows_proto_rawDesc), len(file_workflows_v1_workflows_proto_rawDesc)), NumEnums: 0, - NumMessages: 6, + NumMessages: 21, NumExtensions: 0, NumServices: 1, }, diff --git a/protogen/workflows/v1/workflows_grpc.pb.go b/protogen/workflows/v1/workflows_grpc.pb.go index ba7720e..23bd0ae 100644 --- a/protogen/workflows/v1/workflows_grpc.pb.go +++ b/protogen/workflows/v1/workflows_grpc.pb.go @@ -21,10 +21,16 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - WorkflowsService_CreateCluster_FullMethodName = "/workflows.v1.WorkflowsService/CreateCluster" - WorkflowsService_GetCluster_FullMethodName = "/workflows.v1.WorkflowsService/GetCluster" - WorkflowsService_DeleteCluster_FullMethodName = "/workflows.v1.WorkflowsService/DeleteCluster" - WorkflowsService_ListClusters_FullMethodName = "/workflows.v1.WorkflowsService/ListClusters" + WorkflowsService_CreateCluster_FullMethodName = "/workflows.v1.WorkflowsService/CreateCluster" + WorkflowsService_GetCluster_FullMethodName = "/workflows.v1.WorkflowsService/GetCluster" + WorkflowsService_DeleteCluster_FullMethodName = "/workflows.v1.WorkflowsService/DeleteCluster" + WorkflowsService_ListClusters_FullMethodName = "/workflows.v1.WorkflowsService/ListClusters" + WorkflowsService_CreateWorkflow_FullMethodName = "/workflows.v1.WorkflowsService/CreateWorkflow" + WorkflowsService_ListWorkflows_FullMethodName = "/workflows.v1.WorkflowsService/ListWorkflows" + WorkflowsService_GetWorkflow_FullMethodName = "/workflows.v1.WorkflowsService/GetWorkflow" + WorkflowsService_PublishWorkflowRelease_FullMethodName = "/workflows.v1.WorkflowsService/PublishWorkflowRelease" + WorkflowsService_DeployWorkflowRelease_FullMethodName = "/workflows.v1.WorkflowsService/DeployWorkflowRelease" + WorkflowsService_UndeployWorkflowRelease_FullMethodName = "/workflows.v1.WorkflowsService/UndeployWorkflowRelease" ) // WorkflowsServiceClient is the client API for WorkflowsService service. @@ -37,6 +43,12 @@ type WorkflowsServiceClient interface { GetCluster(ctx context.Context, in *GetClusterRequest, opts ...grpc.CallOption) (*Cluster, error) DeleteCluster(ctx context.Context, in *DeleteClusterRequest, opts ...grpc.CallOption) (*DeleteClusterResponse, error) ListClusters(ctx context.Context, in *ListClustersRequest, opts ...grpc.CallOption) (*ListClustersResponse, error) + CreateWorkflow(ctx context.Context, in *CreateWorkflowRequest, opts ...grpc.CallOption) (*Workflow, error) + ListWorkflows(ctx context.Context, in *ListWorkflowsRequest, opts ...grpc.CallOption) (*ListWorkflowsResponse, error) + GetWorkflow(ctx context.Context, in *GetWorkflowRequest, opts ...grpc.CallOption) (*Workflow, error) + PublishWorkflowRelease(ctx context.Context, in *PublishWorkflowReleaseRequest, opts ...grpc.CallOption) (*WorkflowRelease, error) + DeployWorkflowRelease(ctx context.Context, in *DeployWorkflowReleaseRequest, opts ...grpc.CallOption) (*DeployWorkflowReleaseResponse, error) + UndeployWorkflowRelease(ctx context.Context, in *UndeployWorkflowReleaseRequest, opts ...grpc.CallOption) (*UndeployWorkflowReleaseResponse, error) } type workflowsServiceClient struct { @@ -87,6 +99,66 @@ func (c *workflowsServiceClient) ListClusters(ctx context.Context, in *ListClust return out, nil } +func (c *workflowsServiceClient) CreateWorkflow(ctx context.Context, in *CreateWorkflowRequest, opts ...grpc.CallOption) (*Workflow, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Workflow) + err := c.cc.Invoke(ctx, WorkflowsService_CreateWorkflow_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *workflowsServiceClient) ListWorkflows(ctx context.Context, in *ListWorkflowsRequest, opts ...grpc.CallOption) (*ListWorkflowsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListWorkflowsResponse) + err := c.cc.Invoke(ctx, WorkflowsService_ListWorkflows_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *workflowsServiceClient) GetWorkflow(ctx context.Context, in *GetWorkflowRequest, opts ...grpc.CallOption) (*Workflow, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Workflow) + err := c.cc.Invoke(ctx, WorkflowsService_GetWorkflow_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *workflowsServiceClient) PublishWorkflowRelease(ctx context.Context, in *PublishWorkflowReleaseRequest, opts ...grpc.CallOption) (*WorkflowRelease, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(WorkflowRelease) + err := c.cc.Invoke(ctx, WorkflowsService_PublishWorkflowRelease_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *workflowsServiceClient) DeployWorkflowRelease(ctx context.Context, in *DeployWorkflowReleaseRequest, opts ...grpc.CallOption) (*DeployWorkflowReleaseResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DeployWorkflowReleaseResponse) + err := c.cc.Invoke(ctx, WorkflowsService_DeployWorkflowRelease_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *workflowsServiceClient) UndeployWorkflowRelease(ctx context.Context, in *UndeployWorkflowReleaseRequest, opts ...grpc.CallOption) (*UndeployWorkflowReleaseResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UndeployWorkflowReleaseResponse) + err := c.cc.Invoke(ctx, WorkflowsService_UndeployWorkflowRelease_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // WorkflowsServiceServer is the server API for WorkflowsService service. // All implementations must embed UnimplementedWorkflowsServiceServer // for forward compatibility. @@ -97,6 +169,12 @@ type WorkflowsServiceServer interface { GetCluster(context.Context, *GetClusterRequest) (*Cluster, error) DeleteCluster(context.Context, *DeleteClusterRequest) (*DeleteClusterResponse, error) ListClusters(context.Context, *ListClustersRequest) (*ListClustersResponse, error) + CreateWorkflow(context.Context, *CreateWorkflowRequest) (*Workflow, error) + ListWorkflows(context.Context, *ListWorkflowsRequest) (*ListWorkflowsResponse, error) + GetWorkflow(context.Context, *GetWorkflowRequest) (*Workflow, error) + PublishWorkflowRelease(context.Context, *PublishWorkflowReleaseRequest) (*WorkflowRelease, error) + DeployWorkflowRelease(context.Context, *DeployWorkflowReleaseRequest) (*DeployWorkflowReleaseResponse, error) + UndeployWorkflowRelease(context.Context, *UndeployWorkflowReleaseRequest) (*UndeployWorkflowReleaseResponse, error) mustEmbedUnimplementedWorkflowsServiceServer() } @@ -119,6 +197,24 @@ func (UnimplementedWorkflowsServiceServer) DeleteCluster(context.Context, *Delet func (UnimplementedWorkflowsServiceServer) ListClusters(context.Context, *ListClustersRequest) (*ListClustersResponse, error) { return nil, status.Error(codes.Unimplemented, "method ListClusters not implemented") } +func (UnimplementedWorkflowsServiceServer) CreateWorkflow(context.Context, *CreateWorkflowRequest) (*Workflow, error) { + return nil, status.Error(codes.Unimplemented, "method CreateWorkflow not implemented") +} +func (UnimplementedWorkflowsServiceServer) ListWorkflows(context.Context, *ListWorkflowsRequest) (*ListWorkflowsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListWorkflows not implemented") +} +func (UnimplementedWorkflowsServiceServer) GetWorkflow(context.Context, *GetWorkflowRequest) (*Workflow, error) { + return nil, status.Error(codes.Unimplemented, "method GetWorkflow not implemented") +} +func (UnimplementedWorkflowsServiceServer) PublishWorkflowRelease(context.Context, *PublishWorkflowReleaseRequest) (*WorkflowRelease, error) { + return nil, status.Error(codes.Unimplemented, "method PublishWorkflowRelease not implemented") +} +func (UnimplementedWorkflowsServiceServer) DeployWorkflowRelease(context.Context, *DeployWorkflowReleaseRequest) (*DeployWorkflowReleaseResponse, error) { + return nil, status.Error(codes.Unimplemented, "method DeployWorkflowRelease not implemented") +} +func (UnimplementedWorkflowsServiceServer) UndeployWorkflowRelease(context.Context, *UndeployWorkflowReleaseRequest) (*UndeployWorkflowReleaseResponse, error) { + return nil, status.Error(codes.Unimplemented, "method UndeployWorkflowRelease not implemented") +} func (UnimplementedWorkflowsServiceServer) mustEmbedUnimplementedWorkflowsServiceServer() {} func (UnimplementedWorkflowsServiceServer) testEmbeddedByValue() {} @@ -212,6 +308,114 @@ func _WorkflowsService_ListClusters_Handler(srv interface{}, ctx context.Context return interceptor(ctx, in, info, handler) } +func _WorkflowsService_CreateWorkflow_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateWorkflowRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WorkflowsServiceServer).CreateWorkflow(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WorkflowsService_CreateWorkflow_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WorkflowsServiceServer).CreateWorkflow(ctx, req.(*CreateWorkflowRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WorkflowsService_ListWorkflows_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListWorkflowsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WorkflowsServiceServer).ListWorkflows(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WorkflowsService_ListWorkflows_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WorkflowsServiceServer).ListWorkflows(ctx, req.(*ListWorkflowsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WorkflowsService_GetWorkflow_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetWorkflowRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WorkflowsServiceServer).GetWorkflow(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WorkflowsService_GetWorkflow_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WorkflowsServiceServer).GetWorkflow(ctx, req.(*GetWorkflowRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WorkflowsService_PublishWorkflowRelease_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PublishWorkflowReleaseRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WorkflowsServiceServer).PublishWorkflowRelease(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WorkflowsService_PublishWorkflowRelease_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WorkflowsServiceServer).PublishWorkflowRelease(ctx, req.(*PublishWorkflowReleaseRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WorkflowsService_DeployWorkflowRelease_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeployWorkflowReleaseRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WorkflowsServiceServer).DeployWorkflowRelease(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WorkflowsService_DeployWorkflowRelease_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WorkflowsServiceServer).DeployWorkflowRelease(ctx, req.(*DeployWorkflowReleaseRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WorkflowsService_UndeployWorkflowRelease_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UndeployWorkflowReleaseRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WorkflowsServiceServer).UndeployWorkflowRelease(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WorkflowsService_UndeployWorkflowRelease_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WorkflowsServiceServer).UndeployWorkflowRelease(ctx, req.(*UndeployWorkflowReleaseRequest)) + } + return interceptor(ctx, in, info, handler) +} + // WorkflowsService_ServiceDesc is the grpc.ServiceDesc for WorkflowsService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -235,6 +439,30 @@ var WorkflowsService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListClusters", Handler: _WorkflowsService_ListClusters_Handler, }, + { + MethodName: "CreateWorkflow", + Handler: _WorkflowsService_CreateWorkflow_Handler, + }, + { + MethodName: "ListWorkflows", + Handler: _WorkflowsService_ListWorkflows_Handler, + }, + { + MethodName: "GetWorkflow", + Handler: _WorkflowsService_GetWorkflow_Handler, + }, + { + MethodName: "PublishWorkflowRelease", + Handler: _WorkflowsService_PublishWorkflowRelease_Handler, + }, + { + MethodName: "DeployWorkflowRelease", + Handler: _WorkflowsService_DeployWorkflowRelease_Handler, + }, + { + MethodName: "UndeployWorkflowRelease", + Handler: _WorkflowsService_UndeployWorkflowRelease_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "workflows/v1/workflows.proto", diff --git a/protogen/workflows/v1/workflowsv1connect/task_release.connect.go b/protogen/workflows/v1/workflowsv1connect/task_release.connect.go deleted file mode 100644 index 072ddff..0000000 --- a/protogen/workflows/v1/workflowsv1connect/task_release.connect.go +++ /dev/null @@ -1,169 +0,0 @@ -// The externally facing API allowing users to publish and deploy workflow task releases. - -// Code generated by protoc-gen-connect-go. DO NOT EDIT. -// -// Source: workflows/v1/task_release.proto - -package workflowsv1connect - -import ( - connect "connectrpc.com/connect" - context "context" - errors "errors" - v1 "github.com/tilebox/tilebox-go/protogen/workflows/v1" - http "net/http" - strings "strings" -) - -// This is a compile-time assertion to ensure that this generated file and the connect package are -// compatible. If you get a compiler error that this constant is not defined, this code was -// generated with a version of connect newer than the one compiled into your binary. You can fix the -// problem by either regenerating this code with an older version of connect or updating the connect -// version compiled into your binary. -const _ = connect.IsAtLeastVersion1_13_0 - -const ( - // TaskReleaseServiceName is the fully-qualified name of the TaskReleaseService service. - TaskReleaseServiceName = "workflows.v1.TaskReleaseService" -) - -// These constants are the fully-qualified names of the RPCs defined in this package. They're -// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. -// -// Note that these are different from the fully-qualified method names used by -// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to -// reflection-formatted method names, remove the leading slash and convert the remaining slash to a -// period. -const ( - // TaskReleaseServicePublishReleaseProcedure is the fully-qualified name of the TaskReleaseService's - // PublishRelease RPC. - TaskReleaseServicePublishReleaseProcedure = "/workflows.v1.TaskReleaseService/PublishRelease" - // TaskReleaseServiceDeployReleaseProcedure is the fully-qualified name of the TaskReleaseService's - // DeployRelease RPC. - TaskReleaseServiceDeployReleaseProcedure = "/workflows.v1.TaskReleaseService/DeployRelease" - // TaskReleaseServiceGetClusterDeploymentManifestProcedure is the fully-qualified name of the - // TaskReleaseService's GetClusterDeploymentManifest RPC. - TaskReleaseServiceGetClusterDeploymentManifestProcedure = "/workflows.v1.TaskReleaseService/GetClusterDeploymentManifest" -) - -// TaskReleaseServiceClient is a client for the workflows.v1.TaskReleaseService service. -type TaskReleaseServiceClient interface { - PublishRelease(context.Context, *connect.Request[v1.PublishReleaseRequest]) (*connect.Response[v1.PublishReleaseResponse], error) - DeployRelease(context.Context, *connect.Request[v1.DeployReleaseRequest]) (*connect.Response[v1.DeployReleaseResponse], error) - GetClusterDeploymentManifest(context.Context, *connect.Request[v1.GetClusterDeploymentManifestRequest]) (*connect.Response[v1.GetClusterDeploymentManifestResponse], error) -} - -// NewTaskReleaseServiceClient constructs a client for the workflows.v1.TaskReleaseService service. -// By default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped -// responses, and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the -// connect.WithGRPC() or connect.WithGRPCWeb() options. -// -// The URL supplied here should be the base URL for the Connect or gRPC server (for example, -// http://api.acme.com or https://acme.com/grpc). -func NewTaskReleaseServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) TaskReleaseServiceClient { - baseURL = strings.TrimRight(baseURL, "/") - taskReleaseServiceMethods := v1.File_workflows_v1_task_release_proto.Services().ByName("TaskReleaseService").Methods() - return &taskReleaseServiceClient{ - publishRelease: connect.NewClient[v1.PublishReleaseRequest, v1.PublishReleaseResponse]( - httpClient, - baseURL+TaskReleaseServicePublishReleaseProcedure, - connect.WithSchema(taskReleaseServiceMethods.ByName("PublishRelease")), - connect.WithClientOptions(opts...), - ), - deployRelease: connect.NewClient[v1.DeployReleaseRequest, v1.DeployReleaseResponse]( - httpClient, - baseURL+TaskReleaseServiceDeployReleaseProcedure, - connect.WithSchema(taskReleaseServiceMethods.ByName("DeployRelease")), - connect.WithClientOptions(opts...), - ), - getClusterDeploymentManifest: connect.NewClient[v1.GetClusterDeploymentManifestRequest, v1.GetClusterDeploymentManifestResponse]( - httpClient, - baseURL+TaskReleaseServiceGetClusterDeploymentManifestProcedure, - connect.WithSchema(taskReleaseServiceMethods.ByName("GetClusterDeploymentManifest")), - connect.WithClientOptions(opts...), - ), - } -} - -// taskReleaseServiceClient implements TaskReleaseServiceClient. -type taskReleaseServiceClient struct { - publishRelease *connect.Client[v1.PublishReleaseRequest, v1.PublishReleaseResponse] - deployRelease *connect.Client[v1.DeployReleaseRequest, v1.DeployReleaseResponse] - getClusterDeploymentManifest *connect.Client[v1.GetClusterDeploymentManifestRequest, v1.GetClusterDeploymentManifestResponse] -} - -// PublishRelease calls workflows.v1.TaskReleaseService.PublishRelease. -func (c *taskReleaseServiceClient) PublishRelease(ctx context.Context, req *connect.Request[v1.PublishReleaseRequest]) (*connect.Response[v1.PublishReleaseResponse], error) { - return c.publishRelease.CallUnary(ctx, req) -} - -// DeployRelease calls workflows.v1.TaskReleaseService.DeployRelease. -func (c *taskReleaseServiceClient) DeployRelease(ctx context.Context, req *connect.Request[v1.DeployReleaseRequest]) (*connect.Response[v1.DeployReleaseResponse], error) { - return c.deployRelease.CallUnary(ctx, req) -} - -// GetClusterDeploymentManifest calls workflows.v1.TaskReleaseService.GetClusterDeploymentManifest. -func (c *taskReleaseServiceClient) GetClusterDeploymentManifest(ctx context.Context, req *connect.Request[v1.GetClusterDeploymentManifestRequest]) (*connect.Response[v1.GetClusterDeploymentManifestResponse], error) { - return c.getClusterDeploymentManifest.CallUnary(ctx, req) -} - -// TaskReleaseServiceHandler is an implementation of the workflows.v1.TaskReleaseService service. -type TaskReleaseServiceHandler interface { - PublishRelease(context.Context, *connect.Request[v1.PublishReleaseRequest]) (*connect.Response[v1.PublishReleaseResponse], error) - DeployRelease(context.Context, *connect.Request[v1.DeployReleaseRequest]) (*connect.Response[v1.DeployReleaseResponse], error) - GetClusterDeploymentManifest(context.Context, *connect.Request[v1.GetClusterDeploymentManifestRequest]) (*connect.Response[v1.GetClusterDeploymentManifestResponse], error) -} - -// NewTaskReleaseServiceHandler builds an HTTP handler from the service implementation. It returns -// the path on which to mount the handler and the handler itself. -// -// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf -// and JSON codecs. They also support gzip compression. -func NewTaskReleaseServiceHandler(svc TaskReleaseServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { - taskReleaseServiceMethods := v1.File_workflows_v1_task_release_proto.Services().ByName("TaskReleaseService").Methods() - taskReleaseServicePublishReleaseHandler := connect.NewUnaryHandler( - TaskReleaseServicePublishReleaseProcedure, - svc.PublishRelease, - connect.WithSchema(taskReleaseServiceMethods.ByName("PublishRelease")), - connect.WithHandlerOptions(opts...), - ) - taskReleaseServiceDeployReleaseHandler := connect.NewUnaryHandler( - TaskReleaseServiceDeployReleaseProcedure, - svc.DeployRelease, - connect.WithSchema(taskReleaseServiceMethods.ByName("DeployRelease")), - connect.WithHandlerOptions(opts...), - ) - taskReleaseServiceGetClusterDeploymentManifestHandler := connect.NewUnaryHandler( - TaskReleaseServiceGetClusterDeploymentManifestProcedure, - svc.GetClusterDeploymentManifest, - connect.WithSchema(taskReleaseServiceMethods.ByName("GetClusterDeploymentManifest")), - connect.WithHandlerOptions(opts...), - ) - return "/workflows.v1.TaskReleaseService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - switch r.URL.Path { - case TaskReleaseServicePublishReleaseProcedure: - taskReleaseServicePublishReleaseHandler.ServeHTTP(w, r) - case TaskReleaseServiceDeployReleaseProcedure: - taskReleaseServiceDeployReleaseHandler.ServeHTTP(w, r) - case TaskReleaseServiceGetClusterDeploymentManifestProcedure: - taskReleaseServiceGetClusterDeploymentManifestHandler.ServeHTTP(w, r) - default: - http.NotFound(w, r) - } - }) -} - -// UnimplementedTaskReleaseServiceHandler returns CodeUnimplemented from all methods. -type UnimplementedTaskReleaseServiceHandler struct{} - -func (UnimplementedTaskReleaseServiceHandler) PublishRelease(context.Context, *connect.Request[v1.PublishReleaseRequest]) (*connect.Response[v1.PublishReleaseResponse], error) { - return nil, connect.NewError(connect.CodeUnimplemented, errors.New("workflows.v1.TaskReleaseService.PublishRelease is not implemented")) -} - -func (UnimplementedTaskReleaseServiceHandler) DeployRelease(context.Context, *connect.Request[v1.DeployReleaseRequest]) (*connect.Response[v1.DeployReleaseResponse], error) { - return nil, connect.NewError(connect.CodeUnimplemented, errors.New("workflows.v1.TaskReleaseService.DeployRelease is not implemented")) -} - -func (UnimplementedTaskReleaseServiceHandler) GetClusterDeploymentManifest(context.Context, *connect.Request[v1.GetClusterDeploymentManifestRequest]) (*connect.Response[v1.GetClusterDeploymentManifestResponse], error) { - return nil, connect.NewError(connect.CodeUnimplemented, errors.New("workflows.v1.TaskReleaseService.GetClusterDeploymentManifest is not implemented")) -} diff --git a/protogen/workflows/v1/workflowsv1connect/worker.connect.go b/protogen/workflows/v1/workflowsv1connect/worker.connect.go new file mode 100644 index 0000000..36f491b --- /dev/null +++ b/protogen/workflows/v1/workflowsv1connect/worker.connect.go @@ -0,0 +1,215 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: workflows/v1/worker.proto + +package workflowsv1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + v1 "github.com/tilebox/tilebox-go/protogen/workflows/v1" + emptypb "google.golang.org/protobuf/types/known/emptypb" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // WorkerServiceName is the fully-qualified name of the WorkerService service. + WorkerServiceName = "workflows.v1.WorkerService" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // WorkerServiceListRegisteredTasksProcedure is the fully-qualified name of the WorkerService's + // ListRegisteredTasks RPC. + WorkerServiceListRegisteredTasksProcedure = "/workflows.v1.WorkerService/ListRegisteredTasks" + // WorkerServiceInitializeWorkerProcedure is the fully-qualified name of the WorkerService's + // InitializeWorker RPC. + WorkerServiceInitializeWorkerProcedure = "/workflows.v1.WorkerService/InitializeWorker" + // WorkerServiceExecuteTaskProcedure is the fully-qualified name of the WorkerService's ExecuteTask + // RPC. + WorkerServiceExecuteTaskProcedure = "/workflows.v1.WorkerService/ExecuteTask" + // WorkerServiceShutdownWorkerProcedure is the fully-qualified name of the WorkerService's + // ShutdownWorker RPC. + WorkerServiceShutdownWorkerProcedure = "/workflows.v1.WorkerService/ShutdownWorker" +) + +// WorkerServiceClient is a client for the workflows.v1.WorkerService service. +type WorkerServiceClient interface { + // ListRegisteredTasks is called by the runner to discover the task identifiers that a worker runtime can execute. + ListRegisteredTasks(context.Context, *connect.Request[emptypb.Empty]) (*connect.Response[v1.TaskIdentifiers], error) + // InitializeWorker is called by the runner to initialize a worker runtime with some known metadata about the + // runner. This allows us to add those metadata to any logs and traces emitted by the worker. + InitializeWorker(context.Context, *connect.Request[v1.InitializeRunnerRequest]) (*connect.Response[v1.InitializeRunnerResponse], error) + // ExecuteTask is called by the runner to execute a task on the worker runtime. The worker runtime will execute the + // task, and then respond with the result of the task execution, which can either be a computed task, or a failed + // task. If the worker runtime crashes or becomes unreachable during task execution, the runner will treat the task + // as failed with an unknown error. + ExecuteTask(context.Context, *connect.Request[v1.Task]) (*connect.Response[v1.ExecuteTaskResponse], error) + // Gracefully shuts down the worker runtime. After receiving this request, the worker runtime will + // cleanly shut down. + ShutdownWorker(context.Context, *connect.Request[emptypb.Empty]) (*connect.Response[emptypb.Empty], error) +} + +// NewWorkerServiceClient constructs a client for the workflows.v1.WorkerService service. By +// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, +// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the +// connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewWorkerServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) WorkerServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + workerServiceMethods := v1.File_workflows_v1_worker_proto.Services().ByName("WorkerService").Methods() + return &workerServiceClient{ + listRegisteredTasks: connect.NewClient[emptypb.Empty, v1.TaskIdentifiers]( + httpClient, + baseURL+WorkerServiceListRegisteredTasksProcedure, + connect.WithSchema(workerServiceMethods.ByName("ListRegisteredTasks")), + connect.WithClientOptions(opts...), + ), + initializeWorker: connect.NewClient[v1.InitializeRunnerRequest, v1.InitializeRunnerResponse]( + httpClient, + baseURL+WorkerServiceInitializeWorkerProcedure, + connect.WithSchema(workerServiceMethods.ByName("InitializeWorker")), + connect.WithClientOptions(opts...), + ), + executeTask: connect.NewClient[v1.Task, v1.ExecuteTaskResponse]( + httpClient, + baseURL+WorkerServiceExecuteTaskProcedure, + connect.WithSchema(workerServiceMethods.ByName("ExecuteTask")), + connect.WithClientOptions(opts...), + ), + shutdownWorker: connect.NewClient[emptypb.Empty, emptypb.Empty]( + httpClient, + baseURL+WorkerServiceShutdownWorkerProcedure, + connect.WithSchema(workerServiceMethods.ByName("ShutdownWorker")), + connect.WithClientOptions(opts...), + ), + } +} + +// workerServiceClient implements WorkerServiceClient. +type workerServiceClient struct { + listRegisteredTasks *connect.Client[emptypb.Empty, v1.TaskIdentifiers] + initializeWorker *connect.Client[v1.InitializeRunnerRequest, v1.InitializeRunnerResponse] + executeTask *connect.Client[v1.Task, v1.ExecuteTaskResponse] + shutdownWorker *connect.Client[emptypb.Empty, emptypb.Empty] +} + +// ListRegisteredTasks calls workflows.v1.WorkerService.ListRegisteredTasks. +func (c *workerServiceClient) ListRegisteredTasks(ctx context.Context, req *connect.Request[emptypb.Empty]) (*connect.Response[v1.TaskIdentifiers], error) { + return c.listRegisteredTasks.CallUnary(ctx, req) +} + +// InitializeWorker calls workflows.v1.WorkerService.InitializeWorker. +func (c *workerServiceClient) InitializeWorker(ctx context.Context, req *connect.Request[v1.InitializeRunnerRequest]) (*connect.Response[v1.InitializeRunnerResponse], error) { + return c.initializeWorker.CallUnary(ctx, req) +} + +// ExecuteTask calls workflows.v1.WorkerService.ExecuteTask. +func (c *workerServiceClient) ExecuteTask(ctx context.Context, req *connect.Request[v1.Task]) (*connect.Response[v1.ExecuteTaskResponse], error) { + return c.executeTask.CallUnary(ctx, req) +} + +// ShutdownWorker calls workflows.v1.WorkerService.ShutdownWorker. +func (c *workerServiceClient) ShutdownWorker(ctx context.Context, req *connect.Request[emptypb.Empty]) (*connect.Response[emptypb.Empty], error) { + return c.shutdownWorker.CallUnary(ctx, req) +} + +// WorkerServiceHandler is an implementation of the workflows.v1.WorkerService service. +type WorkerServiceHandler interface { + // ListRegisteredTasks is called by the runner to discover the task identifiers that a worker runtime can execute. + ListRegisteredTasks(context.Context, *connect.Request[emptypb.Empty]) (*connect.Response[v1.TaskIdentifiers], error) + // InitializeWorker is called by the runner to initialize a worker runtime with some known metadata about the + // runner. This allows us to add those metadata to any logs and traces emitted by the worker. + InitializeWorker(context.Context, *connect.Request[v1.InitializeRunnerRequest]) (*connect.Response[v1.InitializeRunnerResponse], error) + // ExecuteTask is called by the runner to execute a task on the worker runtime. The worker runtime will execute the + // task, and then respond with the result of the task execution, which can either be a computed task, or a failed + // task. If the worker runtime crashes or becomes unreachable during task execution, the runner will treat the task + // as failed with an unknown error. + ExecuteTask(context.Context, *connect.Request[v1.Task]) (*connect.Response[v1.ExecuteTaskResponse], error) + // Gracefully shuts down the worker runtime. After receiving this request, the worker runtime will + // cleanly shut down. + ShutdownWorker(context.Context, *connect.Request[emptypb.Empty]) (*connect.Response[emptypb.Empty], error) +} + +// NewWorkerServiceHandler builds an HTTP handler from the service implementation. It returns the +// path on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewWorkerServiceHandler(svc WorkerServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + workerServiceMethods := v1.File_workflows_v1_worker_proto.Services().ByName("WorkerService").Methods() + workerServiceListRegisteredTasksHandler := connect.NewUnaryHandler( + WorkerServiceListRegisteredTasksProcedure, + svc.ListRegisteredTasks, + connect.WithSchema(workerServiceMethods.ByName("ListRegisteredTasks")), + connect.WithHandlerOptions(opts...), + ) + workerServiceInitializeWorkerHandler := connect.NewUnaryHandler( + WorkerServiceInitializeWorkerProcedure, + svc.InitializeWorker, + connect.WithSchema(workerServiceMethods.ByName("InitializeWorker")), + connect.WithHandlerOptions(opts...), + ) + workerServiceExecuteTaskHandler := connect.NewUnaryHandler( + WorkerServiceExecuteTaskProcedure, + svc.ExecuteTask, + connect.WithSchema(workerServiceMethods.ByName("ExecuteTask")), + connect.WithHandlerOptions(opts...), + ) + workerServiceShutdownWorkerHandler := connect.NewUnaryHandler( + WorkerServiceShutdownWorkerProcedure, + svc.ShutdownWorker, + connect.WithSchema(workerServiceMethods.ByName("ShutdownWorker")), + connect.WithHandlerOptions(opts...), + ) + return "/workflows.v1.WorkerService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case WorkerServiceListRegisteredTasksProcedure: + workerServiceListRegisteredTasksHandler.ServeHTTP(w, r) + case WorkerServiceInitializeWorkerProcedure: + workerServiceInitializeWorkerHandler.ServeHTTP(w, r) + case WorkerServiceExecuteTaskProcedure: + workerServiceExecuteTaskHandler.ServeHTTP(w, r) + case WorkerServiceShutdownWorkerProcedure: + workerServiceShutdownWorkerHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedWorkerServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedWorkerServiceHandler struct{} + +func (UnimplementedWorkerServiceHandler) ListRegisteredTasks(context.Context, *connect.Request[emptypb.Empty]) (*connect.Response[v1.TaskIdentifiers], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("workflows.v1.WorkerService.ListRegisteredTasks is not implemented")) +} + +func (UnimplementedWorkerServiceHandler) InitializeWorker(context.Context, *connect.Request[v1.InitializeRunnerRequest]) (*connect.Response[v1.InitializeRunnerResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("workflows.v1.WorkerService.InitializeWorker is not implemented")) +} + +func (UnimplementedWorkerServiceHandler) ExecuteTask(context.Context, *connect.Request[v1.Task]) (*connect.Response[v1.ExecuteTaskResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("workflows.v1.WorkerService.ExecuteTask is not implemented")) +} + +func (UnimplementedWorkerServiceHandler) ShutdownWorker(context.Context, *connect.Request[emptypb.Empty]) (*connect.Response[emptypb.Empty], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("workflows.v1.WorkerService.ShutdownWorker is not implemented")) +} diff --git a/protogen/workflows/v1/workflowsv1connect/workflows.connect.go b/protogen/workflows/v1/workflowsv1connect/workflows.connect.go index 53687a8..045cbb3 100644 --- a/protogen/workflows/v1/workflowsv1connect/workflows.connect.go +++ b/protogen/workflows/v1/workflowsv1connect/workflows.connect.go @@ -47,6 +47,24 @@ const ( // WorkflowsServiceListClustersProcedure is the fully-qualified name of the WorkflowsService's // ListClusters RPC. WorkflowsServiceListClustersProcedure = "/workflows.v1.WorkflowsService/ListClusters" + // WorkflowsServiceCreateWorkflowProcedure is the fully-qualified name of the WorkflowsService's + // CreateWorkflow RPC. + WorkflowsServiceCreateWorkflowProcedure = "/workflows.v1.WorkflowsService/CreateWorkflow" + // WorkflowsServiceListWorkflowsProcedure is the fully-qualified name of the WorkflowsService's + // ListWorkflows RPC. + WorkflowsServiceListWorkflowsProcedure = "/workflows.v1.WorkflowsService/ListWorkflows" + // WorkflowsServiceGetWorkflowProcedure is the fully-qualified name of the WorkflowsService's + // GetWorkflow RPC. + WorkflowsServiceGetWorkflowProcedure = "/workflows.v1.WorkflowsService/GetWorkflow" + // WorkflowsServicePublishWorkflowReleaseProcedure is the fully-qualified name of the + // WorkflowsService's PublishWorkflowRelease RPC. + WorkflowsServicePublishWorkflowReleaseProcedure = "/workflows.v1.WorkflowsService/PublishWorkflowRelease" + // WorkflowsServiceDeployWorkflowReleaseProcedure is the fully-qualified name of the + // WorkflowsService's DeployWorkflowRelease RPC. + WorkflowsServiceDeployWorkflowReleaseProcedure = "/workflows.v1.WorkflowsService/DeployWorkflowRelease" + // WorkflowsServiceUndeployWorkflowReleaseProcedure is the fully-qualified name of the + // WorkflowsService's UndeployWorkflowRelease RPC. + WorkflowsServiceUndeployWorkflowReleaseProcedure = "/workflows.v1.WorkflowsService/UndeployWorkflowRelease" ) // WorkflowsServiceClient is a client for the workflows.v1.WorkflowsService service. @@ -55,6 +73,12 @@ type WorkflowsServiceClient interface { GetCluster(context.Context, *connect.Request[v1.GetClusterRequest]) (*connect.Response[v1.Cluster], error) DeleteCluster(context.Context, *connect.Request[v1.DeleteClusterRequest]) (*connect.Response[v1.DeleteClusterResponse], error) ListClusters(context.Context, *connect.Request[v1.ListClustersRequest]) (*connect.Response[v1.ListClustersResponse], error) + CreateWorkflow(context.Context, *connect.Request[v1.CreateWorkflowRequest]) (*connect.Response[v1.Workflow], error) + ListWorkflows(context.Context, *connect.Request[v1.ListWorkflowsRequest]) (*connect.Response[v1.ListWorkflowsResponse], error) + GetWorkflow(context.Context, *connect.Request[v1.GetWorkflowRequest]) (*connect.Response[v1.Workflow], error) + PublishWorkflowRelease(context.Context, *connect.Request[v1.PublishWorkflowReleaseRequest]) (*connect.Response[v1.WorkflowRelease], error) + DeployWorkflowRelease(context.Context, *connect.Request[v1.DeployWorkflowReleaseRequest]) (*connect.Response[v1.DeployWorkflowReleaseResponse], error) + UndeployWorkflowRelease(context.Context, *connect.Request[v1.UndeployWorkflowReleaseRequest]) (*connect.Response[v1.UndeployWorkflowReleaseResponse], error) } // NewWorkflowsServiceClient constructs a client for the workflows.v1.WorkflowsService service. By @@ -92,15 +116,57 @@ func NewWorkflowsServiceClient(httpClient connect.HTTPClient, baseURL string, op connect.WithSchema(workflowsServiceMethods.ByName("ListClusters")), connect.WithClientOptions(opts...), ), + createWorkflow: connect.NewClient[v1.CreateWorkflowRequest, v1.Workflow]( + httpClient, + baseURL+WorkflowsServiceCreateWorkflowProcedure, + connect.WithSchema(workflowsServiceMethods.ByName("CreateWorkflow")), + connect.WithClientOptions(opts...), + ), + listWorkflows: connect.NewClient[v1.ListWorkflowsRequest, v1.ListWorkflowsResponse]( + httpClient, + baseURL+WorkflowsServiceListWorkflowsProcedure, + connect.WithSchema(workflowsServiceMethods.ByName("ListWorkflows")), + connect.WithClientOptions(opts...), + ), + getWorkflow: connect.NewClient[v1.GetWorkflowRequest, v1.Workflow]( + httpClient, + baseURL+WorkflowsServiceGetWorkflowProcedure, + connect.WithSchema(workflowsServiceMethods.ByName("GetWorkflow")), + connect.WithClientOptions(opts...), + ), + publishWorkflowRelease: connect.NewClient[v1.PublishWorkflowReleaseRequest, v1.WorkflowRelease]( + httpClient, + baseURL+WorkflowsServicePublishWorkflowReleaseProcedure, + connect.WithSchema(workflowsServiceMethods.ByName("PublishWorkflowRelease")), + connect.WithClientOptions(opts...), + ), + deployWorkflowRelease: connect.NewClient[v1.DeployWorkflowReleaseRequest, v1.DeployWorkflowReleaseResponse]( + httpClient, + baseURL+WorkflowsServiceDeployWorkflowReleaseProcedure, + connect.WithSchema(workflowsServiceMethods.ByName("DeployWorkflowRelease")), + connect.WithClientOptions(opts...), + ), + undeployWorkflowRelease: connect.NewClient[v1.UndeployWorkflowReleaseRequest, v1.UndeployWorkflowReleaseResponse]( + httpClient, + baseURL+WorkflowsServiceUndeployWorkflowReleaseProcedure, + connect.WithSchema(workflowsServiceMethods.ByName("UndeployWorkflowRelease")), + connect.WithClientOptions(opts...), + ), } } // workflowsServiceClient implements WorkflowsServiceClient. type workflowsServiceClient struct { - createCluster *connect.Client[v1.CreateClusterRequest, v1.Cluster] - getCluster *connect.Client[v1.GetClusterRequest, v1.Cluster] - deleteCluster *connect.Client[v1.DeleteClusterRequest, v1.DeleteClusterResponse] - listClusters *connect.Client[v1.ListClustersRequest, v1.ListClustersResponse] + createCluster *connect.Client[v1.CreateClusterRequest, v1.Cluster] + getCluster *connect.Client[v1.GetClusterRequest, v1.Cluster] + deleteCluster *connect.Client[v1.DeleteClusterRequest, v1.DeleteClusterResponse] + listClusters *connect.Client[v1.ListClustersRequest, v1.ListClustersResponse] + createWorkflow *connect.Client[v1.CreateWorkflowRequest, v1.Workflow] + listWorkflows *connect.Client[v1.ListWorkflowsRequest, v1.ListWorkflowsResponse] + getWorkflow *connect.Client[v1.GetWorkflowRequest, v1.Workflow] + publishWorkflowRelease *connect.Client[v1.PublishWorkflowReleaseRequest, v1.WorkflowRelease] + deployWorkflowRelease *connect.Client[v1.DeployWorkflowReleaseRequest, v1.DeployWorkflowReleaseResponse] + undeployWorkflowRelease *connect.Client[v1.UndeployWorkflowReleaseRequest, v1.UndeployWorkflowReleaseResponse] } // CreateCluster calls workflows.v1.WorkflowsService.CreateCluster. @@ -123,12 +189,48 @@ func (c *workflowsServiceClient) ListClusters(ctx context.Context, req *connect. return c.listClusters.CallUnary(ctx, req) } +// CreateWorkflow calls workflows.v1.WorkflowsService.CreateWorkflow. +func (c *workflowsServiceClient) CreateWorkflow(ctx context.Context, req *connect.Request[v1.CreateWorkflowRequest]) (*connect.Response[v1.Workflow], error) { + return c.createWorkflow.CallUnary(ctx, req) +} + +// ListWorkflows calls workflows.v1.WorkflowsService.ListWorkflows. +func (c *workflowsServiceClient) ListWorkflows(ctx context.Context, req *connect.Request[v1.ListWorkflowsRequest]) (*connect.Response[v1.ListWorkflowsResponse], error) { + return c.listWorkflows.CallUnary(ctx, req) +} + +// GetWorkflow calls workflows.v1.WorkflowsService.GetWorkflow. +func (c *workflowsServiceClient) GetWorkflow(ctx context.Context, req *connect.Request[v1.GetWorkflowRequest]) (*connect.Response[v1.Workflow], error) { + return c.getWorkflow.CallUnary(ctx, req) +} + +// PublishWorkflowRelease calls workflows.v1.WorkflowsService.PublishWorkflowRelease. +func (c *workflowsServiceClient) PublishWorkflowRelease(ctx context.Context, req *connect.Request[v1.PublishWorkflowReleaseRequest]) (*connect.Response[v1.WorkflowRelease], error) { + return c.publishWorkflowRelease.CallUnary(ctx, req) +} + +// DeployWorkflowRelease calls workflows.v1.WorkflowsService.DeployWorkflowRelease. +func (c *workflowsServiceClient) DeployWorkflowRelease(ctx context.Context, req *connect.Request[v1.DeployWorkflowReleaseRequest]) (*connect.Response[v1.DeployWorkflowReleaseResponse], error) { + return c.deployWorkflowRelease.CallUnary(ctx, req) +} + +// UndeployWorkflowRelease calls workflows.v1.WorkflowsService.UndeployWorkflowRelease. +func (c *workflowsServiceClient) UndeployWorkflowRelease(ctx context.Context, req *connect.Request[v1.UndeployWorkflowReleaseRequest]) (*connect.Response[v1.UndeployWorkflowReleaseResponse], error) { + return c.undeployWorkflowRelease.CallUnary(ctx, req) +} + // WorkflowsServiceHandler is an implementation of the workflows.v1.WorkflowsService service. type WorkflowsServiceHandler interface { CreateCluster(context.Context, *connect.Request[v1.CreateClusterRequest]) (*connect.Response[v1.Cluster], error) GetCluster(context.Context, *connect.Request[v1.GetClusterRequest]) (*connect.Response[v1.Cluster], error) DeleteCluster(context.Context, *connect.Request[v1.DeleteClusterRequest]) (*connect.Response[v1.DeleteClusterResponse], error) ListClusters(context.Context, *connect.Request[v1.ListClustersRequest]) (*connect.Response[v1.ListClustersResponse], error) + CreateWorkflow(context.Context, *connect.Request[v1.CreateWorkflowRequest]) (*connect.Response[v1.Workflow], error) + ListWorkflows(context.Context, *connect.Request[v1.ListWorkflowsRequest]) (*connect.Response[v1.ListWorkflowsResponse], error) + GetWorkflow(context.Context, *connect.Request[v1.GetWorkflowRequest]) (*connect.Response[v1.Workflow], error) + PublishWorkflowRelease(context.Context, *connect.Request[v1.PublishWorkflowReleaseRequest]) (*connect.Response[v1.WorkflowRelease], error) + DeployWorkflowRelease(context.Context, *connect.Request[v1.DeployWorkflowReleaseRequest]) (*connect.Response[v1.DeployWorkflowReleaseResponse], error) + UndeployWorkflowRelease(context.Context, *connect.Request[v1.UndeployWorkflowReleaseRequest]) (*connect.Response[v1.UndeployWorkflowReleaseResponse], error) } // NewWorkflowsServiceHandler builds an HTTP handler from the service implementation. It returns the @@ -162,6 +264,42 @@ func NewWorkflowsServiceHandler(svc WorkflowsServiceHandler, opts ...connect.Han connect.WithSchema(workflowsServiceMethods.ByName("ListClusters")), connect.WithHandlerOptions(opts...), ) + workflowsServiceCreateWorkflowHandler := connect.NewUnaryHandler( + WorkflowsServiceCreateWorkflowProcedure, + svc.CreateWorkflow, + connect.WithSchema(workflowsServiceMethods.ByName("CreateWorkflow")), + connect.WithHandlerOptions(opts...), + ) + workflowsServiceListWorkflowsHandler := connect.NewUnaryHandler( + WorkflowsServiceListWorkflowsProcedure, + svc.ListWorkflows, + connect.WithSchema(workflowsServiceMethods.ByName("ListWorkflows")), + connect.WithHandlerOptions(opts...), + ) + workflowsServiceGetWorkflowHandler := connect.NewUnaryHandler( + WorkflowsServiceGetWorkflowProcedure, + svc.GetWorkflow, + connect.WithSchema(workflowsServiceMethods.ByName("GetWorkflow")), + connect.WithHandlerOptions(opts...), + ) + workflowsServicePublishWorkflowReleaseHandler := connect.NewUnaryHandler( + WorkflowsServicePublishWorkflowReleaseProcedure, + svc.PublishWorkflowRelease, + connect.WithSchema(workflowsServiceMethods.ByName("PublishWorkflowRelease")), + connect.WithHandlerOptions(opts...), + ) + workflowsServiceDeployWorkflowReleaseHandler := connect.NewUnaryHandler( + WorkflowsServiceDeployWorkflowReleaseProcedure, + svc.DeployWorkflowRelease, + connect.WithSchema(workflowsServiceMethods.ByName("DeployWorkflowRelease")), + connect.WithHandlerOptions(opts...), + ) + workflowsServiceUndeployWorkflowReleaseHandler := connect.NewUnaryHandler( + WorkflowsServiceUndeployWorkflowReleaseProcedure, + svc.UndeployWorkflowRelease, + connect.WithSchema(workflowsServiceMethods.ByName("UndeployWorkflowRelease")), + connect.WithHandlerOptions(opts...), + ) return "/workflows.v1.WorkflowsService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case WorkflowsServiceCreateClusterProcedure: @@ -172,6 +310,18 @@ func NewWorkflowsServiceHandler(svc WorkflowsServiceHandler, opts ...connect.Han workflowsServiceDeleteClusterHandler.ServeHTTP(w, r) case WorkflowsServiceListClustersProcedure: workflowsServiceListClustersHandler.ServeHTTP(w, r) + case WorkflowsServiceCreateWorkflowProcedure: + workflowsServiceCreateWorkflowHandler.ServeHTTP(w, r) + case WorkflowsServiceListWorkflowsProcedure: + workflowsServiceListWorkflowsHandler.ServeHTTP(w, r) + case WorkflowsServiceGetWorkflowProcedure: + workflowsServiceGetWorkflowHandler.ServeHTTP(w, r) + case WorkflowsServicePublishWorkflowReleaseProcedure: + workflowsServicePublishWorkflowReleaseHandler.ServeHTTP(w, r) + case WorkflowsServiceDeployWorkflowReleaseProcedure: + workflowsServiceDeployWorkflowReleaseHandler.ServeHTTP(w, r) + case WorkflowsServiceUndeployWorkflowReleaseProcedure: + workflowsServiceUndeployWorkflowReleaseHandler.ServeHTTP(w, r) default: http.NotFound(w, r) } @@ -196,3 +346,27 @@ func (UnimplementedWorkflowsServiceHandler) DeleteCluster(context.Context, *conn func (UnimplementedWorkflowsServiceHandler) ListClusters(context.Context, *connect.Request[v1.ListClustersRequest]) (*connect.Response[v1.ListClustersResponse], error) { return nil, connect.NewError(connect.CodeUnimplemented, errors.New("workflows.v1.WorkflowsService.ListClusters is not implemented")) } + +func (UnimplementedWorkflowsServiceHandler) CreateWorkflow(context.Context, *connect.Request[v1.CreateWorkflowRequest]) (*connect.Response[v1.Workflow], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("workflows.v1.WorkflowsService.CreateWorkflow is not implemented")) +} + +func (UnimplementedWorkflowsServiceHandler) ListWorkflows(context.Context, *connect.Request[v1.ListWorkflowsRequest]) (*connect.Response[v1.ListWorkflowsResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("workflows.v1.WorkflowsService.ListWorkflows is not implemented")) +} + +func (UnimplementedWorkflowsServiceHandler) GetWorkflow(context.Context, *connect.Request[v1.GetWorkflowRequest]) (*connect.Response[v1.Workflow], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("workflows.v1.WorkflowsService.GetWorkflow is not implemented")) +} + +func (UnimplementedWorkflowsServiceHandler) PublishWorkflowRelease(context.Context, *connect.Request[v1.PublishWorkflowReleaseRequest]) (*connect.Response[v1.WorkflowRelease], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("workflows.v1.WorkflowsService.PublishWorkflowRelease is not implemented")) +} + +func (UnimplementedWorkflowsServiceHandler) DeployWorkflowRelease(context.Context, *connect.Request[v1.DeployWorkflowReleaseRequest]) (*connect.Response[v1.DeployWorkflowReleaseResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("workflows.v1.WorkflowsService.DeployWorkflowRelease is not implemented")) +} + +func (UnimplementedWorkflowsServiceHandler) UndeployWorkflowRelease(context.Context, *connect.Request[v1.UndeployWorkflowReleaseRequest]) (*connect.Response[v1.UndeployWorkflowReleaseResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("workflows.v1.WorkflowsService.UndeployWorkflowRelease is not implemented")) +} diff --git a/workflows/v1/client.go b/workflows/v1/client.go index 39c8714..048e52f 100644 --- a/workflows/v1/client.go +++ b/workflows/v1/client.go @@ -2,6 +2,8 @@ package workflows // import "github.com/tilebox/tilebox-go/workflows/v1" import ( "context" + "fmt" + "log/slog" "net" "net/http" "os" @@ -25,6 +27,7 @@ const ( type Client struct { Jobs JobClient Clusters ClusterClient + Workflows WorkflowClient Automations AutomationClient // Used by NewTaskRunner @@ -32,7 +35,7 @@ type Client struct { tracer trace.Tracer } -// NewClient creates a new Tilebox Datasets client. +// NewClient creates a new Tilebox Workflows client. // // By default, the returned Client is configured with: // - "https://api.tilebox.com" as the URL @@ -53,11 +56,13 @@ func NewClient(options ...ClientOption) *Client { automationConnectClient := newConnectClient(workflowsv1connect.NewAutomationServiceClient, cfg) tracer := cfg.tracerProvider.Tracer(otelTracerName) + workflowService := newWorkflowService(workflowConnectClient, tracer) automationService := &automationService{automationClient: automationConnectClient, tracer: tracer} return &Client{ Jobs: &jobClient{service: newJobService(jobConnectClient, tracer), telemetryService: newTelemetryService(telemetryConnectClient, tracer)}, - Clusters: &clusterClient{service: newWorkflowService(workflowConnectClient, tracer)}, + Clusters: &clusterClient{service: workflowService}, + Workflows: &workflowClient{service: workflowService}, Automations: &automationClient{service: automationService}, taskService: newTaskService(taskConnectClient, tracer), @@ -75,6 +80,24 @@ func (c *Client) NewTaskRunner(ctx context.Context, options ...runner.Option) (* return newTaskRunner(ctx, c.taskService, c.Clusters, c.tracer, options...) } +// NewPollingTaskRunner creates a polling task runner for custom task executors. +func (c *Client) NewPollingTaskRunner(ctx context.Context, executor TaskExecutor, options ...runner.Option) (*PollingTaskRunner, error) { + opts := &runner.Options{ + ClusterSlug: "", + Logger: slog.Default(), + MeterProvider: otel.GetMeterProvider(), + } + for _, option := range options { + option(opts) + } + + cluster, err := c.Clusters.Get(ctx, opts.ClusterSlug) + if err != nil { + return nil, fmt.Errorf("failed to get cluster: %w", err) + } + return NewPollingTaskRunner(c.taskService, cluster.Slug, executor, opts.Logger), nil +} + // clientConfig contains the configuration for Tilebox Workflows client. type clientConfig struct { httpClient connect.HTTPClient @@ -84,6 +107,7 @@ type clientConfig struct { tracerProvider trace.TracerProvider disableTracing bool + disableLogging bool } // ClientOption is an interface for configuring a client. Using such options helpers is a @@ -134,6 +158,13 @@ func WithDisableTracing() ClientOption { } } +// WithDisableLogging disables Tilebox OpenTelemetry log export setup for the client. +func WithDisableLogging() ClientOption { + return func(cfg *clientConfig) { + cfg.disableLogging = true + } +} + func newClientConfig(options []ClientOption) *clientConfig { cfg := &clientConfig{ url: "https://api.tilebox.com", diff --git a/workflows/v1/clusters.go b/workflows/v1/clusters.go index 31e3718..031b4f4 100644 --- a/workflows/v1/clusters.go +++ b/workflows/v1/clusters.go @@ -19,6 +19,8 @@ type Cluster struct { Name string // Deletable is true when the cluster can be deleted. Deletable bool + // DeployedWorkflows are the workflows currently deployed to this cluster. Each workflow contains the currently deployed release for that workflow. + DeployedWorkflows []*Workflow } type ClusterClient interface { @@ -78,9 +80,15 @@ func (c clusterClient) List(ctx context.Context) ([]*Cluster, error) { } func protoToCluster(c *workflowsv1.Cluster) *Cluster { + deployedWorkflows := make([]*Workflow, len(c.GetDeployedReleases())) + for i, workflow := range c.GetDeployedReleases() { + deployedWorkflows[i] = protoToWorkflow(workflow) + } + return &Cluster{ - Slug: c.GetSlug(), - Name: c.GetDisplayName(), - Deletable: c.GetDeletable(), + Slug: c.GetSlug(), + Name: c.GetDisplayName(), + Deletable: c.GetDeletable(), + DeployedWorkflows: deployedWorkflows, } } diff --git a/workflows/v1/polling_runner.go b/workflows/v1/polling_runner.go new file mode 100644 index 0000000..b2dbe28 --- /dev/null +++ b/workflows/v1/polling_runner.go @@ -0,0 +1,360 @@ +package workflows + +import ( + "context" + "errors" + "log/slog" + "math/rand/v2" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/google/uuid" + "github.com/samber/lo" + workflowsv1 "github.com/tilebox/tilebox-go/protogen/workflows/v1" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// TaskExecutor is responsible for actually executing a task and keeping track of which tasks can be executed. +type TaskExecutor interface { + // TaskIdentifiers returns the current task capabilities of this executor. + // This method must be cheap and non-blocking. It should only read current in-memory state and must not poll remote + // APIs, download artifacts, or start runtimes. + TaskIdentifiers() []*workflowsv1.TaskIdentifier + + ExecuteTask(ctx context.Context, task *workflowsv1.Task) (*workflowsv1.ExecuteTaskResponse, error) +} + +type TaskExecutionError struct { + Err error + ProgressUpdates []*workflowsv1.Progress +} + +func (e *TaskExecutionError) Error() string { + if e == nil || e.Err == nil { + return "task execution failed" + } + return e.Err.Error() +} + +func (e *TaskExecutionError) Unwrap() error { + if e == nil { + return nil + } + return e.Err +} + +type PollingTaskRunner struct { + service TaskService + + clusterSlug string + logger *slog.Logger + executor TaskExecutor + + requestNewTasks atomic.Bool + + activeMu sync.Mutex + activeTask *workflowsv1.Task + cancelActiveLease context.CancelFunc +} + +func NewPollingTaskRunner(service TaskService, clusterSlug string, executor TaskExecutor, logger *slog.Logger) *PollingTaskRunner { + if logger == nil { + logger = slog.Default() + } + runner := &PollingTaskRunner{ + service: service, + clusterSlug: clusterSlug, + logger: logger, + executor: executor, + } + runner.requestNewTasks.Store(true) + return runner +} + +func (r *PollingTaskRunner) RunForever(ctx context.Context) error { + return r.run(ctx, false) +} + +func (r *PollingTaskRunner) RunAll(ctx context.Context) error { + return r.run(ctx, true) +} + +func (r *PollingTaskRunner) StopRequestingNewTasks() { + r.requestNewTasks.Store(false) +} + +func (r *PollingTaskRunner) IsRequestingTasks() bool { + return r.requestNewTasks.Load() +} + +func (r *PollingTaskRunner) HasActiveTask() bool { + r.activeMu.Lock() + defer r.activeMu.Unlock() + return r.activeTask != nil +} + +func (r *PollingTaskRunner) InterruptActiveTask(ctx context.Context) error { + r.activeMu.Lock() + activeTask := r.activeTask + cancelLease := r.cancelActiveLease + if cancelLease != nil { + cancelLease() + } + r.activeMu.Unlock() + + if activeTask == nil || activeTask.GetId() == nil || activeTask.GetId().AsUUID() == uuid.Nil { + return nil + } + return r.reportTaskFailed(ctx, activeTask.GetId().AsUUID(), activeTask.GetDisplay(), false, nil) +} + +func (r *PollingTaskRunner) run(ctx context.Context, stopWhenIdling bool) error { + var work *workflowsv1.NextTaskResponse + var lastExecutionResult *workflowsv1.ExecuteTaskResponse + + for { + if err := ctx.Err(); err != nil { + if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { + return nil + } + return err + } + + // check if we need to report a task failure: + if lastExecutionResult != nil && lastExecutionResult.GetFailedTask() != nil { + // the last task execution resulted in a task failure, so let's report that back to the orchestrator + pendingFailed := lastExecutionResult.GetFailedTask() + _, err := r.service.TaskFailed(ctx, pendingFailed.GetTaskId().AsUUID(), pendingFailed.GetDisplay(), pendingFailed.GetWasWorkflowError(), pendingFailed.GetProgressUpdates()) + if err != nil { + r.logError(ctx, err, "failed to report task failure", slog.String("task_id", pendingFailed.GetTaskId().AsUUID().String()), slog.String("task_display", pendingFailed.GetDisplay())) + // a failure to report a task as failed typically means something is wrong with our API, so let's do one idle time before continuing with the normal runner loop + if r.idle(ctx, randomFallbackIdleDuration()) { + return nil + } + // we did not clear lastExecutionResult yet, so the next loop will attempt to report the task as failed again + continue + } + lastExecutionResult = nil + work = nil + } + + // we don't have a current task to work on, so let's request one + if work == nil || work.GetNextTask() == nil { + // while requesting a new task, in the same request we also report the result of the previous task if there is one + var lastComputedTask *workflowsv1.ComputedTask + if lastExecutionResult.GetComputedTask() != nil { + lastComputedTask = lastExecutionResult.GetComputedTask() + } + + // check whether the runner should still request a new task + requestingNewTasks := r.requestNewTasks.Load() + // and get a list of all known task identifiers we are requesting work for + taskIdentifiersCapableOfRunning := r.executor.TaskIdentifiers() + + if lastComputedTask == nil && len(taskIdentifiersCapableOfRunning) == 0 { + // no task result to report back, and no tasks we can run, so no need to even send a request, let's just idle locally + if stopWhenIdling { + return nil + } + idleDuration := randomFallbackIdleDuration() + if requestingNewTasks { + r.logger.DebugContext(ctx, "not requesting any work, idling", slog.Duration("duration", idleDuration)) + } else { + r.logger.DebugContext(ctx, "not requesting any work, runner is about to shut down", slog.Duration("duration", idleDuration)) + } + + if r.idle(ctx, idleDuration) { + return nil + } + continue + } + + var nextTaskToRun *workflowsv1.NextTaskToRun + if requestingNewTasks && len(taskIdentifiersCapableOfRunning) > 0 { + nextTaskToRun = workflowsv1.NextTaskToRun_builder{ClusterSlug: r.clusterSlug, Identifiers: taskIdentifiersCapableOfRunning}.Build() + } + + // now let's log a debug message of what exactly we're doing with the NextTask request, depending on whether we have a lastComputedTask, and if we're a requesting a next task or not + + switch { + case nextTaskToRun != nil && lastComputedTask != nil: + // we report a task result, and immediately request a new task + r.logger.DebugContext(ctx, "reporting task result and requesting new task", slog.String("computed_task_id", lastComputedTask.GetId().AsUUID().String()), slog.String("computed_task_display", lastComputedTask.GetDisplay()), slog.Int("known_task_identifiers", len(taskIdentifiersCapableOfRunning))) + case nextTaskToRun != nil && lastComputedTask == nil: + r.logger.DebugContext(ctx, "requesting a task to run", slog.Int("known_task_identifiers", len(taskIdentifiersCapableOfRunning))) + case nextTaskToRun == nil && lastComputedTask != nil: + // no next task to run, but a last computed task means we just report task results + r.logger.DebugContext(ctx, "reporting task computed result", slog.String("task_id", lastComputedTask.GetId().AsUUID().String()), slog.String("task_display", lastComputedTask.GetDisplay())) + default: + r.logger.WarnContext(ctx, "unexpected NextTask request, when both computed_task and next_task is not set") + } + + taskResponse, err := r.service.NextTask(ctx, lastComputedTask, nextTaskToRun) + if err != nil { + r.logError(ctx, err, "failed to request next task") + if r.idle(ctx, randomFallbackIdleDuration()) { + return nil + } + continue + } + lastExecutionResult = nil + work = taskResponse + } + + if work != nil && work.GetNextTask() != nil { + task := work.GetNextTask() + work = nil + if isEmpty(task.GetId()) { + r.logError(ctx, nil, "got a task without an ID - skipping to the next task") + continue + } + if task.GetRetryCount() > 0 { + r.logger.DebugContext(ctx, "retrying task", slog.String("task_id", task.GetId().AsUUID().String()), slog.String("task_display", task.GetDisplay()), slog.Int64("retry_count", task.GetRetryCount())) + } else { + r.logger.DebugContext(ctx, "executing task", slog.String("task_id", task.GetId().AsUUID().String()), slog.String("task_display", task.GetDisplay())) + } + + response, err := r.executeTask(ctx, task) + if err != nil { + lastExecutionResult = workflowsv1.ExecuteTaskResponse_builder{FailedTask: r.failedTaskFromError(task, err)}.Build() + continue + } + if response.GetFailedTask() == nil && response.GetComputedTask() == nil { + lastExecutionResult = workflowsv1.ExecuteTaskResponse_builder{FailedTask: r.failedTaskFromError(task, errors.New("executor returned neither computed nor failed task"))}.Build() + continue + } + lastExecutionResult = response + continue // don't idle, immediately return the result + } + + idleDuration := randomFallbackIdleDuration() + if work != nil && work.GetIdling().GetSuggestedIdlingDuration() != nil { + idleDuration = lo.Clamp(work.GetIdling().GetSuggestedIdlingDuration().AsDuration(), minIdlingDuration, maxIdlingDuration) + } + + r.logger.DebugContext(ctx, "no task to run, idling", slog.Duration("duration", idleDuration)) + if stopWhenIdling { + return nil + } + + if r.idle(ctx, idleDuration) { + return nil + } + } +} + +func (r *PollingTaskRunner) executeTask(ctx context.Context, task *workflowsv1.Task) (*workflowsv1.ExecuteTaskResponse, error) { + leaseCtx, stopLeaseExtensions := context.WithCancel(ctx) + r.activeMu.Lock() + r.activeTask = task + r.cancelActiveLease = stopLeaseExtensions + r.activeMu.Unlock() + + go r.extendTaskLease( + leaseCtx, + task.GetId().AsUUID(), + task.GetLease().GetLease().AsDuration(), + task.GetLease().GetRecommendedWaitUntilNextExtension().AsDuration(), + ) + + defer func() { + stopLeaseExtensions() + r.activeMu.Lock() + if r.activeTask == task { + r.activeTask = nil + r.cancelActiveLease = nil + } + r.activeMu.Unlock() + }() + + return r.executor.ExecuteTask(ctx, task) +} + +func (r *PollingTaskRunner) failedTaskFromError(task *workflowsv1.Task, taskError error) *workflowsv1.TaskFailedRequest { + var executionError *TaskExecutionError + progressUpdates := []*workflowsv1.Progress(nil) + if errors.As(taskError, &executionError) { + progressUpdates = executionError.ProgressUpdates + } + return workflowsv1.TaskFailedRequest_builder{ + TaskId: task.GetId(), + Display: failedTaskDisplay(task.GetDisplay(), taskError), + WasWorkflowError: false, + ProgressUpdates: progressUpdates, + }.Build() +} + +func (r *PollingTaskRunner) reportTaskFailed(ctx context.Context, taskID uuid.UUID, display string, wasWorkflowError bool, progressUpdates []*workflowsv1.Progress) error { + _, err := r.service.TaskFailed(ctx, taskID, display, wasWorkflowError, progressUpdates) + return err +} + +func (r *PollingTaskRunner) extendTaskLease(ctx context.Context, taskID uuid.UUID, initialLease, initialWait time.Duration) { + wait := initialWait + lease := initialLease + for { + timer := time.NewTimer(wait) + select { + case <-ctx.Done(): + timer.Stop() + return + case <-timer.C: + } + r.logger.DebugContext(ctx, "extending task lease", slog.String("task_id", taskID.String()), slog.Duration("lease", lease), slog.Duration("wait", wait)) + extension, err := r.service.ExtendTaskLease(ctx, taskID, 2*lease) + if err != nil { + r.logError(ctx, err, "failed to extend task lease", slog.String("task_id", taskID.String())) + return + } + if extension.GetLease() == nil { + r.logger.DebugContext(ctx, "task lease extension not granted", slog.String("task_id", taskID.String())) + return + } + lease = extension.GetLease().AsDuration() + wait = extension.GetRecommendedWaitUntilNextExtension().AsDuration() + } +} + +func failedTaskDisplay(taskDisplay string, taskError error) string { + errorMessage := taskError.Error() + if len(errorMessage) > 1024 { + errorMessage = errorMessage[:1024] + } + if errorMessage == "" { + return taskDisplay + } + return strings.Join([]string{taskDisplay, errorMessage}, "\n") +} + +func randomFallbackIdleDuration() time.Duration { + return fallbackPollingInterval + rand.N(fallbackJitterInterval) +} + +// idle for the given duration, and return true if idling was interrupted due to a context error (e.g. cancellation) +func (r *PollingTaskRunner) idle(ctx context.Context, duration time.Duration) bool { + timer := time.NewTimer(duration) + defer timer.Stop() + select { + case <-ctx.Done(): + return ctx.Err() != nil + case <-timer.C: + return false + } +} + +func (r *PollingTaskRunner) logError(ctx context.Context, err error, msg string, args ...any) { + switch { + case errors.Is(err, context.Canceled): + return + case status.Code(err) == codes.Canceled: + return + } + + fields := make([]any, 0, len(args)+1) + fields = append(fields, slog.Any("error", err)) + fields = append(fields, args...) + r.logger.ErrorContext(ctx, msg, fields...) +} diff --git a/workflows/v1/runner.go b/workflows/v1/runner.go index 23ef485..e8f7cc7 100644 --- a/workflows/v1/runner.go +++ b/workflows/v1/runner.go @@ -7,16 +7,12 @@ import ( "fmt" "log/slog" "math" - "math/rand/v2" "os/signal" "reflect" - "strings" "sync" "time" - "github.com/avast/retry-go/v4" "github.com/google/uuid" - "github.com/samber/lo" "github.com/tilebox/tilebox-go/internal/span" obslogger "github.com/tilebox/tilebox-go/observability/logger" tileboxv1 "github.com/tilebox/tilebox-go/protogen/tilebox/v1" @@ -27,8 +23,6 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/trace" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" ) @@ -44,7 +38,7 @@ const ( minIdlingDuration = 1 * time.Millisecond // Fallback polling interval and jitter in case the workflows API fails to respond with a suggested idling duration - fallbackPollingInterval = 5 * time.Second + fallbackPollingInterval = 10 * time.Second fallbackJitterInterval = 5 * time.Second ) @@ -122,6 +116,7 @@ func newTaskRunnerMetrics(meter metric.Meter) (*taskRunnerMetrics, error) { // // Documentation: https://docs.tilebox.com/workflows/concepts/task-runners type TaskRunner struct { + pollingRunner *PollingTaskRunner service TaskService taskDefinitions map[taskIdentifier]ExecutableTask @@ -151,7 +146,7 @@ func newTaskRunner(ctx context.Context, service TaskService, clusterClient Clust return nil, fmt.Errorf("failed to create task runner metrics: %w", err) } - return &TaskRunner{ + taskRunner := &TaskRunner{ service: service, taskDefinitions: make(map[taskIdentifier]ExecutableTask), @@ -159,7 +154,9 @@ func newTaskRunner(ctx context.Context, service TaskService, clusterClient Clust tracer: tracer, logger: opts.Logger, metrics: metrics, - }, nil + } + taskRunner.pollingRunner = NewPollingTaskRunner(service, cluster.Slug, taskRunner, opts.Logger) + return taskRunner, nil } // GetRegisteredTask returns the task with the given identifier. @@ -184,22 +181,21 @@ func isEmpty(id *tileboxv1.ID) bool { } // RunForever runs the task runner forever, looking for new tasks to run and polling for new tasks when idle. -func (t *TaskRunner) RunForever(ctx context.Context) { - t.run(ctx, false) +func (t *TaskRunner) RunForever(ctx context.Context) error { + ctxSignal, stop := signal.NotifyContext(ctx, runnerShutdownSignals()...) + defer stop() + t.pollingRunner.service = t.service + return t.pollingRunner.RunForever(ctxSignal) } // RunAll run the task runner and execute all tasks until there are no more tasks available. -func (t *TaskRunner) RunAll(ctx context.Context) { - t.run(ctx, true) +func (t *TaskRunner) RunAll(ctx context.Context) error { + t.pollingRunner.service = t.service + return t.pollingRunner.RunAll(ctx) } -func (t *TaskRunner) run(ctx context.Context, stopWhenIdling bool) { - // Catch signals to gracefully shutdown - ctxSignal, stop := signal.NotifyContext(context.Background(), runnerShutdownSignals()...) - defer stop() - +func (t *TaskRunner) TaskIdentifiers() []*workflowsv1.TaskIdentifier { identifiers := make([]*workflowsv1.TaskIdentifier, 0, len(t.taskDefinitions)) - for _, task := range t.taskDefinitions { identifier := identifierFromTask(task) identifiers = append(identifiers, workflowsv1.TaskIdentifier_builder{ @@ -207,156 +203,35 @@ func (t *TaskRunner) run(ctx context.Context, stopWhenIdling bool) { Version: identifier.Version(), }.Build()) } - - // the work we got as response from our last NextTask request, either a task to execute or an idling response - var work *workflowsv1.NextTaskResponse - - for { - if work == nil || work.GetNextTask() == nil { // if we don't have a task, let's try work-stealing one - taskResponse, err := t.service.NextTask(ctx, - nil, - workflowsv1.NextTaskToRun_builder{ClusterSlug: t.cluster, Identifiers: identifiers}.Build(), - ) - if err != nil { - t.logError(ctx, err, "failed to work-steal a task") - // return // should we even try again, or just stop here? - } else { - work = taskResponse - } - } - - if work != nil && work.GetNextTask() != nil { // we have a task to execute - task := work.GetNextTask() - if isEmpty(task.GetId()) { - t.logError(ctx, nil, "got a task without an ID - skipping to the next task") - work = nil - continue - } - if task.GetRetryCount() > 0 { - t.logger.DebugContext(ctx, "retrying task", slog.String("task_id", task.GetId().AsUUID().String()), slog.Int64("retry_count", task.GetRetryCount())) - } - executionContext, errTask := t.executeTask(ctx, task) - stopExecution := false - if errTask == nil { // in case we got no error, let's mark the task as computed and get the next one - computedTask := workflowsv1.ComputedTask_builder{ - Id: task.GetId(), - Display: task.GetDisplay(), - SubTasks: executionContext.getSubTasks(), - ProgressUpdates: executionContext.getProgressUpdates(), - }.Build() - nextTaskToRun := workflowsv1.NextTaskToRun_builder{ClusterSlug: t.cluster, Identifiers: identifiers}.Build() - select { - case <-ctxSignal.Done(): - // if we got an interrupt signal, don't request a new task - nextTaskToRun = nil - stopExecution = true - case <-ctx.Done(): - // if we got a context cancellation, don't request a new task - nextTaskToRun = nil - stopExecution = true - default: - } - - var err error - work, err = retry.DoWithData( - func() (*workflowsv1.NextTaskResponse, error) { - taskResponse, err := t.service.NextTask(ctx, computedTask, nextTaskToRun) - if err != nil { - t.logError(ctx, err, "failed to mark task as computed, retrying") - return nil, err - } - return taskResponse, nil - }, retry.Context(ctxSignal), retry.DelayType(retry.CombineDelay(retry.BackOffDelay, retry.RandomDelay)), - ) - if err != nil { - t.logError(ctx, err, "failed to retry NextTask") - return // we got a cancellation signal, so let's just stop here - } - } else { // errTask != nil - // the error itself is already logged in executeTask, so we just need to report the task as failed - // even if a task failed it could have made some progress, so if that's the case, we report it - var progressUpdates []*workflowsv1.Progress - if executionContext != nil { - progressUpdates = executionContext.getProgressUpdates() - } - err := t.taskFailed(ctx, ctxSignal, task.GetId().AsUUID(), errTask, task.GetDisplay(), progressUpdates) - if err != nil { - t.logError(ctx, err, "failed to retry TaskFailed") - return // we got a cancellation signal, so let's just stop here - } - work = nil // reported a task failure, let's work-steal again - } - if stopExecution { - return - } - } else { - // if we didn't get a task, let's wait for a bit and try work-stealing again - t.logger.DebugContext(ctx, "no task to run, idling") - - if stopWhenIdling { - return - } - - idlingDuration := fallbackPollingInterval + rand.N(fallbackJitterInterval) - if work != nil && work.GetIdling().GetSuggestedIdlingDuration() != nil { - idlingDuration = work.GetIdling().GetSuggestedIdlingDuration().AsDuration() - idlingDuration = lo.Clamp(idlingDuration, minIdlingDuration, maxIdlingDuration) - } else { - t.logger.DebugContext(ctx, "Didn't receive a task to run, nor an idling response, but runner is not shutting down. Falling back to a default idling period.", slog.Duration("fallback_idling_duration", idlingDuration)) - } - - // instead of time.Sleep we set a timer and select on it, so we still can catch signals like SIGINT - timer := time.NewTimer(idlingDuration) - select { - case <-ctxSignal.Done(): - timer.Stop() // stop the timer before returning, avoids a memory leak - return // if we got a context cancellation, let's just stop here - case <-ctx.Done(): - timer.Stop() // stop the timer before returning, avoids a memory leak - return // if we got a context cancellation, let's just stop here - case <-timer.C: // the timer expired, let's try to work-steal a task again - } - } - } + return identifiers } -func (t *TaskRunner) taskFailed(ctx, ctxSignal context.Context, taskID uuid.UUID, taskError error, taskDisplay string, progressUpdates []*workflowsv1.Progress) error { - // job output is limited to 1KB, so truncate the error message if necessary - errorMessage := taskError.Error() - if len(errorMessage) > 1024 { - errorMessage = errorMessage[:1024] - } - - display := taskDisplay - if errorMessage != "" { - display = strings.Join([]string{taskDisplay, errorMessage}, "\n") +func (t *TaskRunner) ExecuteTask(ctx context.Context, task *workflowsv1.Task) (*workflowsv1.ExecuteTaskResponse, error) { + executionContext, err := t.executeTask(ctx, task) + if err != nil { + var progressUpdates []*workflowsv1.Progress + if executionContext != nil { + progressUpdates = executionContext.getProgressUpdates() + } + failedTask := workflowsv1.TaskFailedRequest_builder{ + TaskId: task.GetId(), + Display: failedTaskDisplay(task.GetDisplay(), err), + WasWorkflowError: true, + ProgressUpdates: progressUpdates, + }.Build() + return workflowsv1.ExecuteTaskResponse_builder{FailedTask: failedTask}.Build(), nil } - return retry.Do( - func() error { - _, err := t.service.TaskFailed(ctx, taskID, display, true, progressUpdates) - if err != nil { - t.logError(ctx, err, "failed to report task failure") - return err - } - return nil - }, retry.Context(ctxSignal), retry.DelayType(retry.CombineDelay(retry.BackOffDelay, retry.RandomDelay)), - ) + computedTask := workflowsv1.ComputedTask_builder{ + Id: task.GetId(), + Display: task.GetDisplay(), + SubTasks: executionContext.getSubTasks(), + ProgressUpdates: executionContext.getProgressUpdates(), + }.Build() + return workflowsv1.ExecuteTaskResponse_builder{ComputedTask: computedTask}.Build(), nil } func (t *TaskRunner) executeTask(ctx context.Context, task *workflowsv1.Task) (*taskExecutionContext, error) { - // start a goroutine to extend the lease of the task continuously until the task execution is finished - leaseCtx, stopLeaseExtensions := context.WithCancel(ctx) - - go t.extendTaskLease( - leaseCtx, - t.service, - task.GetId().AsUUID(), - task.GetLease().GetLease().AsDuration(), - task.GetLease().GetRecommendedWaitUntilNextExtension().AsDuration(), - ) - defer stopLeaseExtensions() - // actually execute the task beforeTime := time.Now().UTC() @@ -443,54 +318,6 @@ func (t *TaskRunner) executeTask(ctx context.Context, task *workflowsv1.Task) (* // extendTaskLease is a function designed to be run as a goroutine, extending the lease of a task continuously until the // context is cancelled, which indicates that the execution of the task is finished. -func (t *TaskRunner) extendTaskLease(ctx context.Context, service TaskService, taskID uuid.UUID, initialLease, initialWait time.Duration) { - wait := initialWait - lease := initialLease - for { - timer := time.NewTimer(wait) - select { - case <-ctx.Done(): // if the context is cancelled, let's stop trying to extend the lease -> the task finished - timer.Stop() // stop the timer before returning, avoids a memory leak - return - case <-timer.C: // the timer expired, let's try to extend the lease - } - t.logger.DebugContext(ctx, "extending task lease", slog.String("task_id", taskID.String()), slog.Duration("lease", lease), slog.Duration("wait", wait)) - // double the current lease duration for the next extension - extension, err := service.ExtendTaskLease(ctx, taskID, 2*lease) - if err != nil { - t.logError(ctx, err, "failed to extend task lease", slog.String("task_id", taskID.String())) - // The server probably has an internal error, but there is no point in trying to extend the lease again - // because it will be expired then, so let's just return - return - } - if extension.GetLease() == nil { - // the server did not return a lease extension, it means that there is no need in trying to extend the lease - t.logger.DebugContext(ctx, "task lease extension not granted", slog.String("task_id", taskID.String())) - return - } - // will probably be double the previous lease (since we requested that) or capped by the server at maxLeaseDuration - lease = extension.GetLease().AsDuration() - wait = extension.GetRecommendedWaitUntilNextExtension().AsDuration() - } -} - -func (t *TaskRunner) logError(ctx context.Context, err error, msg string, args ...any) { - switch { - case errors.Is(err, context.Canceled): - // covers both stdlib context.Canceled and connect context canceled errors - return - case status.Code(err) == codes.Canceled: - // outgoing gRPC requests that are canceled produce a - // status.Error(codes.Canceled, "context canceled") from the google grpc library - return - } - - fields := make([]any, 0, len(args)+1) - fields = append(fields, slog.Any("error", err)) - fields = append(fields, args...) - t.logger.ErrorContext(ctx, msg, fields...) -} - // registerTask makes the task runner aware of a task. func (t *TaskRunner) registerTask(task ExecutableTask) error { identifier := identifierFromTask(task) diff --git a/workflows/v1/runner_test.go b/workflows/v1/runner_test.go index bf00679..3963fda 100644 --- a/workflows/v1/runner_test.go +++ b/workflows/v1/runner_test.go @@ -214,9 +214,13 @@ func Test_isEmpty(t *testing.T) { // mockMinimalTaskService is a mock task service that returns a single next task response. after that it returns an empty response every time type mockMinimalTaskService struct { - computedTasks []*workflowsv1.ComputedTask - nextTask *workflowsv1.Task - failed bool + computedTasks []*workflowsv1.ComputedTask + nextTask *workflowsv1.Task + idlingDuration time.Duration + failed bool + failedDisplay string + failedWasWorkflowError bool + failedProgressUpdates []*workflowsv1.Progress } var _ TaskService = &mockMinimalTaskService{} @@ -232,13 +236,18 @@ func (m *mockMinimalTaskService) NextTask(_ context.Context, computedTask *workf return resp, nil } // subsequent calls => no next task - return workflowsv1.NextTaskResponse_builder{ - NextTask: nil, - }.Build(), nil + response := workflowsv1.NextTaskResponse_builder{} + if m.idlingDuration > 0 { + response.Idling = workflowsv1.IdlingResponse_builder{SuggestedIdlingDuration: durationpb.New(m.idlingDuration)}.Build() + } + return response.Build(), nil } -func (m *mockMinimalTaskService) TaskFailed(context.Context, uuid.UUID, string, bool, []*workflowsv1.Progress) (*workflowsv1.TaskStateResponse, error) { +func (m *mockMinimalTaskService) TaskFailed(_ context.Context, _ uuid.UUID, display string, wasWorkflowError bool, progressUpdates []*workflowsv1.Progress) (*workflowsv1.TaskStateResponse, error) { m.failed = true + m.failedDisplay = display + m.failedWasWorkflowError = wasWorkflowError + m.failedProgressUpdates = progressUpdates return workflowsv1.TaskStateResponse_builder{ State: workflowsv1.TaskState_TASK_STATE_FAILED, }.Build(), nil @@ -297,7 +306,7 @@ func TestTaskRunner_RunForever(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond) // run our one task, then stop defer cancel() - runner.RunForever(ctx) + require.NoError(t, runner.RunForever(ctx)) assert.False(t, mockTaskClient.failed, "task should not have failed") require.Len(t, mockTaskClient.computedTasks, 1) @@ -339,7 +348,7 @@ func TestTaskRunner_RunAll(t *testing.T) { require.NoError(t, err, "failed to register task") // run our one task, then stop - runner.RunAll(context.Background()) + require.NoError(t, runner.RunAll(context.Background())) assert.False(t, mockTaskClient.failed, "task should not have failed") require.Len(t, mockTaskClient.computedTasks, 1) @@ -347,6 +356,95 @@ func TestTaskRunner_RunAll(t *testing.T) { assert.Equal(t, mockNextTask.GetId(), computedTask.GetId()) } +func TestTaskRunner_RunForeverReportsComputedTaskOnce(t *testing.T) { + task := &testTaskExecute{} + taskInput, err := json.Marshal(task) + require.NoError(t, err) + mockNextTask := workflowsv1.Task_builder{ + Id: tileboxv1.NewUUID(uuid.New()), + Identifier: workflowsv1.TaskIdentifier_builder{ + Name: task.Identifier().Name(), + Version: task.Identifier().Version(), + }.Build(), + State: workflowsv1.TaskState_TASK_STATE_RUNNING, + Input: taskInput, + Job: workflowsv1.Job_builder{ + Id: tileboxv1.NewUUID(uuid.New()), + Name: "tilebox-test-job", + }.Build(), + }.Build() + mockTaskClient := &mockMinimalTaskService{nextTask: mockNextTask, idlingDuration: time.Millisecond} + + tracer := noop.NewTracerProvider().Tracer("") + service := mockTaskService{} + mockClusterClient := clusterClient{service: &mockClusterService{}} + runner, err := newTaskRunner(context.Background(), service, mockClusterClient, tracer) + require.NoError(t, err, "failed to create task runner") + runner.service = mockTaskClient + require.NoError(t, runner.RegisterTasks(task)) + + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Millisecond) + defer cancel() + require.NoError(t, runner.RunForever(ctx)) + + require.Len(t, mockTaskClient.computedTasks, 1) + assert.Equal(t, mockNextTask.GetId(), mockTaskClient.computedTasks[0].GetId()) +} + +func TestPollingTaskRunnerReportsExecutorReturnedFailedTaskAsIs(t *testing.T) { + taskID := uuid.New() + taskDisplay := "Python task" + mockNextTask := workflowsv1.Task_builder{ + Id: tileboxv1.NewUUID(taskID), + Identifier: workflowsv1.TaskIdentifier_builder{ + Name: "python.Task", + Version: "v1.0", + }.Build(), + State: workflowsv1.TaskState_TASK_STATE_RUNNING, + Display: &taskDisplay, + Lease: workflowsv1.TaskLease_builder{ + Lease: durationpb.New(5 * time.Minute), + RecommendedWaitUntilNextExtension: durationpb.New(5 * time.Minute), + }.Build(), + }.Build() + progressUpdates := []*workflowsv1.Progress{ + workflowsv1.Progress_builder{Label: "work", Total: 10, Done: 4}.Build(), + } + service := &mockMinimalTaskService{nextTask: mockNextTask} + executor := &failedResponseExecutor{ + response: workflowsv1.ExecuteTaskResponse_builder{ + FailedTask: workflowsv1.TaskFailedRequest_builder{ + TaskId: tileboxv1.NewUUID(taskID), + Display: "Python classified failure", + WasWorkflowError: true, + ProgressUpdates: progressUpdates, + }.Build(), + }.Build(), + } + runner := NewPollingTaskRunner(service, "default", executor, slog.Default()) + + require.NoError(t, runner.RunAll(context.Background())) + + require.True(t, service.failed) + require.Equal(t, "Python classified failure", service.failedDisplay) + require.True(t, service.failedWasWorkflowError) + require.Equal(t, progressUpdates, service.failedProgressUpdates) +} + +type failedResponseExecutor struct { + response *workflowsv1.ExecuteTaskResponse +} + +func (e *failedResponseExecutor) TaskIdentifiers() []*workflowsv1.TaskIdentifier { + return []*workflowsv1.TaskIdentifier{ + workflowsv1.TaskIdentifier_builder{Name: "python.Task", Version: "v1.0"}.Build(), + } +} + +func (e *failedResponseExecutor) ExecuteTask(context.Context, *workflowsv1.Task) (*workflowsv1.ExecuteTaskResponse, error) { + return e.response, nil +} + func Test_withTaskExecutionContextRoundtrip(t *testing.T) { tracer := noop.NewTracerProvider().Tracer("") service := mockTaskService{} @@ -900,7 +998,7 @@ func TestRunnerFibonacciWorkflow(t *testing.T) { _, err = client.Jobs.Submit(ctx, "fibonacci", []Task{&FibonacciTask{N: 7}}) require.NoError(t, err, "failed to submit job") - runner.RunAll(ctx) + require.NoError(t, runner.RunAll(ctx)) // make sure all results are computed assert.Equal(t, 13, cache["fib_7"]) diff --git a/workflows/v1/service.go b/workflows/v1/service.go index 2cb8007..f9868ca 100644 --- a/workflows/v1/service.go +++ b/workflows/v1/service.go @@ -356,6 +356,13 @@ type WorkflowService interface { GetCluster(ctx context.Context, slug string) (*workflowsv1.Cluster, error) DeleteCluster(ctx context.Context, slug string) error ListClusters(ctx context.Context) (*workflowsv1.ListClustersResponse, error) + + CreateWorkflow(ctx context.Context, name, description string) (*workflowsv1.Workflow, error) + ListWorkflows(ctx context.Context) (*workflowsv1.ListWorkflowsResponse, error) + GetWorkflow(ctx context.Context, slug string) (*workflowsv1.Workflow, error) + PublishWorkflowRelease(ctx context.Context, workflowSlug string, artifactID uuid.UUID, content *ReleaseContent) (*workflowsv1.WorkflowRelease, error) + DeployWorkflowRelease(ctx context.Context, workflowSlug string, releaseID uuid.UUID, clusterSlugs []string) (*workflowsv1.DeployWorkflowReleaseResponse, error) + UndeployWorkflowRelease(ctx context.Context, workflowSlug string, releaseID uuid.UUID, clusterSlugs []string) (*workflowsv1.UndeployWorkflowReleaseResponse, error) } var _ WorkflowService = &workflowService{} @@ -421,3 +428,91 @@ func (s *workflowService) ListClusters(ctx context.Context) (*workflowsv1.ListCl return res.Msg, nil }) } + +func (s *workflowService) CreateWorkflow(ctx context.Context, name, description string) (*workflowsv1.Workflow, error) { + return observability.WithSpanResult(ctx, s.tracer, "workflows/workflows/create", func(ctx context.Context) (*workflowsv1.Workflow, error) { + res, err := s.workflowClient.CreateWorkflow(ctx, connect.NewRequest(workflowsv1.CreateWorkflowRequest_builder{ + Name: name, + Description: description, + }.Build())) + if err != nil { + return nil, fmt.Errorf("failed to create workflow: %w", err) + } + + return res.Msg, nil + }) +} + +func (s *workflowService) ListWorkflows(ctx context.Context) (*workflowsv1.ListWorkflowsResponse, error) { + return observability.WithSpanResult(ctx, s.tracer, "workflows/workflows/list", func(ctx context.Context) (*workflowsv1.ListWorkflowsResponse, error) { + res, err := s.workflowClient.ListWorkflows(ctx, connect.NewRequest(&workflowsv1.ListWorkflowsRequest{})) + if err != nil { + return nil, fmt.Errorf("failed to list workflows: %w", err) + } + + return res.Msg, nil + }) +} + +func (s *workflowService) GetWorkflow(ctx context.Context, slug string) (*workflowsv1.Workflow, error) { + return observability.WithSpanResult(ctx, s.tracer, "workflows/workflows/get", func(ctx context.Context) (*workflowsv1.Workflow, error) { + res, err := s.workflowClient.GetWorkflow(ctx, connect.NewRequest(workflowsv1.GetWorkflowRequest_builder{ + WorkflowSlug: slug, + }.Build())) + if err != nil { + return nil, fmt.Errorf("failed to get workflow: %w", err) + } + + return res.Msg, nil + }) +} + +func (s *workflowService) PublishWorkflowRelease(ctx context.Context, workflowSlug string, artifactID uuid.UUID, content *ReleaseContent) (*workflowsv1.WorkflowRelease, error) { + return observability.WithSpanResult(ctx, s.tracer, "workflows/workflows/publish_release", func(ctx context.Context) (*workflowsv1.WorkflowRelease, error) { + protoContent, err := releaseContentToProto(content) + if err != nil { + return nil, err + } + + res, err := s.workflowClient.PublishWorkflowRelease(ctx, connect.NewRequest(workflowsv1.PublishWorkflowReleaseRequest_builder{ + WorkflowSlug: workflowSlug, + ArtifactId: tileboxv1.NewUUID(artifactID), + Content: protoContent, + }.Build())) + if err != nil { + return nil, fmt.Errorf("failed to publish workflow release: %w", err) + } + + return res.Msg, nil + }) +} + +func (s *workflowService) DeployWorkflowRelease(ctx context.Context, workflowSlug string, releaseID uuid.UUID, clusterSlugs []string) (*workflowsv1.DeployWorkflowReleaseResponse, error) { + return observability.WithSpanResult(ctx, s.tracer, "workflows/workflows/deploy_release", func(ctx context.Context) (*workflowsv1.DeployWorkflowReleaseResponse, error) { + res, err := s.workflowClient.DeployWorkflowRelease(ctx, connect.NewRequest(workflowsv1.DeployWorkflowReleaseRequest_builder{ + WorkflowSlug: workflowSlug, + ReleaseId: tileboxv1.NewUUID(releaseID), + ClusterSlugs: clusterSlugs, + }.Build())) + if err != nil { + return nil, fmt.Errorf("failed to deploy workflow release: %w", err) + } + + return res.Msg, nil + }) +} + +func (s *workflowService) UndeployWorkflowRelease(ctx context.Context, workflowSlug string, releaseID uuid.UUID, clusterSlugs []string) (*workflowsv1.UndeployWorkflowReleaseResponse, error) { + return observability.WithSpanResult(ctx, s.tracer, "workflows/workflows/undeploy_release", func(ctx context.Context) (*workflowsv1.UndeployWorkflowReleaseResponse, error) { + res, err := s.workflowClient.UndeployWorkflowRelease(ctx, connect.NewRequest(workflowsv1.UndeployWorkflowReleaseRequest_builder{ + WorkflowSlug: workflowSlug, + ReleaseId: tileboxv1.NewUUID(releaseID), + ClusterSlugs: clusterSlugs, + }.Build())) + if err != nil { + return nil, fmt.Errorf("failed to undeploy workflow release: %w", err) + } + + return res.Msg, nil + }) +} diff --git a/workflows/v1/telemetry.go b/workflows/v1/telemetry.go index 37610c7..ba6aca6 100644 --- a/workflows/v1/telemetry.go +++ b/workflows/v1/telemetry.go @@ -2,6 +2,7 @@ package workflows import ( "context" + "errors" "fmt" "log/slog" "net/url" @@ -74,7 +75,9 @@ func configureTileboxTelemetry(ctx context.Context, cfg *clientConfig) { cfg.tracerProvider = configureTileboxTracing(ctx, cfg) } - configureTileboxLogging(ctx, cfg) + if !cfg.disableLogging { + configureTileboxLogging(ctx, cfg) + } } func configureTileboxTracing(ctx context.Context, cfg *clientConfig) trace.TracerProvider { @@ -116,17 +119,8 @@ func configureTileboxTracing(ctx context.Context, cfg *clientConfig) trace.Trace } func configureTileboxLogging(ctx context.Context, cfg *clientConfig) { - endpoint, ok := otlpEndpointURL(cfg.url, otlpLogsPath) - if !ok { - return - } - tileboxLogHandlerOnce.Do(func() { - otelHandler, _, err := logger.NewOtelHandler(ctx, tileboxTelemetryService, - logger.WithEndpointURL(endpoint), - logger.WithHeaders(tileboxTelemetryHeaders(cfg.apiKey)), - logger.WithLevel(slog.LevelInfo), - ) + otelHandler, _, err := NewTileboxLogHandler(ctx, cfg.url, cfg.apiKey, slog.LevelInfo) if err != nil { otel.Handle(fmt.Errorf("failed to configure Tilebox log exporter: %w", err)) return @@ -136,6 +130,32 @@ func configureTileboxLogging(ctx context.Context, cfg *clientConfig) { }) } +// NewTileboxLogHandler creates a slog handler that exports log records to the Tilebox API. +func NewTileboxLogHandler(ctx context.Context, apiURL string, apiKey string, level slog.Level) (slog.Handler, func(context.Context), error) { + cleanup := func(context.Context) {} + if strings.TrimSpace(apiKey) == "" { + return nil, cleanup, errors.New("tilebox API key is required for log export") + } + if !isHTTPURL(apiURL) { + return nil, cleanup, fmt.Errorf("tilebox API URL must be an HTTP(S) URL for log export: %s", apiURL) + } + + endpoint, ok := otlpEndpointURL(apiURL, otlpLogsPath) + if !ok { + return nil, cleanup, fmt.Errorf("invalid Tilebox API URL for log export: %s", apiURL) + } + + handler, cleanup, err := logger.NewOtelHandler(ctx, tileboxTelemetryService, + logger.WithEndpointURL(endpoint), + logger.WithHeaders(tileboxTelemetryHeaders(apiKey)), + logger.WithLevel(level), + ) + if cleanup == nil { + cleanup = func(context.Context) {} + } + return handler, cleanup, err +} + func configureSlogHandler(handler slog.Handler) { slogHandlersMu.Lock() defer slogHandlersMu.Unlock() diff --git a/workflows/v1/workflows.go b/workflows/v1/workflows.go new file mode 100644 index 0000000..0688073 --- /dev/null +++ b/workflows/v1/workflows.go @@ -0,0 +1,353 @@ +package workflows // import "github.com/tilebox/tilebox-go/workflows/v1" + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/google/uuid" + workflowsv1 "github.com/tilebox/tilebox-go/protogen/workflows/v1" +) + +// Workflow represents a logical grouping for a set of tasks. +type Workflow struct { + // Slug is the unique identifier of the workflow within the namespace. + Slug string + // Name is the human-readable name of the workflow. + Name string + // Description is the workflow description. + Description string + // Releases are the immutable releases published for this workflow. + Releases []*WorkflowRelease +} + +// WorkflowRelease represents an immutable release of a workflow. +type WorkflowRelease struct { + // ID is the unique identifier of the workflow release. + ID uuid.UUID + // Artifact is the artifact associated with this release. + Artifact *Artifact + // Content describes the files and task implementations included in this release. + Content *ReleaseContent + // CreatedAt is the time the workflow release was created. + CreatedAt time.Time +} + +// Artifact represents the artifact associated with a workflow release. +type Artifact struct { + // ID is the unique identifier of the artifact. + ID uuid.UUID + // Digest is the SHA-256 digest of the artifact. + Digest string +} + +// ReleaseContent represents the content included in a workflow release artifact. +type ReleaseContent struct { + // Fingerprint is the SHA-256 fingerprint of the release content. + Fingerprint string + // Tasks are the task implementations included in this release content. + Tasks []TaskIdentifier + // Files are the files and directories included in the release artifact. + Files []*Path + // RunnerObjectPath is the Python module/object path to the runner instance. + RunnerObjectPath string + // CommandOverride is an optional custom command for starting a worker runtime. + CommandOverride []string +} + +// Path represents a file or directory path in release content. +type Path struct { + // Path is the relative path. + Path string + // Directory reports whether this path is a directory. + Directory bool + // Children are nested paths when this path is a directory. + Children []*Path +} + +// WorkflowReleaseDeployment is the result of deploying or undeploying a workflow release. +type WorkflowReleaseDeployment struct { + // Release is the workflow release that was deployed or undeployed. + Release *WorkflowRelease + // Clusters are the clusters affected by the deployment operation. + Clusters []*Cluster +} + +type workflowOptions struct { + description string +} + +// WorkflowOption configures workflow create requests. +type WorkflowOption func(*workflowOptions) + +// WithDescription sets the workflow description. +func WithDescription(description string) WorkflowOption { + return func(options *workflowOptions) { + options.description = description + } +} + +func applyWorkflowOptions(options ...WorkflowOption) workflowOptions { + var applied workflowOptions + for _, option := range options { + option(&applied) + } + return applied +} + +type WorkflowClient interface { + // Create creates a new workflow with the given name. + Create(ctx context.Context, name string, options ...WorkflowOption) (*Workflow, error) + + // List returns all workflows. + List(ctx context.Context) ([]*Workflow, error) + + // Get returns a workflow by its slug. + Get(ctx context.Context, slug string) (*Workflow, error) + + // PublishRelease publishes a new immutable release for a workflow. + PublishRelease(ctx context.Context, workflowSlug string, artifactID uuid.UUID, content *ReleaseContent) (*WorkflowRelease, error) + + // DeployRelease deploys a workflow release to clusters. + DeployRelease(ctx context.Context, workflowSlug string, releaseID uuid.UUID, clusterSlugs []string) (*WorkflowReleaseDeployment, error) + + // UndeployRelease undeploys a workflow release from clusters. + UndeployRelease(ctx context.Context, workflowSlug string, releaseID uuid.UUID, clusterSlugs []string) (*WorkflowReleaseDeployment, error) +} + +var _ WorkflowClient = &workflowClient{} + +type workflowClient struct { + service WorkflowService +} + +func (c workflowClient) Create(ctx context.Context, name string, options ...WorkflowOption) (*Workflow, error) { + appliedOptions := applyWorkflowOptions(options...) + response, err := c.service.CreateWorkflow(ctx, name, appliedOptions.description) + if err != nil { + return nil, err + } + + return protoToWorkflow(response), nil +} + +func (c workflowClient) List(ctx context.Context) ([]*Workflow, error) { + response, err := c.service.ListWorkflows(ctx) + if err != nil { + return nil, err + } + + workflows := make([]*Workflow, len(response.GetWorkflows())) + for i, workflow := range response.GetWorkflows() { + workflows[i] = protoToWorkflow(workflow) + } + + return workflows, nil +} + +func (c workflowClient) Get(ctx context.Context, slug string) (*Workflow, error) { + response, err := c.service.GetWorkflow(ctx, slug) + if err != nil { + return nil, err + } + + return protoToWorkflow(response), nil +} + +func (c workflowClient) PublishRelease(ctx context.Context, workflowSlug string, artifactID uuid.UUID, content *ReleaseContent) (*WorkflowRelease, error) { + response, err := c.service.PublishWorkflowRelease(ctx, workflowSlug, artifactID, content) + if err != nil { + return nil, err + } + + return protoToWorkflowRelease(response), nil +} + +func (c workflowClient) DeployRelease(ctx context.Context, workflowSlug string, releaseID uuid.UUID, clusterSlugs []string) (*WorkflowReleaseDeployment, error) { + response, err := c.service.DeployWorkflowRelease(ctx, workflowSlug, releaseID, clusterSlugs) + if err != nil { + return nil, err + } + + return protoToWorkflowReleaseDeployment(response.GetRelease(), response.GetClusters()), nil +} + +func (c workflowClient) UndeployRelease(ctx context.Context, workflowSlug string, releaseID uuid.UUID, clusterSlugs []string) (*WorkflowReleaseDeployment, error) { + response, err := c.service.UndeployWorkflowRelease(ctx, workflowSlug, releaseID, clusterSlugs) + if err != nil { + return nil, err + } + + return protoToWorkflowReleaseDeployment(response.GetRelease(), response.GetClusters()), nil +} + +func protoToWorkflow(workflow *workflowsv1.Workflow) *Workflow { + if workflow == nil { + return nil + } + + releases := make([]*WorkflowRelease, len(workflow.GetReleases())) + for i, release := range workflow.GetReleases() { + releases[i] = protoToWorkflowRelease(release) + } + + return &Workflow{ + Slug: workflow.GetSlug(), + Name: workflow.GetName(), + Description: workflow.GetDescription(), + Releases: releases, + } +} + +func protoToWorkflowRelease(release *workflowsv1.WorkflowRelease) *WorkflowRelease { + if release == nil { + return nil + } + + var createdAt time.Time + if release.GetCreatedAt() != nil { + createdAt = release.GetCreatedAt().AsTime() + } + + return &WorkflowRelease{ + ID: protoIDToUUID(release.GetId()), + Artifact: protoToArtifact(release.GetArtifact()), + Content: protoToReleaseContent(release.GetContent()), + CreatedAt: createdAt, + } +} + +func protoToArtifact(artifact *workflowsv1.Artifact) *Artifact { + if artifact == nil { + return nil + } + return &Artifact{ + ID: protoIDToUUID(artifact.GetId()), + Digest: artifact.GetDigest(), + } +} + +func protoToReleaseContent(content *workflowsv1.ReleaseContent) *ReleaseContent { + if content == nil { + return nil + } + + tasks := make([]TaskIdentifier, len(content.GetTasks())) + for i, task := range content.GetTasks() { + tasks[i] = protoToTaskIdentifier(task) + } + + return &ReleaseContent{ + Fingerprint: content.GetFingerprint(), + Tasks: tasks, + Files: protoToPaths(content.GetFiles()), + RunnerObjectPath: content.GetRunnerObjectPath(), + CommandOverride: content.GetCommandOverride(), + } +} + +func protoToPaths(paths []*workflowsv1.Path) []*Path { + converted := make([]*Path, len(paths)) + for i, path := range paths { + converted[i] = protoToPath(path) + } + return converted +} + +func protoToPath(path *workflowsv1.Path) *Path { + if path == nil { + return nil + } + + children := make([]*Path, len(path.GetChildren())) + for i, child := range path.GetChildren() { + children[i] = protoToPath(child) + } + + return &Path{ + Path: path.GetPath(), + Directory: path.GetDirectory(), + Children: children, + } +} + +func protoToWorkflowReleaseDeployment(release *workflowsv1.WorkflowRelease, clusters []*workflowsv1.Cluster) *WorkflowReleaseDeployment { + deployedClusters := make([]*Cluster, len(clusters)) + for i, cluster := range clusters { + deployedClusters[i] = protoToCluster(cluster) + } + + return &WorkflowReleaseDeployment{ + Release: protoToWorkflowRelease(release), + Clusters: deployedClusters, + } +} + +func protoToTaskIdentifier(identifier *workflowsv1.TaskIdentifier) TaskIdentifier { + if identifier == nil { + return nil + } + return NewTaskIdentifier(identifier.GetName(), identifier.GetVersion()) +} + +func taskIdentifiersToProto(tasks []TaskIdentifier) ([]*workflowsv1.TaskIdentifier, error) { + protoTasks := make([]*workflowsv1.TaskIdentifier, len(tasks)) + for i, task := range tasks { + if task == nil { + return nil, fmt.Errorf("task identifier at index %d is nil", i) + } + if err := ValidateIdentifier(task); err != nil { + return nil, err + } + protoTasks[i] = workflowsv1.TaskIdentifier_builder{ + Name: task.Name(), + Version: task.Version(), + }.Build() + } + return protoTasks, nil +} + +func releaseContentToProto(content *ReleaseContent) (*workflowsv1.ReleaseContent, error) { + if content == nil { + return nil, errors.New("release content is nil") + } + + tasks, err := taskIdentifiersToProto(content.Tasks) + if err != nil { + return nil, err + } + + return workflowsv1.ReleaseContent_builder{ + Fingerprint: content.Fingerprint, + Tasks: tasks, + Files: pathsToProto(content.Files), + RunnerObjectPath: content.RunnerObjectPath, + CommandOverride: content.CommandOverride, + }.Build(), nil +} + +func pathsToProto(paths []*Path) []*workflowsv1.Path { + converted := make([]*workflowsv1.Path, len(paths)) + for i, path := range paths { + converted[i] = pathToProto(path) + } + return converted +} + +func pathToProto(path *Path) *workflowsv1.Path { + if path == nil { + return nil + } + + children := make([]*workflowsv1.Path, len(path.Children)) + for i, child := range path.Children { + children[i] = pathToProto(child) + } + + return workflowsv1.Path_builder{ + Path: path.Path, + Directory: path.Directory, + Children: children, + }.Build() +} diff --git a/workflows/v1/workflows_test.go b/workflows/v1/workflows_test.go new file mode 100644 index 0000000..3fc53ff --- /dev/null +++ b/workflows/v1/workflows_test.go @@ -0,0 +1,322 @@ +package workflows + +import ( + "context" + "errors" + "strings" + "testing" + "time" + + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + tileboxv1 "github.com/tilebox/tilebox-go/protogen/tilebox/v1" + workflowsv1 "github.com/tilebox/tilebox-go/protogen/workflows/v1" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func TestWorkflowClient_Create(t *testing.T) { + ctx := context.Background() + service := &fakeWorkflowService{ + workflow: workflowsv1.Workflow_builder{ + Slug: "agentic-workflow", + Name: "Agentic Workflow", + Description: "Description", + }.Build(), + } + client := workflowClient{service: service} + + workflow, err := client.Create(ctx, "Agentic Workflow", WithDescription("Description")) + require.NoError(t, err) + + assert.Equal(t, "Agentic Workflow", service.createName) + assert.Equal(t, "Description", service.createDescription) + assert.Equal(t, "agentic-workflow", workflow.Slug) + assert.Equal(t, "Agentic Workflow", workflow.Name) + assert.Equal(t, "Description", workflow.Description) +} + +func TestWorkflowClient_List(t *testing.T) { + ctx := context.Background() + service := &fakeWorkflowService{ + listWorkflowsResponse: workflowsv1.ListWorkflowsResponse_builder{ + Workflows: []*workflowsv1.Workflow{ + workflowsv1.Workflow_builder{Slug: "one", Name: "One"}.Build(), + workflowsv1.Workflow_builder{Slug: "two", Name: "Two"}.Build(), + }, + }.Build(), + } + client := workflowClient{service: service} + + workflows, err := client.List(ctx) + require.NoError(t, err) + + require.Len(t, workflows, 2) + assert.Equal(t, "one", workflows[0].Slug) + assert.Equal(t, "two", workflows[1].Slug) +} + +func TestWorkflowClient_Get(t *testing.T) { + ctx := context.Background() + service := &fakeWorkflowService{ + workflow: workflowsv1.Workflow_builder{Slug: "agentic-workflow", Name: "Agentic Workflow"}.Build(), + } + client := workflowClient{service: service} + + workflow, err := client.Get(ctx, "agentic-workflow") + require.NoError(t, err) + + assert.Equal(t, "agentic-workflow", service.getSlug) + assert.Equal(t, "Agentic Workflow", workflow.Name) +} + +func TestWorkflowClient_PublishRelease(t *testing.T) { + ctx := context.Background() + releaseID := uuid.New() + artifactID := uuid.New() + digest := strings.Repeat("a", 64) + fingerprint := strings.Repeat("b", 64) + createdAt := time.Date(2026, time.May, 29, 12, 0, 0, 0, time.UTC) + service := &fakeWorkflowService{ + workflowRelease: workflowsv1.WorkflowRelease_builder{ + Id: tileboxv1.NewUUID(releaseID), + Artifact: workflowsv1.Artifact_builder{ + Id: tileboxv1.NewUUID(artifactID), + Digest: digest, + }.Build(), + Content: releaseContentToProtoMust(t, &ReleaseContent{ + Fingerprint: fingerprint, + Tasks: []TaskIdentifier{NewTaskIdentifier("tilebox.com/task/Review", "v1.0")}, + Files: []*Path{{ + Path: ".", + Directory: true, + Children: []*Path{{Path: "main.py"}}, + }}, + RunnerObjectPath: "my_module.my_runner:runner", + CommandOverride: []string{"python", "main.py"}, + }), + CreatedAt: timestamppb.New(createdAt), + }.Build(), + } + client := workflowClient{service: service} + content := &ReleaseContent{ + Fingerprint: fingerprint, + Tasks: []TaskIdentifier{NewTaskIdentifier("tilebox.com/task/Review", "v1.0")}, + Files: []*Path{{Path: ".", Directory: true, Children: []*Path{{Path: "main.py"}}}}, + RunnerObjectPath: "my_module.my_runner:runner", + CommandOverride: []string{"python", "main.py"}, + } + + release, err := client.PublishRelease(ctx, "agentic-workflow", artifactID, content) + require.NoError(t, err) + + assert.Equal(t, "agentic-workflow", service.publishWorkflowSlug) + assert.Equal(t, artifactID, service.publishArtifactID) + assert.Equal(t, content, service.publishContent) + assert.Equal(t, releaseID, release.ID) + require.NotNil(t, release.Artifact) + assert.Equal(t, artifactID, release.Artifact.ID) + assert.Equal(t, digest, release.Artifact.Digest) + require.NotNil(t, release.Content) + assert.Equal(t, fingerprint, release.Content.Fingerprint) + require.Len(t, release.Content.Tasks, 1) + assert.Equal(t, "tilebox.com/task/Review", release.Content.Tasks[0].Name()) + assert.Equal(t, "v1.0", release.Content.Tasks[0].Version()) + require.Len(t, release.Content.Files, 1) + assert.Equal(t, ".", release.Content.Files[0].Path) + assert.True(t, release.Content.Files[0].Directory) + require.Len(t, release.Content.Files[0].Children, 1) + assert.Equal(t, "main.py", release.Content.Files[0].Children[0].Path) + assert.Equal(t, "my_module.my_runner:runner", release.Content.RunnerObjectPath) + assert.Equal(t, []string{"python", "main.py"}, release.Content.CommandOverride) + assert.Equal(t, createdAt, release.CreatedAt) +} + +func TestWorkflowClient_DeployRelease(t *testing.T) { + ctx := context.Background() + releaseID := uuid.New() + service := &fakeWorkflowService{ + deployWorkflowReleaseResponse: workflowsv1.DeployWorkflowReleaseResponse_builder{ + Release: workflowsv1.WorkflowRelease_builder{Id: tileboxv1.NewUUID(releaseID)}.Build(), + Clusters: []*workflowsv1.Cluster{ + workflowsv1.Cluster_builder{Slug: "dev", DisplayName: "Dev"}.Build(), + }, + }.Build(), + } + client := workflowClient{service: service} + + deployment, err := client.DeployRelease(ctx, "agentic-workflow", releaseID, []string{"dev"}) + require.NoError(t, err) + + assert.Equal(t, "agentic-workflow", service.deployWorkflowSlug) + assert.Equal(t, releaseID, service.deployReleaseID) + assert.Equal(t, []string{"dev"}, service.deployClusterSlugs) + require.NotNil(t, deployment.Release) + assert.Equal(t, releaseID, deployment.Release.ID) + require.Len(t, deployment.Clusters, 1) + assert.Equal(t, "dev", deployment.Clusters[0].Slug) + assert.Equal(t, "Dev", deployment.Clusters[0].Name) +} + +func TestWorkflowClient_UndeployRelease(t *testing.T) { + ctx := context.Background() + releaseID := uuid.New() + service := &fakeWorkflowService{ + undeployWorkflowReleaseResponse: workflowsv1.UndeployWorkflowReleaseResponse_builder{ + Release: workflowsv1.WorkflowRelease_builder{Id: tileboxv1.NewUUID(releaseID)}.Build(), + Clusters: []*workflowsv1.Cluster{ + workflowsv1.Cluster_builder{Slug: "dev", DisplayName: "Dev"}.Build(), + }, + }.Build(), + } + client := workflowClient{service: service} + + deployment, err := client.UndeployRelease(ctx, "agentic-workflow", releaseID, []string{"dev"}) + require.NoError(t, err) + + assert.Equal(t, "agentic-workflow", service.undeployWorkflowSlug) + assert.Equal(t, releaseID, service.undeployReleaseID) + assert.Equal(t, []string{"dev"}, service.undeployClusterSlugs) + require.NotNil(t, deployment.Release) + assert.Equal(t, releaseID, deployment.Release.ID) + require.Len(t, deployment.Clusters, 1) + assert.Equal(t, "dev", deployment.Clusters[0].Slug) + assert.Equal(t, "Dev", deployment.Clusters[0].Name) +} + +func TestProtoToCluster_MapsDeployedWorkflows(t *testing.T) { + releaseID := uuid.New() + cluster := protoToCluster(workflowsv1.Cluster_builder{ + Slug: "dev", + DisplayName: "Dev", + Deletable: true, + DeployedReleases: []*workflowsv1.Workflow{ + workflowsv1.Workflow_builder{ + Slug: "agentic-workflow", + Name: "Agentic Workflow", + Releases: []*workflowsv1.WorkflowRelease{ + workflowsv1.WorkflowRelease_builder{Id: tileboxv1.NewUUID(releaseID)}.Build(), + }, + }.Build(), + }, + }.Build()) + + assert.Equal(t, "dev", cluster.Slug) + assert.Equal(t, "Dev", cluster.Name) + assert.True(t, cluster.Deletable) + require.Len(t, cluster.DeployedWorkflows, 1) + assert.Equal(t, "agentic-workflow", cluster.DeployedWorkflows[0].Slug) + require.Len(t, cluster.DeployedWorkflows[0].Releases, 1) + assert.Equal(t, releaseID, cluster.DeployedWorkflows[0].Releases[0].ID) +} + +func TestTaskIdentifiersToProto_ValidatesIdentifiers(t *testing.T) { + _, err := taskIdentifiersToProto([]TaskIdentifier{NewTaskIdentifier("task", "invalid")}) + require.Error(t, err) + assert.Contains(t, err.Error(), "invalid task version") +} + +func TestTaskIdentifiersToProto_RejectsNilIdentifiers(t *testing.T) { + _, err := taskIdentifiersToProto([]TaskIdentifier{nil}) + require.Error(t, err) + assert.Contains(t, err.Error(), "task identifier at index 0 is nil") +} + +func TestReleaseContentToProto_RejectsNilContent(t *testing.T) { + _, err := releaseContentToProto(nil) + require.Error(t, err) + assert.Contains(t, err.Error(), "release content is nil") +} + +func TestProtoToWorkflow_HandlesNil(t *testing.T) { + assert.Nil(t, protoToWorkflow(nil)) + assert.Nil(t, protoToWorkflowRelease(nil)) + assert.Nil(t, protoToArtifact(nil)) + assert.Nil(t, protoToReleaseContent(nil)) + assert.Nil(t, protoToPath(nil)) + assert.Nil(t, protoToTaskIdentifier(nil)) +} + +type fakeWorkflowService struct { + workflow *workflowsv1.Workflow + listWorkflowsResponse *workflowsv1.ListWorkflowsResponse + workflowRelease *workflowsv1.WorkflowRelease + deployWorkflowReleaseResponse *workflowsv1.DeployWorkflowReleaseResponse + undeployWorkflowReleaseResponse *workflowsv1.UndeployWorkflowReleaseResponse + err error + + createName string + createDescription string + getSlug string + + publishWorkflowSlug string + publishArtifactID uuid.UUID + publishContent *ReleaseContent + + deployWorkflowSlug string + deployReleaseID uuid.UUID + deployClusterSlugs []string + + undeployWorkflowSlug string + undeployReleaseID uuid.UUID + undeployClusterSlugs []string +} + +func (s *fakeWorkflowService) CreateCluster(context.Context, string) (*workflowsv1.Cluster, error) { + return nil, errors.New("not implemented") +} + +func (s *fakeWorkflowService) GetCluster(context.Context, string) (*workflowsv1.Cluster, error) { + return nil, errors.New("not implemented") +} + +func (s *fakeWorkflowService) DeleteCluster(context.Context, string) error { + return errors.New("not implemented") +} + +func (s *fakeWorkflowService) ListClusters(context.Context) (*workflowsv1.ListClustersResponse, error) { + return nil, errors.New("not implemented") +} + +func (s *fakeWorkflowService) CreateWorkflow(_ context.Context, name, description string) (*workflowsv1.Workflow, error) { + s.createName = name + s.createDescription = description + return s.workflow, s.err +} + +func (s *fakeWorkflowService) ListWorkflows(context.Context) (*workflowsv1.ListWorkflowsResponse, error) { + return s.listWorkflowsResponse, s.err +} + +func (s *fakeWorkflowService) GetWorkflow(_ context.Context, slug string) (*workflowsv1.Workflow, error) { + s.getSlug = slug + return s.workflow, s.err +} + +func (s *fakeWorkflowService) PublishWorkflowRelease(_ context.Context, workflowSlug string, artifactID uuid.UUID, content *ReleaseContent) (*workflowsv1.WorkflowRelease, error) { + s.publishWorkflowSlug = workflowSlug + s.publishArtifactID = artifactID + s.publishContent = content + return s.workflowRelease, s.err +} + +func (s *fakeWorkflowService) DeployWorkflowRelease(_ context.Context, workflowSlug string, releaseID uuid.UUID, clusterSlugs []string) (*workflowsv1.DeployWorkflowReleaseResponse, error) { + s.deployWorkflowSlug = workflowSlug + s.deployReleaseID = releaseID + s.deployClusterSlugs = clusterSlugs + return s.deployWorkflowReleaseResponse, s.err +} + +func (s *fakeWorkflowService) UndeployWorkflowRelease(_ context.Context, workflowSlug string, releaseID uuid.UUID, clusterSlugs []string) (*workflowsv1.UndeployWorkflowReleaseResponse, error) { + s.undeployWorkflowSlug = workflowSlug + s.undeployReleaseID = releaseID + s.undeployClusterSlugs = clusterSlugs + return s.undeployWorkflowReleaseResponse, s.err +} + +func releaseContentToProtoMust(tb testing.TB, content *ReleaseContent) *workflowsv1.ReleaseContent { + tb.Helper() + protoContent, err := releaseContentToProto(content) + require.NoError(tb, err) + return protoContent +}