From 524874b85eedd98f1a0f6f55265dd70e160f8910 Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Tue, 15 Oct 2024 09:48:24 -0400 Subject: [PATCH 01/30] wip: stub schedule page --- frontend/app/src/pages/main/index.tsx | 10 +- .../components/scheduled-runs-columns.tsx | 73 +++++++ .../src/pages/main/scheduled-runs/index.tsx | 185 ++++++++++++++++++ frontend/app/src/router.tsx | 9 + 4 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx create mode 100644 frontend/app/src/pages/main/scheduled-runs/index.tsx diff --git a/frontend/app/src/pages/main/index.tsx b/frontend/app/src/pages/main/index.tsx index 9296e6599..489dd3fa4 100644 --- a/frontend/app/src/pages/main/index.tsx +++ b/frontend/app/src/pages/main/index.tsx @@ -2,6 +2,7 @@ import { Button } from '@/components/ui/button'; import { cn } from '@/lib/utils'; import { AdjustmentsHorizontalIcon, + CalendarDaysIcon, QueueListIcon, ScaleIcon, ServerStackIcon, @@ -156,12 +157,19 @@ function Sidebar({ className, memberships, currTenant }: SidebarProps) { collapsibleChildren={workers} /> } /> + } + />
diff --git a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx new file mode 100644 index 000000000..230a55be8 --- /dev/null +++ b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx @@ -0,0 +1,73 @@ +import { ColumnDef } from '@tanstack/react-table'; +import { DataTableColumnHeader } from '../../../../components/molecules/data-table/data-table-column-header'; +import { RateLimit } from '@/lib/api'; +import RelativeDate from '@/components/molecules/relative-date'; +import { LimitIndicator } from '../../tenant-settings/resource-limits/components/resource-limit-columns'; +import { capitalize } from '@/lib/utils'; + +export type RateLimitRow = RateLimit & { + metadata: { + id: string; + }; +}; + +export const columns: ColumnDef[] = [ + { + accessorKey: 'RateLimitKey', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ + {row.original.key} +
+ ), + enableSorting: false, + enableHiding: true, + }, + { + accessorKey: 'Value', + header: ({ column }) => ( + + ), + cell: ({ row }) => { + return
{row.original.value}
; + }, + }, + { + accessorKey: 'LimitValue', + header: ({ column }) => ( + + ), + cell: ({ row }) => { + return
{row.original.limitValue}
; + }, + }, + { + accessorKey: 'LastRefill', + header: ({ column }) => ( + + ), + cell: ({ row }) => { + return ( +
+ +
+ ); + }, + }, + { + accessorKey: 'Window', + header: ({ column }) => ( + + ), + cell: ({ row }) => { + return
{capitalize(row.original.window)}
; + }, + }, +]; diff --git a/frontend/app/src/pages/main/scheduled-runs/index.tsx b/frontend/app/src/pages/main/scheduled-runs/index.tsx new file mode 100644 index 000000000..6e5e990e6 --- /dev/null +++ b/frontend/app/src/pages/main/scheduled-runs/index.tsx @@ -0,0 +1,185 @@ +import { DataTable } from '../../../components/molecules/data-table/data-table'; +import { RateLimitRow, columns } from './components/scheduled-runs-columns'; +import { Separator } from '@/components/ui/separator'; +import { useEffect, useMemo, useState } from 'react'; +import { + ColumnFiltersState, + PaginationState, + RowSelectionState, + SortingState, + VisibilityState, +} from '@tanstack/react-table'; +import { useQuery } from '@tanstack/react-query'; +import { + RateLimitOrderByDirection, + RateLimitOrderByField, + queries, +} from '@/lib/api'; +import invariant from 'tiny-invariant'; +import { useOutletContext, useSearchParams } from 'react-router-dom'; +import { TenantContextType } from '@/lib/outlet'; + +export default function RateLimits() { + return ( +
+
+

+ Scheduled Runs +

+ + +
+
+ ); +} + +function ScheduledRunsTable() { + const { tenant } = useOutletContext(); + const [searchParams, setSearchParams] = useSearchParams(); + + invariant(tenant); + + const [search, setSearch] = useState( + searchParams.get('search') || undefined, + ); + const [sorting, setSorting] = useState(() => { + const sortParam = searchParams.get('sort'); + if (sortParam) { + const [id, desc] = sortParam.split(':'); + return [{ id, desc: desc === 'desc' }]; + } + return []; + }); + const [columnFilters, setColumnFilters] = useState(() => { + const filtersParam = searchParams.get('filters'); + if (filtersParam) { + return JSON.parse(filtersParam); + } + return []; + }); + const [columnVisibility, setColumnVisibility] = useState({ + RateLimitId: false, + }); + + const [pagination, setPagination] = useState(() => { + const pageIndex = Number(searchParams.get('pageIndex')) || 0; + const pageSize = Number(searchParams.get('pageSize')) || 50; + return { pageIndex, pageSize }; + }); + const [pageSize, setPageSize] = useState( + Number(searchParams.get('pageSize')) || 50, + ); + const [rowSelection, setRowSelection] = useState({}); + + useEffect(() => { + const newSearchParams = new URLSearchParams(searchParams); + if (search) { + newSearchParams.set('search', search); + } else { + newSearchParams.delete('search'); + } + newSearchParams.set( + 'sort', + sorting.map((s) => `${s.id}:${s.desc ? 'desc' : 'asc'}`).join(','), + ); + newSearchParams.set('filters', JSON.stringify(columnFilters)); + newSearchParams.set('pageIndex', pagination.pageIndex.toString()); + newSearchParams.set('pageSize', pagination.pageSize.toString()); + setSearchParams(newSearchParams); + }, [ + search, + sorting, + columnFilters, + pagination, + setSearchParams, + searchParams, + ]); + + const orderByDirection = useMemo((): + | RateLimitOrderByDirection + | undefined => { + if (!sorting.length) { + return; + } + + return sorting[0]?.desc + ? RateLimitOrderByDirection.Desc + : RateLimitOrderByDirection.Asc; + }, [sorting]); + + const orderByField = useMemo((): RateLimitOrderByField | undefined => { + if (!sorting.length) { + return; + } + + switch (sorting[0]?.id) { + case 'Key': + return RateLimitOrderByField.Key; + case 'Value': + return RateLimitOrderByField.Value; + case 'LimitValue': + return RateLimitOrderByField.LimitValue; + default: + return RateLimitOrderByField.Key; + } + }, [sorting]); + + const offset = useMemo(() => { + if (!pagination) { + return; + } + + return pagination.pageIndex * pagination.pageSize; + }, [pagination]); + + const { + data, + isLoading: rateLimitsIsLoading, + error: rateLimitsError, + } = useQuery({ + ...queries.rate_limits.list(tenant.metadata.id, { + search, + orderByField, + orderByDirection, + offset, + limit: pageSize, + }), + refetchInterval: 2000, + }); + + const tableData = + data?.rows?.map( + (row): RateLimitRow => ({ + ...row, + metadata: { + id: row.key, + }, + }), + ) || []; + + return ( + row.metadata.id} + /> + ); +} diff --git a/frontend/app/src/router.tsx b/frontend/app/src/router.tsx index 85fe39553..bd1e9d050 100644 --- a/frontend/app/src/router.tsx +++ b/frontend/app/src/router.tsx @@ -132,6 +132,15 @@ const routes: RouteObject[] = [ }; }), }, + { + path: '/scheduled', + lazy: async () => + import('./pages/main/scheduled-runs').then((res) => { + return { + Component: res.default, + }; + }), + }, { path: '/workflows', lazy: async () => From ee6fc355e3e29ad9eb231c9c36b20d7b83376ef8 Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Tue, 15 Oct 2024 13:22:50 -0400 Subject: [PATCH 02/30] wip: stub list --- .../openapi/components/schemas/_index.yaml | 6 + .../components/schemas/workflow_run.yaml | 45 ++ api-contracts/openapi/openapi.yaml | 2 + .../openapi/paths/workflow/workflow.yaml | 83 +++ .../handlers/workflows/list_scheduled.go | 121 ++++ api/v1/server/oas/gen/openapi.gen.go | 537 ++++++++++++------ .../server/oas/transformers/workflow_run.go | 15 + frontend/app/src/lib/api/generated/Api.ts | 51 ++ .../src/lib/api/generated/data-contracts.ts | 21 + frontend/app/src/lib/api/queries.ts | 8 + .../components/scheduled-runs-columns.tsx | 64 +-- .../src/pages/main/scheduled-runs/index.tsx | 58 +- pkg/client/rest/gen.go | 274 +++++++++ .../prisma/dbsqlc/workflow_runs.sql | 38 ++ .../prisma/dbsqlc/workflow_runs.sql.go | 108 ++++ pkg/repository/prisma/workflow_run.go | 37 ++ pkg/repository/workflow_run.go | 23 + 17 files changed, 1234 insertions(+), 257 deletions(-) create mode 100644 api/v1/server/handlers/workflows/list_scheduled.go diff --git a/api-contracts/openapi/components/schemas/_index.yaml b/api-contracts/openapi/components/schemas/_index.yaml index 9c20d96c2..a8dce9abc 100644 --- a/api-contracts/openapi/components/schemas/_index.yaml +++ b/api-contracts/openapi/components/schemas/_index.yaml @@ -152,6 +152,12 @@ ReplayWorkflowRunsResponse: $ref: "./workflow_run.yaml#/ReplayWorkflowRunsResponse" WorkflowRunList: $ref: "./workflow_run.yaml#/WorkflowRunList" +ScheduledWorkflows: + $ref: "./workflow_run.yaml#/ScheduledWorkflows" +ScheduledWorkflowsList: + $ref: "./workflow_run.yaml#/ScheduledWorkflowsList" +ScheduledWorkflowsOrderByField: + $ref: "./workflow_run.yaml#/ScheduledWorkflowsOrderByField" WorkflowRunOrderByField: $ref: "./workflow_run.yaml#/WorkflowRunOrderByField" WorkflowRunOrderByDirection: diff --git a/api-contracts/openapi/components/schemas/workflow_run.yaml b/api-contracts/openapi/components/schemas/workflow_run.yaml index 778360af0..d8d0c8deb 100644 --- a/api-contracts/openapi/components/schemas/workflow_run.yaml +++ b/api-contracts/openapi/components/schemas/workflow_run.yaml @@ -6,6 +6,11 @@ WorkflowRunOrderByField: - finishedAt - duration +ScheduledWorkflowsOrderByField: + type: string + enum: + - triggerAt + WorkflowRunOrderByDirection: type: string enum: @@ -161,6 +166,46 @@ WorkflowRunList: pagination: $ref: "./metadata.yaml#/PaginationResponse" +ScheduledWorkflows: + type: object + properties: + metadata: + $ref: "./metadata.yaml#/APIResourceMeta" + tenantId: + type: string + workflowVersionId: + type: string + workflowId: + type: string + workflowName: + type: string + triggerAt: + type: string + format: date-time + input: + type: object + additionalProperties: true + additionalMetadata: + type: object + additionalProperties: true + required: + - metadata + - tenantId + - workflowVersionId + - workflowName + - workflowId + - triggerAt + +ScheduledWorkflowsList: + type: object + properties: + rows: + type: array + items: + $ref: "#/ScheduledWorkflows" + pagination: + $ref: "./metadata.yaml#/PaginationResponse" + WorkflowRunsMetricsCounts: type: object properties: diff --git a/api-contracts/openapi/openapi.yaml b/api-contracts/openapi/openapi.yaml index cc4af51db..ec57e0404 100644 --- a/api-contracts/openapi/openapi.yaml +++ b/api-contracts/openapi/openapi.yaml @@ -116,6 +116,8 @@ paths: $ref: "./paths/event/event.yaml#/keys" /api/v1/tenants/{tenant}/workflows: $ref: "./paths/workflow/workflow.yaml#/withTenant" + /api/v1/tenants/{tenant}/workflows/scheduled: + $ref: "./paths/workflow/workflow.yaml#/scheduledList" /api/v1/tenants/{tenant}/workflows/cancel: $ref: "./paths/workflow/workflow.yaml#/cancelWorkflowRuns" /api/v1/workflows/{workflow}: diff --git a/api-contracts/openapi/paths/workflow/workflow.yaml b/api-contracts/openapi/paths/workflow/workflow.yaml index 1d8ccc70c..5c5ee78ba 100644 --- a/api-contracts/openapi/paths/workflow/workflow.yaml +++ b/api-contracts/openapi/paths/workflow/workflow.yaml @@ -826,3 +826,86 @@ workflowWorkersCount: summary: Get workflow worker count tags: - Workflow + + +scheduledList: + get: + x-resources: ["tenant"] + description: Get all scheduled workflow runs for a tenant + operationId: workflow-scheduled:list + parameters: + - description: The tenant id + in: path + name: tenant + required: true + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + - description: The number to skip + in: query + name: offset + required: false + schema: + type: integer + format: int64 + - description: The number to limit by + in: query + name: limit + required: false + schema: + type: integer + format: int64 + - description: The workflow id to get runs for. + in: query + name: workflowId + required: false + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + - description: A list of metadata key value pairs to filter by + in: query + name: additionalMetadata + example: ["key1:value1", "key2:value2"] + required: false + schema: + type: array + items: + type: string + - description: The order by field + in: query + name: orderByField + required: false + schema: + $ref: "../../components/schemas/_index.yaml#/ScheduledWorkflowsOrderByField" + - description: The order by direction + in: query + name: orderByDirection + required: false + schema: + $ref: "../../components/schemas/_index.yaml#/WorkflowRunOrderByDirection" + responses: + "200": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/ScheduledWorkflowsList" + description: Successfully retrieved the workflow runs + "400": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: A malformed or bad request + "403": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: Forbidden + summary: Get workflow runs + tags: + - ScheduledWorkflows diff --git a/api/v1/server/handlers/workflows/list_scheduled.go b/api/v1/server/handlers/workflows/list_scheduled.go new file mode 100644 index 000000000..1d4274829 --- /dev/null +++ b/api/v1/server/handlers/workflows/list_scheduled.go @@ -0,0 +1,121 @@ +package workflows + +import ( + "context" + "fmt" + "math" + "strings" + "time" + + "github.com/labstack/echo/v4" + + "github.com/hatchet-dev/hatchet/api/v1/server/oas/apierrors" + "github.com/hatchet-dev/hatchet/api/v1/server/oas/gen" + "github.com/hatchet-dev/hatchet/api/v1/server/oas/transformers" + "github.com/hatchet-dev/hatchet/pkg/repository" + "github.com/hatchet-dev/hatchet/pkg/repository/prisma/db" +) + +func (t *WorkflowService) WorkflowScheduledList(ctx echo.Context, request gen.WorkflowScheduledListRequestObject) (gen.WorkflowScheduledListResponseObject, error) { + tenant := ctx.Get("tenant").(*db.TenantModel) + + limit := 50 + offset := 0 + orderDirection := "DESC" + orderBy := "triggerAt" + + listOpts := &repository.ListScheduledWorkflowsOpts{ + Limit: &limit, + Offset: &offset, + OrderBy: &orderBy, + OrderDirection: &orderDirection, + } + + if request.Params.OrderByField != nil { + orderBy = string(*request.Params.OrderByField) + listOpts.OrderBy = &orderBy + } + + if request.Params.OrderByDirection != nil { + orderDirection = string(*request.Params.OrderByDirection) + listOpts.OrderDirection = &orderDirection + } + + if request.Params.Limit != nil { + limit = int(*request.Params.Limit) + listOpts.Limit = &limit + } + + if request.Params.Offset != nil { + offset = int(*request.Params.Offset) + listOpts.Offset = &offset + } + + if request.Params.WorkflowId != nil { + workflowIdStr := request.Params.WorkflowId.String() + listOpts.WorkflowId = &workflowIdStr + } + + // if request.Params.Statuses != nil { + // statuses := make([]db.WorkflowRunStatus, len(*request.Params.Statuses)) + + // for i, status := range *request.Params.Statuses { + // statuses[i] = db.WorkflowRunStatus(status) + // } + + // listOpts.Statuses = &statuses + // } + + if request.Params.AdditionalMetadata != nil { + additionalMetadata := make(map[string]interface{}, len(*request.Params.AdditionalMetadata)) + + for _, v := range *request.Params.AdditionalMetadata { + splitValue := strings.Split(fmt.Sprintf("%v", v), ":") + + if len(splitValue) == 2 { + additionalMetadata[splitValue[0]] = splitValue[1] + } else { + return gen.WorkflowScheduledList400JSONResponse(apierrors.NewAPIErrors("Additional metadata filters must be in the format key:value.")), nil + + } + } + + listOpts.AdditionalMetadata = additionalMetadata + } + + dbCtx, cancel := context.WithTimeout(ctx.Request().Context(), 30*time.Second) + defer cancel() + + scheduled, count, err := t.config.APIRepository.WorkflowRun().ListScheduledWorkflows(dbCtx, tenant.ID, listOpts) + + if err != nil { + return nil, err + } + + rows := make([]gen.ScheduledWorkflows, len(scheduled)) + + for i, workflow := range scheduled { + workflowCp := workflow + rows[i] = *transformers.ToScheduledWorkflowsFromSQLC(workflowCp) + } + + // use the total rows and limit to calculate the total pages + totalPages := int64(math.Ceil(float64(count) / float64(limit))) + currPage := 1 + int64(math.Ceil(float64(offset)/float64(limit))) + nextPage := currPage + 1 + + if currPage == totalPages { + nextPage = currPage + } + + return gen.WorkflowScheduledList200JSONResponse( + gen.ScheduledWorkflowsList{ + Rows: &rows, + Pagination: &gen.PaginationResponse{ + NumPages: &totalPages, + CurrentPage: &currPage, + NextPage: &nextPage, + }, + }, + ), nil +} diff --git a/api/v1/server/oas/gen/openapi.gen.go b/api/v1/server/oas/gen/openapi.gen.go index c3c9a14dd..dac147a85 100644 --- a/api/v1/server/oas/gen/openapi.gen.go +++ b/api/v1/server/oas/gen/openapi.gen.go @@ -78,6 +78,11 @@ const ( Value RateLimitOrderByField = "value" ) +// Defines values for ScheduledWorkflowsOrderByField. +const ( + TriggerAt ScheduledWorkflowsOrderByField = "triggerAt" +) + // Defines values for StepRunEventReason. const ( StepRunEventReasonASSIGNED StepRunEventReason = "ASSIGNED" @@ -610,6 +615,27 @@ type SNSIntegration struct { TopicArn string `json:"topicArn"` } +// ScheduledWorkflows defines model for ScheduledWorkflows. +type ScheduledWorkflows struct { + AdditionalMetadata *map[string]interface{} `json:"additionalMetadata,omitempty"` + Input *map[string]interface{} `json:"input,omitempty"` + Metadata APIResourceMeta `json:"metadata"` + TenantId string `json:"tenantId"` + TriggerAt time.Time `json:"triggerAt"` + WorkflowId string `json:"workflowId"` + WorkflowName string `json:"workflowName"` + WorkflowVersionId string `json:"workflowVersionId"` +} + +// ScheduledWorkflowsList defines model for ScheduledWorkflowsList. +type ScheduledWorkflowsList struct { + Pagination *PaginationResponse `json:"pagination,omitempty"` + Rows *[]ScheduledWorkflows `json:"rows,omitempty"` +} + +// ScheduledWorkflowsOrderByField defines model for ScheduledWorkflowsOrderByField. +type ScheduledWorkflowsOrderByField string + // SemaphoreSlots defines model for SemaphoreSlots. type SemaphoreSlots struct { // ActionId The action id. @@ -1520,6 +1546,27 @@ type WorkflowRunGetMetricsParams struct { CreatedBefore *time.Time `form:"createdBefore,omitempty" json:"createdBefore,omitempty"` } +// WorkflowScheduledListParams defines parameters for WorkflowScheduledList. +type WorkflowScheduledListParams struct { + // Offset The number to skip + Offset *int64 `form:"offset,omitempty" json:"offset,omitempty"` + + // Limit The number to limit by + Limit *int64 `form:"limit,omitempty" json:"limit,omitempty"` + + // WorkflowId The workflow id to get runs for. + WorkflowId *openapi_types.UUID `form:"workflowId,omitempty" json:"workflowId,omitempty"` + + // AdditionalMetadata A list of metadata key value pairs to filter by + AdditionalMetadata *[]string `form:"additionalMetadata,omitempty" json:"additionalMetadata,omitempty"` + + // OrderByField The order by field + OrderByField *ScheduledWorkflowsOrderByField `form:"orderByField,omitempty" json:"orderByField,omitempty"` + + // OrderByDirection The order by direction + OrderByDirection *WorkflowRunOrderByDirection `form:"orderByDirection,omitempty" json:"orderByDirection,omitempty"` +} + // WorkflowGetMetricsParams defines parameters for WorkflowGetMetrics. type WorkflowGetMetricsParams struct { // Status A status of workflow run statuses to filter by @@ -1792,6 +1839,9 @@ type ServerInterface interface { // Get workflow runs // (GET /api/v1/tenants/{tenant}/workflows/runs/metrics) WorkflowRunGetMetrics(ctx echo.Context, tenant openapi_types.UUID, params WorkflowRunGetMetricsParams) error + // Get workflow runs + // (GET /api/v1/tenants/{tenant}/workflows/scheduled) + WorkflowScheduledList(ctx echo.Context, tenant openapi_types.UUID, params WorkflowScheduledListParams) error // Get workflow worker count // (GET /api/v1/tenants/{tenant}/workflows/{workflow}/worker-count) WorkflowGetWorkersCount(ctx echo.Context, tenant openapi_types.UUID, workflow openapi_types.UUID) error @@ -3454,6 +3504,70 @@ func (w *ServerInterfaceWrapper) WorkflowRunGetMetrics(ctx echo.Context) error { return err } +// WorkflowScheduledList converts echo context to params. +func (w *ServerInterfaceWrapper) WorkflowScheduledList(ctx echo.Context) error { + var err error + // ------------- Path parameter "tenant" ------------- + var tenant openapi_types.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "tenant", runtime.ParamLocationPath, ctx.Param("tenant"), &tenant) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tenant: %s", err)) + } + + ctx.Set(BearerAuthScopes, []string{}) + + ctx.Set(CookieAuthScopes, []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params WorkflowScheduledListParams + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "workflowId" ------------- + + err = runtime.BindQueryParameter("form", true, false, "workflowId", ctx.QueryParams(), ¶ms.WorkflowId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter workflowId: %s", err)) + } + + // ------------- Optional query parameter "additionalMetadata" ------------- + + err = runtime.BindQueryParameter("form", true, false, "additionalMetadata", ctx.QueryParams(), ¶ms.AdditionalMetadata) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter additionalMetadata: %s", err)) + } + + // ------------- Optional query parameter "orderByField" ------------- + + err = runtime.BindQueryParameter("form", true, false, "orderByField", ctx.QueryParams(), ¶ms.OrderByField) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderByField: %s", err)) + } + + // ------------- Optional query parameter "orderByDirection" ------------- + + err = runtime.BindQueryParameter("form", true, false, "orderByDirection", ctx.QueryParams(), ¶ms.OrderByDirection) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderByDirection: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.WorkflowScheduledList(ctx, tenant, params) + return err +} + // WorkflowGetWorkersCount converts echo context to params. func (w *ServerInterfaceWrapper) WorkflowGetWorkersCount(ctx echo.Context) error { var err error @@ -3949,6 +4063,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.POST(baseURL+"/api/v1/tenants/:tenant/workflows/cancel", wrapper.WorkflowRunCancel) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/runs", wrapper.WorkflowRunList) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/runs/metrics", wrapper.WorkflowRunGetMetrics) + router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/scheduled", wrapper.WorkflowScheduledList) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/:workflow/worker-count", wrapper.WorkflowGetWorkersCount) router.GET(baseURL+"/api/v1/users/current", wrapper.UserGetCurrent) router.GET(baseURL+"/api/v1/users/github/callback", wrapper.UserUpdateGithubOauthCallback) @@ -6190,6 +6305,42 @@ func (response WorkflowRunGetMetrics403JSONResponse) VisitWorkflowRunGetMetricsR return json.NewEncoder(w).Encode(response) } +type WorkflowScheduledListRequestObject struct { + Tenant openapi_types.UUID `json:"tenant"` + Params WorkflowScheduledListParams +} + +type WorkflowScheduledListResponseObject interface { + VisitWorkflowScheduledListResponse(w http.ResponseWriter) error +} + +type WorkflowScheduledList200JSONResponse ScheduledWorkflowsList + +func (response WorkflowScheduledList200JSONResponse) VisitWorkflowScheduledListResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type WorkflowScheduledList400JSONResponse APIErrors + +func (response WorkflowScheduledList400JSONResponse) VisitWorkflowScheduledListResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(400) + + return json.NewEncoder(w).Encode(response) +} + +type WorkflowScheduledList403JSONResponse APIErrors + +func (response WorkflowScheduledList403JSONResponse) VisitWorkflowScheduledListResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(403) + + return json.NewEncoder(w).Encode(response) +} + type WorkflowGetWorkersCountRequestObject struct { Tenant openapi_types.UUID `json:"tenant"` Workflow openapi_types.UUID `json:"workflow"` @@ -7230,6 +7381,8 @@ type StrictServerInterface interface { WorkflowRunGetMetrics(ctx echo.Context, request WorkflowRunGetMetricsRequestObject) (WorkflowRunGetMetricsResponseObject, error) + WorkflowScheduledList(ctx echo.Context, request WorkflowScheduledListRequestObject) (WorkflowScheduledListResponseObject, error) + WorkflowGetWorkersCount(ctx echo.Context, request WorkflowGetWorkersCountRequestObject) (WorkflowGetWorkersCountResponseObject, error) UserGetCurrent(ctx echo.Context, request UserGetCurrentRequestObject) (UserGetCurrentResponseObject, error) @@ -8872,6 +9025,32 @@ func (sh *strictHandler) WorkflowRunGetMetrics(ctx echo.Context, tenant openapi_ return nil } +// WorkflowScheduledList operation middleware +func (sh *strictHandler) WorkflowScheduledList(ctx echo.Context, tenant openapi_types.UUID, params WorkflowScheduledListParams) error { + var request WorkflowScheduledListRequestObject + + request.Tenant = tenant + request.Params = params + + handler := func(ctx echo.Context, request interface{}) (interface{}, error) { + return sh.ssi.WorkflowScheduledList(ctx, request.(WorkflowScheduledListRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "WorkflowScheduledList") + } + + response, err := handler(ctx, request) + + if err != nil { + return err + } else if validResponse, ok := response.(WorkflowScheduledListResponseObject); ok { + return validResponse.VisitWorkflowScheduledListResponse(ctx.Response()) + } else if response != nil { + return fmt.Errorf("Unexpected response type: %T", response) + } + return nil +} + // WorkflowGetWorkersCount operation middleware func (sh *strictHandler) WorkflowGetWorkersCount(ctx echo.Context, tenant openapi_types.UUID, workflow openapi_types.UUID) error { var request WorkflowGetWorkersCountRequestObject @@ -9525,185 +9704,187 @@ func (sh *strictHandler) WorkflowVersionGet(ctx echo.Context, workflow openapi_t var swaggerSpec = []string{ "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/v1/server/oas/transformers/workflow_run.go b/api/v1/server/oas/transformers/workflow_run.go index a54771552..0cd9e8dc6 100644 --- a/api/v1/server/oas/transformers/workflow_run.go +++ b/api/v1/server/oas/transformers/workflow_run.go @@ -482,3 +482,18 @@ func ToWorkflowRunFromSQLC(row *dbsqlc.ListWorkflowRunsRow) *gen.WorkflowRun { return res } + +func ToScheduledWorkflowsFromSQLC(scheduled *dbsqlc.ListScheduledWorkflowsRow) *gen.ScheduledWorkflows { + + res := &gen.ScheduledWorkflows{ + Metadata: *toAPIMetadata(sqlchelpers.UUIDToStr(scheduled.ID), time.Now(), time.Now()), + WorkflowVersionId: sqlchelpers.UUIDToStr(scheduled.WorkflowVersionId), + WorkflowId: sqlchelpers.UUIDToStr(scheduled.WorkflowId), + WorkflowName: scheduled.Name, + TenantId: sqlchelpers.UUIDToStr(scheduled.TenantId), + TriggerAt: scheduled.TriggerAt.Time, + // AdditionalMetadata: &additionalMetadata, + } + + return res +} diff --git a/frontend/app/src/lib/api/generated/Api.ts b/frontend/app/src/lib/api/generated/Api.ts index 8ecc19847..ebded887d 100644 --- a/frontend/app/src/lib/api/generated/Api.ts +++ b/frontend/app/src/lib/api/generated/Api.ts @@ -49,6 +49,8 @@ import { ReplayWorkflowRunsRequest, ReplayWorkflowRunsResponse, RerunStepRunRequest, + ScheduledWorkflowsList, + ScheduledWorkflowsOrderByField, SNSIntegration, StepRun, StepRunArchiveList, @@ -1115,6 +1117,55 @@ export class Api extends HttpClient + this.request({ + path: `/api/v1/tenants/${tenant}/workflows/scheduled`, + method: 'GET', + query: query, + secure: true, + format: 'json', + ...params, + }); /** * @description Cancel a batch of workflow runs * diff --git a/frontend/app/src/lib/api/generated/data-contracts.ts b/frontend/app/src/lib/api/generated/data-contracts.ts index 0a4f1bf6a..da3ea0a27 100644 --- a/frontend/app/src/lib/api/generated/data-contracts.ts +++ b/frontend/app/src/lib/api/generated/data-contracts.ts @@ -760,6 +760,27 @@ export interface WorkflowRunList { pagination?: PaginationResponse; } +export interface ScheduledWorkflows { + metadata: APIResourceMeta; + tenantId: string; + workflowVersionId: string; + workflowId: string; + workflowName: string; + /** @format date-time */ + triggerAt: string; + input?: Record; + additionalMetadata?: Record; +} + +export interface ScheduledWorkflowsList { + rows?: ScheduledWorkflows[]; + pagination?: PaginationResponse; +} + +export enum ScheduledWorkflowsOrderByField { + TriggerAt = 'triggerAt', +} + export enum WorkflowRunOrderByField { CreatedAt = 'createdAt', StartedAt = 'startedAt', diff --git a/frontend/app/src/lib/api/queries.ts b/frontend/app/src/lib/api/queries.ts index 42b8953c2..513b917bc 100644 --- a/frontend/app/src/lib/api/queries.ts +++ b/frontend/app/src/lib/api/queries.ts @@ -14,6 +14,7 @@ type WorkflowRunMetrics = Parameters[1]; type WorkflowRunEventsMetrics = Parameters< typeof cloudApi.workflowRunEventsGetMetrics >[1]; +type WorkflowScheduledQuery = Parameters[1]; export const queries = createQueryKeyStore({ cloud: { @@ -179,6 +180,13 @@ export const queries = createQueryKeyStore({ // ).data, // }), }, + scheduledRuns: { + list: (tenant: string, query: WorkflowScheduledQuery) => ({ + queryKey: ['scheduled-run:list', tenant, query], + queryFn: async () => + (await api.workflowScheduledList(tenant, query)).data, + }), + }, workflowRuns: { list: (tenant: string, query: ListWorkflowRunsQuery) => ({ queryKey: ['workflow-run:list', tenant, query], diff --git a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx index 230a55be8..0380f42c3 100644 --- a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx +++ b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx @@ -1,9 +1,7 @@ import { ColumnDef } from '@tanstack/react-table'; import { DataTableColumnHeader } from '../../../../components/molecules/data-table/data-table-column-header'; -import { RateLimit } from '@/lib/api'; +import { RateLimit, ScheduledWorkflows } from '@/lib/api'; import RelativeDate from '@/components/molecules/relative-date'; -import { LimitIndicator } from '../../tenant-settings/resource-limits/components/resource-limit-columns'; -import { capitalize } from '@/lib/utils'; export type RateLimitRow = RateLimit & { metadata: { @@ -11,63 +9,31 @@ export type RateLimitRow = RateLimit & { }; }; -export const columns: ColumnDef[] = [ +export const columns: ColumnDef[] = [ { - accessorKey: 'RateLimitKey', + accessorKey: 'triggerAt', header: ({ column }) => ( - + ), cell: ({ row }) => (
- - {row.original.key} +
), - enableSorting: false, - enableHiding: true, - }, - { - accessorKey: 'Value', - header: ({ column }) => ( - - ), - cell: ({ row }) => { - return
{row.original.value}
; - }, - }, - { - accessorKey: 'LimitValue', - header: ({ column }) => ( - - ), - cell: ({ row }) => { - return
{row.original.limitValue}
; - }, }, { - accessorKey: 'LastRefill', + accessorKey: 'Workflow', header: ({ column }) => ( - + ), - cell: ({ row }) => { - return ( -
- -
- ); - }, - }, - { - accessorKey: 'Window', - header: ({ column }) => ( - + cell: ({ row }) => ( + ), - cell: ({ row }) => { - return
{capitalize(row.original.window)}
; - }, + enableSorting: false, + enableHiding: true, }, ]; diff --git a/frontend/app/src/pages/main/scheduled-runs/index.tsx b/frontend/app/src/pages/main/scheduled-runs/index.tsx index 6e5e990e6..7374a28d4 100644 --- a/frontend/app/src/pages/main/scheduled-runs/index.tsx +++ b/frontend/app/src/pages/main/scheduled-runs/index.tsx @@ -1,5 +1,5 @@ import { DataTable } from '../../../components/molecules/data-table/data-table'; -import { RateLimitRow, columns } from './components/scheduled-runs-columns'; +import { columns } from './components/scheduled-runs-columns'; import { Separator } from '@/components/ui/separator'; import { useEffect, useMemo, useState } from 'react'; import { @@ -11,8 +11,8 @@ import { } from '@tanstack/react-table'; import { useQuery } from '@tanstack/react-query'; import { - RateLimitOrderByDirection, - RateLimitOrderByField, + ScheduledWorkflowsOrderByField, + WorkflowRunOrderByDirection, queries, } from '@/lib/api'; import invariant from 'tiny-invariant'; @@ -96,31 +96,29 @@ function ScheduledRunsTable() { ]); const orderByDirection = useMemo((): - | RateLimitOrderByDirection + | WorkflowRunOrderByDirection | undefined => { if (!sorting.length) { return; } return sorting[0]?.desc - ? RateLimitOrderByDirection.Desc - : RateLimitOrderByDirection.Asc; + ? WorkflowRunOrderByDirection.DESC + : WorkflowRunOrderByDirection.ASC; }, [sorting]); - const orderByField = useMemo((): RateLimitOrderByField | undefined => { + const orderByField = useMemo((): + | ScheduledWorkflowsOrderByField + | undefined => { if (!sorting.length) { return; } switch (sorting[0]?.id) { - case 'Key': - return RateLimitOrderByField.Key; - case 'Value': - return RateLimitOrderByField.Value; - case 'LimitValue': - return RateLimitOrderByField.LimitValue; + case 'triggerAt': + return ScheduledWorkflowsOrderByField.TriggerAt; default: - return RateLimitOrderByField.Key; + return ScheduledWorkflowsOrderByField.TriggerAt; } }, [sorting]); @@ -134,11 +132,11 @@ function ScheduledRunsTable() { const { data, - isLoading: rateLimitsIsLoading, - error: rateLimitsError, + isLoading: queryIsLoading, + error: queryError, } = useQuery({ - ...queries.rate_limits.list(tenant.metadata.id, { - search, + ...queries.scheduledRuns.list(tenant.metadata.id, { + // TODO: add filters orderByField, orderByDirection, offset, @@ -147,22 +145,22 @@ function ScheduledRunsTable() { refetchInterval: 2000, }); - const tableData = - data?.rows?.map( - (row): RateLimitRow => ({ - ...row, - metadata: { - id: row.key, - }, - }), - ) || []; + // const tableData = + // data?.rows?.map( + // (row): ScheduledWorkflows => ({ + // ...row, + // metadata: { + // id: row.key, + // }, + // }), + // ) || []; return ( Date: Thu, 24 Oct 2024 10:47:43 -0400 Subject: [PATCH 03/30] fix: 2025 bug... --- frontend/app/src/components/molecules/relative-date.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/app/src/components/molecules/relative-date.tsx b/frontend/app/src/components/molecules/relative-date.tsx index 12ee1ba3b..3e588c102 100644 --- a/frontend/app/src/components/molecules/relative-date.tsx +++ b/frontend/app/src/components/molecules/relative-date.tsx @@ -65,6 +65,10 @@ const RelativeDate: React.FC = ({ } }, [formattedDate, future]); + if (date == '0001-01-01T00:00:00Z') { + return null; + } + return ( From 2757bd97da3111acbb78564f86e89c4c2ce1308d Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Thu, 24 Oct 2024 10:53:53 -0400 Subject: [PATCH 04/30] feat: wip cron list --- .../openapi/components/schemas/_index.yaml | 6 + .../components/schemas/workflow_run.yaml | 44 ++ api-contracts/openapi/openapi.yaml | 2 + .../openapi/paths/workflow/workflow.yaml | 84 ++- .../server/handlers/workflows/list_crons.go | 121 ++++ api/v1/server/oas/gen/openapi.gen.go | 549 ++++++++++++------ .../server/oas/transformers/workflow_run.go | 16 + frontend/app/src/lib/api/generated/Api.ts | 53 +- .../src/lib/api/generated/data-contracts.ts | 20 + frontend/app/src/lib/api/queries.ts | 7 + .../main/crons/components/crons-columns.tsx | 52 ++ frontend/app/src/pages/main/crons/index.tsx | 181 ++++++ frontend/app/src/pages/main/index.tsx | 9 +- frontend/app/src/router.tsx | 9 + pkg/client/rest/gen.go | 282 ++++++++- .../prisma/dbsqlc/workflow_runs.sql | 32 + .../prisma/dbsqlc/workflow_runs.sql.go | 99 ++++ pkg/repository/prisma/workflow_run.go | 37 ++ pkg/repository/workflow_run.go | 23 + 19 files changed, 1436 insertions(+), 190 deletions(-) create mode 100644 api/v1/server/handlers/workflows/list_crons.go create mode 100644 frontend/app/src/pages/main/crons/components/crons-columns.tsx create mode 100644 frontend/app/src/pages/main/crons/index.tsx diff --git a/api-contracts/openapi/components/schemas/_index.yaml b/api-contracts/openapi/components/schemas/_index.yaml index a8dce9abc..001f4fbea 100644 --- a/api-contracts/openapi/components/schemas/_index.yaml +++ b/api-contracts/openapi/components/schemas/_index.yaml @@ -158,6 +158,12 @@ ScheduledWorkflowsList: $ref: "./workflow_run.yaml#/ScheduledWorkflowsList" ScheduledWorkflowsOrderByField: $ref: "./workflow_run.yaml#/ScheduledWorkflowsOrderByField" +CronWorkflows: + $ref: "./workflow_run.yaml#/CronWorkflows" +CronWorkflowsList: + $ref: "./workflow_run.yaml#/CronWorkflowsList" +CronWorkflowsOrderByField: + $ref: "./workflow_run.yaml#/CronWorkflowsOrderByField" WorkflowRunOrderByField: $ref: "./workflow_run.yaml#/WorkflowRunOrderByField" WorkflowRunOrderByDirection: diff --git a/api-contracts/openapi/components/schemas/workflow_run.yaml b/api-contracts/openapi/components/schemas/workflow_run.yaml index 73d28e949..6128d43af 100644 --- a/api-contracts/openapi/components/schemas/workflow_run.yaml +++ b/api-contracts/openapi/components/schemas/workflow_run.yaml @@ -11,6 +11,11 @@ ScheduledWorkflowsOrderByField: enum: - triggerAt +CronWorkflowsOrderByField: + type: string + enum: + - createdAt + WorkflowRunOrderByDirection: type: string enum: @@ -206,6 +211,45 @@ ScheduledWorkflowsList: pagination: $ref: "./metadata.yaml#/PaginationResponse" +CronWorkflows: + type: object + properties: + metadata: + $ref: "./metadata.yaml#/APIResourceMeta" + tenantId: + type: string + workflowVersionId: + type: string + workflowId: + type: string + workflowName: + type: string + cron: + type: string + input: + type: object + additionalProperties: true + additionalMetadata: + type: object + additionalProperties: true + required: + - metadata + - tenantId + - workflowVersionId + - workflowName + - workflowId + - cron + +CronWorkflowsList: + type: object + properties: + rows: + type: array + items: + $ref: "#/CronWorkflows" + pagination: + $ref: "./metadata.yaml#/PaginationResponse" + WorkflowRunsMetricsCounts: type: object properties: diff --git a/api-contracts/openapi/openapi.yaml b/api-contracts/openapi/openapi.yaml index ec57e0404..e2c847fc2 100644 --- a/api-contracts/openapi/openapi.yaml +++ b/api-contracts/openapi/openapi.yaml @@ -118,6 +118,8 @@ paths: $ref: "./paths/workflow/workflow.yaml#/withTenant" /api/v1/tenants/{tenant}/workflows/scheduled: $ref: "./paths/workflow/workflow.yaml#/scheduledList" + /api/v1/tenants/{tenant}/workflows/crons: + $ref: "./paths/workflow/workflow.yaml#/cronsList" /api/v1/tenants/{tenant}/workflows/cancel: $ref: "./paths/workflow/workflow.yaml#/cancelWorkflowRuns" /api/v1/workflows/{workflow}: diff --git a/api-contracts/openapi/paths/workflow/workflow.yaml b/api-contracts/openapi/paths/workflow/workflow.yaml index 5c5ee78ba..6807f6fa1 100644 --- a/api-contracts/openapi/paths/workflow/workflow.yaml +++ b/api-contracts/openapi/paths/workflow/workflow.yaml @@ -908,4 +908,86 @@ scheduledList: description: Forbidden summary: Get workflow runs tags: - - ScheduledWorkflows + - Workflow + +cronsList: + get: + x-resources: ["tenant"] + description: Get all cron job workflow runs for a tenant + operationId: cron-workflow:list + parameters: + - description: The tenant id + in: path + name: tenant + required: true + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + - description: The number to skip + in: query + name: offset + required: false + schema: + type: integer + format: int64 + - description: The number to limit by + in: query + name: limit + required: false + schema: + type: integer + format: int64 + - description: The workflow id to get runs for. + in: query + name: workflowId + required: false + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + - description: A list of metadata key value pairs to filter by + in: query + name: additionalMetadata + example: ["key1:value1", "key2:value2"] + required: false + schema: + type: array + items: + type: string + - description: The order by field + in: query + name: orderByField + required: false + schema: + $ref: "../../components/schemas/_index.yaml#/CronWorkflowsOrderByField" + - description: The order by direction + in: query + name: orderByDirection + required: false + schema: + $ref: "../../components/schemas/_index.yaml#/WorkflowRunOrderByDirection" + responses: + "200": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/CronWorkflowsList" + description: Successfully retrieved the workflow runs + "400": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: A malformed or bad request + "403": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: Forbidden + summary: Get workflow runs + tags: + - Workflow diff --git a/api/v1/server/handlers/workflows/list_crons.go b/api/v1/server/handlers/workflows/list_crons.go new file mode 100644 index 000000000..6dc0e5d55 --- /dev/null +++ b/api/v1/server/handlers/workflows/list_crons.go @@ -0,0 +1,121 @@ +package workflows + +import ( + "context" + "fmt" + "math" + "strings" + "time" + + "github.com/labstack/echo/v4" + + "github.com/hatchet-dev/hatchet/api/v1/server/oas/apierrors" + "github.com/hatchet-dev/hatchet/api/v1/server/oas/gen" + "github.com/hatchet-dev/hatchet/api/v1/server/oas/transformers" + "github.com/hatchet-dev/hatchet/pkg/repository" + "github.com/hatchet-dev/hatchet/pkg/repository/prisma/db" +) + +func (t *WorkflowService) CronWorkflowList(ctx echo.Context, request gen.CronWorkflowListRequestObject) (gen.CronWorkflowListResponseObject, error) { + tenant := ctx.Get("tenant").(*db.TenantModel) + + limit := 50 + offset := 0 + orderDirection := "DESC" + orderBy := "triggerAt" + + listOpts := &repository.ListCronWorkflowsOpts{ + Limit: &limit, + Offset: &offset, + OrderBy: &orderBy, + OrderDirection: &orderDirection, + } + + if request.Params.OrderByField != nil { + orderBy = string(*request.Params.OrderByField) + listOpts.OrderBy = &orderBy + } + + if request.Params.OrderByDirection != nil { + orderDirection = string(*request.Params.OrderByDirection) + listOpts.OrderDirection = &orderDirection + } + + if request.Params.Limit != nil { + limit = int(*request.Params.Limit) + listOpts.Limit = &limit + } + + if request.Params.Offset != nil { + offset = int(*request.Params.Offset) + listOpts.Offset = &offset + } + + if request.Params.WorkflowId != nil { + workflowIdStr := request.Params.WorkflowId.String() + listOpts.WorkflowId = &workflowIdStr + } + + // if request.Params.Statuses != nil { + // statuses := make([]db.WorkflowRunStatus, len(*request.Params.Statuses)) + + // for i, status := range *request.Params.Statuses { + // statuses[i] = db.WorkflowRunStatus(status) + // } + + // listOpts.Statuses = &statuses + // } + + if request.Params.AdditionalMetadata != nil { + additionalMetadata := make(map[string]interface{}, len(*request.Params.AdditionalMetadata)) + + for _, v := range *request.Params.AdditionalMetadata { + splitValue := strings.Split(fmt.Sprintf("%v", v), ":") + + if len(splitValue) == 2 { + additionalMetadata[splitValue[0]] = splitValue[1] + } else { + return gen.CronWorkflowList400JSONResponse(apierrors.NewAPIErrors("Additional metadata filters must be in the format key:value.")), nil + + } + } + + listOpts.AdditionalMetadata = additionalMetadata + } + + dbCtx, cancel := context.WithTimeout(ctx.Request().Context(), 30*time.Second) + defer cancel() + + scheduled, count, err := t.config.APIRepository.WorkflowRun().ListCronWorkflows(dbCtx, tenant.ID, listOpts) + + if err != nil { + return nil, err + } + + rows := make([]gen.CronWorkflows, len(scheduled)) + + for i, workflow := range scheduled { + workflowCp := workflow + rows[i] = *transformers.ToCronWorkflowsFromSQLC(workflowCp) + } + + // use the total rows and limit to calculate the total pages + totalPages := int64(math.Ceil(float64(count) / float64(limit))) + currPage := 1 + int64(math.Ceil(float64(offset)/float64(limit))) + nextPage := currPage + 1 + + if currPage == totalPages { + nextPage = currPage + } + + return gen.CronWorkflowList200JSONResponse( + gen.CronWorkflowsList{ + Rows: &rows, + Pagination: &gen.PaginationResponse{ + NumPages: &totalPages, + CurrentPage: &currPage, + NextPage: &nextPage, + }, + }, + ), nil +} diff --git a/api/v1/server/oas/gen/openapi.gen.go b/api/v1/server/oas/gen/openapi.gen.go index d74c376c1..9dd0cc401 100644 --- a/api/v1/server/oas/gen/openapi.gen.go +++ b/api/v1/server/oas/gen/openapi.gen.go @@ -26,6 +26,11 @@ const ( CookieAuthScopes = "cookieAuth.Scopes" ) +// Defines values for CronWorkflowsOrderByField. +const ( + CronWorkflowsOrderByFieldCreatedAt CronWorkflowsOrderByField = "createdAt" +) + // Defines values for EventOrderByDirection. const ( EventOrderByDirectionAsc EventOrderByDirection = "asc" @@ -176,10 +181,10 @@ const ( // Defines values for WorkflowRunOrderByField. const ( - CreatedAt WorkflowRunOrderByField = "createdAt" - Duration WorkflowRunOrderByField = "duration" - FinishedAt WorkflowRunOrderByField = "finishedAt" - StartedAt WorkflowRunOrderByField = "startedAt" + WorkflowRunOrderByFieldCreatedAt WorkflowRunOrderByField = "createdAt" + WorkflowRunOrderByFieldDuration WorkflowRunOrderByField = "duration" + WorkflowRunOrderByFieldFinishedAt WorkflowRunOrderByField = "finishedAt" + WorkflowRunOrderByFieldStartedAt WorkflowRunOrderByField = "startedAt" ) // Defines values for WorkflowRunStatus. @@ -355,6 +360,27 @@ type CreateTenantRequest struct { Slug string `json:"slug" validate:"required,hatchetName"` } +// CronWorkflows defines model for CronWorkflows. +type CronWorkflows struct { + AdditionalMetadata *map[string]interface{} `json:"additionalMetadata,omitempty"` + Cron string `json:"cron"` + Input *map[string]interface{} `json:"input,omitempty"` + Metadata APIResourceMeta `json:"metadata"` + TenantId string `json:"tenantId"` + WorkflowId string `json:"workflowId"` + WorkflowName string `json:"workflowName"` + WorkflowVersionId string `json:"workflowVersionId"` +} + +// CronWorkflowsList defines model for CronWorkflowsList. +type CronWorkflowsList struct { + Pagination *PaginationResponse `json:"pagination,omitempty"` + Rows *[]CronWorkflows `json:"rows,omitempty"` +} + +// CronWorkflowsOrderByField defines model for CronWorkflowsOrderByField. +type CronWorkflowsOrderByField string + // Event defines model for Event. type Event struct { // AdditionalMetadata Additional metadata for the event. @@ -1475,6 +1501,27 @@ type WorkflowRunListStepRunEventsParams struct { LastId *int32 `form:"lastId,omitempty" json:"lastId,omitempty"` } +// CronWorkflowListParams defines parameters for CronWorkflowList. +type CronWorkflowListParams struct { + // Offset The number to skip + Offset *int64 `form:"offset,omitempty" json:"offset,omitempty"` + + // Limit The number to limit by + Limit *int64 `form:"limit,omitempty" json:"limit,omitempty"` + + // WorkflowId The workflow id to get runs for. + WorkflowId *openapi_types.UUID `form:"workflowId,omitempty" json:"workflowId,omitempty"` + + // AdditionalMetadata A list of metadata key value pairs to filter by + AdditionalMetadata *[]string `form:"additionalMetadata,omitempty" json:"additionalMetadata,omitempty"` + + // OrderByField The order by field + OrderByField *CronWorkflowsOrderByField `form:"orderByField,omitempty" json:"orderByField,omitempty"` + + // OrderByDirection The order by direction + OrderByDirection *WorkflowRunOrderByDirection `form:"orderByDirection,omitempty" json:"orderByDirection,omitempty"` +} + // WorkflowRunListParams defines parameters for WorkflowRunList. type WorkflowRunListParams struct { // Offset The number to skip @@ -1835,6 +1882,9 @@ type ServerInterface interface { // (POST /api/v1/tenants/{tenant}/workflows/cancel) WorkflowRunCancel(ctx echo.Context, tenant openapi_types.UUID) error // Get workflow runs + // (GET /api/v1/tenants/{tenant}/workflows/crons) + CronWorkflowList(ctx echo.Context, tenant openapi_types.UUID, params CronWorkflowListParams) error + // Get workflow runs // (GET /api/v1/tenants/{tenant}/workflows/runs) WorkflowRunList(ctx echo.Context, tenant openapi_types.UUID, params WorkflowRunListParams) error // Get workflow runs @@ -3307,6 +3357,70 @@ func (w *ServerInterfaceWrapper) WorkflowRunCancel(ctx echo.Context) error { return err } +// CronWorkflowList converts echo context to params. +func (w *ServerInterfaceWrapper) CronWorkflowList(ctx echo.Context) error { + var err error + // ------------- Path parameter "tenant" ------------- + var tenant openapi_types.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "tenant", runtime.ParamLocationPath, ctx.Param("tenant"), &tenant) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tenant: %s", err)) + } + + ctx.Set(BearerAuthScopes, []string{}) + + ctx.Set(CookieAuthScopes, []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params CronWorkflowListParams + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "workflowId" ------------- + + err = runtime.BindQueryParameter("form", true, false, "workflowId", ctx.QueryParams(), ¶ms.WorkflowId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter workflowId: %s", err)) + } + + // ------------- Optional query parameter "additionalMetadata" ------------- + + err = runtime.BindQueryParameter("form", true, false, "additionalMetadata", ctx.QueryParams(), ¶ms.AdditionalMetadata) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter additionalMetadata: %s", err)) + } + + // ------------- Optional query parameter "orderByField" ------------- + + err = runtime.BindQueryParameter("form", true, false, "orderByField", ctx.QueryParams(), ¶ms.OrderByField) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderByField: %s", err)) + } + + // ------------- Optional query parameter "orderByDirection" ------------- + + err = runtime.BindQueryParameter("form", true, false, "orderByDirection", ctx.QueryParams(), ¶ms.OrderByDirection) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderByDirection: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.CronWorkflowList(ctx, tenant, params) + return err +} + // WorkflowRunList converts echo context to params. func (w *ServerInterfaceWrapper) WorkflowRunList(ctx echo.Context) error { var err error @@ -4062,6 +4176,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/api/v1/tenants/:tenant/workflow-runs/:workflow-run/step-run-events", wrapper.WorkflowRunListStepRunEvents) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows", wrapper.WorkflowList) router.POST(baseURL+"/api/v1/tenants/:tenant/workflows/cancel", wrapper.WorkflowRunCancel) + router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/crons", wrapper.CronWorkflowList) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/runs", wrapper.WorkflowRunList) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/runs/metrics", wrapper.WorkflowRunGetMetrics) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/scheduled", wrapper.WorkflowScheduledList) @@ -6234,6 +6349,42 @@ func (response WorkflowRunCancel403JSONResponse) VisitWorkflowRunCancelResponse( return json.NewEncoder(w).Encode(response) } +type CronWorkflowListRequestObject struct { + Tenant openapi_types.UUID `json:"tenant"` + Params CronWorkflowListParams +} + +type CronWorkflowListResponseObject interface { + VisitCronWorkflowListResponse(w http.ResponseWriter) error +} + +type CronWorkflowList200JSONResponse CronWorkflowsList + +func (response CronWorkflowList200JSONResponse) VisitCronWorkflowListResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type CronWorkflowList400JSONResponse APIErrors + +func (response CronWorkflowList400JSONResponse) VisitCronWorkflowListResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(400) + + return json.NewEncoder(w).Encode(response) +} + +type CronWorkflowList403JSONResponse APIErrors + +func (response CronWorkflowList403JSONResponse) VisitCronWorkflowListResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(403) + + return json.NewEncoder(w).Encode(response) +} + type WorkflowRunListRequestObject struct { Tenant openapi_types.UUID `json:"tenant"` Params WorkflowRunListParams @@ -7378,6 +7529,8 @@ type StrictServerInterface interface { WorkflowRunCancel(ctx echo.Context, request WorkflowRunCancelRequestObject) (WorkflowRunCancelResponseObject, error) + CronWorkflowList(ctx echo.Context, request CronWorkflowListRequestObject) (CronWorkflowListResponseObject, error) + WorkflowRunList(ctx echo.Context, request WorkflowRunListRequestObject) (WorkflowRunListResponseObject, error) WorkflowRunGetMetrics(ctx echo.Context, request WorkflowRunGetMetricsRequestObject) (WorkflowRunGetMetricsResponseObject, error) @@ -8974,6 +9127,32 @@ func (sh *strictHandler) WorkflowRunCancel(ctx echo.Context, tenant openapi_type return nil } +// CronWorkflowList operation middleware +func (sh *strictHandler) CronWorkflowList(ctx echo.Context, tenant openapi_types.UUID, params CronWorkflowListParams) error { + var request CronWorkflowListRequestObject + + request.Tenant = tenant + request.Params = params + + handler := func(ctx echo.Context, request interface{}) (interface{}, error) { + return sh.ssi.CronWorkflowList(ctx, request.(CronWorkflowListRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "CronWorkflowList") + } + + response, err := handler(ctx, request) + + if err != nil { + return err + } else if validResponse, ok := response.(CronWorkflowListResponseObject); ok { + return validResponse.VisitCronWorkflowListResponse(ctx.Response()) + } else if response != nil { + return fmt.Errorf("Unexpected response type: %T", response) + } + return nil +} + // WorkflowRunList operation middleware func (sh *strictHandler) WorkflowRunList(ctx echo.Context, tenant openapi_types.UUID, params WorkflowRunListParams) error { var request WorkflowRunListRequestObject @@ -9705,185 +9884,189 @@ func (sh *strictHandler) WorkflowVersionGet(ctx echo.Context, workflow openapi_t var swaggerSpec = []string{ "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", + "2QEA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/v1/server/oas/transformers/workflow_run.go b/api/v1/server/oas/transformers/workflow_run.go index 0cd9e8dc6..b636c56fb 100644 --- a/api/v1/server/oas/transformers/workflow_run.go +++ b/api/v1/server/oas/transformers/workflow_run.go @@ -497,3 +497,19 @@ func ToScheduledWorkflowsFromSQLC(scheduled *dbsqlc.ListScheduledWorkflowsRow) * return res } + +func ToCronWorkflowsFromSQLC(scheduled *dbsqlc.ListCronWorkflowsRow) *gen.CronWorkflows { + + res := &gen.CronWorkflows{ + Metadata: *toAPIMetadata(sqlchelpers.UUIDToStr(scheduled.ID), time.Now(), time.Now()), + WorkflowVersionId: sqlchelpers.UUIDToStr(scheduled.WorkflowVersionId), + WorkflowId: sqlchelpers.UUIDToStr(scheduled.WorkflowId), + WorkflowName: scheduled.Name, + TenantId: sqlchelpers.UUIDToStr(scheduled.TenantId), + Cron: scheduled.Cron, + // TriggerAt: scheduled.TriggerAt.Time, + // AdditionalMetadata: &additionalMetadata, + } + + return res +} diff --git a/frontend/app/src/lib/api/generated/Api.ts b/frontend/app/src/lib/api/generated/Api.ts index ebded887d..2c04161e8 100644 --- a/frontend/app/src/lib/api/generated/Api.ts +++ b/frontend/app/src/lib/api/generated/Api.ts @@ -24,6 +24,8 @@ import { CreateTenantAlertEmailGroupRequest, CreateTenantInviteRequest, CreateTenantRequest, + CronWorkflowsList, + CronWorkflowsOrderByField, Event, EventData, EventKey, @@ -1120,7 +1122,7 @@ export class Api extends HttpClient extends HttpClient + this.request({ + path: `/api/v1/tenants/${tenant}/workflows/crons`, + method: 'GET', + query: query, + secure: true, + format: 'json', + ...params, + }); /** * @description Cancel a batch of workflow runs * diff --git a/frontend/app/src/lib/api/generated/data-contracts.ts b/frontend/app/src/lib/api/generated/data-contracts.ts index ed0d1b5a3..15642d3f5 100644 --- a/frontend/app/src/lib/api/generated/data-contracts.ts +++ b/frontend/app/src/lib/api/generated/data-contracts.ts @@ -781,6 +781,26 @@ export enum ScheduledWorkflowsOrderByField { TriggerAt = 'triggerAt', } +export interface CronWorkflows { + metadata: APIResourceMeta; + tenantId: string; + workflowVersionId: string; + workflowId: string; + workflowName: string; + cron: string; + input?: Record; + additionalMetadata?: Record; +} + +export interface CronWorkflowsList { + rows?: CronWorkflows[]; + pagination?: PaginationResponse; +} + +export enum CronWorkflowsOrderByField { + CreatedAt = 'createdAt', +} + export enum WorkflowRunOrderByField { CreatedAt = 'createdAt', StartedAt = 'startedAt', diff --git a/frontend/app/src/lib/api/queries.ts b/frontend/app/src/lib/api/queries.ts index 513b917bc..87ef738f5 100644 --- a/frontend/app/src/lib/api/queries.ts +++ b/frontend/app/src/lib/api/queries.ts @@ -15,6 +15,7 @@ type WorkflowRunEventsMetrics = Parameters< typeof cloudApi.workflowRunEventsGetMetrics >[1]; type WorkflowScheduledQuery = Parameters[1]; +type CronWorkflowsQuery = Parameters[1]; export const queries = createQueryKeyStore({ cloud: { @@ -187,6 +188,12 @@ export const queries = createQueryKeyStore({ (await api.workflowScheduledList(tenant, query)).data, }), }, + cronRuns: { + list: (tenant: string, query: CronWorkflowsQuery) => ({ + queryKey: ['cron-run:list', tenant, query], + queryFn: async () => (await api.cronWorkflowList(tenant, query)).data, + }), + }, workflowRuns: { list: (tenant: string, query: ListWorkflowRunsQuery) => ({ queryKey: ['workflow-run:list', tenant, query], diff --git a/frontend/app/src/pages/main/crons/components/crons-columns.tsx b/frontend/app/src/pages/main/crons/components/crons-columns.tsx new file mode 100644 index 000000000..1f7c88ccf --- /dev/null +++ b/frontend/app/src/pages/main/crons/components/crons-columns.tsx @@ -0,0 +1,52 @@ +import { ColumnDef } from '@tanstack/react-table'; +import { DataTableColumnHeader } from '../../../../components/molecules/data-table/data-table-column-header'; +import { CronWorkflows, RateLimit } from '@/lib/api'; +import CronPrettifier from 'cronstrue'; + +export type RateLimitRow = RateLimit & { + metadata: { + id: string; + }; +}; + +export const columns: ColumnDef[] = [ + { + accessorKey: 'crons', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ {row.original.cron} +
+ ), + enableSorting: false, + }, + { + accessorKey: 'readable', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ (runs {CronPrettifier.toString(row.original.cron).toLowerCase()} UTC) +
+ ), + enableSorting: false, + }, + { + accessorKey: 'Workflow', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( + + ), + enableSorting: false, + enableHiding: true, + }, +]; diff --git a/frontend/app/src/pages/main/crons/index.tsx b/frontend/app/src/pages/main/crons/index.tsx new file mode 100644 index 000000000..626869d1a --- /dev/null +++ b/frontend/app/src/pages/main/crons/index.tsx @@ -0,0 +1,181 @@ +import { DataTable } from '../../../components/molecules/data-table/data-table'; +import { columns } from './components/crons-columns'; +import { Separator } from '@/components/ui/separator'; +import { useEffect, useMemo, useState } from 'react'; +import { + ColumnFiltersState, + PaginationState, + RowSelectionState, + SortingState, + VisibilityState, +} from '@tanstack/react-table'; +import { useQuery } from '@tanstack/react-query'; +import { + CronWorkflowsOrderByField, + WorkflowRunOrderByDirection, + queries, +} from '@/lib/api'; +import invariant from 'tiny-invariant'; +import { useOutletContext, useSearchParams } from 'react-router-dom'; +import { TenantContextType } from '@/lib/outlet'; + +export default function RateLimits() { + return ( +
+
+

+ Cron Runs +

+ + +
+
+ ); +} + +function ScheduledRunsTable() { + const { tenant } = useOutletContext(); + const [searchParams, setSearchParams] = useSearchParams(); + + invariant(tenant); + + const [search, setSearch] = useState( + searchParams.get('search') || undefined, + ); + const [sorting, setSorting] = useState(() => { + const sortParam = searchParams.get('sort'); + if (sortParam) { + const [id, desc] = sortParam.split(':'); + return [{ id, desc: desc === 'desc' }]; + } + return []; + }); + const [columnFilters, setColumnFilters] = useState(() => { + const filtersParam = searchParams.get('filters'); + if (filtersParam) { + return JSON.parse(filtersParam); + } + return []; + }); + const [columnVisibility, setColumnVisibility] = useState({ + RateLimitId: false, + }); + + const [pagination, setPagination] = useState(() => { + const pageIndex = Number(searchParams.get('pageIndex')) || 0; + const pageSize = Number(searchParams.get('pageSize')) || 50; + return { pageIndex, pageSize }; + }); + const [pageSize, setPageSize] = useState( + Number(searchParams.get('pageSize')) || 50, + ); + const [rowSelection, setRowSelection] = useState({}); + + useEffect(() => { + const newSearchParams = new URLSearchParams(searchParams); + if (search) { + newSearchParams.set('search', search); + } else { + newSearchParams.delete('search'); + } + newSearchParams.set( + 'sort', + sorting.map((s) => `${s.id}:${s.desc ? 'desc' : 'asc'}`).join(','), + ); + newSearchParams.set('filters', JSON.stringify(columnFilters)); + newSearchParams.set('pageIndex', pagination.pageIndex.toString()); + newSearchParams.set('pageSize', pagination.pageSize.toString()); + setSearchParams(newSearchParams); + }, [ + search, + sorting, + columnFilters, + pagination, + setSearchParams, + searchParams, + ]); + + const orderByDirection = useMemo((): + | WorkflowRunOrderByDirection + | undefined => { + if (!sorting.length) { + return; + } + + return sorting[0]?.desc + ? WorkflowRunOrderByDirection.DESC + : WorkflowRunOrderByDirection.ASC; + }, [sorting]); + + const orderByField = useMemo((): CronWorkflowsOrderByField | undefined => { + if (!sorting.length) { + return; + } + + switch (sorting[0]?.id) { + case 'triggerAt': + return CronWorkflowsOrderByField.CreatedAt; + default: + return CronWorkflowsOrderByField.CreatedAt; + } + }, [sorting]); + + const offset = useMemo(() => { + if (!pagination) { + return; + } + + return pagination.pageIndex * pagination.pageSize; + }, [pagination]); + + const { + data, + isLoading: queryIsLoading, + error: queryError, + } = useQuery({ + ...queries.cronRuns.list(tenant.metadata.id, { + // TODO: add filters + orderByField, + orderByDirection, + offset, + limit: pageSize, + }), + refetchInterval: 2000, + }); + + // const tableData = + // data?.rows?.map( + // (row): CronWorkflows => ({ + // ...row, + // metadata: { + // id: row.key, + // }, + // }), + // ) || []; + + return ( + row.metadata.id} + /> + ); +} diff --git a/frontend/app/src/pages/main/index.tsx b/frontend/app/src/pages/main/index.tsx index 489dd3fa4..87db674bc 100644 --- a/frontend/app/src/pages/main/index.tsx +++ b/frontend/app/src/pages/main/index.tsx @@ -11,7 +11,7 @@ import { import { Link, Outlet, useLocation, useOutletContext } from 'react-router-dom'; import { Tenant, TenantMember } from '@/lib/api'; -import { GearIcon } from '@radix-ui/react-icons'; +import { ClockIcon, GearIcon, StarIcon } from '@radix-ui/react-icons'; import React, { useCallback } from 'react'; import { MembershipsContextType, @@ -170,6 +170,13 @@ function Sidebar({ className, memberships, currTenant }: SidebarProps) { name="Scheduled Runs" icon={} /> + } + />
diff --git a/frontend/app/src/router.tsx b/frontend/app/src/router.tsx index bd1e9d050..4c25c764a 100644 --- a/frontend/app/src/router.tsx +++ b/frontend/app/src/router.tsx @@ -141,6 +141,15 @@ const routes: RouteObject[] = [ }; }), }, + { + path: '/crons', + lazy: async () => + import('./pages/main/crons').then((res) => { + return { + Component: res.default, + }; + }), + }, { path: '/workflows', lazy: async () => diff --git a/pkg/client/rest/gen.go b/pkg/client/rest/gen.go index cc4a30a30..010b09dfe 100644 --- a/pkg/client/rest/gen.go +++ b/pkg/client/rest/gen.go @@ -23,6 +23,11 @@ const ( CookieAuthScopes = "cookieAuth.Scopes" ) +// Defines values for CronWorkflowsOrderByField. +const ( + CronWorkflowsOrderByFieldCreatedAt CronWorkflowsOrderByField = "createdAt" +) + // Defines values for EventOrderByDirection. const ( EventOrderByDirectionAsc EventOrderByDirection = "asc" @@ -173,10 +178,10 @@ const ( // Defines values for WorkflowRunOrderByField. const ( - CreatedAt WorkflowRunOrderByField = "createdAt" - Duration WorkflowRunOrderByField = "duration" - FinishedAt WorkflowRunOrderByField = "finishedAt" - StartedAt WorkflowRunOrderByField = "startedAt" + WorkflowRunOrderByFieldCreatedAt WorkflowRunOrderByField = "createdAt" + WorkflowRunOrderByFieldDuration WorkflowRunOrderByField = "duration" + WorkflowRunOrderByFieldFinishedAt WorkflowRunOrderByField = "finishedAt" + WorkflowRunOrderByFieldStartedAt WorkflowRunOrderByField = "startedAt" ) // Defines values for WorkflowRunStatus. @@ -352,6 +357,27 @@ type CreateTenantRequest struct { Slug string `json:"slug" validate:"required,hatchetName"` } +// CronWorkflows defines model for CronWorkflows. +type CronWorkflows struct { + AdditionalMetadata *map[string]interface{} `json:"additionalMetadata,omitempty"` + Cron string `json:"cron"` + Input *map[string]interface{} `json:"input,omitempty"` + Metadata APIResourceMeta `json:"metadata"` + TenantId string `json:"tenantId"` + WorkflowId string `json:"workflowId"` + WorkflowName string `json:"workflowName"` + WorkflowVersionId string `json:"workflowVersionId"` +} + +// CronWorkflowsList defines model for CronWorkflowsList. +type CronWorkflowsList struct { + Pagination *PaginationResponse `json:"pagination,omitempty"` + Rows *[]CronWorkflows `json:"rows,omitempty"` +} + +// CronWorkflowsOrderByField defines model for CronWorkflowsOrderByField. +type CronWorkflowsOrderByField string + // Event defines model for Event. type Event struct { // AdditionalMetadata Additional metadata for the event. @@ -1472,6 +1498,27 @@ type WorkflowRunListStepRunEventsParams struct { LastId *int32 `form:"lastId,omitempty" json:"lastId,omitempty"` } +// CronWorkflowListParams defines parameters for CronWorkflowList. +type CronWorkflowListParams struct { + // Offset The number to skip + Offset *int64 `form:"offset,omitempty" json:"offset,omitempty"` + + // Limit The number to limit by + Limit *int64 `form:"limit,omitempty" json:"limit,omitempty"` + + // WorkflowId The workflow id to get runs for. + WorkflowId *openapi_types.UUID `form:"workflowId,omitempty" json:"workflowId,omitempty"` + + // AdditionalMetadata A list of metadata key value pairs to filter by + AdditionalMetadata *[]string `form:"additionalMetadata,omitempty" json:"additionalMetadata,omitempty"` + + // OrderByField The order by field + OrderByField *CronWorkflowsOrderByField `form:"orderByField,omitempty" json:"orderByField,omitempty"` + + // OrderByDirection The order by direction + OrderByDirection *WorkflowRunOrderByDirection `form:"orderByDirection,omitempty" json:"orderByDirection,omitempty"` +} + // WorkflowRunListParams defines parameters for WorkflowRunList. type WorkflowRunListParams struct { // Offset The number to skip @@ -1934,6 +1981,9 @@ type ClientInterface interface { WorkflowRunCancel(ctx context.Context, tenant openapi_types.UUID, body WorkflowRunCancelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // CronWorkflowList request + CronWorkflowList(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // WorkflowRunList request WorkflowRunList(ctx context.Context, tenant openapi_types.UUID, params *WorkflowRunListParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -2911,6 +2961,18 @@ func (c *Client) WorkflowRunCancel(ctx context.Context, tenant openapi_types.UUI return c.Client.Do(req) } +func (c *Client) CronWorkflowList(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCronWorkflowListRequest(c.Server, tenant, params) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) WorkflowRunList(ctx context.Context, tenant openapi_types.UUID, params *WorkflowRunListParams, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewWorkflowRunListRequest(c.Server, tenant, params) if err != nil { @@ -6021,6 +6083,142 @@ func NewWorkflowRunCancelRequestWithBody(server string, tenant openapi_types.UUI return req, nil } +// NewCronWorkflowListRequest generates requests for CronWorkflowList +func NewCronWorkflowListRequest(server string, tenant openapi_types.UUID, params *CronWorkflowListParams) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "tenant", runtime.ParamLocationPath, tenant) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/api/v1/tenants/%s/workflows/crons", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + if params != nil { + queryValues := queryURL.Query() + + if params.Offset != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "offset", runtime.ParamLocationQuery, *params.Offset); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.Limit != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "limit", runtime.ParamLocationQuery, *params.Limit); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.WorkflowId != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "workflowId", runtime.ParamLocationQuery, *params.WorkflowId); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.AdditionalMetadata != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "additionalMetadata", runtime.ParamLocationQuery, *params.AdditionalMetadata); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.OrderByField != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "orderByField", runtime.ParamLocationQuery, *params.OrderByField); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.OrderByDirection != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "orderByDirection", runtime.ParamLocationQuery, *params.OrderByDirection); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + queryURL.RawQuery = queryValues.Encode() + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewWorkflowRunListRequest generates requests for WorkflowRunList func NewWorkflowRunListRequest(server string, tenant openapi_types.UUID, params *WorkflowRunListParams) (*http.Request, error) { var err error @@ -7780,6 +7978,9 @@ type ClientWithResponsesInterface interface { WorkflowRunCancelWithResponse(ctx context.Context, tenant openapi_types.UUID, body WorkflowRunCancelJSONRequestBody, reqEditors ...RequestEditorFn) (*WorkflowRunCancelResponse, error) + // CronWorkflowListWithResponse request + CronWorkflowListWithResponse(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*CronWorkflowListResponse, error) + // WorkflowRunListWithResponse request WorkflowRunListWithResponse(ctx context.Context, tenant openapi_types.UUID, params *WorkflowRunListParams, reqEditors ...RequestEditorFn) (*WorkflowRunListResponse, error) @@ -9256,6 +9457,30 @@ func (r WorkflowRunCancelResponse) StatusCode() int { return 0 } +type CronWorkflowListResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *CronWorkflowsList + JSON400 *APIErrors + JSON403 *APIErrors +} + +// Status returns HTTPResponse.Status +func (r CronWorkflowListResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r CronWorkflowListResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type WorkflowRunListResponse struct { Body []byte HTTPResponse *http.Response @@ -10563,6 +10788,15 @@ func (c *ClientWithResponses) WorkflowRunCancelWithResponse(ctx context.Context, return ParseWorkflowRunCancelResponse(rsp) } +// CronWorkflowListWithResponse request returning *CronWorkflowListResponse +func (c *ClientWithResponses) CronWorkflowListWithResponse(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*CronWorkflowListResponse, error) { + rsp, err := c.CronWorkflowList(ctx, tenant, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseCronWorkflowListResponse(rsp) +} + // WorkflowRunListWithResponse request returning *WorkflowRunListResponse func (c *ClientWithResponses) WorkflowRunListWithResponse(ctx context.Context, tenant openapi_types.UUID, params *WorkflowRunListParams, reqEditors ...RequestEditorFn) (*WorkflowRunListResponse, error) { rsp, err := c.WorkflowRunList(ctx, tenant, params, reqEditors...) @@ -13175,6 +13409,46 @@ func ParseWorkflowRunCancelResponse(rsp *http.Response) (*WorkflowRunCancelRespo return response, nil } +// ParseCronWorkflowListResponse parses an HTTP response from a CronWorkflowListWithResponse call +func ParseCronWorkflowListResponse(rsp *http.Response) (*CronWorkflowListResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &CronWorkflowListResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest CronWorkflowsList + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + } + + return response, nil +} + // ParseWorkflowRunListResponse parses an HTTP response from a WorkflowRunListWithResponse call func ParseWorkflowRunListResponse(rsp *http.Response) (*WorkflowRunListResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/pkg/repository/prisma/dbsqlc/workflow_runs.sql b/pkg/repository/prisma/dbsqlc/workflow_runs.sql index 6147de186..a692fe66f 100644 --- a/pkg/repository/prisma/dbsqlc/workflow_runs.sql +++ b/pkg/repository/prisma/dbsqlc/workflow_runs.sql @@ -1447,6 +1447,38 @@ OFFSET LIMIT COALESCE(sqlc.narg('limit'), 50); +-- name: ListCronWorkflows :many +SELECT + w."name", + w."id" as "workflowId", + v."id" as "workflowVersionId", + w."tenantId", + t.*, + c.* +FROM "WorkflowTriggerCronRef" c +JOIN "WorkflowTriggers" t ON c."parentId" = t."id" +JOIN "WorkflowVersion" v ON t."workflowVersionId" = v."id" +JOIN "Workflow" w on v."workflowId" = w."id" +WHERE v."deletedAt" IS NULL + AND w."tenantId" = @tenantId::uuid + -- TODO page +ORDER BY + -- case when @orderBy = 'triggerAt ASC' THEN t."triggerAt" END ASC , + -- case when @orderBy = 'triggerAt DESC' THEN t."triggerAt" END DESC, + case when @orderBy = 'createdAt ASC' THEN t."createdAt" END ASC , + case when @orderBy = 'createdAt DESC' THEN t."createdAt" END DESC, + -- case when @orderBy = 'finishedAt ASC' THEN t."finishedAt" END ASC , + -- case when @orderBy = 'finishedAt DESC' THEN t."finishedAt" END DESC, + -- case when @orderBy = 'startedAt ASC' THEN t."startedAt" END ASC , + -- case when @orderBy = 'startedAt DESC' THEN t."startedAt" END DESC, + -- case when @orderBy = 'duration ASC' THEN t."duration" END ASC NULLS FIRST, + -- case when @orderBy = 'duration DESC' THEN runs."duration" END DESC NULLS LAST, + t."id" ASC +OFFSET + COALESCE(sqlc.narg('offset'), 0) +LIMIT + COALESCE(sqlc.narg('limit'), 50); + -- name: CountScheduledWorkflows :one SELECT count(*) FROM "WorkflowTriggerScheduledRef" t JOIN "WorkflowVersion" v ON t."parentId" = v."id" diff --git a/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go b/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go index f9160d951..c281e52c9 100644 --- a/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go +++ b/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go @@ -2105,6 +2105,105 @@ func (q *Queries) ListChildWorkflowRunCounts(ctx context.Context, db DBTX, stepr return items, nil } +const listCronWorkflows = `-- name: ListCronWorkflows :many +SELECT + w."name", + w."id" as "workflowId", + v."id" as "workflowVersionId", + w."tenantId", + t.id, t."createdAt", t."updatedAt", t."deletedAt", t."workflowVersionId", t."tenantId", + c."parentId", c.cron, c."tickerId", c.input, c.enabled +FROM "WorkflowTriggerCronRef" c +JOIN "WorkflowTriggers" t ON c."parentId" = t."id" +JOIN "WorkflowVersion" v ON t."workflowVersionId" = v."id" +JOIN "Workflow" w on v."workflowId" = w."id" +WHERE v."deletedAt" IS NULL + AND w."tenantId" = $1::uuid + -- TODO page +ORDER BY + -- case when @orderBy = 'triggerAt ASC' THEN t."triggerAt" END ASC , + -- case when @orderBy = 'triggerAt DESC' THEN t."triggerAt" END DESC, + case when $2 = 'createdAt ASC' THEN t."createdAt" END ASC , + case when $2 = 'createdAt DESC' THEN t."createdAt" END DESC, + -- case when @orderBy = 'finishedAt ASC' THEN t."finishedAt" END ASC , + -- case when @orderBy = 'finishedAt DESC' THEN t."finishedAt" END DESC, + -- case when @orderBy = 'startedAt ASC' THEN t."startedAt" END ASC , + -- case when @orderBy = 'startedAt DESC' THEN t."startedAt" END DESC, + -- case when @orderBy = 'duration ASC' THEN t."duration" END ASC NULLS FIRST, + -- case when @orderBy = 'duration DESC' THEN runs."duration" END DESC NULLS LAST, + t."id" ASC +OFFSET + COALESCE($3, 0) +LIMIT + COALESCE($4, 50) +` + +type ListCronWorkflowsParams struct { + Tenantid pgtype.UUID `json:"tenantid"` + Orderby interface{} `json:"orderby"` + Offset interface{} `json:"offset"` + Limit interface{} `json:"limit"` +} + +type ListCronWorkflowsRow struct { + Name string `json:"name"` + WorkflowId pgtype.UUID `json:"workflowId"` + WorkflowVersionId pgtype.UUID `json:"workflowVersionId"` + TenantId pgtype.UUID `json:"tenantId"` + ID pgtype.UUID `json:"id"` + CreatedAt pgtype.Timestamp `json:"createdAt"` + UpdatedAt pgtype.Timestamp `json:"updatedAt"` + DeletedAt pgtype.Timestamp `json:"deletedAt"` + WorkflowVersionId_2 pgtype.UUID `json:"workflowVersionId_2"` + TenantId_2 pgtype.UUID `json:"tenantId_2"` + ParentId pgtype.UUID `json:"parentId"` + Cron string `json:"cron"` + TickerId pgtype.UUID `json:"tickerId"` + Input []byte `json:"input"` + Enabled bool `json:"enabled"` +} + +func (q *Queries) ListCronWorkflows(ctx context.Context, db DBTX, arg ListCronWorkflowsParams) ([]*ListCronWorkflowsRow, error) { + rows, err := db.Query(ctx, listCronWorkflows, + arg.Tenantid, + arg.Orderby, + arg.Offset, + arg.Limit, + ) + if err != nil { + return nil, err + } + defer rows.Close() + var items []*ListCronWorkflowsRow + for rows.Next() { + var i ListCronWorkflowsRow + if err := rows.Scan( + &i.Name, + &i.WorkflowId, + &i.WorkflowVersionId, + &i.TenantId, + &i.ID, + &i.CreatedAt, + &i.UpdatedAt, + &i.DeletedAt, + &i.WorkflowVersionId_2, + &i.TenantId_2, + &i.ParentId, + &i.Cron, + &i.TickerId, + &i.Input, + &i.Enabled, + ); err != nil { + return nil, err + } + items = append(items, &i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const listScheduledWorkflows = `-- name: ListScheduledWorkflows :many SELECT w."name", diff --git a/pkg/repository/prisma/workflow_run.go b/pkg/repository/prisma/workflow_run.go index 8d3c9d9a5..62e049177 100644 --- a/pkg/repository/prisma/workflow_run.go +++ b/pkg/repository/prisma/workflow_run.go @@ -153,6 +153,43 @@ func (w *workflowRunAPIRepository) ListScheduledWorkflows(ctx context.Context, t return scheduledWorkflows, count, nil } +func (w *workflowRunAPIRepository) ListCronWorkflows(ctx context.Context, tenantId string, opts *repository.ListCronWorkflowsOpts) ([]*dbsqlc.ListCronWorkflowsRow, int64, error) { + + ctx, cancel := context.WithTimeout(ctx, time.Second*30) + defer cancel() + + count, err := w.queries.CountScheduledWorkflows(ctx, w.pool, sqlchelpers.UUIDFromStr(tenantId)) + + if err != nil { + return nil, 0, err + } + + listOpts := dbsqlc.ListCronWorkflowsParams{ + Tenantid: sqlchelpers.UUIDFromStr(tenantId), + } + + if opts.Limit != nil { + listOpts.Limit = pgtype.Int4{ + Int32: int32(*opts.Limit), // nolint: gosec + Valid: true, + } + } + + if opts.Offset != nil { + listOpts.Offset = pgtype.Int4{ + Int32: int32(*opts.Offset), // nolint: gosec + Valid: true, + } + } + + cronWorkflows, err := w.queries.ListCronWorkflows(ctx, w.pool, listOpts) + if err != nil { + return nil, 0, err + } + + return cronWorkflows, count, nil +} + func (w *workflowRunEngineRepository) GetWorkflowRunInputData(tenantId, workflowRunId string) (map[string]interface{}, error) { lookupData := datautils.JobRunLookupData{} diff --git a/pkg/repository/workflow_run.go b/pkg/repository/workflow_run.go index c696532e7..e37e1ef23 100644 --- a/pkg/repository/workflow_run.go +++ b/pkg/repository/workflow_run.go @@ -408,6 +408,26 @@ type ListScheduledWorkflowsOpts struct { AdditionalMetadata map[string]interface{} `validate:"omitempty"` } +type ListCronWorkflowsOpts struct { + // (optional) number of events to skip + Offset *int + + // (optional) number of events to return + Limit *int + + // (optional) the order by field + OrderBy *string `validate:"omitempty,oneof=createdAt finishedAt startedAt duration"` + + // (optional) the order direction + OrderDirection *string `validate:"omitempty,oneof=ASC DESC"` + + // (optional) the workflow id + WorkflowId *string `validate:"omitempty,uuid"` + + // (optional) additional metadata for the workflow run + AdditionalMetadata map[string]interface{} `validate:"omitempty"` +} + type WorkflowRunAPIRepository interface { RegisterCreateCallback(callback Callback[*dbsqlc.WorkflowRun]) @@ -420,6 +440,9 @@ type WorkflowRunAPIRepository interface { // List ScheduledWorkflows lists workflows by scheduled trigger ListScheduledWorkflows(ctx context.Context, tenantId string, opts *ListScheduledWorkflowsOpts) ([]*dbsqlc.ListScheduledWorkflowsRow, int64, error) + // List ScheduledWorkflows lists workflows by scheduled trigger + ListCronWorkflows(ctx context.Context, tenantId string, opts *ListCronWorkflowsOpts) ([]*dbsqlc.ListCronWorkflowsRow, int64, error) + // CreateNewWorkflowRun creates a new workflow run for a workflow version. CreateNewWorkflowRun(ctx context.Context, tenantId string, opts *CreateWorkflowRunOpts) (*dbsqlc.WorkflowRun, error) From ab0721d558c69a0bf8deb66498bc5c51057ffa4a Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Thu, 24 Oct 2024 12:47:19 -0400 Subject: [PATCH 05/30] feat: addl meta --- api-contracts/workflows/workflows.proto | 3 + .../server/oas/transformers/workflow_run.go | 1 - .../services/admin/contracts/workflows.pb.go | 288 +++++++++--------- internal/services/admin/server.go | 11 +- internal/services/ticker/schedule_workflow.go | 15 +- pkg/repository/prisma/dbsqlc/models.go | 12 +- pkg/repository/prisma/dbsqlc/schema.sql | 4 +- pkg/repository/prisma/dbsqlc/tickers.sql | 3 +- pkg/repository/prisma/dbsqlc/tickers.sql.go | 27 +- .../prisma/dbsqlc/workflow_runs.sql.go | 11 +- pkg/repository/prisma/dbsqlc/workflows.sql | 6 +- pkg/repository/prisma/dbsqlc/workflows.sql.go | 35 ++- pkg/repository/prisma/workflow.go | 7 +- pkg/repository/workflow.go | 3 +- .../20241024160901_tmp/migration.sql | 5 + prisma/schema.prisma | 4 + sql/migrations/20241024160910_tmp.sql | 4 + sql/migrations/atlas.sum | 3 +- sql/schema/schema.sql | 4 +- 19 files changed, 262 insertions(+), 184 deletions(-) create mode 100644 prisma/migrations/20241024160901_tmp/migration.sql create mode 100644 sql/migrations/20241024160910_tmp.sql diff --git a/api-contracts/workflows/workflows.proto b/api-contracts/workflows/workflows.proto index 351a4136e..4d174268a 100644 --- a/api-contracts/workflows/workflows.proto +++ b/api-contracts/workflows/workflows.proto @@ -149,6 +149,9 @@ message ScheduleWorkflowRequest { // (optional) the key for the child. if this is set, matches on the index or the // child key will be a no-op, even if the schedule has changed. optional string child_key = 7; + + // (optional) the additional metadata for the workflow + optional string additional_metadata = 8; } // WorkflowVersion represents the WorkflowVersion model. diff --git a/api/v1/server/oas/transformers/workflow_run.go b/api/v1/server/oas/transformers/workflow_run.go index b636c56fb..1d14d2ead 100644 --- a/api/v1/server/oas/transformers/workflow_run.go +++ b/api/v1/server/oas/transformers/workflow_run.go @@ -507,7 +507,6 @@ func ToCronWorkflowsFromSQLC(scheduled *dbsqlc.ListCronWorkflowsRow) *gen.CronWo WorkflowName: scheduled.Name, TenantId: sqlchelpers.UUIDToStr(scheduled.TenantId), Cron: scheduled.Cron, - // TriggerAt: scheduled.TriggerAt.Time, // AdditionalMetadata: &additionalMetadata, } diff --git a/internal/services/admin/contracts/workflows.pb.go b/internal/services/admin/contracts/workflows.pb.go index 3bc847015..7aef855b2 100644 --- a/internal/services/admin/contracts/workflows.pb.go +++ b/internal/services/admin/contracts/workflows.pb.go @@ -969,6 +969,8 @@ type ScheduleWorkflowRequest struct { // (optional) the key for the child. if this is set, matches on the index or the // child key will be a no-op, even if the schedule has changed. ChildKey *string `protobuf:"bytes,7,opt,name=child_key,json=childKey,proto3,oneof" json:"child_key,omitempty"` + // (optional) the additional metadata for the workflow + AdditionalMetadata *string `protobuf:"bytes,8,opt,name=additional_metadata,json=additionalMetadata,proto3,oneof" json:"additional_metadata,omitempty"` } func (x *ScheduleWorkflowRequest) Reset() { @@ -1052,6 +1054,13 @@ func (x *ScheduleWorkflowRequest) GetChildKey() string { return "" } +func (x *ScheduleWorkflowRequest) GetAdditionalMetadata() string { + if x != nil && x.AdditionalMetadata != nil { + return *x.AdditionalMetadata + } + return "" +} + // WorkflowVersion represents the WorkflowVersion model. type WorkflowVersion struct { state protoimpl.MessageState @@ -1768,7 +1777,7 @@ var file_workflows_proto_rawDesc = []byte{ 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x5f, 0x65, 0x78, 0x70, 0x72, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0xdc, 0x02, 0x0a, 0x17, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x57, 0x6f, + 0x74, 0x22, 0xaa, 0x03, 0x0a, 0x17, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, @@ -1785,143 +1794,148 @@ var file_workflows_proto_rawDesc = []byte{ 0x6e, 0x64, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x48, 0x02, 0x52, 0x0a, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, - 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, - 0x0a, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x42, 0x15, 0x0a, 0x13, 0x5f, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x72, 0x75, 0x6e, 0x5f, - 0x69, 0x64, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6b, 0x65, 0x79, - 0x22, 0xe8, 0x01, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, - 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x22, 0x53, 0x0a, 0x17, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, - 0x22, 0x49, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, - 0x67, 0x65, 0x72, 0x43, 0x72, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x22, 0x53, 0x0a, 0x1a, 0x42, - 0x75, 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x09, 0x77, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x54, - 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, - 0x22, 0x47, 0x0a, 0x1b, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x28, 0x0a, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, - 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x73, 0x22, 0xe4, 0x03, 0x0a, 0x16, 0x54, 0x72, - 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x20, - 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, - 0x12, 0x30, 0x0a, 0x12, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, - 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0f, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x65, 0x70, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x88, - 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x48, 0x02, 0x52, 0x0a, 0x63, 0x68, 0x69, 0x6c, 0x64, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x68, 0x69, 0x6c, - 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x08, 0x63, - 0x68, 0x69, 0x6c, 0x64, 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x13, 0x61, 0x64, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x12, 0x61, 0x64, 0x64, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x88, 0x01, 0x01, - 0x12, 0x2f, 0x0a, 0x11, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x6b, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x0f, 0x64, - 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x49, 0x64, 0x88, 0x01, - 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x05, 0x48, 0x06, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x88, - 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, - 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, - 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x68, 0x69, 0x6c, - 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x68, 0x69, 0x6c, - 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x14, 0x0a, - 0x12, 0x5f, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x22, 0x41, 0x0a, 0x17, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x77, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, - 0x6e, 0x49, 0x64, 0x22, 0x6d, 0x0a, 0x13, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, - 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, - 0x69, 0x74, 0x12, 0x2e, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, - 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x24, 0x0a, 0x0e, 0x53, 0x74, - 0x69, 0x63, 0x6b, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, - 0x53, 0x4f, 0x46, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x41, 0x52, 0x44, 0x10, 0x01, - 0x2a, 0x32, 0x0a, 0x0c, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4b, 0x69, 0x6e, 0x64, - 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x0b, - 0x0a, 0x07, 0x44, 0x55, 0x52, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x44, - 0x41, 0x47, 0x10, 0x02, 0x2a, 0x6c, 0x0a, 0x18, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x63, 0x79, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, - 0x12, 0x16, 0x0a, 0x12, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x5f, 0x49, 0x4e, 0x5f, 0x50, 0x52, - 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x44, 0x52, 0x4f, 0x50, - 0x5f, 0x4e, 0x45, 0x57, 0x45, 0x53, 0x54, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x51, 0x55, 0x45, - 0x55, 0x45, 0x5f, 0x4e, 0x45, 0x57, 0x45, 0x53, 0x54, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x47, - 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x52, 0x4f, 0x42, 0x49, 0x4e, - 0x10, 0x03, 0x2a, 0x85, 0x01, 0x0a, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4c, 0x61, 0x62, - 0x65, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x09, 0x0a, 0x05, - 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x54, 0x5f, 0x45, - 0x51, 0x55, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x47, 0x52, 0x45, 0x41, 0x54, 0x45, - 0x52, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x47, 0x52, 0x45, 0x41, - 0x54, 0x45, 0x52, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x45, 0x51, 0x55, 0x41, - 0x4c, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x48, 0x41, 0x4e, - 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x5f, - 0x4f, 0x52, 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x05, 0x2a, 0x5d, 0x0a, 0x11, 0x52, 0x61, - 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x0a, 0x0a, 0x06, 0x53, 0x45, 0x43, 0x4f, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4d, - 0x49, 0x4e, 0x55, 0x54, 0x45, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x55, 0x52, 0x10, - 0x02, 0x12, 0x07, 0x0a, 0x03, 0x44, 0x41, 0x59, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x45, - 0x45, 0x4b, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x4d, 0x4f, 0x4e, 0x54, 0x48, 0x10, 0x05, 0x12, - 0x08, 0x0a, 0x04, 0x59, 0x45, 0x41, 0x52, 0x10, 0x06, 0x32, 0xdc, 0x02, 0x0a, 0x0f, 0x57, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, - 0x0b, 0x50, 0x75, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x13, 0x2e, 0x50, - 0x75, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x10, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x10, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, - 0x6c, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x10, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x0f, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x17, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, - 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x18, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x13, 0x42, 0x75, 0x6c, + 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, + 0x13, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x12, 0x61, 0x64, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, + 0x64, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x65, + 0x70, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x68, 0x69, + 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x68, 0x69, + 0x6c, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x61, 0x64, 0x64, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xe8, + 0x01, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, + 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x22, 0x53, 0x0a, 0x17, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, + 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x49, + 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, + 0x72, 0x43, 0x72, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, + 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x22, 0x53, 0x0a, 0x1a, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x12, 0x1b, 0x2e, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, - 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0c, 0x50, - 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x14, 0x2e, 0x50, 0x75, - 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x15, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x2d, 0x64, - 0x65, 0x76, 0x2f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x54, 0x72, 0x69, + 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x22, 0x47, + 0x0a, 0x1b, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, + 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x73, 0x22, 0xe4, 0x03, 0x0a, 0x16, 0x54, 0x72, 0x69, 0x67, + 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x20, 0x0a, 0x09, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x00, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x30, + 0x0a, 0x12, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x72, 0x75, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0f, 0x70, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x65, 0x70, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01, + 0x12, 0x24, 0x0a, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x05, 0x48, 0x02, 0x52, 0x0a, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, + 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x08, 0x63, 0x68, 0x69, + 0x6c, 0x64, 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x13, 0x61, 0x64, 0x64, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x12, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x61, 0x6c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x88, 0x01, 0x01, 0x12, 0x2f, + 0x0a, 0x11, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x0f, 0x64, 0x65, 0x73, + 0x69, 0x72, 0x65, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, + 0x1f, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x05, 0x48, 0x06, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x88, 0x01, 0x01, + 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x42, 0x15, + 0x0a, 0x13, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x72, + 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, + 0x6b, 0x65, 0x79, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x14, 0x0a, 0x12, 0x5f, + 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x41, + 0x0a, 0x17, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, + 0x64, 0x22, 0x6d, 0x0a, 0x13, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, + 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, + 0x12, 0x2e, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x44, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x16, 0x0a, 0x14, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x24, 0x0a, 0x0e, 0x53, 0x74, 0x69, 0x63, + 0x6b, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x4f, + 0x46, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x41, 0x52, 0x44, 0x10, 0x01, 0x2a, 0x32, + 0x0a, 0x0c, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0c, + 0x0a, 0x08, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, + 0x44, 0x55, 0x52, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x44, 0x41, 0x47, + 0x10, 0x02, 0x2a, 0x6c, 0x0a, 0x18, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, + 0x79, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x16, + 0x0a, 0x12, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x5f, 0x49, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x47, + 0x52, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x44, 0x52, 0x4f, 0x50, 0x5f, 0x4e, + 0x45, 0x57, 0x45, 0x53, 0x54, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x51, 0x55, 0x45, 0x55, 0x45, + 0x5f, 0x4e, 0x45, 0x57, 0x45, 0x53, 0x54, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x47, 0x52, 0x4f, + 0x55, 0x50, 0x5f, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x52, 0x4f, 0x42, 0x49, 0x4e, 0x10, 0x03, + 0x2a, 0x85, 0x01, 0x0a, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4c, 0x61, 0x62, 0x65, 0x6c, + 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x51, + 0x55, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x51, 0x55, + 0x41, 0x4c, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x47, 0x52, 0x45, 0x41, 0x54, 0x45, 0x52, 0x5f, + 0x54, 0x48, 0x41, 0x4e, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x47, 0x52, 0x45, 0x41, 0x54, 0x45, + 0x52, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, + 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x10, 0x04, + 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x5f, 0x4f, 0x52, + 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x05, 0x2a, 0x5d, 0x0a, 0x11, 0x52, 0x61, 0x74, 0x65, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, + 0x06, 0x53, 0x45, 0x43, 0x4f, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x49, 0x4e, + 0x55, 0x54, 0x45, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x55, 0x52, 0x10, 0x02, 0x12, + 0x07, 0x0a, 0x03, 0x44, 0x41, 0x59, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x45, 0x45, 0x4b, + 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x4d, 0x4f, 0x4e, 0x54, 0x48, 0x10, 0x05, 0x12, 0x08, 0x0a, + 0x04, 0x59, 0x45, 0x41, 0x52, 0x10, 0x06, 0x32, 0xdc, 0x02, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x0b, 0x50, + 0x75, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x13, 0x2e, 0x50, 0x75, 0x74, + 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x10, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x3e, 0x0a, 0x10, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, + 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x10, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x44, 0x0a, 0x0f, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x17, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, + 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x13, 0x42, 0x75, 0x6c, 0x6b, 0x54, + 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x1b, + 0x2e, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x42, 0x75, + 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0c, 0x50, 0x75, 0x74, + 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x14, 0x2e, 0x50, 0x75, 0x74, 0x52, + 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x15, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x2d, 0x64, 0x65, 0x76, + 0x2f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( diff --git a/internal/services/admin/server.go b/internal/services/admin/server.go index 83aa37d53..9c6edf362 100644 --- a/internal/services/admin/server.go +++ b/internal/services/admin/server.go @@ -334,15 +334,20 @@ func (a *AdminServiceImpl) ScheduleWorkflow(ctx context.Context, req *contracts. workflowVersionId := sqlchelpers.UUIDToStr(currWorkflow.WorkflowVersion.ID) - // FIXME add additional metadata? + var additionalMetadata []byte + + if req.AdditionalMetadata != nil { + additionalMetadata = []byte(*req.AdditionalMetadata) + } _, err = a.repo.Workflow().CreateSchedules( ctx, tenantId, workflowVersionId, &repository.CreateWorkflowSchedulesOpts{ - ScheduledTriggers: dbSchedules, - Input: []byte(req.Input), + ScheduledTriggers: dbSchedules, + Input: []byte(req.Input), + AdditionalMetadata: additionalMetadata, }, ) diff --git a/internal/services/ticker/schedule_workflow.go b/internal/services/ticker/schedule_workflow.go index 5e7bf8235..535880e80 100644 --- a/internal/services/ticker/schedule_workflow.go +++ b/internal/services/ticker/schedule_workflow.go @@ -129,6 +129,16 @@ func (t *TickerImpl) runScheduledWorkflow(tenantId, workflowVersionId, scheduled fs := make([]repository.CreateWorkflowRunOpt, 0) + var additionalMetadata map[string]interface{} + + if scheduled.AdditionalMetadata != nil { + err := json.Unmarshal(scheduled.AdditionalMetadata, &additionalMetadata) + if err != nil { + t.l.Err(err).Msg("could not unmarshal additional metadata") + return + } + } + if scheduled.ParentWorkflowRunId.Valid { var childKey *string @@ -158,18 +168,17 @@ func (t *TickerImpl) runScheduledWorkflow(tenantId, workflowVersionId, scheduled sqlchelpers.UUIDToStr(scheduled.ParentStepRunId), int(scheduled.ChildIndex.Int32), childKey, - nil, + additionalMetadata, parentAdditionalMeta, )) } // create a new workflow run in the database - // FIXME additionalMetadata is not used for scheduled runs createOpts, err := repository.GetCreateWorkflowRunOptsFromSchedule( scheduledWorkflowId, workflowVersion, scheduled.Input, - nil, + additionalMetadata, fs..., ) diff --git a/pkg/repository/prisma/dbsqlc/models.go b/pkg/repository/prisma/dbsqlc/models.go index 485c2322a..2b8ba9de9 100644 --- a/pkg/repository/prisma/dbsqlc/models.go +++ b/pkg/repository/prisma/dbsqlc/models.go @@ -1667,11 +1667,12 @@ type WorkflowToWorkflowTag struct { } type WorkflowTriggerCronRef struct { - ParentId pgtype.UUID `json:"parentId"` - Cron string `json:"cron"` - TickerId pgtype.UUID `json:"tickerId"` - Input []byte `json:"input"` - Enabled bool `json:"enabled"` + ParentId pgtype.UUID `json:"parentId"` + Cron string `json:"cron"` + TickerId pgtype.UUID `json:"tickerId"` + Input []byte `json:"input"` + Enabled bool `json:"enabled"` + AdditionalMetadata []byte `json:"additionalMetadata"` } type WorkflowTriggerEventRef struct { @@ -1689,6 +1690,7 @@ type WorkflowTriggerScheduledRef struct { ChildKey pgtype.Text `json:"childKey"` ParentStepRunId pgtype.UUID `json:"parentStepRunId"` ParentWorkflowRunId pgtype.UUID `json:"parentWorkflowRunId"` + AdditionalMetadata []byte `json:"additionalMetadata"` } type WorkflowTriggers struct { diff --git a/pkg/repository/prisma/dbsqlc/schema.sql b/pkg/repository/prisma/dbsqlc/schema.sql index fda852653..af5e266e7 100644 --- a/pkg/repository/prisma/dbsqlc/schema.sql +++ b/pkg/repository/prisma/dbsqlc/schema.sql @@ -893,7 +893,8 @@ CREATE TABLE "WorkflowTriggerCronRef" ( "cron" TEXT NOT NULL, "tickerId" UUID, "input" JSONB, - "enabled" BOOLEAN NOT NULL DEFAULT true + "enabled" BOOLEAN NOT NULL DEFAULT true, + "additionalMetadata" JSONB ); -- CreateTable @@ -913,6 +914,7 @@ CREATE TABLE "WorkflowTriggerScheduledRef" ( "childKey" TEXT, "parentStepRunId" UUID, "parentWorkflowRunId" UUID, + "additionalMetadata" JSONB, CONSTRAINT "WorkflowTriggerScheduledRef_pkey" PRIMARY KEY ("id") ); diff --git a/pkg/repository/prisma/dbsqlc/tickers.sql b/pkg/repository/prisma/dbsqlc/tickers.sql index c89173f07..ddb9407e2 100644 --- a/pkg/repository/prisma/dbsqlc/tickers.sql +++ b/pkg/repository/prisma/dbsqlc/tickers.sql @@ -156,7 +156,8 @@ not_run_scheduled_workflows AS ( SELECT scheduledWorkflow."id", versions."id" AS "workflowVersionId", - workflow."tenantId" AS "tenantId" + workflow."tenantId" AS "tenantId", + scheduledWorkflow."additionalMetadata" AS "additionalMetadata" FROM "WorkflowTriggerScheduledRef" as scheduledWorkflow JOIN diff --git a/pkg/repository/prisma/dbsqlc/tickers.sql.go b/pkg/repository/prisma/dbsqlc/tickers.sql.go index 50414566c..f50f85292 100644 --- a/pkg/repository/prisma/dbsqlc/tickers.sql.go +++ b/pkg/repository/prisma/dbsqlc/tickers.sql.go @@ -227,17 +227,18 @@ FROM active_cron_schedules WHERE cronSchedules."parentId" = active_cron_schedules."parentId" -RETURNING cronschedules."parentId", cronschedules.cron, cronschedules."tickerId", cronschedules.input, cronschedules.enabled, active_cron_schedules."workflowVersionId", active_cron_schedules."tenantId" +RETURNING cronschedules."parentId", cronschedules.cron, cronschedules."tickerId", cronschedules.input, cronschedules.enabled, cronschedules."additionalMetadata", active_cron_schedules."workflowVersionId", active_cron_schedules."tenantId" ` type PollCronSchedulesRow struct { - ParentId pgtype.UUID `json:"parentId"` - Cron string `json:"cron"` - TickerId pgtype.UUID `json:"tickerId"` - Input []byte `json:"input"` - Enabled bool `json:"enabled"` - WorkflowVersionId pgtype.UUID `json:"workflowVersionId"` - TenantId pgtype.UUID `json:"tenantId"` + ParentId pgtype.UUID `json:"parentId"` + Cron string `json:"cron"` + TickerId pgtype.UUID `json:"tickerId"` + Input []byte `json:"input"` + Enabled bool `json:"enabled"` + AdditionalMetadata []byte `json:"additionalMetadata"` + WorkflowVersionId pgtype.UUID `json:"workflowVersionId"` + TenantId pgtype.UUID `json:"tenantId"` } func (q *Queries) PollCronSchedules(ctx context.Context, db DBTX, tickerid pgtype.UUID) ([]*PollCronSchedulesRow, error) { @@ -255,6 +256,7 @@ func (q *Queries) PollCronSchedules(ctx context.Context, db DBTX, tickerid pgtyp &i.TickerId, &i.Input, &i.Enabled, + &i.AdditionalMetadata, &i.WorkflowVersionId, &i.TenantId, ); err != nil { @@ -415,7 +417,8 @@ not_run_scheduled_workflows AS ( SELECT scheduledWorkflow."id", versions."id" AS "workflowVersionId", - workflow."tenantId" AS "tenantId" + workflow."tenantId" AS "tenantId", + scheduledWorkflow."additionalMetadata" AS "additionalMetadata" FROM "WorkflowTriggerScheduledRef" as scheduledWorkflow JOIN @@ -441,7 +444,7 @@ not_run_scheduled_workflows AS ( ), active_scheduled_workflows AS ( SELECT - id, "workflowVersionId", "tenantId" + id, "workflowVersionId", "tenantId", "additionalMetadata" FROM not_run_scheduled_workflows FOR UPDATE SKIP LOCKED @@ -454,7 +457,7 @@ FROM active_scheduled_workflows WHERE scheduledWorkflows."id" = active_scheduled_workflows."id" -RETURNING scheduledworkflows.id, scheduledworkflows."parentId", scheduledworkflows."triggerAt", scheduledworkflows."tickerId", scheduledworkflows.input, scheduledworkflows."childIndex", scheduledworkflows."childKey", scheduledworkflows."parentStepRunId", scheduledworkflows."parentWorkflowRunId", active_scheduled_workflows."workflowVersionId", active_scheduled_workflows."tenantId" +RETURNING scheduledworkflows.id, scheduledworkflows."parentId", scheduledworkflows."triggerAt", scheduledworkflows."tickerId", scheduledworkflows.input, scheduledworkflows."childIndex", scheduledworkflows."childKey", scheduledworkflows."parentStepRunId", scheduledworkflows."parentWorkflowRunId", scheduledworkflows."additionalMetadata", active_scheduled_workflows."workflowVersionId", active_scheduled_workflows."tenantId" ` type PollScheduledWorkflowsRow struct { @@ -467,6 +470,7 @@ type PollScheduledWorkflowsRow struct { ChildKey pgtype.Text `json:"childKey"` ParentStepRunId pgtype.UUID `json:"parentStepRunId"` ParentWorkflowRunId pgtype.UUID `json:"parentWorkflowRunId"` + AdditionalMetadata []byte `json:"additionalMetadata"` WorkflowVersionId pgtype.UUID `json:"workflowVersionId"` TenantId pgtype.UUID `json:"tenantId"` } @@ -492,6 +496,7 @@ func (q *Queries) PollScheduledWorkflows(ctx context.Context, db DBTX, tickerid &i.ChildKey, &i.ParentStepRunId, &i.ParentWorkflowRunId, + &i.AdditionalMetadata, &i.WorkflowVersionId, &i.TenantId, ); err != nil { diff --git a/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go b/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go index c281e52c9..0f4366490 100644 --- a/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go +++ b/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go @@ -1232,7 +1232,7 @@ func (q *Queries) GetChildWorkflowRunsByKey(ctx context.Context, db DBTX, arg Ge const getScheduledChildWorkflowRun = `-- name: GetScheduledChildWorkflowRun :one SELECT - id, "parentId", "triggerAt", "tickerId", input, "childIndex", "childKey", "parentStepRunId", "parentWorkflowRunId" + id, "parentId", "triggerAt", "tickerId", input, "childIndex", "childKey", "parentStepRunId", "parentWorkflowRunId", "additionalMetadata" FROM "WorkflowTriggerScheduledRef" WHERE @@ -1270,6 +1270,7 @@ func (q *Queries) GetScheduledChildWorkflowRun(ctx context.Context, db DBTX, arg &i.ChildKey, &i.ParentStepRunId, &i.ParentWorkflowRunId, + &i.AdditionalMetadata, ) return &i, err } @@ -2112,7 +2113,7 @@ SELECT v."id" as "workflowVersionId", w."tenantId", t.id, t."createdAt", t."updatedAt", t."deletedAt", t."workflowVersionId", t."tenantId", - c."parentId", c.cron, c."tickerId", c.input, c.enabled + c."parentId", c.cron, c."tickerId", c.input, c.enabled, c."additionalMetadata" FROM "WorkflowTriggerCronRef" c JOIN "WorkflowTriggers" t ON c."parentId" = t."id" JOIN "WorkflowVersion" v ON t."workflowVersionId" = v."id" @@ -2161,6 +2162,7 @@ type ListCronWorkflowsRow struct { TickerId pgtype.UUID `json:"tickerId"` Input []byte `json:"input"` Enabled bool `json:"enabled"` + AdditionalMetadata []byte `json:"additionalMetadata"` } func (q *Queries) ListCronWorkflows(ctx context.Context, db DBTX, arg ListCronWorkflowsParams) ([]*ListCronWorkflowsRow, error) { @@ -2193,6 +2195,7 @@ func (q *Queries) ListCronWorkflows(ctx context.Context, db DBTX, arg ListCronWo &i.TickerId, &i.Input, &i.Enabled, + &i.AdditionalMetadata, ); err != nil { return nil, err } @@ -2210,7 +2213,7 @@ SELECT w."id" as "workflowId", v."id" as "workflowVersionId", w."tenantId", - t.id, t."parentId", t."triggerAt", t."tickerId", t.input, t."childIndex", t."childKey", t."parentStepRunId", t."parentWorkflowRunId" + t.id, t."parentId", t."triggerAt", t."tickerId", t.input, t."childIndex", t."childKey", t."parentStepRunId", t."parentWorkflowRunId", t."additionalMetadata" FROM "WorkflowTriggerScheduledRef" t JOIN "WorkflowVersion" v ON t."parentId" = v."id" JOIN "Workflow" w on v."workflowId" = w."id" @@ -2256,6 +2259,7 @@ type ListScheduledWorkflowsRow struct { ChildKey pgtype.Text `json:"childKey"` ParentStepRunId pgtype.UUID `json:"parentStepRunId"` ParentWorkflowRunId pgtype.UUID `json:"parentWorkflowRunId"` + AdditionalMetadata []byte `json:"additionalMetadata"` } func (q *Queries) ListScheduledWorkflows(ctx context.Context, db DBTX, arg ListScheduledWorkflowsParams) ([]*ListScheduledWorkflowsRow, error) { @@ -2286,6 +2290,7 @@ func (q *Queries) ListScheduledWorkflows(ctx context.Context, db DBTX, arg ListS &i.ChildKey, &i.ParentStepRunId, &i.ParentWorkflowRunId, + &i.AdditionalMetadata, ); err != nil { return nil, err } diff --git a/pkg/repository/prisma/dbsqlc/workflows.sql b/pkg/repository/prisma/dbsqlc/workflows.sql index 977fef4e3..ccd7b7ddc 100644 --- a/pkg/repository/prisma/dbsqlc/workflows.sql +++ b/pkg/repository/prisma/dbsqlc/workflows.sql @@ -455,12 +455,14 @@ INSERT INTO "WorkflowTriggerScheduledRef" ( "id", "parentId", "triggerAt", - "input" + "input", + "additionalMetadata" ) VALUES ( gen_random_uuid(), @workflowRunId::uuid, unnest(@triggerTimes::timestamp[]), - @input::jsonb + @input::jsonb, + @additionalMetadata::json ) RETURNING *; -- name: GetWorkflowLatestVersion :one diff --git a/pkg/repository/prisma/dbsqlc/workflows.sql.go b/pkg/repository/prisma/dbsqlc/workflows.sql.go index 6af2aea73..951b2f7a1 100644 --- a/pkg/repository/prisma/dbsqlc/workflows.sql.go +++ b/pkg/repository/prisma/dbsqlc/workflows.sql.go @@ -242,23 +242,31 @@ INSERT INTO "WorkflowTriggerScheduledRef" ( "id", "parentId", "triggerAt", - "input" + "input", + "additionalMetadata" ) VALUES ( gen_random_uuid(), $1::uuid, unnest($2::timestamp[]), - $3::jsonb -) RETURNING id, "parentId", "triggerAt", "tickerId", input, "childIndex", "childKey", "parentStepRunId", "parentWorkflowRunId" + $3::jsonb, + $4::json +) RETURNING id, "parentId", "triggerAt", "tickerId", input, "childIndex", "childKey", "parentStepRunId", "parentWorkflowRunId", "additionalMetadata" ` type CreateSchedulesParams struct { - Workflowrunid pgtype.UUID `json:"workflowrunid"` - Triggertimes []pgtype.Timestamp `json:"triggertimes"` - Input []byte `json:"input"` + Workflowrunid pgtype.UUID `json:"workflowrunid"` + Triggertimes []pgtype.Timestamp `json:"triggertimes"` + Input []byte `json:"input"` + Additionalmetadata []byte `json:"additionalmetadata"` } func (q *Queries) CreateSchedules(ctx context.Context, db DBTX, arg CreateSchedulesParams) ([]*WorkflowTriggerScheduledRef, error) { - rows, err := db.Query(ctx, createSchedules, arg.Workflowrunid, arg.Triggertimes, arg.Input) + rows, err := db.Query(ctx, createSchedules, + arg.Workflowrunid, + arg.Triggertimes, + arg.Input, + arg.Additionalmetadata, + ) if err != nil { return nil, err } @@ -276,6 +284,7 @@ func (q *Queries) CreateSchedules(ctx context.Context, db DBTX, arg CreateSchedu &i.ChildKey, &i.ParentStepRunId, &i.ParentWorkflowRunId, + &i.AdditionalMetadata, ); err != nil { return nil, err } @@ -560,7 +569,7 @@ INSERT INTO "WorkflowTriggerCronRef" ( $1::uuid, $2::text, $3::jsonb -) RETURNING "parentId", cron, "tickerId", input, enabled +) RETURNING "parentId", cron, "tickerId", input, enabled, "additionalMetadata" ` type CreateWorkflowTriggerCronRefParams struct { @@ -578,6 +587,7 @@ func (q *Queries) CreateWorkflowTriggerCronRef(ctx context.Context, db DBTX, arg &i.TickerId, &i.Input, &i.Enabled, + &i.AdditionalMetadata, ) return &i, err } @@ -617,7 +627,7 @@ INSERT INTO "WorkflowTriggerScheduledRef" ( $2::timestamp, NULL, -- or provide a tickerId if applicable NULL -- or provide input if applicable -) RETURNING id, "parentId", "triggerAt", "tickerId", input, "childIndex", "childKey", "parentStepRunId", "parentWorkflowRunId" +) RETURNING id, "parentId", "triggerAt", "tickerId", input, "childIndex", "childKey", "parentStepRunId", "parentWorkflowRunId", "additionalMetadata" ` type CreateWorkflowTriggerScheduledRefParams struct { @@ -638,6 +648,7 @@ func (q *Queries) CreateWorkflowTriggerScheduledRef(ctx context.Context, db DBTX &i.ChildKey, &i.ParentStepRunId, &i.ParentWorkflowRunId, + &i.AdditionalMetadata, ) return &i, err } @@ -961,7 +972,7 @@ func (q *Queries) GetWorkflowVersionById(ctx context.Context, db DBTX, id pgtype const getWorkflowVersionCronTriggerRefs = `-- name: GetWorkflowVersionCronTriggerRefs :many SELECT - wtc."parentId", wtc.cron, wtc."tickerId", wtc.input, wtc.enabled + wtc."parentId", wtc.cron, wtc."tickerId", wtc.input, wtc.enabled, wtc."additionalMetadata" FROM "WorkflowTriggerCronRef" as wtc JOIN "WorkflowTriggers" as wt ON wt."id" = wtc."parentId" @@ -984,6 +995,7 @@ func (q *Queries) GetWorkflowVersionCronTriggerRefs(ctx context.Context, db DBTX &i.TickerId, &i.Input, &i.Enabled, + &i.AdditionalMetadata, ); err != nil { return nil, err } @@ -1101,7 +1113,7 @@ func (q *Queries) GetWorkflowVersionForEngine(ctx context.Context, db DBTX, arg const getWorkflowVersionScheduleTriggerRefs = `-- name: GetWorkflowVersionScheduleTriggerRefs :many SELECT - wtc.id, wtc."parentId", wtc."triggerAt", wtc."tickerId", wtc.input, wtc."childIndex", wtc."childKey", wtc."parentStepRunId", wtc."parentWorkflowRunId" + wtc.id, wtc."parentId", wtc."triggerAt", wtc."tickerId", wtc.input, wtc."childIndex", wtc."childKey", wtc."parentStepRunId", wtc."parentWorkflowRunId", wtc."additionalMetadata" FROM "WorkflowTriggerScheduledRef" as wtc JOIN "WorkflowTriggers" as wt ON wt."id" = wtc."parentId" @@ -1128,6 +1140,7 @@ func (q *Queries) GetWorkflowVersionScheduleTriggerRefs(ctx context.Context, db &i.ChildKey, &i.ParentStepRunId, &i.ParentWorkflowRunId, + &i.AdditionalMetadata, ); err != nil { return nil, err } diff --git a/pkg/repository/prisma/workflow.go b/pkg/repository/prisma/workflow.go index 939cf1fe8..ac1e5f4cb 100644 --- a/pkg/repository/prisma/workflow.go +++ b/pkg/repository/prisma/workflow.go @@ -492,9 +492,10 @@ func (r *workflowEngineRepository) CreateSchedules( } createParams := dbsqlc.CreateSchedulesParams{ - Workflowrunid: sqlchelpers.UUIDFromStr(workflowVersionId), - Input: opts.Input, - Triggertimes: make([]pgtype.Timestamp, len(opts.ScheduledTriggers)), + Workflowrunid: sqlchelpers.UUIDFromStr(workflowVersionId), + Input: opts.Input, + Triggertimes: make([]pgtype.Timestamp, len(opts.ScheduledTriggers)), + Additionalmetadata: opts.AdditionalMetadata, } for i, scheduledTrigger := range opts.ScheduledTriggers { diff --git a/pkg/repository/workflow.go b/pkg/repository/workflow.go index 8a49a7857..e4a135bba 100644 --- a/pkg/repository/workflow.go +++ b/pkg/repository/workflow.go @@ -92,7 +92,8 @@ func (o *CreateWorkflowVersionOpts) Checksum() (string, error) { type CreateWorkflowSchedulesOpts struct { ScheduledTriggers []time.Time - Input []byte + Input []byte + AdditionalMetadata []byte } type CreateWorkflowTagOpts struct { diff --git a/prisma/migrations/20241024160901_tmp/migration.sql b/prisma/migrations/20241024160901_tmp/migration.sql new file mode 100644 index 000000000..14cba0639 --- /dev/null +++ b/prisma/migrations/20241024160901_tmp/migration.sql @@ -0,0 +1,5 @@ +-- AlterTable +ALTER TABLE "WorkflowTriggerCronRef" ADD COLUMN "additionalMetadata" JSONB; + +-- AlterTable +ALTER TABLE "WorkflowTriggerScheduledRef" ADD COLUMN "additionalMetadata" JSONB; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 525f2dfde..8c19a235d 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -664,6 +664,8 @@ model WorkflowTriggerCronRef { // the input parameters to the scheduled workflow input Json? + additionalMetadata Json? + // cron references must be unique per workflow @@unique([parentId, cron]) } @@ -700,6 +702,8 @@ model WorkflowTriggerScheduledRef { triggered WorkflowRunTriggeredBy? + additionalMetadata Json? + @@unique([parentId, parentStepRunId, childKey]) } diff --git a/sql/migrations/20241024160910_tmp.sql b/sql/migrations/20241024160910_tmp.sql new file mode 100644 index 000000000..d5647c99c --- /dev/null +++ b/sql/migrations/20241024160910_tmp.sql @@ -0,0 +1,4 @@ +-- Modify "WorkflowTriggerCronRef" table +ALTER TABLE "WorkflowTriggerCronRef" ADD COLUMN "additionalMetadata" jsonb NULL; +-- Modify "WorkflowTriggerScheduledRef" table +ALTER TABLE "WorkflowTriggerScheduledRef" ADD COLUMN "additionalMetadata" jsonb NULL; diff --git a/sql/migrations/atlas.sum b/sql/migrations/atlas.sum index 5290e4e9c..97a99ae47 100644 --- a/sql/migrations/atlas.sum +++ b/sql/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:CIM7NAv26L+YhyBC6tFMerwS5zoQM4Nxj2gERfvn1i0= +h1:/9h1f/7QmsCJjSdRw9m/jNx+mJC/LQu2W8Sc4rEFdcM= 20240115180414_init.sql h1:Ef3ZyjAHkmJPdGF/dEWCahbwgcg6uGJKnDxW2JCRi2k= 20240122014727_v0_6_0.sql h1:o/LdlteAeFgoHJ3e/M4Xnghqt9826IE/Y/h0q95Acuo= 20240126235456_v0_7_0.sql h1:KiVzt/hXgQ6esbdC6OMJOOWuYEXmy1yeCpmsVAHTFKs= @@ -71,3 +71,4 @@ h1:CIM7NAv26L+YhyBC6tFMerwS5zoQM4Nxj2gERfvn1i0= 20241022124210_v0.50.2.sql h1:UerCQiYQTz9dC4EvuOiPH2afsL/ORa8fZt71K9uGDyU= 20241023112235_v0.50.3.sql h1:aW7fMNTT9o3gg8TJhDM3juB/tWho3j9M6VYsbMqSNcw= 20241023223039_v0.50.4.sql h1:eXJLlkM6ZzqzZ4RbAZtoTiW7WjJPIJ5L6UkIKy6w9Uk= +20241024160910_tmp.sql h1:lksU5JyC0aW5zbAJCEjOkEx7F5ye/ezIXZBn/z0W9+A= diff --git a/sql/schema/schema.sql b/sql/schema/schema.sql index d9e31b46d..13b9e250d 100644 --- a/sql/schema/schema.sql +++ b/sql/schema/schema.sql @@ -893,7 +893,8 @@ CREATE TABLE "WorkflowTriggerCronRef" ( "cron" TEXT NOT NULL, "tickerId" UUID, "input" JSONB, - "enabled" BOOLEAN NOT NULL DEFAULT true + "enabled" BOOLEAN NOT NULL DEFAULT true, + "additionalMetadata" JSONB ); -- CreateTable @@ -913,6 +914,7 @@ CREATE TABLE "WorkflowTriggerScheduledRef" ( "childKey" TEXT, "parentStepRunId" UUID, "parentWorkflowRunId" UUID, + "additionalMetadata" JSONB, CONSTRAINT "WorkflowTriggerScheduledRef_pkey" PRIMARY KEY ("id") ); From dbd9ed57144d8e30ebe0b0f6a3c6b1b985769855 Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Thu, 24 Oct 2024 12:53:22 -0400 Subject: [PATCH 06/30] feat: expose metadata column --- .../server/oas/transformers/workflow_run.go | 45 +++++++++++++------ .../main/crons/components/crons-columns.tsx | 15 +++++++ .../components/scheduled-runs-columns.tsx | 15 +++++++ 3 files changed, 61 insertions(+), 14 deletions(-) diff --git a/api/v1/server/oas/transformers/workflow_run.go b/api/v1/server/oas/transformers/workflow_run.go index 1d14d2ead..8650edc84 100644 --- a/api/v1/server/oas/transformers/workflow_run.go +++ b/api/v1/server/oas/transformers/workflow_run.go @@ -485,29 +485,46 @@ func ToWorkflowRunFromSQLC(row *dbsqlc.ListWorkflowRunsRow) *gen.WorkflowRun { func ToScheduledWorkflowsFromSQLC(scheduled *dbsqlc.ListScheduledWorkflowsRow) *gen.ScheduledWorkflows { + var additionalMetadata map[string]interface{} + + if scheduled.AdditionalMetadata != nil { + err := json.Unmarshal(scheduled.AdditionalMetadata, &additionalMetadata) + if err != nil { + return nil + } + } + res := &gen.ScheduledWorkflows{ - Metadata: *toAPIMetadata(sqlchelpers.UUIDToStr(scheduled.ID), time.Now(), time.Now()), - WorkflowVersionId: sqlchelpers.UUIDToStr(scheduled.WorkflowVersionId), - WorkflowId: sqlchelpers.UUIDToStr(scheduled.WorkflowId), - WorkflowName: scheduled.Name, - TenantId: sqlchelpers.UUIDToStr(scheduled.TenantId), - TriggerAt: scheduled.TriggerAt.Time, - // AdditionalMetadata: &additionalMetadata, + Metadata: *toAPIMetadata(sqlchelpers.UUIDToStr(scheduled.ID), time.Now(), time.Now()), + WorkflowVersionId: sqlchelpers.UUIDToStr(scheduled.WorkflowVersionId), + WorkflowId: sqlchelpers.UUIDToStr(scheduled.WorkflowId), + WorkflowName: scheduled.Name, + TenantId: sqlchelpers.UUIDToStr(scheduled.TenantId), + TriggerAt: scheduled.TriggerAt.Time, + AdditionalMetadata: &additionalMetadata, } return res } func ToCronWorkflowsFromSQLC(scheduled *dbsqlc.ListCronWorkflowsRow) *gen.CronWorkflows { + var additionalMetadata map[string]interface{} + + if scheduled.AdditionalMetadata != nil { + err := json.Unmarshal(scheduled.AdditionalMetadata, &additionalMetadata) + if err != nil { + return nil + } + } res := &gen.CronWorkflows{ - Metadata: *toAPIMetadata(sqlchelpers.UUIDToStr(scheduled.ID), time.Now(), time.Now()), - WorkflowVersionId: sqlchelpers.UUIDToStr(scheduled.WorkflowVersionId), - WorkflowId: sqlchelpers.UUIDToStr(scheduled.WorkflowId), - WorkflowName: scheduled.Name, - TenantId: sqlchelpers.UUIDToStr(scheduled.TenantId), - Cron: scheduled.Cron, - // AdditionalMetadata: &additionalMetadata, + Metadata: *toAPIMetadata(sqlchelpers.UUIDToStr(scheduled.ID), time.Now(), time.Now()), + WorkflowVersionId: sqlchelpers.UUIDToStr(scheduled.WorkflowVersionId), + WorkflowId: sqlchelpers.UUIDToStr(scheduled.WorkflowId), + WorkflowName: scheduled.Name, + TenantId: sqlchelpers.UUIDToStr(scheduled.TenantId), + Cron: scheduled.Cron, + AdditionalMetadata: &additionalMetadata, } return res diff --git a/frontend/app/src/pages/main/crons/components/crons-columns.tsx b/frontend/app/src/pages/main/crons/components/crons-columns.tsx index 1f7c88ccf..240ec1dbb 100644 --- a/frontend/app/src/pages/main/crons/components/crons-columns.tsx +++ b/frontend/app/src/pages/main/crons/components/crons-columns.tsx @@ -2,6 +2,7 @@ import { ColumnDef } from '@tanstack/react-table'; import { DataTableColumnHeader } from '../../../../components/molecules/data-table/data-table-column-header'; import { CronWorkflows, RateLimit } from '@/lib/api'; import CronPrettifier from 'cronstrue'; +import { AdditionalMetadata } from '../../events/components/additional-metadata'; export type RateLimitRow = RateLimit & { metadata: { @@ -49,4 +50,18 @@ export const columns: ColumnDef[] = [ enableSorting: false, enableHiding: true, }, + { + accessorKey: 'Metadata', + header: ({ column }) => ( + + ), + cell: ({ row }) => { + if (!row.original.additionalMetadata) { + return
; + } + + return ; + }, + enableSorting: false, + }, ]; diff --git a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx index 0380f42c3..057146187 100644 --- a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx +++ b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx @@ -2,6 +2,7 @@ import { ColumnDef } from '@tanstack/react-table'; import { DataTableColumnHeader } from '../../../../components/molecules/data-table/data-table-column-header'; import { RateLimit, ScheduledWorkflows } from '@/lib/api'; import RelativeDate from '@/components/molecules/relative-date'; +import { AdditionalMetadata } from '../../events/components/additional-metadata'; export type RateLimitRow = RateLimit & { metadata: { @@ -36,4 +37,18 @@ export const columns: ColumnDef[] = [ enableSorting: false, enableHiding: true, }, + { + accessorKey: 'Metadata', + header: ({ column }) => ( + + ), + cell: ({ row }) => { + if (!row.original.additionalMetadata) { + return
; + } + + return ; + }, + enableSorting: false, + }, ]; From ae8304f4b6b083d420b744e4725bd9b6f567ad0a Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Thu, 24 Oct 2024 13:09:51 -0400 Subject: [PATCH 07/30] feat: sort and created at --- .../components/schemas/workflow_run.yaml | 2 +- api/v1/server/oas/gen/openapi.gen.go | 285 +++++++++--------- .../server/oas/transformers/workflow_run.go | 20 +- .../src/lib/api/generated/data-contracts.ts | 1 + .../main/crons/components/crons-columns.tsx | 14 + frontend/app/src/pages/main/crons/index.tsx | 8 +- .../components/scheduled-runs-columns.tsx | 13 + .../src/pages/main/scheduled-runs/index.tsx | 14 +- pkg/client/rest/gen.go | 11 +- pkg/repository/prisma/dbsqlc/models.go | 18 +- pkg/repository/prisma/dbsqlc/schema.sql | 8 +- pkg/repository/prisma/dbsqlc/tickers.sql.go | 32 +- .../prisma/dbsqlc/workflow_runs.sql | 4 +- .../prisma/dbsqlc/workflow_runs.sql.go | 25 +- pkg/repository/prisma/dbsqlc/workflows.sql.go | 25 +- pkg/repository/prisma/workflow_run.go | 28 ++ pkg/repository/workflow_run.go | 2 +- .../20241024170325_tmp/migration.sql | 9 + prisma/schema.prisma | 7 + sql/migrations/20241024170334_tmp.sql | 4 + sql/migrations/atlas.sum | 3 +- sql/schema/schema.sql | 8 +- 22 files changed, 336 insertions(+), 205 deletions(-) create mode 100644 prisma/migrations/20241024170325_tmp/migration.sql create mode 100644 sql/migrations/20241024170334_tmp.sql diff --git a/api-contracts/openapi/components/schemas/workflow_run.yaml b/api-contracts/openapi/components/schemas/workflow_run.yaml index 6128d43af..b5a2f2646 100644 --- a/api-contracts/openapi/components/schemas/workflow_run.yaml +++ b/api-contracts/openapi/components/schemas/workflow_run.yaml @@ -10,7 +10,7 @@ ScheduledWorkflowsOrderByField: type: string enum: - triggerAt - + - createdAt CronWorkflowsOrderByField: type: string enum: diff --git a/api/v1/server/oas/gen/openapi.gen.go b/api/v1/server/oas/gen/openapi.gen.go index 9dd0cc401..1b20d4b39 100644 --- a/api/v1/server/oas/gen/openapi.gen.go +++ b/api/v1/server/oas/gen/openapi.gen.go @@ -85,7 +85,8 @@ const ( // Defines values for ScheduledWorkflowsOrderByField. const ( - TriggerAt ScheduledWorkflowsOrderByField = "triggerAt" + ScheduledWorkflowsOrderByFieldCreatedAt ScheduledWorkflowsOrderByField = "createdAt" + ScheduledWorkflowsOrderByFieldTriggerAt ScheduledWorkflowsOrderByField = "triggerAt" ) // Defines values for StepRunEventReason. @@ -181,10 +182,10 @@ const ( // Defines values for WorkflowRunOrderByField. const ( - WorkflowRunOrderByFieldCreatedAt WorkflowRunOrderByField = "createdAt" - WorkflowRunOrderByFieldDuration WorkflowRunOrderByField = "duration" - WorkflowRunOrderByFieldFinishedAt WorkflowRunOrderByField = "finishedAt" - WorkflowRunOrderByFieldStartedAt WorkflowRunOrderByField = "startedAt" + CreatedAt WorkflowRunOrderByField = "createdAt" + Duration WorkflowRunOrderByField = "duration" + FinishedAt WorkflowRunOrderByField = "finishedAt" + StartedAt WorkflowRunOrderByField = "startedAt" ) // Defines values for WorkflowRunStatus. @@ -9930,143 +9931,143 @@ var swaggerSpec = []string{ "xxFwBOMAPP1Sjmh8SYoZBhtXVqCHl12f0vzD4WHNepfgNq3aZDBRutsL7SW7li18ErqEcjlj9gq2Eg4K", "1TdS3oyOumTb0Aw4g5hcJwYd63p05pDIwTD0meeVuN5ih0TbeSo2HRBpiP6i2oAPQ4KmCCaZFikUIOGQ", "zh3E1PiNCQyicCYhrpGVvW36p9kZMit9zsbeHPppAP3tOsi0yw+GJGg2g8kqxuhX5zqTr9Vu+1ugqmpo", - "0sqTptzPpIjqkJLv1RguQDyPEjgOIrJhzbOg1ekfA/lVCwcRv3iKHvZmzBW1QPFOZFoW/ewkqVxYvdhT", - "H3zqF4qCQL6E2q+0pLhqLoWiiT3oS1yYo6WnarrLr0PyVYiSj2oYL5uy5yAMYWCCV3x2kK+/gWM6uPPA", - "R9ffbfgI50a/UDkF8w9dcZK1JDNYmFZPv62xdNrdvG42+DqLboVCYXfkS0Rk6C7SRU8hQ+2xQGBsknv6", - "9/s5CvwEFh8ja+4TW3pzj0FSip+qhSSBwAeTAJo2V37PIii5QKwlk7VcQQwzmClAWUWBHOTTtdhAbpWv", - "2PotuH70ySCOCi8cilVvQw4ijAhvTPesWhoodMcnURoSPbjQCOUqJqK8TwWGlq9pBQ8XCwcJ4c+Ttd88", - "20UpMYG4Ikeyp4v+lMDEHpkbd7jhXSp2Zg1ty9bXjLY1iRMLWdNkxVmXihVT1cfg52N1OGUUmK2s0qlG", - "oK6feHN0D1+lXFK9F+zga5WIiegtSt+pgusTSJKnCim6NX5UrjG7YYmKG4OCBInHntYjwETvbbiOFxlQ", - "+3wk2hgCUTwzFcjTpmwx8vUdFCcdDclJHrRYj7C/sx6UbuA9TBB5atJ7LPtY0d1nlGAyhlxJtqe9M9C0", - "V0P3R37LKAC4NHOGWQVNqmcS398KYm5LDEWBTGsJORfp0m40GvzrenA9OL09v7i9uRh9G4zcXv7jqH81", - "uD0bfh9euT13fPJ1cHp9Njz/cns1/D44vb24pj/3x+Phl3Pm7Dm+6o+u2F/9k2/nFzdng9Mv3B10eD4c", - "fy16ho4GV6N/c8/R3Em059KhL66vbkeDz6OB6DMaKJOoc4/PLmjLs0F/nI05HJzefvr37fWYLYWu6fPZ", - "xc3t6Pr89svo4vry9tvg37eqr6qhiQBUa07TcYyCVMVVTSxwNLwanvTPqkarcrIVf91yNHwfnC8h3toJ", - "N/ubttYBkydPW07rBhMR+jswBGjfyPRQkcNaSyvBgvXC+9pcUCAEwRNBHr6IyUVKKkbNzQ5zgJ0oJtB3", - "xNUyG0Q/x9ZTzJjCgteOK65PSGMMEdYG3e822n5L+U/MQffaNbdASOv3QpecYBbtcZJzR+yR4Lm4KhTO", - "xpDQ/+DdsShPoTZ4jBHdZea2zoCpHp/34tNg54FlimIe+A5IoAPiOImAN0fhjKeMYgiuml8mDeBEwpxy", - "VoSCL1nm5CrDw7x4KnGhWGQ+AxSkCbQAhT0Qq4CohnzM4gD1cwYA86WaH1lyPz8Qip1lDy0iVNXSswc8", - "SiL7zGwVofdkdOFzprKJA4h0SxNUtVn7ulkSaAE2y4Vh5m+znfwbz1l6sMoHIpkUTiQC3WXCtNWSfNQ9", - "EwiGMj1yyM9mrPEWVc8cbIRCGqUVTsxCdpJ8r9RA9Braac1RIki52QnC97QM/4sRlH3OA8p6da2vMUx4", - "j8t0EiCvihTYeBV5alSYW7PpYv9W2fSR2Cd5s7i4OWe3o/7p9+G523O/D75/GowqLgTVUQHMro3NzjA6", - "q0cJ5yy8oQ4TBTgUw0DV3E3GW/YZyxAgKV/FYnZfHvzBb2TqTZLd+i7O83vzoAK9BbVGp9mBZFHhUs++", - "O8wLWS+DudM/iZwHkLCQ9JK+w3vrXdSbRRnoAww2EzvAxzYvUQ//euHO2bbXc2hGJHaRA3Ub1jxgYAEJ", - "TGTYgDwq+VjO39A+3HeOHB889Zwj5wHCO/rfRRSS+d9XfJXP0KMNIzBLVomoyyhAniZ1BlfBq26lWUpd", - "3lSjFzSQrEX2q3NLFcCZVycMOluXmUw6cb8v5UbSMPOi2bHR1n/2miUWfotJ/tSV1zj7byS/nlFfUQEx", - "7/8rNuF1NoiXtUFs0TawlaS71hbaZyM33TCnAHOYAb4EKdbFrqrkzj0LHISdmLV2QOg7HgjDiDiAZQtn", - "ZUdkTqJlxGuhw7pLXK0RA/h+AjFWjRkFvUzejss2DfrhK8BznbSeAzxXh/x/eGk6Ib+5asOrdox5AQzn", - "ZA6IccI/YIKmqA69zCRDZcm9aC4qxxRg0FP0HGBzfRrtHCArSONgSHb41OAjHAfgqUDQcv8aWz+K2P1h", - "ILBiAR9zqlb4YEYi40H4kGNN6mh62Fc4trMCQc/MJ6sKkAyISvytB0MpQ0hWvkjFkwnlZ9EMhasnCV6N", - "v9fKGdw6jMs1xnW4HsEZwqRCurcR3XYnnUEwtHC3ZEkN201T1WM8RzF+rZa5kqVyh6f5Nk4ZPplu20TM", - "CFelNmp5tmMGEfsg1DAtW6SmuE7ZN02CVR7m6bi1KOH50NfMhG6xSAy9BBreDvm3LOuI4GF6E3KGU1Y/", - "Lk6ie+RDv+cAJwGhHy1kJxbkNIHODIYwASKmS41RPt4axpuj2W8nAa62N7sm5QzOWmRTqdySLHtF8WMV", - "cVnoYmRM4e96C4gxMTVkV7089w4fSi2Q1ujJdx75jVYrQP/Oe2Ze/SfasrIU5K9XV5cOb8TqyUoKTgTy", - "LZIkKVjJYC5M/MMS4dUkJNPsmJ4IuP1Q0rxsbW0S1lLAyrTzPds6+Wr0ZXDl9tzLizH7z/UVs6GaTkge", - "34Sr4nIxfzEQlgYPhE4ME0pX+408tcA9QAGYBFCGGdVkai5PCx+hlxLoeFEoXjiCJ/0TBlU1WPmLZFhT", - "1o89j6BZCH0n77SJAn9r5tkIwAQGuPp5h7VhLJUfB9kxYJ0sAyZndBzdlgUAk68QJGQCgUVYstgq9lqH", - "KYDAmcvem84BBjgTU7VggAmYBCxao0UQLsCjmdA1KcrWI/jt6xlm/SIpZZ3SBYPSNllEfP6c1pBglzJc", - "aWgWywQEOmVHJCngAfSccVYEZCnhgQ6QzN1alxmAHYMl3EoR3j+5Gv4xYDlJsz8v+9djg7s4/yE/AcaD", - "s89fL8bcU/57/7zPneRvBp++Xlx80w4hTjNjTgBx2IliyEWoaxMbiN7Xderj9ehMM3xTbZK112oCirRr", - "li1R5selXTcd3F/xjs/f72smr66CUoGHlzduGPVmAaR0vFm/OoJ8htJunv1LC3vJyt5a9Bb6P6OJgevp", - "Fx1AVrgSOfc35v/eRPAbMSftcpozF8xWX6vc+yug1SRFWYbmOcFEAqAsrUaVE8ayXDExEh33RJ7POleT", - "GSTK9yxKYumhK5RJcPhr5gwSzHDn5V2dGe2bCUjlfXbf6Oo0JgkgcPZkOob4V4dE/A1NlltWZ+UuUazI", - "NPDmIpurOGh4rM/t8Pz2cnTxZTQYj92eezq6uLw9H9wM2AWEBXrl/+ThT6OL6/PT29HFp+G59jRqqDzl", - "+lHxvXm5Csu74/o7ppx6GYE97UZWUcXwVPegmQE4PNVum+z9DYWFW93n6/OTqyHz9zu9HvU/nVGd4LSv", - "D7JSB5FyvhGnsNk1rCe/6w+PtVKQ7PjcYWeL3a1btDZ6WjG+/AbzyG2NOFxKrV1m6zv4hPW6vRyekmXF", - "FEt3CSomgINj6KEp8vJJnL/FAGPoO/cIOFMUEJj83TJz902xusjGM96JBwJjQrjMLUPNe3l0qKSh3FrG", - "kdWS8fG0DfZ0macc2eAxz1OJcMV+11YMPvdYjfPeNQhbywmsVmjLcpTY5FCE/qenBoNfKb3KWREbqj5b", - "z6uY5TBWF/ujWpi05CZSlTW2Cvyq9N/98Qk9pgfjk8pzOh+lohaGSssFKaZIxppJxnMQw052d7K7k90v", - "KbtrMuL+QqJ9I4XdxCXytFa6sclWuu8UCcFw6VnaUM2jbRReKhyryWoVhTLjrraBSBC/nfyONyuW+KvZ", - "YnzC8nmtkrx+m7n2l3PP1yzCeLljiXqa0JEc6oR3rNMelpqX5hf8oA3Xkbyk/Sh4RvtNsp72Y86N+sRd", - "xtVcgZkOfwE/y9e3065tsNR7+HAIqwhEcP1JQjXMqZ7xK9I43iIDu9VNKFIqTQ21Lm7Fm8Wmp8X6FTbX", - "ppfwphGtbB0rD5zhZ7NaFz8H9ejLj8ZbYYZujmYe/rGBwI/654gqMBQ1Y5llC+Zsmw1RLeBU24dTkAbk", - "MkGRTF2lY3/WyIlFKx0D11pv8/eWF3pFyTI9WoCKxdl/lWc01iiwyLsz2uvpt9xsb/VEo/B0A9bCykOL", - "4XGSf7QCQo2itzXMVirLZiVWwpznjlQG+lHPDmxfN2nZbkIgbwrh/PU3N2kXMT5NIPOtqEiHugCPNS0a", - "pnU0JWXkTrQpFVJUfV9wCCcQJDDpp4QFrjGMMtnLfs43ZU4IS8XlRdEdgrI5orvKf5IvjB/dOXM/U2LW", - "QIy+QfEgjsJpZPCs5N2c/uWQpaEk7Ipe/DWjLPdo/3D/kBFmDEMQI/ej+27/aP+QRUiQOVvaAYjRQSBy", - "B890zsNf5AMlbRVCjJ3sekh3EchyH+6Z+P6FrUs6e7JZjg8PywN/hSAgcyaVP+i+n0ckm7OwM+7H//zo", - "uThdLEDyxCHMG8qn6v+I8b059O7cH7Q/W2sCgf9Uv1jaDFWtdiQbbHK5DDgW4MoDOkkCplORf6Zq9Rm0", - "tcu/PzoAIvp2jwVb7LH3Inzwk/2s/vbMYQwg0ejip+x37ICsJCYL8uYhJax7CWNLAf18BEaLCWDZJijY", - "FUmbSjM47CrJ+IvSc85dpaW4KvdzMyCXi2vfTZ9/lPb+fRlb49TzIMbTNAieHI5Sv1BPtIS85577nlOJ", - "F4VEJA4GcRwgj2H04E+RfTVfR81pxdJ0i7Ch5afqBQgoFqDvRIkzAb50deZgvNs4GDooPkfJBPk+5Lps", - "Tt+cTqrITFK8SPL0o+c+7mXx8KyiEf/Q0xDGD3aJIp4mJJkr7+uQOB/h1yBxRg+fIi47N0IMFsk+NGRS", - "iS0SOanEeREbz3oRvZGFGHJylmEviAEOaCcGLMUAp5btiQH1gIzRHk/ucfAz+5udhnGENUrDCN5Hdyxf", - "Zv9yyNOCCKeMbMYlMREjlndEmgdodxspkQ1vkAkS1lYddwlbnqBzBt2vTdS4CVUL0qEbeyV2TpJx/lsV", - "JWdbXqBgL4hS/0C9ypq1XdkqczeU1wk2iINCTEDI8nIVifiEfpavyGYlePu4ZYA4aZiFHbWGwGq0do5g", - "9VlObP135UHmcU8OsRfF/E1bnGjKfnPj6sFP9t/nqv2mUoq12i9tKLOx8o2slURsCKNywr7uVAhtbrNF", - "+YOawzuBJEHwXog1jg22Y51sK5C4gpmcvDmKK6Qap58fZgo/qBNrbFsyqVZD86eZAHvrdH/KSLij/XbR", - "/gKufIYbT+/dHdwi9XoTmsqOxFdykG/iCKdjHCiFT7Fxx88QphegwCm0Nm0wbT0sNtzabtO5xI6rZfCb", - "bb6Mui+srk2EkG0924ilTSjvv7rJrIzuwU/2HwvzqjNWy+6WtlitpWxvTS2MaTzKGIitNJsWcdKmM+do", - "N2BchyAl8yhB/wt9PvGH3UzME1CwPD4gCKIH6OtNtctUK3mC/V519nGiK3JMiA9+4hBbcUuxdHSZX0Lc", - "gE2W6lAbGUWI1NaxyRIyOkZpIaOUCDZjlfNxJaOEWMMm/POzagbQGyzpvPKuUmKRxo8WJs7IoN0Wc/TM", - "N7Q7+LTqFU2B4fjDhwIQR9ZXsgoGjZOI/gP63RnWItY0afeIzNOJA+JYUnv5WONtlviRwHgvSdnhJf58", - "PgC8SGydZi9aybhOkUilzKo8XoPp3HJgC6aV45kPNAHvrhlXRLWSyMF3KJaw/ZXC5CkHLppOMbuxakBB", - "IfntvTbAtXo6HvY+eTJMyT43nHGbhhpNCeQVLDb4jVtr6KzvdzNrgeseAGbCZxqloa+7TxbYX2H+TDOg", - "P43SylehjIXrZVLulm2WSLxNA3k04IN20ujNSKO8hnUni34dWaQw/vYlURDNquUQdoJo5gQoLOlG5Xed", - "s2h2hkJ+OnZiqB1iqGeu0BTAexhgOi/PU1IxMWtZmLnSIi3ogPbiAfeGlWNID16HzabAMY0SAyC8Q1NA", - "xryXBogbVs01cphrvXn9kZo8oOHkhcQDBjzw6f0sw0ElFKdKs1Ugyftv95BSpUHd+URJsjucDM+a7FTI", - "pLByFpxFs+bHAP+MzXYqnmwdO4AVfzE403F3P97U3Y6nKh+8WBOt2jWVRCI19ws4otaSuEg0oniedn6m", - "GYnzvc6Jrc6rVEfRmSmWZ7ep8C5nrimPCBMUzqoJ/PWYZXfgLm7HhHmY2Ys6hnf8uDG/7wZe3pV8qY+B", - "qvaxAZm2avJBx3XxILbXkVZw8C6DJVawHJg3oeOdgrpWRa32zNRroKI1D5TKtLe3eripGubmYqGsVdCj", - "F46FKp+AXSyUrY66ViyU3Sl5gCGh/8X1cdOyiyO7VEdCKeSCwtlY9LF0xn4jx6SCmDXOSHVPOlYquO8a", - "0bQxPsoCCqsf2rL4PmwXP9jpk5nPMcMHzrPCNuITmTyks/UtK49ZECJuFplYpzCuECzb6YgMAZLWFbVw", - "myaM5Uk7/toUfwlGWDH0t/rAsfDqwCyEpODawXsbguRey1nzlp9R7+CT1SMqbVeY1SqjHiMDlqSqnJDV", - "DJNSBcUKtlxWNAZQKceyGohJGop0T9AKVtnW+vlTn8L4hZ6k2X6+zIM0m7oFz9EqHOpjdAWxZKGWd/BJ", - "lG2LAUpK9JJlUP8PZbejj6zpEa/Vdsz/dUzFu249miz9WmaozZNsXoYMZLaic5Gs2sCSm83tvPUY584L", - "YCM3Ayh9PC0jm21NyFWB+t0VgCFAJEOuNAtz/n4ZNwS7FBqqzZdH5bx5L9Djf+xmVpm4Vqin8NGD0C8F", - "qYkLioyYsubz+ovJwSQN7sxuP5/S4E6QB85lAq4UCrTPGxYMdPkNhQN+IelQAtXSpFCSF53beMsEBuNb", - "VWrgDYsNj9UfqfAXZN+5ZUMpjVjQeU1ihPuZ8BHesobBEGCvYYgbRALjADxtXI68WH2Z5bTgNaKJIQ36", - "xYL3nZBqo5AaMUrdjnxidjVLoys31lkYXr/Bp+6dL7c+rnR9Z8jurvC6K7wjjMGb5ANxGlQkzKXfcbOj", - "eSSPmLd6NHMEtOVo3oydjQPXafVv7cBE4T0isKnHteyl9yIbsq/dWSmdxxR8rOQ2JrHdOYvp/KlzWtyS", - "EzWfoJLWO3u44jbNUWLnLc1x+6Iu0hzcVTyjBWF0bKl3h874ZjO+m4LP5Q97/N/NaiNZsHLjakjtcrAp", - "8lU1bHsZOl772VrLvZpSTy3jXl1awmx/TOHcxX1sUkLJghNeef7BFnLCdmNxVzt3Xywa15JzNdWZ2sy5", - "Ikq2MedWnXwLuJiIcrIN7miyl57Fv7Ov3R1NUqOCj5XuaBLbnTKou6PltLgZXVCMd/CT/2GTkxoIIJxp", - "Ei3q4uA4NfwaqqBYtgk2/nn3mbM3zrur6IBvg2tblPbu3JDlLmPSwsZsTF78lcIU7i2o4PZwbbki1toR", - "rbNX5EqB8QWSf9Fe38UUr1FmvKpQgdfk/b197aVAe6uFhGW17iWXdDLxhWUiFUfZ7iwywSIlouScVWVi", - "AgjcYw9ONq4StDV/nqrzlRgBAs9owy5Qra2BapsKaqrF5DZDlzI6a0H40jIsu8qnWeS1Bs44Cjt33jhL", - "d1YVN7m4pah2zvivq0pc0WMvjgLkPdXncJEdHN7BJoOLdCW4ZD26/C0HOrSsZuJZ2o3O1LPzNEi8LFll", - "5pZCyTNcWamvM37ypC0qTprcHpZQ3RVPalFdM4UXDHUxa2oAWjDiASYgIUZ2HNOv/By76Kdk7rDLyjJD", - "XmOY8DcTBtAFRSjr+Ro5893hcU3NMYYycawUsDKHwBdvPEHECaZIK8tzPy9Vy6JkF90hSAdl2ZAL5bMY", - "SoszSkKgO7AyHdQl0loqrId1de46OSzk8Pm4UB+4gSRexnIni1sni8uMYFVisjZ/l0Wt1c47kSGgyF+V", - "abs2R7PFSa29DLuisS1maCPnWXJ05YkqCnTs7eLJStQMe20vV9s3F+gQ08xmkBWyKuxM96jShkeVbG/K", - "jypr2ic05dQqWTevnOZMnjhDaWs5vhI7Xq+tJd12UHhxRfnQSYTWVVxURcRGqixayYnanBp9QuAiFtli", - "WFuLIrCvLZlGJ0GqHNgQZu79QoRwIgjad0F44Ue8OkbZFUMnkHasiL1nSUpseZg171i4jdkAkjQUW1UT", - "fIHCOGX+EPxxV7fc51ZoKl0ugAr5wjb8JQRKvqZKWwBvZlkl/gskYz5sJ1peTjtoluXKYGkQw3UXijZf", - "KOQubUVqiLf4vYcouasKGMvdOo2OEp2PRO6izlFxw5BKEVKVKZMiI3Oj5x0duR2dEb9tr3IK+a+eKkQM", - "YmKhN//6VuAfjo0d1czRzOw3SvQht7bj3PY9v6mMt4qxnkvlavM8PSG58K72vc3Phjd/WOaY6EpTrX3V", - "lCFAxdhpjuNVH6kkovn1snmGSLVIjyZRpFJZp0sXqaSLVPCCa8xEhTJIL5c8Uge3ddU5xYJUIJjuetrK", - "pJLFPSoHGVZfUJsInJ/qP+texwucUHsCCzJ9zY/lS6yvB03F4CtWE8R2rRqv3D2em6OFi3bp+kjhXpGm", - "VufnA/bEUWui5g8hnKFVoPdr+HrIRu+Y++WZO8+NcKmUhuAwrmPNLuKIbXdn0N6RQftGxX1ok5Ug36Sm", - "KsPmJA6egxhuSY8Ys7E7efNqlAm+YZ1G8QtpFJlHvEUt7UIZ7SDIXt2wRteoYn0WjsUfyAcy3X4nAzYO", - "4BnAxBmesqSVc+gEQO6gKfkJwGToG7OfvDvWZT/ZgedekzIbquTpfGta+mK/giyxf863k4XY6mWCtbTT", - "aLrXiVxT6N4nNq8ibDI3WTamZaVJBzgTQLx56X2i6pB/8yUmVdM+R4at/6pwqy5b99903cmge/CoyRPE", - "yWYXjw34wEuisP4Qpa2cP6NJEajqE/UkicLXdqq+zSSH2aYin047gyTb3v2aXLame8amc+2+pkS2FakV", - "J0/OVKRv3FiGR5XPsH2Wx8nT9hI9KkfmjlM9FpCxhv7aHUo1Zq7t6LFsYNsbncUZtGSs6o6gth5BsgSs", - "7fnD2m/38Gn1yUiBi0FCkWawXS6BxRvfqFeDHcGniTzSwiashLvSKApowwSQFEOrNP6y7Sqn4Zj1FeeS", - "DXB3KPStoGING4P0DYV+PTSvXvkiaAEdMKWAll7PHwCWzuzqEtzjw+OjvUP6v6vDw4/sf/9jwL3o3qcT", - "6InXBwTuUShc26o0FOIJnEYJ3CbIn9gMm4S5AstTFCI8Xx1m2X+neN4U0BvF9PYuE2XN/c1eJZZ1x+4i", - "8couEgc2aeGAI0CjB12R/dU8cZaeMK+5sFGnhndq+O7V8E637HTLF/GBw2sWAmMCqEtY+ULnOwXRTwN6", - "LNZYC7OWq9gNx7JzZz3sHrC6B6zt3DkzJutesYwY6W6gr+2EyvyzZQ6FPS9KQ1JzGWVtpKevTKoA7gEK", - "wCSA7NCS4xoPrS+Q8Nh3fMJmfPVO2XUO2a/czbKwWSvyOCcVTj4drxt4vYCk1cI0iuyfYpjgAy9NEljN", - "2bzAk2jo0G7aEk9fIDkRg22R7lgpo2Z0xiDu0vu8fHof20pWlO6XyK1YyapMxjNE5unkwANBMKkqIHgS", - "UQWVwAZFy76woVnVshM5fOOiYJ6YdxtlwQq4kwusKgRmRN9mq70piJPl3lpTSq1Z5TQNwqJoFsDt0Bsb", - "+henN46+DdNbjrhfjt5QeI8ItEn3KbVh3iGrE1R7fNMReGmUoZhr6yV4+ERN61oXF9jpi9bHKot4W8Je", - "uSyOkfYOgOfBmFRUr2DfcWaYFJMYalPxzed93O0Ev/DB+UT16SgrqI+vXEd/XYXovCYDQ1Jp7+3pK4Es", - "EKciTx393oy+eB93W1nf6OAboC++8o6+anLyUyStQF9BNEMVRTrOohl2UOgAdjbuVygYZ2yg7dASO4Lp", - "+DvKm2t1jw6i2Qz6DuqKU7br+lw81inV2N6Tg2gWpaSGGaKU2HFDlL68rUfQaNSyLFIdkdYoo4x6bMl2", - "ARcTmOA5ihtcgZROdtcgfoR8z7uJh/OtErh+0ub3IRVF3Z1olTuRisF6kowBxg9R4ptlKReTQpI6sn2V", - "SL2UY25PxziZg3CWTdQmZcNjkPkZojpx/orEOSerIqVbMFECZ1SQJVWXPt4CV2okWQGObbGNBKNNDCOR", - "1z1zvQo9XZKQrc6DA+DdbeWFYUxHbvEDQ42oafjisFQx6+Cn+OGZr5AOVV7rKeQ4rS39wxvauKnIUlFG", - "h5Bsoh37g1SVo4X5HneFclpYKIeTn0WhnF5GX3bMcSDwbHPfkk1l1rxqjhFHKLb1Sm4t32y+fpVAzSoF", - "6LLt6tizpRXo8i1qyqMZb7I/bApqaIwbnMIsC2cIZ7Mq30U2xestX7WCr2LL1OvW1K1qULaqJ0mHFV0E", - "xJtXmE0qCZm3ejW0vIVbKUNA4dyoKjZF7x0SZburL2XJaxyyjtP0nCYYYh1mWzpNlp38629CajJkq+Cz", - "BveiVnrKv29yM5IAdlm+d5Tl+9yQ1FsQq0IxK/rJ96xKjVhxQgOV6y0EjKwYJNLx1kvzlhqNsg5j2ah9", - "9tzVTA9sBYNtL8u3rMZql+Gba11FLtu1cmglEZbVw04eGBXE9ZizRk20yklEN6mYfChjvHuYYB7DbDwp", - "G+QgagM/a2LmeYbFDSRpXD1Fox6wWRKlMYvgz0GQG2UEhXX6Bp8KwLyE2rBmwhNBel3OkzZqE9mubE1w", - "kQTNZlVuBle8gQOcED6sVksw80F4nZLrSsMu+85wyqzbOKXUAf2eKOJFICYZTyHsTCHx5tA35SvJBX/L", - "FSlBBsqu2ipTpSqDL6FJ2ZRaFgmuurKIbRCJrasVL+VgTVFI28KvFqJZyAZsW95VSh0rsfwHb/yKTDC/", - "glzespQTm7qmKtjJu1apgDkprqoCLvuQTSBIYJL5kPW0XmUwuZfyIE0C96PrPv94/v8BAAD//9vtasL6", - "2QEA", + "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", + "2gEA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/v1/server/oas/transformers/workflow_run.go b/api/v1/server/oas/transformers/workflow_run.go index 8650edc84..57267db8a 100644 --- a/api/v1/server/oas/transformers/workflow_run.go +++ b/api/v1/server/oas/transformers/workflow_run.go @@ -495,7 +495,7 @@ func ToScheduledWorkflowsFromSQLC(scheduled *dbsqlc.ListScheduledWorkflowsRow) * } res := &gen.ScheduledWorkflows{ - Metadata: *toAPIMetadata(sqlchelpers.UUIDToStr(scheduled.ID), time.Now(), time.Now()), + Metadata: *toAPIMetadata(sqlchelpers.UUIDToStr(scheduled.ID), scheduled.CreatedAt.Time, scheduled.UpdatedAt.Time), WorkflowVersionId: sqlchelpers.UUIDToStr(scheduled.WorkflowVersionId), WorkflowId: sqlchelpers.UUIDToStr(scheduled.WorkflowId), WorkflowName: scheduled.Name, @@ -507,23 +507,23 @@ func ToScheduledWorkflowsFromSQLC(scheduled *dbsqlc.ListScheduledWorkflowsRow) * return res } -func ToCronWorkflowsFromSQLC(scheduled *dbsqlc.ListCronWorkflowsRow) *gen.CronWorkflows { +func ToCronWorkflowsFromSQLC(cron *dbsqlc.ListCronWorkflowsRow) *gen.CronWorkflows { var additionalMetadata map[string]interface{} - if scheduled.AdditionalMetadata != nil { - err := json.Unmarshal(scheduled.AdditionalMetadata, &additionalMetadata) + if cron.AdditionalMetadata != nil { + err := json.Unmarshal(cron.AdditionalMetadata, &additionalMetadata) if err != nil { return nil } } res := &gen.CronWorkflows{ - Metadata: *toAPIMetadata(sqlchelpers.UUIDToStr(scheduled.ID), time.Now(), time.Now()), - WorkflowVersionId: sqlchelpers.UUIDToStr(scheduled.WorkflowVersionId), - WorkflowId: sqlchelpers.UUIDToStr(scheduled.WorkflowId), - WorkflowName: scheduled.Name, - TenantId: sqlchelpers.UUIDToStr(scheduled.TenantId), - Cron: scheduled.Cron, + Metadata: *toAPIMetadata(sqlchelpers.UUIDToStr(cron.ID), cron.CreatedAt.Time, cron.UpdatedAt.Time), + WorkflowVersionId: sqlchelpers.UUIDToStr(cron.WorkflowVersionId), + WorkflowId: sqlchelpers.UUIDToStr(cron.WorkflowId), + WorkflowName: cron.Name, + TenantId: sqlchelpers.UUIDToStr(cron.TenantId), + Cron: cron.Cron, AdditionalMetadata: &additionalMetadata, } diff --git a/frontend/app/src/lib/api/generated/data-contracts.ts b/frontend/app/src/lib/api/generated/data-contracts.ts index 15642d3f5..d0084a9da 100644 --- a/frontend/app/src/lib/api/generated/data-contracts.ts +++ b/frontend/app/src/lib/api/generated/data-contracts.ts @@ -779,6 +779,7 @@ export interface ScheduledWorkflowsList { export enum ScheduledWorkflowsOrderByField { TriggerAt = 'triggerAt', + CreatedAt = 'createdAt', } export interface CronWorkflows { diff --git a/frontend/app/src/pages/main/crons/components/crons-columns.tsx b/frontend/app/src/pages/main/crons/components/crons-columns.tsx index 240ec1dbb..d672999ee 100644 --- a/frontend/app/src/pages/main/crons/components/crons-columns.tsx +++ b/frontend/app/src/pages/main/crons/components/crons-columns.tsx @@ -3,6 +3,7 @@ import { DataTableColumnHeader } from '../../../../components/molecules/data-tab import { CronWorkflows, RateLimit } from '@/lib/api'; import CronPrettifier from 'cronstrue'; import { AdditionalMetadata } from '../../events/components/additional-metadata'; +import RelativeDate from '@/components/molecules/relative-date'; export type RateLimitRow = RateLimit & { metadata: { @@ -64,4 +65,17 @@ export const columns: ColumnDef[] = [ }, enableSorting: false, }, + { + accessorKey: 'createdAt', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ +
+ ), + enableSorting: true, + enableHiding: true, + }, ]; diff --git a/frontend/app/src/pages/main/crons/index.tsx b/frontend/app/src/pages/main/crons/index.tsx index 626869d1a..09d139567 100644 --- a/frontend/app/src/pages/main/crons/index.tsx +++ b/frontend/app/src/pages/main/crons/index.tsx @@ -19,7 +19,7 @@ import invariant from 'tiny-invariant'; import { useOutletContext, useSearchParams } from 'react-router-dom'; import { TenantContextType } from '@/lib/outlet'; -export default function RateLimits() { +export default function Crons() { return (
@@ -27,13 +27,13 @@ export default function RateLimits() { Cron Runs - +
); } -function ScheduledRunsTable() { +function CronsTable() { const { tenant } = useOutletContext(); const [searchParams, setSearchParams] = useSearchParams(); @@ -58,7 +58,7 @@ function ScheduledRunsTable() { return []; }); const [columnVisibility, setColumnVisibility] = useState({ - RateLimitId: false, + createdAt: false, }); const [pagination, setPagination] = useState(() => { diff --git a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx index 057146187..d506a7b67 100644 --- a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx +++ b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx @@ -51,4 +51,17 @@ export const columns: ColumnDef[] = [ }, enableSorting: false, }, + { + accessorKey: 'createdAt', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ +
+ ), + enableSorting: true, + enableHiding: true, + }, ]; diff --git a/frontend/app/src/pages/main/scheduled-runs/index.tsx b/frontend/app/src/pages/main/scheduled-runs/index.tsx index 7374a28d4..5c0388506 100644 --- a/frontend/app/src/pages/main/scheduled-runs/index.tsx +++ b/frontend/app/src/pages/main/scheduled-runs/index.tsx @@ -58,7 +58,7 @@ function ScheduledRunsTable() { return []; }); const [columnVisibility, setColumnVisibility] = useState({ - RateLimitId: false, + createdAt: false, }); const [pagination, setPagination] = useState(() => { @@ -115,6 +115,8 @@ function ScheduledRunsTable() { } switch (sorting[0]?.id) { + case 'createdAt': + return ScheduledWorkflowsOrderByField.CreatedAt; case 'triggerAt': return ScheduledWorkflowsOrderByField.TriggerAt; default: @@ -145,16 +147,6 @@ function ScheduledRunsTable() { refetchInterval: 2000, }); - // const tableData = - // data?.rows?.map( - // (row): ScheduledWorkflows => ({ - // ...row, - // metadata: { - // id: row.key, - // }, - // }), - // ) || []; - return ( Date: Thu, 24 Oct 2024 13:19:05 -0400 Subject: [PATCH 08/30] cron to recurring --- frontend/app/src/pages/main/index.tsx | 37 +++++++++++-------- .../components/recurring-columns.tsx} | 0 .../pages/main/{crons => recurring}/index.tsx | 4 +- frontend/app/src/router.tsx | 4 +- 4 files changed, 26 insertions(+), 19 deletions(-) rename frontend/app/src/pages/main/{crons/components/crons-columns.tsx => recurring/components/recurring-columns.tsx} (100%) rename frontend/app/src/pages/main/{crons => recurring}/index.tsx (98%) diff --git a/frontend/app/src/pages/main/index.tsx b/frontend/app/src/pages/main/index.tsx index 87db674bc..587a90cdb 100644 --- a/frontend/app/src/pages/main/index.tsx +++ b/frontend/app/src/pages/main/index.tsx @@ -11,7 +11,7 @@ import { import { Link, Outlet, useLocation, useOutletContext } from 'react-router-dom'; import { Tenant, TenantMember } from '@/lib/api'; -import { ClockIcon, GearIcon, StarIcon } from '@radix-ui/react-icons'; +import { ClockIcon, GearIcon } from '@radix-ui/react-icons'; import React, { useCallback } from 'react'; import { MembershipsContextType, @@ -135,6 +135,27 @@ function Sidebar({ className, memberships, currTenant }: SidebarProps) { />
+
+

+ Triggers +

+
+ } + /> + } + /> +
+

Resources @@ -163,20 +184,6 @@ function Sidebar({ className, memberships, currTenant }: SidebarProps) { name="Rate Limits" icon={} /> - } - /> - } - />

diff --git a/frontend/app/src/pages/main/crons/components/crons-columns.tsx b/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx similarity index 100% rename from frontend/app/src/pages/main/crons/components/crons-columns.tsx rename to frontend/app/src/pages/main/recurring/components/recurring-columns.tsx diff --git a/frontend/app/src/pages/main/crons/index.tsx b/frontend/app/src/pages/main/recurring/index.tsx similarity index 98% rename from frontend/app/src/pages/main/crons/index.tsx rename to frontend/app/src/pages/main/recurring/index.tsx index 09d139567..ef081171e 100644 --- a/frontend/app/src/pages/main/crons/index.tsx +++ b/frontend/app/src/pages/main/recurring/index.tsx @@ -1,5 +1,5 @@ import { DataTable } from '../../../components/molecules/data-table/data-table'; -import { columns } from './components/crons-columns'; +import { columns } from './components/recurring-columns'; import { Separator } from '@/components/ui/separator'; import { useEffect, useMemo, useState } from 'react'; import { @@ -24,7 +24,7 @@ export default function Crons() {

- Cron Runs + Recurring Runs

diff --git a/frontend/app/src/router.tsx b/frontend/app/src/router.tsx index 4c25c764a..f9e5ef85a 100644 --- a/frontend/app/src/router.tsx +++ b/frontend/app/src/router.tsx @@ -142,9 +142,9 @@ const routes: RouteObject[] = [ }), }, { - path: '/crons', + path: '/recurring', lazy: async () => - import('./pages/main/crons').then((res) => { + import('./pages/main/recurring').then((res) => { return { Component: res.default, }; From 5ee9c1f3848aac72b5baa8556371c41ea228de6f Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Thu, 24 Oct 2024 13:40:05 -0400 Subject: [PATCH 09/30] scheduled: with statuses --- .../components/schemas/workflow_run.yaml | 14 + api/v1/server/oas/gen/openapi.gen.go | 296 +++++++++--------- .../server/oas/transformers/workflow_run.go | 31 +- .../src/lib/api/generated/data-contracts.ts | 11 + .../components/scheduled-runs-columns.tsx | 12 + .../workflow-runs/components/run-statuses.tsx | 7 +- pkg/client/rest/gen.go | 20 +- .../prisma/dbsqlc/workflow_runs.sql | 8 +- .../prisma/dbsqlc/workflow_runs.sql.go | 50 +-- 9 files changed, 268 insertions(+), 181 deletions(-) diff --git a/api-contracts/openapi/components/schemas/workflow_run.yaml b/api-contracts/openapi/components/schemas/workflow_run.yaml index b5a2f2646..9f7029265 100644 --- a/api-contracts/openapi/components/schemas/workflow_run.yaml +++ b/api-contracts/openapi/components/schemas/workflow_run.yaml @@ -11,6 +11,7 @@ ScheduledWorkflowsOrderByField: enum: - triggerAt - createdAt + CronWorkflowsOrderByField: type: string enum: @@ -193,6 +194,19 @@ ScheduledWorkflows: additionalMetadata: type: object additionalProperties: true + workflowRunCreatedAt: + type: string + format: date-time + workflowRunName: + type: string + workflowRunStatus: + $ref: "#/WorkflowRunStatus" + workflowRunId: + type: string + example: bb214807-246e-43a5-a25d-41761d1cff9e + minLength: 36 + maxLength: 36 + format: uuid required: - metadata - tenantId diff --git a/api/v1/server/oas/gen/openapi.gen.go b/api/v1/server/oas/gen/openapi.gen.go index 1b20d4b39..53df14cdc 100644 --- a/api/v1/server/oas/gen/openapi.gen.go +++ b/api/v1/server/oas/gen/openapi.gen.go @@ -645,14 +645,18 @@ type SNSIntegration struct { // ScheduledWorkflows defines model for ScheduledWorkflows. type ScheduledWorkflows struct { - AdditionalMetadata *map[string]interface{} `json:"additionalMetadata,omitempty"` - Input *map[string]interface{} `json:"input,omitempty"` - Metadata APIResourceMeta `json:"metadata"` - TenantId string `json:"tenantId"` - TriggerAt time.Time `json:"triggerAt"` - WorkflowId string `json:"workflowId"` - WorkflowName string `json:"workflowName"` - WorkflowVersionId string `json:"workflowVersionId"` + AdditionalMetadata *map[string]interface{} `json:"additionalMetadata,omitempty"` + Input *map[string]interface{} `json:"input,omitempty"` + Metadata APIResourceMeta `json:"metadata"` + TenantId string `json:"tenantId"` + TriggerAt time.Time `json:"triggerAt"` + WorkflowId string `json:"workflowId"` + WorkflowName string `json:"workflowName"` + WorkflowRunCreatedAt *time.Time `json:"workflowRunCreatedAt,omitempty"` + WorkflowRunId *openapi_types.UUID `json:"workflowRunId,omitempty"` + WorkflowRunName *string `json:"workflowRunName,omitempty"` + WorkflowRunStatus *WorkflowRunStatus `json:"workflowRunStatus,omitempty"` + WorkflowVersionId string `json:"workflowVersionId"` } // ScheduledWorkflowsList defines model for ScheduledWorkflowsList. @@ -9930,144 +9934,144 @@ var swaggerSpec = []string{ "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", - "2gEA", + "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", + "HqRJ4H503ecfz/8/AAD//z6iua4v2wEA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/v1/server/oas/transformers/workflow_run.go b/api/v1/server/oas/transformers/workflow_run.go index 57267db8a..cac024e7b 100644 --- a/api/v1/server/oas/transformers/workflow_run.go +++ b/api/v1/server/oas/transformers/workflow_run.go @@ -494,14 +494,31 @@ func ToScheduledWorkflowsFromSQLC(scheduled *dbsqlc.ListScheduledWorkflowsRow) * } } + var workflowRunStatus gen.WorkflowRunStatus + + if scheduled.WorkflowRunStatus.Valid { + workflowRunStatus = gen.WorkflowRunStatus(scheduled.WorkflowRunStatus.WorkflowRunStatus) + } + + var workflowRunIdPtr *uuid.UUID + + if scheduled.WorkflowRunId.Valid { + workflowRunId := uuid.MustParse(sqlchelpers.UUIDToStr(scheduled.WorkflowRunId)) + workflowRunIdPtr = &workflowRunId + } + res := &gen.ScheduledWorkflows{ - Metadata: *toAPIMetadata(sqlchelpers.UUIDToStr(scheduled.ID), scheduled.CreatedAt.Time, scheduled.UpdatedAt.Time), - WorkflowVersionId: sqlchelpers.UUIDToStr(scheduled.WorkflowVersionId), - WorkflowId: sqlchelpers.UUIDToStr(scheduled.WorkflowId), - WorkflowName: scheduled.Name, - TenantId: sqlchelpers.UUIDToStr(scheduled.TenantId), - TriggerAt: scheduled.TriggerAt.Time, - AdditionalMetadata: &additionalMetadata, + Metadata: *toAPIMetadata(sqlchelpers.UUIDToStr(scheduled.ID), scheduled.CreatedAt.Time, scheduled.UpdatedAt.Time), + WorkflowVersionId: sqlchelpers.UUIDToStr(scheduled.WorkflowVersionId), + WorkflowId: sqlchelpers.UUIDToStr(scheduled.WorkflowId), + WorkflowName: scheduled.Name, + TenantId: sqlchelpers.UUIDToStr(scheduled.TenantId), + TriggerAt: scheduled.TriggerAt.Time, + AdditionalMetadata: &additionalMetadata, + WorkflowRunCreatedAt: &scheduled.WorkflowRunCreatedAt.Time, + WorkflowRunStatus: &workflowRunStatus, + WorkflowRunId: workflowRunIdPtr, + WorkflowRunName: &scheduled.WorkflowRunName.String, } return res diff --git a/frontend/app/src/lib/api/generated/data-contracts.ts b/frontend/app/src/lib/api/generated/data-contracts.ts index d0084a9da..e2360d7c1 100644 --- a/frontend/app/src/lib/api/generated/data-contracts.ts +++ b/frontend/app/src/lib/api/generated/data-contracts.ts @@ -770,6 +770,17 @@ export interface ScheduledWorkflows { triggerAt: string; input?: Record; additionalMetadata?: Record; + /** @format date-time */ + workflowRunCreatedAt?: string; + workflowRunName?: string; + workflowRunStatus?: WorkflowRunStatus; + /** + * @format uuid + * @minLength 36 + * @maxLength 36 + * @example "bb214807-246e-43a5-a25d-41761d1cff9e" + */ + workflowRunId?: string; } export interface ScheduledWorkflowsList { diff --git a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx index d506a7b67..3a34ef68b 100644 --- a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx +++ b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx @@ -3,6 +3,7 @@ import { DataTableColumnHeader } from '../../../../components/molecules/data-tab import { RateLimit, ScheduledWorkflows } from '@/lib/api'; import RelativeDate from '@/components/molecules/relative-date'; import { AdditionalMetadata } from '../../events/components/additional-metadata'; +import { RunStatus } from '../../workflow-runs/components/run-statuses'; export type RateLimitRow = RateLimit & { metadata: { @@ -11,6 +12,17 @@ export type RateLimitRow = RateLimit & { }; export const columns: ColumnDef[] = [ + { + accessorKey: 'status', + header: ({ column }) => ( + + ), + cell: ({ row }) => { + return ( + + ); + }, + }, { accessorKey: 'triggerAt', header: ({ column }) => ( diff --git a/frontend/app/src/pages/main/workflow-runs/components/run-statuses.tsx b/frontend/app/src/pages/main/workflow-runs/components/run-statuses.tsx index 8b82da033..0e5aabb76 100644 --- a/frontend/app/src/pages/main/workflow-runs/components/run-statuses.tsx +++ b/frontend/app/src/pages/main/workflow-runs/components/run-statuses.tsx @@ -8,7 +8,8 @@ import { import { JobRunStatus, StepRunStatus, WorkflowRunStatus } from '@/lib/api'; import { capitalize, cn } from '@/lib/utils'; -type RunStatusType = `${StepRunStatus | WorkflowRunStatus | JobRunStatus}`; +type RunStatusType = + `${StepRunStatus | WorkflowRunStatus | JobRunStatus | 'SCHEDULED'}`; type RunStatusVariant = { text: string; @@ -52,6 +53,10 @@ const RUN_STATUS_VARIANTS: Record = { text: 'Assigned', variant: 'inProgress', }, + SCHEDULED: { + text: 'Scheduled', + variant: 'outline', + }, }; const RUN_STATUS_REASONS: Record = { diff --git a/pkg/client/rest/gen.go b/pkg/client/rest/gen.go index 2f30e95ec..d0940e417 100644 --- a/pkg/client/rest/gen.go +++ b/pkg/client/rest/gen.go @@ -642,14 +642,18 @@ type SNSIntegration struct { // ScheduledWorkflows defines model for ScheduledWorkflows. type ScheduledWorkflows struct { - AdditionalMetadata *map[string]interface{} `json:"additionalMetadata,omitempty"` - Input *map[string]interface{} `json:"input,omitempty"` - Metadata APIResourceMeta `json:"metadata"` - TenantId string `json:"tenantId"` - TriggerAt time.Time `json:"triggerAt"` - WorkflowId string `json:"workflowId"` - WorkflowName string `json:"workflowName"` - WorkflowVersionId string `json:"workflowVersionId"` + AdditionalMetadata *map[string]interface{} `json:"additionalMetadata,omitempty"` + Input *map[string]interface{} `json:"input,omitempty"` + Metadata APIResourceMeta `json:"metadata"` + TenantId string `json:"tenantId"` + TriggerAt time.Time `json:"triggerAt"` + WorkflowId string `json:"workflowId"` + WorkflowName string `json:"workflowName"` + WorkflowRunCreatedAt *time.Time `json:"workflowRunCreatedAt,omitempty"` + WorkflowRunId *openapi_types.UUID `json:"workflowRunId,omitempty"` + WorkflowRunName *string `json:"workflowRunName,omitempty"` + WorkflowRunStatus *WorkflowRunStatus `json:"workflowRunStatus,omitempty"` + WorkflowVersionId string `json:"workflowVersionId"` } // ScheduledWorkflowsList defines model for ScheduledWorkflowsList. diff --git a/pkg/repository/prisma/dbsqlc/workflow_runs.sql b/pkg/repository/prisma/dbsqlc/workflow_runs.sql index e6e52a423..fec3fe15a 100644 --- a/pkg/repository/prisma/dbsqlc/workflow_runs.sql +++ b/pkg/repository/prisma/dbsqlc/workflow_runs.sql @@ -1423,10 +1423,16 @@ SELECT w."id" as "workflowId", v."id" as "workflowVersionId", w."tenantId", - t.* + t.*, + wr."createdAt" as "workflowRunCreatedAt", + wr."status" as "workflowRunStatus", + wr."id" as "workflowRunId", + wr."displayName" as "workflowRunName" FROM "WorkflowTriggerScheduledRef" t JOIN "WorkflowVersion" v ON t."parentId" = v."id" JOIN "Workflow" w on v."workflowId" = w."id" +LEFT JOIN "WorkflowRunTriggeredBy" tb ON t."id" = tb."scheduledId" +LEFT JOIN "WorkflowRun" wr ON tb."parentId" = wr."id" WHERE v."deletedAt" IS NULL AND w."tenantId" = @tenantId::uuid -- TODO page diff --git a/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go b/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go index 0071b69f1..9210bc848 100644 --- a/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go +++ b/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go @@ -2222,10 +2222,16 @@ SELECT w."id" as "workflowId", v."id" as "workflowVersionId", w."tenantId", - t.id, t."parentId", t."triggerAt", t."tickerId", t.input, t."childIndex", t."childKey", t."parentStepRunId", t."parentWorkflowRunId", t."additionalMetadata", t."createdAt", t."deletedAt", t."updatedAt" + t.id, t."parentId", t."triggerAt", t."tickerId", t.input, t."childIndex", t."childKey", t."parentStepRunId", t."parentWorkflowRunId", t."additionalMetadata", t."createdAt", t."deletedAt", t."updatedAt", + wr."createdAt" as "workflowRunCreatedAt", + wr."status" as "workflowRunStatus", + wr."id" as "workflowRunId", + wr."displayName" as "workflowRunName" FROM "WorkflowTriggerScheduledRef" t JOIN "WorkflowVersion" v ON t."parentId" = v."id" JOIN "Workflow" w on v."workflowId" = w."id" +LEFT JOIN "WorkflowRunTriggeredBy" tb ON t."id" = tb."scheduledId" +LEFT JOIN "WorkflowRun" wr ON tb."parentId" = wr."id" WHERE v."deletedAt" IS NULL AND w."tenantId" = $1::uuid -- TODO page @@ -2255,23 +2261,27 @@ type ListScheduledWorkflowsParams struct { } type ListScheduledWorkflowsRow struct { - Name string `json:"name"` - WorkflowId pgtype.UUID `json:"workflowId"` - WorkflowVersionId pgtype.UUID `json:"workflowVersionId"` - TenantId pgtype.UUID `json:"tenantId"` - ID pgtype.UUID `json:"id"` - ParentId pgtype.UUID `json:"parentId"` - TriggerAt pgtype.Timestamp `json:"triggerAt"` - TickerId pgtype.UUID `json:"tickerId"` - Input []byte `json:"input"` - ChildIndex pgtype.Int4 `json:"childIndex"` - ChildKey pgtype.Text `json:"childKey"` - ParentStepRunId pgtype.UUID `json:"parentStepRunId"` - ParentWorkflowRunId pgtype.UUID `json:"parentWorkflowRunId"` - AdditionalMetadata []byte `json:"additionalMetadata"` - CreatedAt pgtype.Timestamp `json:"createdAt"` - DeletedAt pgtype.Timestamp `json:"deletedAt"` - UpdatedAt pgtype.Timestamp `json:"updatedAt"` + Name string `json:"name"` + WorkflowId pgtype.UUID `json:"workflowId"` + WorkflowVersionId pgtype.UUID `json:"workflowVersionId"` + TenantId pgtype.UUID `json:"tenantId"` + ID pgtype.UUID `json:"id"` + ParentId pgtype.UUID `json:"parentId"` + TriggerAt pgtype.Timestamp `json:"triggerAt"` + TickerId pgtype.UUID `json:"tickerId"` + Input []byte `json:"input"` + ChildIndex pgtype.Int4 `json:"childIndex"` + ChildKey pgtype.Text `json:"childKey"` + ParentStepRunId pgtype.UUID `json:"parentStepRunId"` + ParentWorkflowRunId pgtype.UUID `json:"parentWorkflowRunId"` + AdditionalMetadata []byte `json:"additionalMetadata"` + CreatedAt pgtype.Timestamp `json:"createdAt"` + DeletedAt pgtype.Timestamp `json:"deletedAt"` + UpdatedAt pgtype.Timestamp `json:"updatedAt"` + WorkflowRunCreatedAt pgtype.Timestamp `json:"workflowRunCreatedAt"` + WorkflowRunStatus NullWorkflowRunStatus `json:"workflowRunStatus"` + WorkflowRunId pgtype.UUID `json:"workflowRunId"` + WorkflowRunName pgtype.Text `json:"workflowRunName"` } func (q *Queries) ListScheduledWorkflows(ctx context.Context, db DBTX, arg ListScheduledWorkflowsParams) ([]*ListScheduledWorkflowsRow, error) { @@ -2306,6 +2316,10 @@ func (q *Queries) ListScheduledWorkflows(ctx context.Context, db DBTX, arg ListS &i.CreatedAt, &i.DeletedAt, &i.UpdatedAt, + &i.WorkflowRunCreatedAt, + &i.WorkflowRunStatus, + &i.WorkflowRunId, + &i.WorkflowRunName, ); err != nil { return nil, err } From de2e44cce1dd8070cc16bc29878afa3945c92645 Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Thu, 24 Oct 2024 13:57:42 -0400 Subject: [PATCH 10/30] fix: links --- .../components/scheduled-runs-columns.tsx | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx index 3a34ef68b..620deeedd 100644 --- a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx +++ b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx @@ -4,6 +4,7 @@ import { RateLimit, ScheduledWorkflows } from '@/lib/api'; import RelativeDate from '@/components/molecules/relative-date'; import { AdditionalMetadata } from '../../events/components/additional-metadata'; import { RunStatus } from '../../workflow-runs/components/run-statuses'; +import { Link } from 'react-router-dom'; export type RateLimitRow = RateLimit & { metadata: { @@ -13,16 +14,29 @@ export type RateLimitRow = RateLimit & { export const columns: ColumnDef[] = [ { - accessorKey: 'status', + accessorKey: 'runId', header: ({ column }) => ( - + ), cell: ({ row }) => { - return ( - - ); + return row.original.workflowRunId ? ( + +
+ {row.original.workflowRunName} +
+ + ) : null; }, }, + { + accessorKey: 'status', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( + + ), + }, { accessorKey: 'triggerAt', header: ({ column }) => ( @@ -41,9 +55,11 @@ export const columns: ColumnDef[] = [ ), cell: ({ row }) => ( ), enableSorting: false, From e21aeebcee1ec90eea9d78fefef82899a7cf21f3 Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Thu, 24 Oct 2024 15:29:53 -0400 Subject: [PATCH 11/30] feat: expose schedule ids --- api-contracts/workflows/workflows.proto | 10 +- .../services/admin/contracts/workflows.pb.go | 487 ++- internal/services/admin/server.go | 30 +- pkg/repository/prisma/db/db_gen.go | 3519 ++++++++++++++++- prisma/schema.prisma | 2 +- 5 files changed, 3803 insertions(+), 245 deletions(-) diff --git a/api-contracts/workflows/workflows.proto b/api-contracts/workflows/workflows.proto index 4d174268a..74ccfad84 100644 --- a/api-contracts/workflows/workflows.proto +++ b/api-contracts/workflows/workflows.proto @@ -154,16 +154,24 @@ message ScheduleWorkflowRequest { optional string additional_metadata = 8; } +// ScheduledWorkflow represents a scheduled workflow. +message ScheduledWorkflow { + string id = 1; + google.protobuf.Timestamp trigger_at = 2; +} + // WorkflowVersion represents the WorkflowVersion model. message WorkflowVersion { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Timestamp updated_at = 3; string version = 5; - int32 order = 6; + int64 order = 6; string workflow_id = 7; + repeated ScheduledWorkflow scheduled_workflows = 8; } + // WorkflowTriggerEventRef represents the WorkflowTriggerEventRef model. message WorkflowTriggerEventRef { string parent_id = 1; diff --git a/internal/services/admin/contracts/workflows.pb.go b/internal/services/admin/contracts/workflows.pb.go index 7aef855b2..fe0dfd33c 100644 --- a/internal/services/admin/contracts/workflows.pb.go +++ b/internal/services/admin/contracts/workflows.pb.go @@ -1061,24 +1061,81 @@ func (x *ScheduleWorkflowRequest) GetAdditionalMetadata() string { return "" } +// ScheduledWorkflow represents a scheduled workflow. +type ScheduledWorkflow struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + TriggerAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=trigger_at,json=triggerAt,proto3" json:"trigger_at,omitempty"` +} + +func (x *ScheduledWorkflow) Reset() { + *x = ScheduledWorkflow{} + if protoimpl.UnsafeEnabled { + mi := &file_workflows_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ScheduledWorkflow) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ScheduledWorkflow) ProtoMessage() {} + +func (x *ScheduledWorkflow) ProtoReflect() protoreflect.Message { + mi := &file_workflows_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ScheduledWorkflow.ProtoReflect.Descriptor instead. +func (*ScheduledWorkflow) Descriptor() ([]byte, []int) { + return file_workflows_proto_rawDescGZIP(), []int{9} +} + +func (x *ScheduledWorkflow) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *ScheduledWorkflow) GetTriggerAt() *timestamppb.Timestamp { + if x != nil { + return x.TriggerAt + } + return nil +} + // WorkflowVersion represents the WorkflowVersion model. type WorkflowVersion struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - CreatedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` - UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` - Version string `protobuf:"bytes,5,opt,name=version,proto3" json:"version,omitempty"` - Order int32 `protobuf:"varint,6,opt,name=order,proto3" json:"order,omitempty"` - WorkflowId string `protobuf:"bytes,7,opt,name=workflow_id,json=workflowId,proto3" json:"workflow_id,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + Version string `protobuf:"bytes,5,opt,name=version,proto3" json:"version,omitempty"` + Order int64 `protobuf:"varint,6,opt,name=order,proto3" json:"order,omitempty"` + WorkflowId string `protobuf:"bytes,7,opt,name=workflow_id,json=workflowId,proto3" json:"workflow_id,omitempty"` + ScheduledWorkflows []*ScheduledWorkflow `protobuf:"bytes,8,rep,name=scheduled_workflows,json=scheduledWorkflows,proto3" json:"scheduled_workflows,omitempty"` } func (x *WorkflowVersion) Reset() { *x = WorkflowVersion{} if protoimpl.UnsafeEnabled { - mi := &file_workflows_proto_msgTypes[9] + mi := &file_workflows_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1091,7 +1148,7 @@ func (x *WorkflowVersion) String() string { func (*WorkflowVersion) ProtoMessage() {} func (x *WorkflowVersion) ProtoReflect() protoreflect.Message { - mi := &file_workflows_proto_msgTypes[9] + mi := &file_workflows_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1104,7 +1161,7 @@ func (x *WorkflowVersion) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkflowVersion.ProtoReflect.Descriptor instead. func (*WorkflowVersion) Descriptor() ([]byte, []int) { - return file_workflows_proto_rawDescGZIP(), []int{9} + return file_workflows_proto_rawDescGZIP(), []int{10} } func (x *WorkflowVersion) GetId() string { @@ -1135,7 +1192,7 @@ func (x *WorkflowVersion) GetVersion() string { return "" } -func (x *WorkflowVersion) GetOrder() int32 { +func (x *WorkflowVersion) GetOrder() int64 { if x != nil { return x.Order } @@ -1149,6 +1206,13 @@ func (x *WorkflowVersion) GetWorkflowId() string { return "" } +func (x *WorkflowVersion) GetScheduledWorkflows() []*ScheduledWorkflow { + if x != nil { + return x.ScheduledWorkflows + } + return nil +} + // WorkflowTriggerEventRef represents the WorkflowTriggerEventRef model. type WorkflowTriggerEventRef struct { state protoimpl.MessageState @@ -1162,7 +1226,7 @@ type WorkflowTriggerEventRef struct { func (x *WorkflowTriggerEventRef) Reset() { *x = WorkflowTriggerEventRef{} if protoimpl.UnsafeEnabled { - mi := &file_workflows_proto_msgTypes[10] + mi := &file_workflows_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1175,7 +1239,7 @@ func (x *WorkflowTriggerEventRef) String() string { func (*WorkflowTriggerEventRef) ProtoMessage() {} func (x *WorkflowTriggerEventRef) ProtoReflect() protoreflect.Message { - mi := &file_workflows_proto_msgTypes[10] + mi := &file_workflows_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1188,7 +1252,7 @@ func (x *WorkflowTriggerEventRef) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkflowTriggerEventRef.ProtoReflect.Descriptor instead. func (*WorkflowTriggerEventRef) Descriptor() ([]byte, []int) { - return file_workflows_proto_rawDescGZIP(), []int{10} + return file_workflows_proto_rawDescGZIP(), []int{11} } func (x *WorkflowTriggerEventRef) GetParentId() string { @@ -1218,7 +1282,7 @@ type WorkflowTriggerCronRef struct { func (x *WorkflowTriggerCronRef) Reset() { *x = WorkflowTriggerCronRef{} if protoimpl.UnsafeEnabled { - mi := &file_workflows_proto_msgTypes[11] + mi := &file_workflows_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1231,7 +1295,7 @@ func (x *WorkflowTriggerCronRef) String() string { func (*WorkflowTriggerCronRef) ProtoMessage() {} func (x *WorkflowTriggerCronRef) ProtoReflect() protoreflect.Message { - mi := &file_workflows_proto_msgTypes[11] + mi := &file_workflows_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1244,7 +1308,7 @@ func (x *WorkflowTriggerCronRef) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkflowTriggerCronRef.ProtoReflect.Descriptor instead. func (*WorkflowTriggerCronRef) Descriptor() ([]byte, []int) { - return file_workflows_proto_rawDescGZIP(), []int{11} + return file_workflows_proto_rawDescGZIP(), []int{12} } func (x *WorkflowTriggerCronRef) GetParentId() string { @@ -1272,7 +1336,7 @@ type BulkTriggerWorkflowRequest struct { func (x *BulkTriggerWorkflowRequest) Reset() { *x = BulkTriggerWorkflowRequest{} if protoimpl.UnsafeEnabled { - mi := &file_workflows_proto_msgTypes[12] + mi := &file_workflows_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1285,7 +1349,7 @@ func (x *BulkTriggerWorkflowRequest) String() string { func (*BulkTriggerWorkflowRequest) ProtoMessage() {} func (x *BulkTriggerWorkflowRequest) ProtoReflect() protoreflect.Message { - mi := &file_workflows_proto_msgTypes[12] + mi := &file_workflows_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1298,7 +1362,7 @@ func (x *BulkTriggerWorkflowRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BulkTriggerWorkflowRequest.ProtoReflect.Descriptor instead. func (*BulkTriggerWorkflowRequest) Descriptor() ([]byte, []int) { - return file_workflows_proto_rawDescGZIP(), []int{12} + return file_workflows_proto_rawDescGZIP(), []int{13} } func (x *BulkTriggerWorkflowRequest) GetWorkflows() []*TriggerWorkflowRequest { @@ -1319,7 +1383,7 @@ type BulkTriggerWorkflowResponse struct { func (x *BulkTriggerWorkflowResponse) Reset() { *x = BulkTriggerWorkflowResponse{} if protoimpl.UnsafeEnabled { - mi := &file_workflows_proto_msgTypes[13] + mi := &file_workflows_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1332,7 +1396,7 @@ func (x *BulkTriggerWorkflowResponse) String() string { func (*BulkTriggerWorkflowResponse) ProtoMessage() {} func (x *BulkTriggerWorkflowResponse) ProtoReflect() protoreflect.Message { - mi := &file_workflows_proto_msgTypes[13] + mi := &file_workflows_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1345,7 +1409,7 @@ func (x *BulkTriggerWorkflowResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BulkTriggerWorkflowResponse.ProtoReflect.Descriptor instead. func (*BulkTriggerWorkflowResponse) Descriptor() ([]byte, []int) { - return file_workflows_proto_rawDescGZIP(), []int{13} + return file_workflows_proto_rawDescGZIP(), []int{14} } func (x *BulkTriggerWorkflowResponse) GetWorkflowRunIds() []string { @@ -1387,7 +1451,7 @@ type TriggerWorkflowRequest struct { func (x *TriggerWorkflowRequest) Reset() { *x = TriggerWorkflowRequest{} if protoimpl.UnsafeEnabled { - mi := &file_workflows_proto_msgTypes[14] + mi := &file_workflows_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1400,7 +1464,7 @@ func (x *TriggerWorkflowRequest) String() string { func (*TriggerWorkflowRequest) ProtoMessage() {} func (x *TriggerWorkflowRequest) ProtoReflect() protoreflect.Message { - mi := &file_workflows_proto_msgTypes[14] + mi := &file_workflows_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1413,7 +1477,7 @@ func (x *TriggerWorkflowRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use TriggerWorkflowRequest.ProtoReflect.Descriptor instead. func (*TriggerWorkflowRequest) Descriptor() ([]byte, []int) { - return file_workflows_proto_rawDescGZIP(), []int{14} + return file_workflows_proto_rawDescGZIP(), []int{15} } func (x *TriggerWorkflowRequest) GetName() string { @@ -1490,7 +1554,7 @@ type TriggerWorkflowResponse struct { func (x *TriggerWorkflowResponse) Reset() { *x = TriggerWorkflowResponse{} if protoimpl.UnsafeEnabled { - mi := &file_workflows_proto_msgTypes[15] + mi := &file_workflows_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1503,7 +1567,7 @@ func (x *TriggerWorkflowResponse) String() string { func (*TriggerWorkflowResponse) ProtoMessage() {} func (x *TriggerWorkflowResponse) ProtoReflect() protoreflect.Message { - mi := &file_workflows_proto_msgTypes[15] + mi := &file_workflows_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1516,7 +1580,7 @@ func (x *TriggerWorkflowResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use TriggerWorkflowResponse.ProtoReflect.Descriptor instead. func (*TriggerWorkflowResponse) Descriptor() ([]byte, []int) { - return file_workflows_proto_rawDescGZIP(), []int{15} + return file_workflows_proto_rawDescGZIP(), []int{16} } func (x *TriggerWorkflowResponse) GetWorkflowRunId() string { @@ -1542,7 +1606,7 @@ type PutRateLimitRequest struct { func (x *PutRateLimitRequest) Reset() { *x = PutRateLimitRequest{} if protoimpl.UnsafeEnabled { - mi := &file_workflows_proto_msgTypes[16] + mi := &file_workflows_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1555,7 +1619,7 @@ func (x *PutRateLimitRequest) String() string { func (*PutRateLimitRequest) ProtoMessage() {} func (x *PutRateLimitRequest) ProtoReflect() protoreflect.Message { - mi := &file_workflows_proto_msgTypes[16] + mi := &file_workflows_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1568,7 +1632,7 @@ func (x *PutRateLimitRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PutRateLimitRequest.ProtoReflect.Descriptor instead. func (*PutRateLimitRequest) Descriptor() ([]byte, []int) { - return file_workflows_proto_rawDescGZIP(), []int{16} + return file_workflows_proto_rawDescGZIP(), []int{17} } func (x *PutRateLimitRequest) GetKey() string { @@ -1601,7 +1665,7 @@ type PutRateLimitResponse struct { func (x *PutRateLimitResponse) Reset() { *x = PutRateLimitResponse{} if protoimpl.UnsafeEnabled { - mi := &file_workflows_proto_msgTypes[17] + mi := &file_workflows_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1614,7 +1678,7 @@ func (x *PutRateLimitResponse) String() string { func (*PutRateLimitResponse) ProtoMessage() {} func (x *PutRateLimitResponse) ProtoReflect() protoreflect.Message { - mi := &file_workflows_proto_msgTypes[17] + mi := &file_workflows_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1627,7 +1691,7 @@ func (x *PutRateLimitResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PutRateLimitResponse.ProtoReflect.Descriptor instead. func (*PutRateLimitResponse) Descriptor() ([]byte, []int) { - return file_workflows_proto_rawDescGZIP(), []int{17} + return file_workflows_proto_rawDescGZIP(), []int{18} } var File_workflows_proto protoreflect.FileDescriptor @@ -1803,8 +1867,14 @@ var file_workflows_proto_rawDesc = []byte{ 0x70, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x61, 0x64, 0x64, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xe8, - 0x01, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x5e, + 0x0a, 0x11, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x61, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x41, 0x74, 0x22, 0xad, + 0x02, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, @@ -1816,126 +1886,130 @@ var file_workflows_proto_rawDesc = []byte{ 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, + 0x03, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x22, 0x53, 0x0a, 0x17, 0x57, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x52, 0x65, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, - 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x49, - 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, - 0x72, 0x43, 0x72, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x22, 0x53, 0x0a, 0x1a, 0x42, 0x75, 0x6c, - 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x54, 0x72, 0x69, - 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x22, 0x47, - 0x0a, 0x1b, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, - 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x73, 0x22, 0xe4, 0x03, 0x0a, 0x16, 0x54, 0x72, 0x69, 0x67, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x43, 0x0a, 0x13, 0x73, 0x63, 0x68, + 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, + 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, + 0x65, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x12, 0x73, 0x63, 0x68, 0x65, + 0x64, 0x75, 0x6c, 0x65, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x22, 0x53, + 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, + 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, + 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x4b, 0x65, 0x79, 0x22, 0x49, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, + 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x72, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x12, 0x1b, 0x0a, + 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x72, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x22, 0x53, + 0x0a, 0x1a, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x09, + 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x73, 0x22, 0x47, 0x0a, 0x1b, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, + 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, + 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x73, 0x22, 0xe4, 0x03, 0x0a, + 0x16, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, + 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, + 0x74, 0x12, 0x20, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, + 0x88, 0x01, 0x01, 0x12, 0x30, 0x0a, 0x12, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, + 0x65, 0x70, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x01, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x65, 0x70, 0x52, 0x75, 0x6e, + 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, + 0x6e, 0x64, 0x65, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x48, 0x02, 0x52, 0x0a, 0x63, 0x68, + 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x63, + 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, + 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, + 0x13, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x12, 0x61, 0x64, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x11, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x77, + 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, + 0x52, 0x0f, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x49, + 0x64, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x48, 0x06, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, + 0x74, 0x79, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x5f, 0x69, 0x64, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, + 0x74, 0x65, 0x70, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, + 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, + 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x61, 0x64, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x77, 0x6f, 0x72, + 0x6b, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x22, 0x41, 0x0a, 0x17, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, + 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x22, 0x6d, 0x0a, 0x13, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, + 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, + 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2e, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, + 0x6d, 0x69, 0x74, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x24, 0x0a, + 0x0e, 0x53, 0x74, 0x69, 0x63, 0x6b, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, + 0x08, 0x0a, 0x04, 0x53, 0x4f, 0x46, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x41, 0x52, + 0x44, 0x10, 0x01, 0x2a, 0x32, 0x0a, 0x0c, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4b, + 0x69, 0x6e, 0x64, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, + 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x55, 0x52, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x07, + 0x0a, 0x03, 0x44, 0x41, 0x47, 0x10, 0x02, 0x2a, 0x6c, 0x0a, 0x18, 0x43, 0x6f, 0x6e, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, + 0x65, 0x67, 0x79, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x5f, 0x49, 0x4e, + 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x44, + 0x52, 0x4f, 0x50, 0x5f, 0x4e, 0x45, 0x57, 0x45, 0x53, 0x54, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, + 0x51, 0x55, 0x45, 0x55, 0x45, 0x5f, 0x4e, 0x45, 0x57, 0x45, 0x53, 0x54, 0x10, 0x02, 0x12, 0x15, + 0x0a, 0x11, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x52, 0x4f, + 0x42, 0x49, 0x4e, 0x10, 0x03, 0x2a, 0x85, 0x01, 0x0a, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, + 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, + 0x09, 0x0a, 0x05, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, + 0x54, 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x47, 0x52, 0x45, + 0x41, 0x54, 0x45, 0x52, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x47, + 0x52, 0x45, 0x41, 0x54, 0x45, 0x52, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x45, + 0x51, 0x55, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x54, + 0x48, 0x41, 0x4e, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x48, + 0x41, 0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x05, 0x2a, 0x5d, 0x0a, + 0x11, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x45, 0x43, 0x4f, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x0a, + 0x0a, 0x06, 0x4d, 0x49, 0x4e, 0x55, 0x54, 0x45, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, + 0x55, 0x52, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x44, 0x41, 0x59, 0x10, 0x03, 0x12, 0x08, 0x0a, + 0x04, 0x57, 0x45, 0x45, 0x4b, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x4d, 0x4f, 0x4e, 0x54, 0x48, + 0x10, 0x05, 0x12, 0x08, 0x0a, 0x04, 0x59, 0x45, 0x41, 0x52, 0x10, 0x06, 0x32, 0xdc, 0x02, 0x0a, + 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x34, 0x0a, 0x0b, 0x50, 0x75, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, + 0x13, 0x2e, 0x50, 0x75, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x10, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, + 0x6c, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x2e, 0x53, 0x63, 0x68, + 0x65, 0x64, 0x75, 0x6c, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x0f, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, + 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x17, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x20, 0x0a, 0x09, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, - 0x00, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x30, - 0x0a, 0x12, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x72, 0x75, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0f, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x65, 0x70, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01, - 0x12, 0x24, 0x0a, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x05, 0x48, 0x02, 0x52, 0x0a, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, - 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x08, 0x63, 0x68, 0x69, - 0x6c, 0x64, 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x13, 0x61, 0x64, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x12, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x61, 0x6c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x88, 0x01, 0x01, 0x12, 0x2f, - 0x0a, 0x11, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x0f, 0x64, 0x65, 0x73, - 0x69, 0x72, 0x65, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, - 0x1f, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x05, 0x48, 0x06, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x88, 0x01, 0x01, - 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x42, 0x15, - 0x0a, 0x13, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x72, - 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, - 0x6b, 0x65, 0x79, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x14, 0x0a, 0x12, 0x5f, - 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x41, - 0x0a, 0x17, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, - 0x64, 0x22, 0x6d, 0x0a, 0x13, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, - 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, - 0x12, 0x2e, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x44, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x22, 0x16, 0x0a, 0x14, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x24, 0x0a, 0x0e, 0x53, 0x74, 0x69, 0x63, - 0x6b, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x4f, - 0x46, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x41, 0x52, 0x44, 0x10, 0x01, 0x2a, 0x32, - 0x0a, 0x0c, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0c, - 0x0a, 0x08, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, - 0x44, 0x55, 0x52, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x44, 0x41, 0x47, - 0x10, 0x02, 0x2a, 0x6c, 0x0a, 0x18, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, - 0x79, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x16, - 0x0a, 0x12, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x5f, 0x49, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x47, - 0x52, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x44, 0x52, 0x4f, 0x50, 0x5f, 0x4e, - 0x45, 0x57, 0x45, 0x53, 0x54, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x51, 0x55, 0x45, 0x55, 0x45, - 0x5f, 0x4e, 0x45, 0x57, 0x45, 0x53, 0x54, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x47, 0x52, 0x4f, - 0x55, 0x50, 0x5f, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x52, 0x4f, 0x42, 0x49, 0x4e, 0x10, 0x03, - 0x2a, 0x85, 0x01, 0x0a, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4c, 0x61, 0x62, 0x65, 0x6c, - 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x51, - 0x55, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x51, 0x55, - 0x41, 0x4c, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x47, 0x52, 0x45, 0x41, 0x54, 0x45, 0x52, 0x5f, - 0x54, 0x48, 0x41, 0x4e, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x47, 0x52, 0x45, 0x41, 0x54, 0x45, - 0x52, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, - 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x10, 0x04, - 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x5f, 0x4f, 0x52, - 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x05, 0x2a, 0x5d, 0x0a, 0x11, 0x52, 0x61, 0x74, 0x65, - 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, - 0x06, 0x53, 0x45, 0x43, 0x4f, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x49, 0x4e, - 0x55, 0x54, 0x45, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x55, 0x52, 0x10, 0x02, 0x12, - 0x07, 0x0a, 0x03, 0x44, 0x41, 0x59, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x45, 0x45, 0x4b, - 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x4d, 0x4f, 0x4e, 0x54, 0x48, 0x10, 0x05, 0x12, 0x08, 0x0a, - 0x04, 0x59, 0x45, 0x41, 0x52, 0x10, 0x06, 0x32, 0xdc, 0x02, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x0b, 0x50, - 0x75, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x13, 0x2e, 0x50, 0x75, 0x74, - 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x10, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x3e, 0x0a, 0x10, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x57, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, - 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x10, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x44, 0x0a, 0x0f, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x17, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, - 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x13, 0x42, 0x75, 0x6c, 0x6b, 0x54, - 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x1b, - 0x2e, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x42, 0x75, - 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0c, 0x50, 0x75, 0x74, - 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x14, 0x2e, 0x50, 0x75, 0x74, 0x52, - 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x15, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x2d, 0x64, 0x65, 0x76, - 0x2f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x13, + 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x12, 0x1b, 0x2e, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, + 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1c, 0x2e, 0x42, 0x75, 0x6c, 0x6b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, + 0x0a, 0x0c, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x14, + 0x2e, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, + 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x42, 0x5a, 0x40, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, + 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x2f, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, + 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1951,7 +2025,7 @@ func file_workflows_proto_rawDescGZIP() []byte { } var file_workflows_proto_enumTypes = make([]protoimpl.EnumInfo, 5) -var file_workflows_proto_msgTypes = make([]protoimpl.MessageInfo, 19) +var file_workflows_proto_msgTypes = make([]protoimpl.MessageInfo, 20) var file_workflows_proto_goTypes = []interface{}{ (StickyStrategy)(0), // 0: StickyStrategy (WorkflowKind)(0), // 1: WorkflowKind @@ -1967,21 +2041,22 @@ var file_workflows_proto_goTypes = []interface{}{ (*CreateStepRateLimit)(nil), // 11: CreateStepRateLimit (*ListWorkflowsRequest)(nil), // 12: ListWorkflowsRequest (*ScheduleWorkflowRequest)(nil), // 13: ScheduleWorkflowRequest - (*WorkflowVersion)(nil), // 14: WorkflowVersion - (*WorkflowTriggerEventRef)(nil), // 15: WorkflowTriggerEventRef - (*WorkflowTriggerCronRef)(nil), // 16: WorkflowTriggerCronRef - (*BulkTriggerWorkflowRequest)(nil), // 17: BulkTriggerWorkflowRequest - (*BulkTriggerWorkflowResponse)(nil), // 18: BulkTriggerWorkflowResponse - (*TriggerWorkflowRequest)(nil), // 19: TriggerWorkflowRequest - (*TriggerWorkflowResponse)(nil), // 20: TriggerWorkflowResponse - (*PutRateLimitRequest)(nil), // 21: PutRateLimitRequest - (*PutRateLimitResponse)(nil), // 22: PutRateLimitResponse - nil, // 23: CreateWorkflowStepOpts.WorkerLabelsEntry - (*timestamppb.Timestamp)(nil), // 24: google.protobuf.Timestamp + (*ScheduledWorkflow)(nil), // 14: ScheduledWorkflow + (*WorkflowVersion)(nil), // 15: WorkflowVersion + (*WorkflowTriggerEventRef)(nil), // 16: WorkflowTriggerEventRef + (*WorkflowTriggerCronRef)(nil), // 17: WorkflowTriggerCronRef + (*BulkTriggerWorkflowRequest)(nil), // 18: BulkTriggerWorkflowRequest + (*BulkTriggerWorkflowResponse)(nil), // 19: BulkTriggerWorkflowResponse + (*TriggerWorkflowRequest)(nil), // 20: TriggerWorkflowRequest + (*TriggerWorkflowResponse)(nil), // 21: TriggerWorkflowResponse + (*PutRateLimitRequest)(nil), // 22: PutRateLimitRequest + (*PutRateLimitResponse)(nil), // 23: PutRateLimitResponse + nil, // 24: CreateWorkflowStepOpts.WorkerLabelsEntry + (*timestamppb.Timestamp)(nil), // 25: google.protobuf.Timestamp } var file_workflows_proto_depIdxs = []int32{ 6, // 0: PutWorkflowRequest.opts:type_name -> CreateWorkflowVersionOpts - 24, // 1: CreateWorkflowVersionOpts.scheduled_triggers:type_name -> google.protobuf.Timestamp + 25, // 1: CreateWorkflowVersionOpts.scheduled_triggers:type_name -> google.protobuf.Timestamp 8, // 2: CreateWorkflowVersionOpts.jobs:type_name -> CreateWorkflowJobOpts 7, // 3: CreateWorkflowVersionOpts.concurrency:type_name -> WorkflowConcurrencyOpts 8, // 4: CreateWorkflowVersionOpts.on_failure_job:type_name -> CreateWorkflowJobOpts @@ -1991,29 +2066,31 @@ var file_workflows_proto_depIdxs = []int32{ 10, // 8: CreateWorkflowJobOpts.steps:type_name -> CreateWorkflowStepOpts 3, // 9: DesiredWorkerLabels.comparator:type_name -> WorkerLabelComparator 11, // 10: CreateWorkflowStepOpts.rate_limits:type_name -> CreateStepRateLimit - 23, // 11: CreateWorkflowStepOpts.worker_labels:type_name -> CreateWorkflowStepOpts.WorkerLabelsEntry + 24, // 11: CreateWorkflowStepOpts.worker_labels:type_name -> CreateWorkflowStepOpts.WorkerLabelsEntry 4, // 12: CreateStepRateLimit.duration:type_name -> RateLimitDuration - 24, // 13: ScheduleWorkflowRequest.schedules:type_name -> google.protobuf.Timestamp - 24, // 14: WorkflowVersion.created_at:type_name -> google.protobuf.Timestamp - 24, // 15: WorkflowVersion.updated_at:type_name -> google.protobuf.Timestamp - 19, // 16: BulkTriggerWorkflowRequest.workflows:type_name -> TriggerWorkflowRequest - 4, // 17: PutRateLimitRequest.duration:type_name -> RateLimitDuration - 9, // 18: CreateWorkflowStepOpts.WorkerLabelsEntry.value:type_name -> DesiredWorkerLabels - 5, // 19: WorkflowService.PutWorkflow:input_type -> PutWorkflowRequest - 13, // 20: WorkflowService.ScheduleWorkflow:input_type -> ScheduleWorkflowRequest - 19, // 21: WorkflowService.TriggerWorkflow:input_type -> TriggerWorkflowRequest - 17, // 22: WorkflowService.BulkTriggerWorkflow:input_type -> BulkTriggerWorkflowRequest - 21, // 23: WorkflowService.PutRateLimit:input_type -> PutRateLimitRequest - 14, // 24: WorkflowService.PutWorkflow:output_type -> WorkflowVersion - 14, // 25: WorkflowService.ScheduleWorkflow:output_type -> WorkflowVersion - 20, // 26: WorkflowService.TriggerWorkflow:output_type -> TriggerWorkflowResponse - 18, // 27: WorkflowService.BulkTriggerWorkflow:output_type -> BulkTriggerWorkflowResponse - 22, // 28: WorkflowService.PutRateLimit:output_type -> PutRateLimitResponse - 24, // [24:29] is the sub-list for method output_type - 19, // [19:24] is the sub-list for method input_type - 19, // [19:19] is the sub-list for extension type_name - 19, // [19:19] is the sub-list for extension extendee - 0, // [0:19] is the sub-list for field type_name + 25, // 13: ScheduleWorkflowRequest.schedules:type_name -> google.protobuf.Timestamp + 25, // 14: ScheduledWorkflow.trigger_at:type_name -> google.protobuf.Timestamp + 25, // 15: WorkflowVersion.created_at:type_name -> google.protobuf.Timestamp + 25, // 16: WorkflowVersion.updated_at:type_name -> google.protobuf.Timestamp + 14, // 17: WorkflowVersion.scheduled_workflows:type_name -> ScheduledWorkflow + 20, // 18: BulkTriggerWorkflowRequest.workflows:type_name -> TriggerWorkflowRequest + 4, // 19: PutRateLimitRequest.duration:type_name -> RateLimitDuration + 9, // 20: CreateWorkflowStepOpts.WorkerLabelsEntry.value:type_name -> DesiredWorkerLabels + 5, // 21: WorkflowService.PutWorkflow:input_type -> PutWorkflowRequest + 13, // 22: WorkflowService.ScheduleWorkflow:input_type -> ScheduleWorkflowRequest + 20, // 23: WorkflowService.TriggerWorkflow:input_type -> TriggerWorkflowRequest + 18, // 24: WorkflowService.BulkTriggerWorkflow:input_type -> BulkTriggerWorkflowRequest + 22, // 25: WorkflowService.PutRateLimit:input_type -> PutRateLimitRequest + 15, // 26: WorkflowService.PutWorkflow:output_type -> WorkflowVersion + 15, // 27: WorkflowService.ScheduleWorkflow:output_type -> WorkflowVersion + 21, // 28: WorkflowService.TriggerWorkflow:output_type -> TriggerWorkflowResponse + 19, // 29: WorkflowService.BulkTriggerWorkflow:output_type -> BulkTriggerWorkflowResponse + 23, // 30: WorkflowService.PutRateLimit:output_type -> PutRateLimitResponse + 26, // [26:31] is the sub-list for method output_type + 21, // [21:26] is the sub-list for method input_type + 21, // [21:21] is the sub-list for extension type_name + 21, // [21:21] is the sub-list for extension extendee + 0, // [0:21] is the sub-list for field type_name } func init() { file_workflows_proto_init() } @@ -2131,7 +2208,7 @@ func file_workflows_proto_init() { } } file_workflows_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkflowVersion); i { + switch v := v.(*ScheduledWorkflow); i { case 0: return &v.state case 1: @@ -2143,7 +2220,7 @@ func file_workflows_proto_init() { } } file_workflows_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkflowTriggerEventRef); i { + switch v := v.(*WorkflowVersion); i { case 0: return &v.state case 1: @@ -2155,7 +2232,7 @@ func file_workflows_proto_init() { } } file_workflows_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkflowTriggerCronRef); i { + switch v := v.(*WorkflowTriggerEventRef); i { case 0: return &v.state case 1: @@ -2167,7 +2244,7 @@ func file_workflows_proto_init() { } } file_workflows_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BulkTriggerWorkflowRequest); i { + switch v := v.(*WorkflowTriggerCronRef); i { case 0: return &v.state case 1: @@ -2179,7 +2256,7 @@ func file_workflows_proto_init() { } } file_workflows_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BulkTriggerWorkflowResponse); i { + switch v := v.(*BulkTriggerWorkflowRequest); i { case 0: return &v.state case 1: @@ -2191,7 +2268,7 @@ func file_workflows_proto_init() { } } file_workflows_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TriggerWorkflowRequest); i { + switch v := v.(*BulkTriggerWorkflowResponse); i { case 0: return &v.state case 1: @@ -2203,7 +2280,7 @@ func file_workflows_proto_init() { } } file_workflows_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TriggerWorkflowResponse); i { + switch v := v.(*TriggerWorkflowRequest); i { case 0: return &v.state case 1: @@ -2215,7 +2292,7 @@ func file_workflows_proto_init() { } } file_workflows_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PutRateLimitRequest); i { + switch v := v.(*TriggerWorkflowResponse); i { case 0: return &v.state case 1: @@ -2227,6 +2304,18 @@ func file_workflows_proto_init() { } } file_workflows_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PutRateLimitRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_workflows_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PutRateLimitResponse); i { case 0: return &v.state @@ -2244,14 +2333,14 @@ func file_workflows_proto_init() { file_workflows_proto_msgTypes[4].OneofWrappers = []interface{}{} file_workflows_proto_msgTypes[6].OneofWrappers = []interface{}{} file_workflows_proto_msgTypes[8].OneofWrappers = []interface{}{} - file_workflows_proto_msgTypes[14].OneofWrappers = []interface{}{} + file_workflows_proto_msgTypes[15].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_workflows_proto_rawDesc, NumEnums: 5, - NumMessages: 19, + NumMessages: 20, NumExtensions: 0, NumServices: 1, }, diff --git a/internal/services/admin/server.go b/internal/services/admin/server.go index 9c6edf362..e9afd33e0 100644 --- a/internal/services/admin/server.go +++ b/internal/services/admin/server.go @@ -248,7 +248,7 @@ func (a *AdminServiceImpl) PutWorkflow(ctx context.Context, req *contracts.PutWo } } - resp := toWorkflowVersion(workflowVersion) + resp := toWorkflowVersion(workflowVersion, nil) return resp, nil } @@ -322,7 +322,7 @@ func (a *AdminServiceImpl) ScheduleWorkflow(ctx context.Context, req *contracts. } if err == nil && existing != nil { - return toWorkflowVersion(currWorkflow), nil + return toWorkflowVersion(currWorkflow, nil), nil } } @@ -340,7 +340,7 @@ func (a *AdminServiceImpl) ScheduleWorkflow(ctx context.Context, req *contracts. additionalMetadata = []byte(*req.AdditionalMetadata) } - _, err = a.repo.Workflow().CreateSchedules( + scheduledRef, err := a.repo.Workflow().CreateSchedules( ctx, tenantId, workflowVersionId, @@ -355,7 +355,7 @@ func (a *AdminServiceImpl) ScheduleWorkflow(ctx context.Context, req *contracts. return nil, err } - resp := toWorkflowVersion(currWorkflow) + resp := toWorkflowVersion(currWorkflow, scheduledRef) return resp, nil } @@ -586,13 +586,23 @@ func getCreateJobOpts(req *contracts.CreateWorkflowJobOpts, kind string) (*repos }, nil } -func toWorkflowVersion(workflowVersion *dbsqlc.GetWorkflowVersionForEngineRow) *contracts.WorkflowVersion { +func toWorkflowVersion(workflowVersion *dbsqlc.GetWorkflowVersionForEngineRow, scheduledRefs []*dbsqlc.WorkflowTriggerScheduledRef) *contracts.WorkflowVersion { + scheduledWorkflows := make([]*contracts.ScheduledWorkflow, len(scheduledRefs)) + + for i, ref := range scheduledRefs { + scheduledWorkflows[i] = &contracts.ScheduledWorkflow{ + Id: sqlchelpers.UUIDToStr(ref.ID), + TriggerAt: timestamppb.New(ref.TriggerAt.Time), + } + } + version := &contracts.WorkflowVersion{ - Id: sqlchelpers.UUIDToStr(workflowVersion.WorkflowVersion.ID), - CreatedAt: timestamppb.New(workflowVersion.WorkflowVersion.CreatedAt.Time), - UpdatedAt: timestamppb.New(workflowVersion.WorkflowVersion.UpdatedAt.Time), - Order: int32(workflowVersion.WorkflowVersion.Order), - WorkflowId: sqlchelpers.UUIDToStr(workflowVersion.WorkflowVersion.WorkflowId), + Id: sqlchelpers.UUIDToStr(workflowVersion.WorkflowVersion.ID), + CreatedAt: timestamppb.New(workflowVersion.WorkflowVersion.CreatedAt.Time), + UpdatedAt: timestamppb.New(workflowVersion.WorkflowVersion.UpdatedAt.Time), + Order: workflowVersion.WorkflowVersion.Order, + WorkflowId: sqlchelpers.UUIDToStr(workflowVersion.WorkflowVersion.WorkflowId), + ScheduledWorkflows: scheduledWorkflows, } if workflowVersion.WorkflowVersion.Version.String != "" { diff --git a/pkg/repository/prisma/db/db_gen.go b/pkg/repository/prisma/db/db_gen.go index 8e074f062..da9c9742a 100644 --- a/pkg/repository/prisma/db/db_gen.go +++ b/pkg/repository/prisma/db/db_gen.go @@ -723,8 +723,11 @@ model WorkflowTriggerCronRef { parent WorkflowTriggers @relation(fields: [parentId], references: [id], onDelete: Cascade, onUpdate: Cascade) parentId String @db.Uuid + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + deletedAt DateTime? // the cron expression - cron String + cron String // whether this cron is enabled or not enabled Boolean @default(true) @@ -738,6 +741,8 @@ model WorkflowTriggerCronRef { // the input parameters to the scheduled workflow input Json? + additionalMetadata Json? + // cron references must be unique per workflow @@unique([parentId, cron]) } @@ -745,6 +750,10 @@ model WorkflowTriggerCronRef { model WorkflowTriggerScheduledRef { id String @id @unique @default(uuid()) @db.Uuid + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + deletedAt DateTime? + // the parent workflow parent WorkflowVersion @relation(fields: [parentId], references: [id], onDelete: Cascade, onUpdate: Cascade) parentId String @db.Uuid @@ -774,6 +783,8 @@ model WorkflowTriggerScheduledRef { triggered WorkflowRunTriggeredBy? + additionalMetadata Json? + @@unique([parentId, parentStepRunId, childKey]) } @@ -2742,17 +2753,24 @@ const ( type WorkflowTriggerCronRefScalarFieldEnum string const ( - WorkflowTriggerCronRefScalarFieldEnumParentID WorkflowTriggerCronRefScalarFieldEnum = "parentId" - WorkflowTriggerCronRefScalarFieldEnumCron WorkflowTriggerCronRefScalarFieldEnum = "cron" - WorkflowTriggerCronRefScalarFieldEnumEnabled WorkflowTriggerCronRefScalarFieldEnum = "enabled" - WorkflowTriggerCronRefScalarFieldEnumTickerID WorkflowTriggerCronRefScalarFieldEnum = "tickerId" - WorkflowTriggerCronRefScalarFieldEnumInput WorkflowTriggerCronRefScalarFieldEnum = "input" + WorkflowTriggerCronRefScalarFieldEnumParentID WorkflowTriggerCronRefScalarFieldEnum = "parentId" + WorkflowTriggerCronRefScalarFieldEnumCreatedAt WorkflowTriggerCronRefScalarFieldEnum = "createdAt" + WorkflowTriggerCronRefScalarFieldEnumUpdatedAt WorkflowTriggerCronRefScalarFieldEnum = "updatedAt" + WorkflowTriggerCronRefScalarFieldEnumDeletedAt WorkflowTriggerCronRefScalarFieldEnum = "deletedAt" + WorkflowTriggerCronRefScalarFieldEnumCron WorkflowTriggerCronRefScalarFieldEnum = "cron" + WorkflowTriggerCronRefScalarFieldEnumEnabled WorkflowTriggerCronRefScalarFieldEnum = "enabled" + WorkflowTriggerCronRefScalarFieldEnumTickerID WorkflowTriggerCronRefScalarFieldEnum = "tickerId" + WorkflowTriggerCronRefScalarFieldEnumInput WorkflowTriggerCronRefScalarFieldEnum = "input" + WorkflowTriggerCronRefScalarFieldEnumAdditionalMetadata WorkflowTriggerCronRefScalarFieldEnum = "additionalMetadata" ) type WorkflowTriggerScheduledRefScalarFieldEnum string const ( WorkflowTriggerScheduledRefScalarFieldEnumID WorkflowTriggerScheduledRefScalarFieldEnum = "id" + WorkflowTriggerScheduledRefScalarFieldEnumCreatedAt WorkflowTriggerScheduledRefScalarFieldEnum = "createdAt" + WorkflowTriggerScheduledRefScalarFieldEnumUpdatedAt WorkflowTriggerScheduledRefScalarFieldEnum = "updatedAt" + WorkflowTriggerScheduledRefScalarFieldEnumDeletedAt WorkflowTriggerScheduledRefScalarFieldEnum = "deletedAt" WorkflowTriggerScheduledRefScalarFieldEnumParentID WorkflowTriggerScheduledRefScalarFieldEnum = "parentId" WorkflowTriggerScheduledRefScalarFieldEnumTriggerAt WorkflowTriggerScheduledRefScalarFieldEnum = "triggerAt" WorkflowTriggerScheduledRefScalarFieldEnumTickerID WorkflowTriggerScheduledRefScalarFieldEnum = "tickerId" @@ -2761,6 +2779,7 @@ const ( WorkflowTriggerScheduledRefScalarFieldEnumParentStepRunID WorkflowTriggerScheduledRefScalarFieldEnum = "parentStepRunId" WorkflowTriggerScheduledRefScalarFieldEnumChildIndex WorkflowTriggerScheduledRefScalarFieldEnum = "childIndex" WorkflowTriggerScheduledRefScalarFieldEnumChildKey WorkflowTriggerScheduledRefScalarFieldEnum = "childKey" + WorkflowTriggerScheduledRefScalarFieldEnumAdditionalMetadata WorkflowTriggerScheduledRefScalarFieldEnum = "additionalMetadata" ) type JobScalarFieldEnum string @@ -3885,6 +3904,12 @@ const workflowTriggerCronRefFieldParent workflowTriggerCronRefPrismaFields = "pa const workflowTriggerCronRefFieldParentID workflowTriggerCronRefPrismaFields = "parentId" +const workflowTriggerCronRefFieldCreatedAt workflowTriggerCronRefPrismaFields = "createdAt" + +const workflowTriggerCronRefFieldUpdatedAt workflowTriggerCronRefPrismaFields = "updatedAt" + +const workflowTriggerCronRefFieldDeletedAt workflowTriggerCronRefPrismaFields = "deletedAt" + const workflowTriggerCronRefFieldCron workflowTriggerCronRefPrismaFields = "cron" const workflowTriggerCronRefFieldEnabled workflowTriggerCronRefPrismaFields = "enabled" @@ -3897,10 +3922,18 @@ const workflowTriggerCronRefFieldTriggered workflowTriggerCronRefPrismaFields = const workflowTriggerCronRefFieldInput workflowTriggerCronRefPrismaFields = "input" +const workflowTriggerCronRefFieldAdditionalMetadata workflowTriggerCronRefPrismaFields = "additionalMetadata" + type workflowTriggerScheduledRefPrismaFields = prismaFields const workflowTriggerScheduledRefFieldID workflowTriggerScheduledRefPrismaFields = "id" +const workflowTriggerScheduledRefFieldCreatedAt workflowTriggerScheduledRefPrismaFields = "createdAt" + +const workflowTriggerScheduledRefFieldUpdatedAt workflowTriggerScheduledRefPrismaFields = "updatedAt" + +const workflowTriggerScheduledRefFieldDeletedAt workflowTriggerScheduledRefPrismaFields = "deletedAt" + const workflowTriggerScheduledRefFieldParent workflowTriggerScheduledRefPrismaFields = "parent" const workflowTriggerScheduledRefFieldParentID workflowTriggerScheduledRefPrismaFields = "parentId" @@ -3927,6 +3960,8 @@ const workflowTriggerScheduledRefFieldChildKey workflowTriggerScheduledRefPrisma const workflowTriggerScheduledRefFieldTriggered workflowTriggerScheduledRefPrismaFields = "triggered" +const workflowTriggerScheduledRefFieldAdditionalMetadata workflowTriggerScheduledRefPrismaFields = "additionalMetadata" + type jobPrismaFields = prismaFields const jobFieldID jobPrismaFields = "id" @@ -9517,20 +9552,28 @@ type WorkflowTriggerCronRefModel struct { // InnerWorkflowTriggerCronRef holds the actual data type InnerWorkflowTriggerCronRef struct { - ParentID string `json:"parentId"` - Cron string `json:"cron"` - Enabled bool `json:"enabled"` - TickerID *string `json:"tickerId,omitempty"` - Input *JSON `json:"input,omitempty"` + ParentID string `json:"parentId"` + CreatedAt DateTime `json:"createdAt"` + UpdatedAt DateTime `json:"updatedAt"` + DeletedAt *DateTime `json:"deletedAt,omitempty"` + Cron string `json:"cron"` + Enabled bool `json:"enabled"` + TickerID *string `json:"tickerId,omitempty"` + Input *JSON `json:"input,omitempty"` + AdditionalMetadata *JSON `json:"additionalMetadata,omitempty"` } // RawWorkflowTriggerCronRefModel is a struct for WorkflowTriggerCronRef when used in raw queries type RawWorkflowTriggerCronRefModel struct { - ParentID RawString `json:"parentId"` - Cron RawString `json:"cron"` - Enabled RawBoolean `json:"enabled"` - TickerID *RawString `json:"tickerId,omitempty"` - Input *RawJSON `json:"input,omitempty"` + ParentID RawString `json:"parentId"` + CreatedAt RawDateTime `json:"createdAt"` + UpdatedAt RawDateTime `json:"updatedAt"` + DeletedAt *RawDateTime `json:"deletedAt,omitempty"` + Cron RawString `json:"cron"` + Enabled RawBoolean `json:"enabled"` + TickerID *RawString `json:"tickerId,omitempty"` + Input *RawJSON `json:"input,omitempty"` + AdditionalMetadata *RawJSON `json:"additionalMetadata,omitempty"` } // RelationsWorkflowTriggerCronRef holds the relation data separately @@ -9547,6 +9590,13 @@ func (r WorkflowTriggerCronRefModel) Parent() (value *WorkflowTriggersModel) { return r.RelationsWorkflowTriggerCronRef.Parent } +func (r WorkflowTriggerCronRefModel) DeletedAt() (value DateTime, ok bool) { + if r.InnerWorkflowTriggerCronRef.DeletedAt == nil { + return value, false + } + return *r.InnerWorkflowTriggerCronRef.DeletedAt, true +} + func (r WorkflowTriggerCronRefModel) Ticker() (value *TickerModel, ok bool) { if r.RelationsWorkflowTriggerCronRef.Ticker == nil { return value, false @@ -9575,6 +9625,13 @@ func (r WorkflowTriggerCronRefModel) Input() (value JSON, ok bool) { return *r.InnerWorkflowTriggerCronRef.Input, true } +func (r WorkflowTriggerCronRefModel) AdditionalMetadata() (value JSON, ok bool) { + if r.InnerWorkflowTriggerCronRef.AdditionalMetadata == nil { + return value, false + } + return *r.InnerWorkflowTriggerCronRef.AdditionalMetadata, true +} + // WorkflowTriggerScheduledRefModel represents the WorkflowTriggerScheduledRef model and is a wrapper for accessing fields and methods type WorkflowTriggerScheduledRefModel struct { InnerWorkflowTriggerScheduledRef @@ -9583,28 +9640,36 @@ type WorkflowTriggerScheduledRefModel struct { // InnerWorkflowTriggerScheduledRef holds the actual data type InnerWorkflowTriggerScheduledRef struct { - ID string `json:"id"` - ParentID string `json:"parentId"` - TriggerAt DateTime `json:"triggerAt"` - TickerID *string `json:"tickerId,omitempty"` - Input *JSON `json:"input,omitempty"` - ParentWorkflowRunID *string `json:"parentWorkflowRunId,omitempty"` - ParentStepRunID *string `json:"parentStepRunId,omitempty"` - ChildIndex *int `json:"childIndex,omitempty"` - ChildKey *string `json:"childKey,omitempty"` + ID string `json:"id"` + CreatedAt DateTime `json:"createdAt"` + UpdatedAt DateTime `json:"updatedAt"` + DeletedAt *DateTime `json:"deletedAt,omitempty"` + ParentID string `json:"parentId"` + TriggerAt DateTime `json:"triggerAt"` + TickerID *string `json:"tickerId,omitempty"` + Input *JSON `json:"input,omitempty"` + ParentWorkflowRunID *string `json:"parentWorkflowRunId,omitempty"` + ParentStepRunID *string `json:"parentStepRunId,omitempty"` + ChildIndex *int `json:"childIndex,omitempty"` + ChildKey *string `json:"childKey,omitempty"` + AdditionalMetadata *JSON `json:"additionalMetadata,omitempty"` } // RawWorkflowTriggerScheduledRefModel is a struct for WorkflowTriggerScheduledRef when used in raw queries type RawWorkflowTriggerScheduledRefModel struct { - ID RawString `json:"id"` - ParentID RawString `json:"parentId"` - TriggerAt RawDateTime `json:"triggerAt"` - TickerID *RawString `json:"tickerId,omitempty"` - Input *RawJSON `json:"input,omitempty"` - ParentWorkflowRunID *RawString `json:"parentWorkflowRunId,omitempty"` - ParentStepRunID *RawString `json:"parentStepRunId,omitempty"` - ChildIndex *RawInt `json:"childIndex,omitempty"` - ChildKey *RawString `json:"childKey,omitempty"` + ID RawString `json:"id"` + CreatedAt RawDateTime `json:"createdAt"` + UpdatedAt RawDateTime `json:"updatedAt"` + DeletedAt *RawDateTime `json:"deletedAt,omitempty"` + ParentID RawString `json:"parentId"` + TriggerAt RawDateTime `json:"triggerAt"` + TickerID *RawString `json:"tickerId,omitempty"` + Input *RawJSON `json:"input,omitempty"` + ParentWorkflowRunID *RawString `json:"parentWorkflowRunId,omitempty"` + ParentStepRunID *RawString `json:"parentStepRunId,omitempty"` + ChildIndex *RawInt `json:"childIndex,omitempty"` + ChildKey *RawString `json:"childKey,omitempty"` + AdditionalMetadata *RawJSON `json:"additionalMetadata,omitempty"` } // RelationsWorkflowTriggerScheduledRef holds the relation data separately @@ -9616,6 +9681,13 @@ type RelationsWorkflowTriggerScheduledRef struct { Triggered *WorkflowRunTriggeredByModel `json:"triggered,omitempty"` } +func (r WorkflowTriggerScheduledRefModel) DeletedAt() (value DateTime, ok bool) { + if r.InnerWorkflowTriggerScheduledRef.DeletedAt == nil { + return value, false + } + return *r.InnerWorkflowTriggerScheduledRef.DeletedAt, true +} + func (r WorkflowTriggerScheduledRefModel) Parent() (value *WorkflowVersionModel) { if r.RelationsWorkflowTriggerScheduledRef.Parent == nil { panic("attempted to access parent but did not fetch it using the .With() syntax") @@ -9693,6 +9765,13 @@ func (r WorkflowTriggerScheduledRefModel) Triggered() (value *WorkflowRunTrigger return r.RelationsWorkflowTriggerScheduledRef.Triggered, true } +func (r WorkflowTriggerScheduledRefModel) AdditionalMetadata() (value JSON, ok bool) { + if r.InnerWorkflowTriggerScheduledRef.AdditionalMetadata == nil { + return value, false + } + return *r.InnerWorkflowTriggerScheduledRef.AdditionalMetadata, true +} + // JobModel represents the Job model and is a wrapper for accessing fields and methods type JobModel struct { InnerJob @@ -80629,6 +80708,21 @@ type workflowTriggerCronRefQuery struct { // @required ParentID workflowTriggerCronRefQueryParentIDString + // CreatedAt + // + // @required + CreatedAt workflowTriggerCronRefQueryCreatedAtDateTime + + // UpdatedAt + // + // @required + UpdatedAt workflowTriggerCronRefQueryUpdatedAtDateTime + + // DeletedAt + // + // @optional + DeletedAt workflowTriggerCronRefQueryDeletedAtDateTime + // Cron // // @required @@ -80652,6 +80746,11 @@ type workflowTriggerCronRefQuery struct { // // @optional Input workflowTriggerCronRefQueryInputJson + + // AdditionalMetadata + // + // @optional + AdditionalMetadata workflowTriggerCronRefQueryAdditionalMetadataJson } func (workflowTriggerCronRefQuery) Not(params ...WorkflowTriggerCronRefWhereParam) workflowTriggerCronRefDefaultParam { @@ -81158,6 +81257,984 @@ func (r workflowTriggerCronRefQueryParentIDString) Field() workflowTriggerCronRe return workflowTriggerCronRefFieldParentID } +// base struct +type workflowTriggerCronRefQueryCreatedAtDateTime struct{} + +// Set the required value of CreatedAt +func (r workflowTriggerCronRefQueryCreatedAtDateTime) Set(value DateTime) workflowTriggerCronRefSetParam { + + return workflowTriggerCronRefSetParam{ + data: builder.Field{ + Name: "createdAt", + Value: value, + }, + } + +} + +// Set the optional value of CreatedAt dynamically +func (r workflowTriggerCronRefQueryCreatedAtDateTime) SetIfPresent(value *DateTime) workflowTriggerCronRefSetParam { + if value == nil { + return workflowTriggerCronRefSetParam{} + } + + return r.Set(*value) +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) Equals(value DateTime) workflowTriggerCronRefWithPrismaCreatedAtEqualsParam { + + return workflowTriggerCronRefWithPrismaCreatedAtEqualsParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "equals", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) EqualsIfPresent(value *DateTime) workflowTriggerCronRefWithPrismaCreatedAtEqualsParam { + if value == nil { + return workflowTriggerCronRefWithPrismaCreatedAtEqualsParam{} + } + return r.Equals(*value) +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) Order(direction SortOrder) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Value: direction, + }, + } +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) Cursor(cursor DateTime) workflowTriggerCronRefCursorParam { + return workflowTriggerCronRefCursorParam{ + data: builder.Field{ + Name: "createdAt", + Value: cursor, + }, + } +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) In(value []DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "in", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) InIfPresent(value []DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.In(value) +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) NotIn(value []DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "notIn", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) NotInIfPresent(value []DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.NotIn(value) +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) Lt(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "lt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) LtIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Lt(*value) +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) Lte(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "lte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) LteIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Lte(*value) +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) Gt(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "gt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) GtIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Gt(*value) +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) Gte(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "gte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) GteIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Gte(*value) +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) Not(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "not", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) NotIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Not(*value) +} + +// deprecated: Use Lt instead. + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) Before(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "lt", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use LtIfPresent instead. +func (r workflowTriggerCronRefQueryCreatedAtDateTime) BeforeIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Before(*value) +} + +// deprecated: Use Gt instead. + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) After(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "gt", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use GtIfPresent instead. +func (r workflowTriggerCronRefQueryCreatedAtDateTime) AfterIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.After(*value) +} + +// deprecated: Use Lte instead. + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) BeforeEquals(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "lte", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use LteIfPresent instead. +func (r workflowTriggerCronRefQueryCreatedAtDateTime) BeforeEqualsIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.BeforeEquals(*value) +} + +// deprecated: Use Gte instead. + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) AfterEquals(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "gte", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use GteIfPresent instead. +func (r workflowTriggerCronRefQueryCreatedAtDateTime) AfterEqualsIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.AfterEquals(*value) +} + +func (r workflowTriggerCronRefQueryCreatedAtDateTime) Field() workflowTriggerCronRefPrismaFields { + return workflowTriggerCronRefFieldCreatedAt +} + +// base struct +type workflowTriggerCronRefQueryUpdatedAtDateTime struct{} + +// Set the required value of UpdatedAt +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) Set(value DateTime) workflowTriggerCronRefSetParam { + + return workflowTriggerCronRefSetParam{ + data: builder.Field{ + Name: "updatedAt", + Value: value, + }, + } + +} + +// Set the optional value of UpdatedAt dynamically +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) SetIfPresent(value *DateTime) workflowTriggerCronRefSetParam { + if value == nil { + return workflowTriggerCronRefSetParam{} + } + + return r.Set(*value) +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) Equals(value DateTime) workflowTriggerCronRefWithPrismaUpdatedAtEqualsParam { + + return workflowTriggerCronRefWithPrismaUpdatedAtEqualsParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "equals", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) EqualsIfPresent(value *DateTime) workflowTriggerCronRefWithPrismaUpdatedAtEqualsParam { + if value == nil { + return workflowTriggerCronRefWithPrismaUpdatedAtEqualsParam{} + } + return r.Equals(*value) +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) Order(direction SortOrder) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Value: direction, + }, + } +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) Cursor(cursor DateTime) workflowTriggerCronRefCursorParam { + return workflowTriggerCronRefCursorParam{ + data: builder.Field{ + Name: "updatedAt", + Value: cursor, + }, + } +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) In(value []DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "in", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) InIfPresent(value []DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.In(value) +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) NotIn(value []DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "notIn", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) NotInIfPresent(value []DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.NotIn(value) +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) Lt(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "lt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) LtIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Lt(*value) +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) Lte(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "lte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) LteIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Lte(*value) +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) Gt(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "gt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) GtIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Gt(*value) +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) Gte(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "gte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) GteIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Gte(*value) +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) Not(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "not", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) NotIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Not(*value) +} + +// deprecated: Use Lt instead. + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) Before(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "lt", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use LtIfPresent instead. +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) BeforeIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Before(*value) +} + +// deprecated: Use Gt instead. + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) After(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "gt", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use GtIfPresent instead. +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) AfterIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.After(*value) +} + +// deprecated: Use Lte instead. + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) BeforeEquals(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "lte", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use LteIfPresent instead. +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) BeforeEqualsIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.BeforeEquals(*value) +} + +// deprecated: Use Gte instead. + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) AfterEquals(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "gte", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use GteIfPresent instead. +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) AfterEqualsIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.AfterEquals(*value) +} + +func (r workflowTriggerCronRefQueryUpdatedAtDateTime) Field() workflowTriggerCronRefPrismaFields { + return workflowTriggerCronRefFieldUpdatedAt +} + +// base struct +type workflowTriggerCronRefQueryDeletedAtDateTime struct{} + +// Set the optional value of DeletedAt +func (r workflowTriggerCronRefQueryDeletedAtDateTime) Set(value DateTime) workflowTriggerCronRefSetParam { + + return workflowTriggerCronRefSetParam{ + data: builder.Field{ + Name: "deletedAt", + Value: value, + }, + } + +} + +// Set the optional value of DeletedAt dynamically +func (r workflowTriggerCronRefQueryDeletedAtDateTime) SetIfPresent(value *DateTime) workflowTriggerCronRefSetParam { + if value == nil { + return workflowTriggerCronRefSetParam{} + } + + return r.Set(*value) +} + +// Set the optional value of DeletedAt dynamically +func (r workflowTriggerCronRefQueryDeletedAtDateTime) SetOptional(value *DateTime) workflowTriggerCronRefSetParam { + if value == nil { + + var v *DateTime + return workflowTriggerCronRefSetParam{ + data: builder.Field{ + Name: "deletedAt", + Value: v, + }, + } + } + + return r.Set(*value) +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) Equals(value DateTime) workflowTriggerCronRefWithPrismaDeletedAtEqualsParam { + + return workflowTriggerCronRefWithPrismaDeletedAtEqualsParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "equals", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) EqualsIfPresent(value *DateTime) workflowTriggerCronRefWithPrismaDeletedAtEqualsParam { + if value == nil { + return workflowTriggerCronRefWithPrismaDeletedAtEqualsParam{} + } + return r.Equals(*value) +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) EqualsOptional(value *DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "equals", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) IsNull() workflowTriggerCronRefDefaultParam { + var str *string = nil + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "equals", + Value: str, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) Order(direction SortOrder) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Value: direction, + }, + } +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) Cursor(cursor DateTime) workflowTriggerCronRefCursorParam { + return workflowTriggerCronRefCursorParam{ + data: builder.Field{ + Name: "deletedAt", + Value: cursor, + }, + } +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) In(value []DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "in", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) InIfPresent(value []DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.In(value) +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) NotIn(value []DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "notIn", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) NotInIfPresent(value []DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.NotIn(value) +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) Lt(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "lt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) LtIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Lt(*value) +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) Lte(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "lte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) LteIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Lte(*value) +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) Gt(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "gt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) GtIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Gt(*value) +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) Gte(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "gte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) GteIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Gte(*value) +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) Not(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "not", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) NotIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Not(*value) +} + +// deprecated: Use Lt instead. + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) Before(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "lt", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use LtIfPresent instead. +func (r workflowTriggerCronRefQueryDeletedAtDateTime) BeforeIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Before(*value) +} + +// deprecated: Use Gt instead. + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) After(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "gt", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use GtIfPresent instead. +func (r workflowTriggerCronRefQueryDeletedAtDateTime) AfterIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.After(*value) +} + +// deprecated: Use Lte instead. + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) BeforeEquals(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "lte", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use LteIfPresent instead. +func (r workflowTriggerCronRefQueryDeletedAtDateTime) BeforeEqualsIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.BeforeEquals(*value) +} + +// deprecated: Use Gte instead. + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) AfterEquals(value DateTime) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "gte", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use GteIfPresent instead. +func (r workflowTriggerCronRefQueryDeletedAtDateTime) AfterEqualsIfPresent(value *DateTime) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.AfterEquals(*value) +} + +func (r workflowTriggerCronRefQueryDeletedAtDateTime) Field() workflowTriggerCronRefPrismaFields { + return workflowTriggerCronRefFieldDeletedAt +} + // base struct type workflowTriggerCronRefQueryCronString struct{} @@ -82590,6 +83667,371 @@ func (r workflowTriggerCronRefQueryInputJson) Field() workflowTriggerCronRefPris return workflowTriggerCronRefFieldInput } +// base struct +type workflowTriggerCronRefQueryAdditionalMetadataJson struct{} + +// Set the optional value of AdditionalMetadata +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) Set(value JSON) workflowTriggerCronRefSetParam { + + return workflowTriggerCronRefSetParam{ + data: builder.Field{ + Name: "additionalMetadata", + Value: value, + }, + } + +} + +// Set the optional value of AdditionalMetadata dynamically +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) SetIfPresent(value *JSON) workflowTriggerCronRefSetParam { + if value == nil { + return workflowTriggerCronRefSetParam{} + } + + return r.Set(*value) +} + +// Set the optional value of AdditionalMetadata dynamically +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) SetOptional(value *JSON) workflowTriggerCronRefSetParam { + if value == nil { + + var v *JSON + return workflowTriggerCronRefSetParam{ + data: builder.Field{ + Name: "additionalMetadata", + Value: v, + }, + } + } + + return r.Set(*value) +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) Equals(value JSON) workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsParam { + + return workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "equals", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) EqualsIfPresent(value *JSON) workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsParam { + if value == nil { + return workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsParam{} + } + return r.Equals(*value) +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) EqualsOptional(value *JSON) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "equals", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) IsNull() workflowTriggerCronRefDefaultParam { + var str *string = nil + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "equals", + Value: str, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) Order(direction SortOrder) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Value: direction, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) Cursor(cursor JSON) workflowTriggerCronRefCursorParam { + return workflowTriggerCronRefCursorParam{ + data: builder.Field{ + Name: "additionalMetadata", + Value: cursor, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) Path(value []string) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "path", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) PathIfPresent(value []string) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Path(value) +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) StringContains(value string) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "string_contains", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) StringContainsIfPresent(value *string) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.StringContains(*value) +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) StringStartsWith(value string) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "string_starts_with", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) StringStartsWithIfPresent(value *string) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.StringStartsWith(*value) +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) StringEndsWith(value string) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "string_ends_with", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) StringEndsWithIfPresent(value *string) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.StringEndsWith(*value) +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) ArrayContains(value JSON) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "array_contains", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) ArrayContainsIfPresent(value *JSON) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.ArrayContains(*value) +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) ArrayStartsWith(value JSON) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "array_starts_with", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) ArrayStartsWithIfPresent(value *JSON) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.ArrayStartsWith(*value) +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) ArrayEndsWith(value JSON) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "array_ends_with", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) ArrayEndsWithIfPresent(value *JSON) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.ArrayEndsWith(*value) +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) Lt(value JSON) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "lt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) LtIfPresent(value *JSON) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Lt(*value) +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) Lte(value JSON) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "lte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) LteIfPresent(value *JSON) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Lte(*value) +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) Gt(value JSON) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "gt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) GtIfPresent(value *JSON) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Gt(*value) +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) Gte(value JSON) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "gte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) GteIfPresent(value *JSON) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Gte(*value) +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) Not(value JSONNullValueFilter) workflowTriggerCronRefDefaultParam { + return workflowTriggerCronRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "not", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) NotIfPresent(value *JSONNullValueFilter) workflowTriggerCronRefDefaultParam { + if value == nil { + return workflowTriggerCronRefDefaultParam{} + } + return r.Not(*value) +} + +func (r workflowTriggerCronRefQueryAdditionalMetadataJson) Field() workflowTriggerCronRefPrismaFields { + return workflowTriggerCronRefFieldAdditionalMetadata +} + // WorkflowTriggerScheduledRef acts as a namespaces to access query methods for the WorkflowTriggerScheduledRef model var WorkflowTriggerScheduledRef = workflowTriggerScheduledRefQuery{} @@ -82601,6 +84043,21 @@ type workflowTriggerScheduledRefQuery struct { // @required ID workflowTriggerScheduledRefQueryIDString + // CreatedAt + // + // @required + CreatedAt workflowTriggerScheduledRefQueryCreatedAtDateTime + + // UpdatedAt + // + // @required + UpdatedAt workflowTriggerScheduledRefQueryUpdatedAtDateTime + + // DeletedAt + // + // @optional + DeletedAt workflowTriggerScheduledRefQueryDeletedAtDateTime + Parent workflowTriggerScheduledRefQueryParentRelations // ParentID @@ -82650,6 +84107,11 @@ type workflowTriggerScheduledRefQuery struct { ChildKey workflowTriggerScheduledRefQueryChildKeyString Triggered workflowTriggerScheduledRefQueryTriggeredRelations + + // AdditionalMetadata + // + // @optional + AdditionalMetadata workflowTriggerScheduledRefQueryAdditionalMetadataJson } func (workflowTriggerScheduledRefQuery) Not(params ...WorkflowTriggerScheduledRefWhereParam) workflowTriggerScheduledRefDefaultParam { @@ -83071,6 +84533,984 @@ func (r workflowTriggerScheduledRefQueryIDString) Field() workflowTriggerSchedul return workflowTriggerScheduledRefFieldID } +// base struct +type workflowTriggerScheduledRefQueryCreatedAtDateTime struct{} + +// Set the required value of CreatedAt +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) Set(value DateTime) workflowTriggerScheduledRefSetParam { + + return workflowTriggerScheduledRefSetParam{ + data: builder.Field{ + Name: "createdAt", + Value: value, + }, + } + +} + +// Set the optional value of CreatedAt dynamically +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) SetIfPresent(value *DateTime) workflowTriggerScheduledRefSetParam { + if value == nil { + return workflowTriggerScheduledRefSetParam{} + } + + return r.Set(*value) +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) Equals(value DateTime) workflowTriggerScheduledRefWithPrismaCreatedAtEqualsParam { + + return workflowTriggerScheduledRefWithPrismaCreatedAtEqualsParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "equals", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) EqualsIfPresent(value *DateTime) workflowTriggerScheduledRefWithPrismaCreatedAtEqualsParam { + if value == nil { + return workflowTriggerScheduledRefWithPrismaCreatedAtEqualsParam{} + } + return r.Equals(*value) +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) Order(direction SortOrder) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Value: direction, + }, + } +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) Cursor(cursor DateTime) workflowTriggerScheduledRefCursorParam { + return workflowTriggerScheduledRefCursorParam{ + data: builder.Field{ + Name: "createdAt", + Value: cursor, + }, + } +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) In(value []DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "in", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) InIfPresent(value []DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.In(value) +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) NotIn(value []DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "notIn", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) NotInIfPresent(value []DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.NotIn(value) +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) Lt(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "lt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) LtIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Lt(*value) +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) Lte(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "lte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) LteIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Lte(*value) +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) Gt(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "gt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) GtIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Gt(*value) +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) Gte(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "gte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) GteIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Gte(*value) +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) Not(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "not", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) NotIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Not(*value) +} + +// deprecated: Use Lt instead. + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) Before(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "lt", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use LtIfPresent instead. +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) BeforeIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Before(*value) +} + +// deprecated: Use Gt instead. + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) After(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "gt", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use GtIfPresent instead. +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) AfterIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.After(*value) +} + +// deprecated: Use Lte instead. + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) BeforeEquals(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "lte", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use LteIfPresent instead. +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) BeforeEqualsIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.BeforeEquals(*value) +} + +// deprecated: Use Gte instead. + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) AfterEquals(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "createdAt", + Fields: []builder.Field{ + { + Name: "gte", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use GteIfPresent instead. +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) AfterEqualsIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.AfterEquals(*value) +} + +func (r workflowTriggerScheduledRefQueryCreatedAtDateTime) Field() workflowTriggerScheduledRefPrismaFields { + return workflowTriggerScheduledRefFieldCreatedAt +} + +// base struct +type workflowTriggerScheduledRefQueryUpdatedAtDateTime struct{} + +// Set the required value of UpdatedAt +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) Set(value DateTime) workflowTriggerScheduledRefSetParam { + + return workflowTriggerScheduledRefSetParam{ + data: builder.Field{ + Name: "updatedAt", + Value: value, + }, + } + +} + +// Set the optional value of UpdatedAt dynamically +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) SetIfPresent(value *DateTime) workflowTriggerScheduledRefSetParam { + if value == nil { + return workflowTriggerScheduledRefSetParam{} + } + + return r.Set(*value) +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) Equals(value DateTime) workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsParam { + + return workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "equals", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) EqualsIfPresent(value *DateTime) workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsParam { + if value == nil { + return workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsParam{} + } + return r.Equals(*value) +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) Order(direction SortOrder) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Value: direction, + }, + } +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) Cursor(cursor DateTime) workflowTriggerScheduledRefCursorParam { + return workflowTriggerScheduledRefCursorParam{ + data: builder.Field{ + Name: "updatedAt", + Value: cursor, + }, + } +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) In(value []DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "in", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) InIfPresent(value []DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.In(value) +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) NotIn(value []DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "notIn", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) NotInIfPresent(value []DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.NotIn(value) +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) Lt(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "lt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) LtIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Lt(*value) +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) Lte(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "lte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) LteIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Lte(*value) +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) Gt(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "gt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) GtIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Gt(*value) +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) Gte(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "gte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) GteIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Gte(*value) +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) Not(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "not", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) NotIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Not(*value) +} + +// deprecated: Use Lt instead. + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) Before(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "lt", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use LtIfPresent instead. +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) BeforeIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Before(*value) +} + +// deprecated: Use Gt instead. + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) After(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "gt", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use GtIfPresent instead. +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) AfterIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.After(*value) +} + +// deprecated: Use Lte instead. + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) BeforeEquals(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "lte", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use LteIfPresent instead. +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) BeforeEqualsIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.BeforeEquals(*value) +} + +// deprecated: Use Gte instead. + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) AfterEquals(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "updatedAt", + Fields: []builder.Field{ + { + Name: "gte", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use GteIfPresent instead. +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) AfterEqualsIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.AfterEquals(*value) +} + +func (r workflowTriggerScheduledRefQueryUpdatedAtDateTime) Field() workflowTriggerScheduledRefPrismaFields { + return workflowTriggerScheduledRefFieldUpdatedAt +} + +// base struct +type workflowTriggerScheduledRefQueryDeletedAtDateTime struct{} + +// Set the optional value of DeletedAt +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) Set(value DateTime) workflowTriggerScheduledRefSetParam { + + return workflowTriggerScheduledRefSetParam{ + data: builder.Field{ + Name: "deletedAt", + Value: value, + }, + } + +} + +// Set the optional value of DeletedAt dynamically +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) SetIfPresent(value *DateTime) workflowTriggerScheduledRefSetParam { + if value == nil { + return workflowTriggerScheduledRefSetParam{} + } + + return r.Set(*value) +} + +// Set the optional value of DeletedAt dynamically +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) SetOptional(value *DateTime) workflowTriggerScheduledRefSetParam { + if value == nil { + + var v *DateTime + return workflowTriggerScheduledRefSetParam{ + data: builder.Field{ + Name: "deletedAt", + Value: v, + }, + } + } + + return r.Set(*value) +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) Equals(value DateTime) workflowTriggerScheduledRefWithPrismaDeletedAtEqualsParam { + + return workflowTriggerScheduledRefWithPrismaDeletedAtEqualsParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "equals", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) EqualsIfPresent(value *DateTime) workflowTriggerScheduledRefWithPrismaDeletedAtEqualsParam { + if value == nil { + return workflowTriggerScheduledRefWithPrismaDeletedAtEqualsParam{} + } + return r.Equals(*value) +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) EqualsOptional(value *DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "equals", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) IsNull() workflowTriggerScheduledRefDefaultParam { + var str *string = nil + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "equals", + Value: str, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) Order(direction SortOrder) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Value: direction, + }, + } +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) Cursor(cursor DateTime) workflowTriggerScheduledRefCursorParam { + return workflowTriggerScheduledRefCursorParam{ + data: builder.Field{ + Name: "deletedAt", + Value: cursor, + }, + } +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) In(value []DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "in", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) InIfPresent(value []DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.In(value) +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) NotIn(value []DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "notIn", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) NotInIfPresent(value []DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.NotIn(value) +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) Lt(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "lt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) LtIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Lt(*value) +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) Lte(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "lte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) LteIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Lte(*value) +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) Gt(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "gt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) GtIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Gt(*value) +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) Gte(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "gte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) GteIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Gte(*value) +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) Not(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "not", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) NotIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Not(*value) +} + +// deprecated: Use Lt instead. + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) Before(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "lt", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use LtIfPresent instead. +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) BeforeIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Before(*value) +} + +// deprecated: Use Gt instead. + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) After(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "gt", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use GtIfPresent instead. +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) AfterIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.After(*value) +} + +// deprecated: Use Lte instead. + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) BeforeEquals(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "lte", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use LteIfPresent instead. +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) BeforeEqualsIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.BeforeEquals(*value) +} + +// deprecated: Use Gte instead. + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) AfterEquals(value DateTime) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "deletedAt", + Fields: []builder.Field{ + { + Name: "gte", + Value: value, + }, + }, + }, + } +} + +// deprecated: Use GteIfPresent instead. +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) AfterEqualsIfPresent(value *DateTime) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.AfterEquals(*value) +} + +func (r workflowTriggerScheduledRefQueryDeletedAtDateTime) Field() workflowTriggerScheduledRefPrismaFields { + return workflowTriggerScheduledRefFieldDeletedAt +} + // base struct type workflowTriggerScheduledRefQueryParentWorkflowVersion struct{} @@ -86546,6 +88986,371 @@ func (r workflowTriggerScheduledRefQueryTriggeredWorkflowRunTriggeredBy) Field() return workflowTriggerScheduledRefFieldTriggered } +// base struct +type workflowTriggerScheduledRefQueryAdditionalMetadataJson struct{} + +// Set the optional value of AdditionalMetadata +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) Set(value JSON) workflowTriggerScheduledRefSetParam { + + return workflowTriggerScheduledRefSetParam{ + data: builder.Field{ + Name: "additionalMetadata", + Value: value, + }, + } + +} + +// Set the optional value of AdditionalMetadata dynamically +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) SetIfPresent(value *JSON) workflowTriggerScheduledRefSetParam { + if value == nil { + return workflowTriggerScheduledRefSetParam{} + } + + return r.Set(*value) +} + +// Set the optional value of AdditionalMetadata dynamically +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) SetOptional(value *JSON) workflowTriggerScheduledRefSetParam { + if value == nil { + + var v *JSON + return workflowTriggerScheduledRefSetParam{ + data: builder.Field{ + Name: "additionalMetadata", + Value: v, + }, + } + } + + return r.Set(*value) +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) Equals(value JSON) workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsParam { + + return workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "equals", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) EqualsIfPresent(value *JSON) workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsParam { + if value == nil { + return workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsParam{} + } + return r.Equals(*value) +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) EqualsOptional(value *JSON) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "equals", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) IsNull() workflowTriggerScheduledRefDefaultParam { + var str *string = nil + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "equals", + Value: str, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) Order(direction SortOrder) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Value: direction, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) Cursor(cursor JSON) workflowTriggerScheduledRefCursorParam { + return workflowTriggerScheduledRefCursorParam{ + data: builder.Field{ + Name: "additionalMetadata", + Value: cursor, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) Path(value []string) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "path", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) PathIfPresent(value []string) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Path(value) +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) StringContains(value string) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "string_contains", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) StringContainsIfPresent(value *string) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.StringContains(*value) +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) StringStartsWith(value string) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "string_starts_with", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) StringStartsWithIfPresent(value *string) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.StringStartsWith(*value) +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) StringEndsWith(value string) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "string_ends_with", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) StringEndsWithIfPresent(value *string) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.StringEndsWith(*value) +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) ArrayContains(value JSON) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "array_contains", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) ArrayContainsIfPresent(value *JSON) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.ArrayContains(*value) +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) ArrayStartsWith(value JSON) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "array_starts_with", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) ArrayStartsWithIfPresent(value *JSON) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.ArrayStartsWith(*value) +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) ArrayEndsWith(value JSON) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "array_ends_with", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) ArrayEndsWithIfPresent(value *JSON) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.ArrayEndsWith(*value) +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) Lt(value JSON) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "lt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) LtIfPresent(value *JSON) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Lt(*value) +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) Lte(value JSON) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "lte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) LteIfPresent(value *JSON) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Lte(*value) +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) Gt(value JSON) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "gt", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) GtIfPresent(value *JSON) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Gt(*value) +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) Gte(value JSON) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "gte", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) GteIfPresent(value *JSON) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Gte(*value) +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) Not(value JSONNullValueFilter) workflowTriggerScheduledRefDefaultParam { + return workflowTriggerScheduledRefDefaultParam{ + data: builder.Field{ + Name: "additionalMetadata", + Fields: []builder.Field{ + { + Name: "not", + Value: value, + }, + }, + }, + } +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) NotIfPresent(value *JSONNullValueFilter) workflowTriggerScheduledRefDefaultParam { + if value == nil { + return workflowTriggerScheduledRefDefaultParam{} + } + return r.Not(*value) +} + +func (r workflowTriggerScheduledRefQueryAdditionalMetadataJson) Field() workflowTriggerScheduledRefPrismaFields { + return workflowTriggerScheduledRefFieldAdditionalMetadata +} + // Job acts as a namespaces to access query methods for the Job model var Job = jobQuery{} @@ -229072,10 +231877,14 @@ type workflowTriggerCronRefActions struct { var workflowTriggerCronRefOutput = []builder.Output{ {Name: "parentId"}, + {Name: "createdAt"}, + {Name: "updatedAt"}, + {Name: "deletedAt"}, {Name: "cron"}, {Name: "enabled"}, {Name: "tickerId"}, {Name: "input"}, + {Name: "additionalMetadata"}, } type WorkflowTriggerCronRefRelationWith interface { @@ -229398,6 +232207,240 @@ func (p workflowTriggerCronRefWithPrismaParentIDEqualsUniqueParam) parentIDField func (workflowTriggerCronRefWithPrismaParentIDEqualsUniqueParam) unique() {} func (workflowTriggerCronRefWithPrismaParentIDEqualsUniqueParam) equals() {} +type WorkflowTriggerCronRefWithPrismaCreatedAtEqualsSetParam interface { + field() builder.Field + getQuery() builder.Query + equals() + workflowTriggerCronRefModel() + createdAtField() +} + +type WorkflowTriggerCronRefWithPrismaCreatedAtSetParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerCronRefModel() + createdAtField() +} + +type workflowTriggerCronRefWithPrismaCreatedAtSetParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerCronRefWithPrismaCreatedAtSetParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerCronRefWithPrismaCreatedAtSetParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerCronRefWithPrismaCreatedAtSetParam) workflowTriggerCronRefModel() {} + +func (p workflowTriggerCronRefWithPrismaCreatedAtSetParam) createdAtField() {} + +type WorkflowTriggerCronRefWithPrismaCreatedAtWhereParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerCronRefModel() + createdAtField() +} + +type workflowTriggerCronRefWithPrismaCreatedAtEqualsParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerCronRefWithPrismaCreatedAtEqualsParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerCronRefWithPrismaCreatedAtEqualsParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerCronRefWithPrismaCreatedAtEqualsParam) workflowTriggerCronRefModel() {} + +func (p workflowTriggerCronRefWithPrismaCreatedAtEqualsParam) createdAtField() {} + +func (workflowTriggerCronRefWithPrismaCreatedAtSetParam) settable() {} +func (workflowTriggerCronRefWithPrismaCreatedAtEqualsParam) equals() {} + +type workflowTriggerCronRefWithPrismaCreatedAtEqualsUniqueParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerCronRefWithPrismaCreatedAtEqualsUniqueParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerCronRefWithPrismaCreatedAtEqualsUniqueParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerCronRefWithPrismaCreatedAtEqualsUniqueParam) workflowTriggerCronRefModel() {} +func (p workflowTriggerCronRefWithPrismaCreatedAtEqualsUniqueParam) createdAtField() {} + +func (workflowTriggerCronRefWithPrismaCreatedAtEqualsUniqueParam) unique() {} +func (workflowTriggerCronRefWithPrismaCreatedAtEqualsUniqueParam) equals() {} + +type WorkflowTriggerCronRefWithPrismaUpdatedAtEqualsSetParam interface { + field() builder.Field + getQuery() builder.Query + equals() + workflowTriggerCronRefModel() + updatedAtField() +} + +type WorkflowTriggerCronRefWithPrismaUpdatedAtSetParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerCronRefModel() + updatedAtField() +} + +type workflowTriggerCronRefWithPrismaUpdatedAtSetParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerCronRefWithPrismaUpdatedAtSetParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerCronRefWithPrismaUpdatedAtSetParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerCronRefWithPrismaUpdatedAtSetParam) workflowTriggerCronRefModel() {} + +func (p workflowTriggerCronRefWithPrismaUpdatedAtSetParam) updatedAtField() {} + +type WorkflowTriggerCronRefWithPrismaUpdatedAtWhereParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerCronRefModel() + updatedAtField() +} + +type workflowTriggerCronRefWithPrismaUpdatedAtEqualsParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerCronRefWithPrismaUpdatedAtEqualsParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerCronRefWithPrismaUpdatedAtEqualsParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerCronRefWithPrismaUpdatedAtEqualsParam) workflowTriggerCronRefModel() {} + +func (p workflowTriggerCronRefWithPrismaUpdatedAtEqualsParam) updatedAtField() {} + +func (workflowTriggerCronRefWithPrismaUpdatedAtSetParam) settable() {} +func (workflowTriggerCronRefWithPrismaUpdatedAtEqualsParam) equals() {} + +type workflowTriggerCronRefWithPrismaUpdatedAtEqualsUniqueParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerCronRefWithPrismaUpdatedAtEqualsUniqueParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerCronRefWithPrismaUpdatedAtEqualsUniqueParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerCronRefWithPrismaUpdatedAtEqualsUniqueParam) workflowTriggerCronRefModel() {} +func (p workflowTriggerCronRefWithPrismaUpdatedAtEqualsUniqueParam) updatedAtField() {} + +func (workflowTriggerCronRefWithPrismaUpdatedAtEqualsUniqueParam) unique() {} +func (workflowTriggerCronRefWithPrismaUpdatedAtEqualsUniqueParam) equals() {} + +type WorkflowTriggerCronRefWithPrismaDeletedAtEqualsSetParam interface { + field() builder.Field + getQuery() builder.Query + equals() + workflowTriggerCronRefModel() + deletedAtField() +} + +type WorkflowTriggerCronRefWithPrismaDeletedAtSetParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerCronRefModel() + deletedAtField() +} + +type workflowTriggerCronRefWithPrismaDeletedAtSetParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerCronRefWithPrismaDeletedAtSetParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerCronRefWithPrismaDeletedAtSetParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerCronRefWithPrismaDeletedAtSetParam) workflowTriggerCronRefModel() {} + +func (p workflowTriggerCronRefWithPrismaDeletedAtSetParam) deletedAtField() {} + +type WorkflowTriggerCronRefWithPrismaDeletedAtWhereParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerCronRefModel() + deletedAtField() +} + +type workflowTriggerCronRefWithPrismaDeletedAtEqualsParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerCronRefWithPrismaDeletedAtEqualsParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerCronRefWithPrismaDeletedAtEqualsParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerCronRefWithPrismaDeletedAtEqualsParam) workflowTriggerCronRefModel() {} + +func (p workflowTriggerCronRefWithPrismaDeletedAtEqualsParam) deletedAtField() {} + +func (workflowTriggerCronRefWithPrismaDeletedAtSetParam) settable() {} +func (workflowTriggerCronRefWithPrismaDeletedAtEqualsParam) equals() {} + +type workflowTriggerCronRefWithPrismaDeletedAtEqualsUniqueParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerCronRefWithPrismaDeletedAtEqualsUniqueParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerCronRefWithPrismaDeletedAtEqualsUniqueParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerCronRefWithPrismaDeletedAtEqualsUniqueParam) workflowTriggerCronRefModel() {} +func (p workflowTriggerCronRefWithPrismaDeletedAtEqualsUniqueParam) deletedAtField() {} + +func (workflowTriggerCronRefWithPrismaDeletedAtEqualsUniqueParam) unique() {} +func (workflowTriggerCronRefWithPrismaDeletedAtEqualsUniqueParam) equals() {} + type WorkflowTriggerCronRefWithPrismaCronEqualsSetParam interface { field() builder.Field getQuery() builder.Query @@ -229866,6 +232909,87 @@ func (p workflowTriggerCronRefWithPrismaInputEqualsUniqueParam) inputField() func (workflowTriggerCronRefWithPrismaInputEqualsUniqueParam) unique() {} func (workflowTriggerCronRefWithPrismaInputEqualsUniqueParam) equals() {} +type WorkflowTriggerCronRefWithPrismaAdditionalMetadataEqualsSetParam interface { + field() builder.Field + getQuery() builder.Query + equals() + workflowTriggerCronRefModel() + additionalMetadataField() +} + +type WorkflowTriggerCronRefWithPrismaAdditionalMetadataSetParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerCronRefModel() + additionalMetadataField() +} + +type workflowTriggerCronRefWithPrismaAdditionalMetadataSetParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerCronRefWithPrismaAdditionalMetadataSetParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerCronRefWithPrismaAdditionalMetadataSetParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerCronRefWithPrismaAdditionalMetadataSetParam) workflowTriggerCronRefModel() {} + +func (p workflowTriggerCronRefWithPrismaAdditionalMetadataSetParam) additionalMetadataField() {} + +type WorkflowTriggerCronRefWithPrismaAdditionalMetadataWhereParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerCronRefModel() + additionalMetadataField() +} + +type workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsParam) workflowTriggerCronRefModel() { +} + +func (p workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsParam) additionalMetadataField() {} + +func (workflowTriggerCronRefWithPrismaAdditionalMetadataSetParam) settable() {} +func (workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsParam) equals() {} + +type workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsUniqueParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsUniqueParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsUniqueParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsUniqueParam) workflowTriggerCronRefModel() { +} +func (p workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsUniqueParam) additionalMetadataField() { +} + +func (workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsUniqueParam) unique() {} +func (workflowTriggerCronRefWithPrismaAdditionalMetadataEqualsUniqueParam) equals() {} + type workflowTriggerScheduledRefActions struct { // client holds the prisma client client *PrismaClient @@ -229873,6 +232997,9 @@ type workflowTriggerScheduledRefActions struct { var workflowTriggerScheduledRefOutput = []builder.Output{ {Name: "id"}, + {Name: "createdAt"}, + {Name: "updatedAt"}, + {Name: "deletedAt"}, {Name: "parentId"}, {Name: "triggerAt"}, {Name: "tickerId"}, @@ -229881,6 +233008,7 @@ var workflowTriggerScheduledRefOutput = []builder.Output{ {Name: "parentStepRunId"}, {Name: "childIndex"}, {Name: "childKey"}, + {Name: "additionalMetadata"}, } type WorkflowTriggerScheduledRefRelationWith interface { @@ -230126,6 +233254,246 @@ func (p workflowTriggerScheduledRefWithPrismaIDEqualsUniqueParam) idField() {} func (workflowTriggerScheduledRefWithPrismaIDEqualsUniqueParam) unique() {} func (workflowTriggerScheduledRefWithPrismaIDEqualsUniqueParam) equals() {} +type WorkflowTriggerScheduledRefWithPrismaCreatedAtEqualsSetParam interface { + field() builder.Field + getQuery() builder.Query + equals() + workflowTriggerScheduledRefModel() + createdAtField() +} + +type WorkflowTriggerScheduledRefWithPrismaCreatedAtSetParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerScheduledRefModel() + createdAtField() +} + +type workflowTriggerScheduledRefWithPrismaCreatedAtSetParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerScheduledRefWithPrismaCreatedAtSetParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerScheduledRefWithPrismaCreatedAtSetParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerScheduledRefWithPrismaCreatedAtSetParam) workflowTriggerScheduledRefModel() {} + +func (p workflowTriggerScheduledRefWithPrismaCreatedAtSetParam) createdAtField() {} + +type WorkflowTriggerScheduledRefWithPrismaCreatedAtWhereParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerScheduledRefModel() + createdAtField() +} + +type workflowTriggerScheduledRefWithPrismaCreatedAtEqualsParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerScheduledRefWithPrismaCreatedAtEqualsParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerScheduledRefWithPrismaCreatedAtEqualsParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerScheduledRefWithPrismaCreatedAtEqualsParam) workflowTriggerScheduledRefModel() { +} + +func (p workflowTriggerScheduledRefWithPrismaCreatedAtEqualsParam) createdAtField() {} + +func (workflowTriggerScheduledRefWithPrismaCreatedAtSetParam) settable() {} +func (workflowTriggerScheduledRefWithPrismaCreatedAtEqualsParam) equals() {} + +type workflowTriggerScheduledRefWithPrismaCreatedAtEqualsUniqueParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerScheduledRefWithPrismaCreatedAtEqualsUniqueParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerScheduledRefWithPrismaCreatedAtEqualsUniqueParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerScheduledRefWithPrismaCreatedAtEqualsUniqueParam) workflowTriggerScheduledRefModel() { +} +func (p workflowTriggerScheduledRefWithPrismaCreatedAtEqualsUniqueParam) createdAtField() {} + +func (workflowTriggerScheduledRefWithPrismaCreatedAtEqualsUniqueParam) unique() {} +func (workflowTriggerScheduledRefWithPrismaCreatedAtEqualsUniqueParam) equals() {} + +type WorkflowTriggerScheduledRefWithPrismaUpdatedAtEqualsSetParam interface { + field() builder.Field + getQuery() builder.Query + equals() + workflowTriggerScheduledRefModel() + updatedAtField() +} + +type WorkflowTriggerScheduledRefWithPrismaUpdatedAtSetParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerScheduledRefModel() + updatedAtField() +} + +type workflowTriggerScheduledRefWithPrismaUpdatedAtSetParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerScheduledRefWithPrismaUpdatedAtSetParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerScheduledRefWithPrismaUpdatedAtSetParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerScheduledRefWithPrismaUpdatedAtSetParam) workflowTriggerScheduledRefModel() {} + +func (p workflowTriggerScheduledRefWithPrismaUpdatedAtSetParam) updatedAtField() {} + +type WorkflowTriggerScheduledRefWithPrismaUpdatedAtWhereParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerScheduledRefModel() + updatedAtField() +} + +type workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsParam) workflowTriggerScheduledRefModel() { +} + +func (p workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsParam) updatedAtField() {} + +func (workflowTriggerScheduledRefWithPrismaUpdatedAtSetParam) settable() {} +func (workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsParam) equals() {} + +type workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsUniqueParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsUniqueParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsUniqueParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsUniqueParam) workflowTriggerScheduledRefModel() { +} +func (p workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsUniqueParam) updatedAtField() {} + +func (workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsUniqueParam) unique() {} +func (workflowTriggerScheduledRefWithPrismaUpdatedAtEqualsUniqueParam) equals() {} + +type WorkflowTriggerScheduledRefWithPrismaDeletedAtEqualsSetParam interface { + field() builder.Field + getQuery() builder.Query + equals() + workflowTriggerScheduledRefModel() + deletedAtField() +} + +type WorkflowTriggerScheduledRefWithPrismaDeletedAtSetParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerScheduledRefModel() + deletedAtField() +} + +type workflowTriggerScheduledRefWithPrismaDeletedAtSetParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerScheduledRefWithPrismaDeletedAtSetParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerScheduledRefWithPrismaDeletedAtSetParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerScheduledRefWithPrismaDeletedAtSetParam) workflowTriggerScheduledRefModel() {} + +func (p workflowTriggerScheduledRefWithPrismaDeletedAtSetParam) deletedAtField() {} + +type WorkflowTriggerScheduledRefWithPrismaDeletedAtWhereParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerScheduledRefModel() + deletedAtField() +} + +type workflowTriggerScheduledRefWithPrismaDeletedAtEqualsParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerScheduledRefWithPrismaDeletedAtEqualsParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerScheduledRefWithPrismaDeletedAtEqualsParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerScheduledRefWithPrismaDeletedAtEqualsParam) workflowTriggerScheduledRefModel() { +} + +func (p workflowTriggerScheduledRefWithPrismaDeletedAtEqualsParam) deletedAtField() {} + +func (workflowTriggerScheduledRefWithPrismaDeletedAtSetParam) settable() {} +func (workflowTriggerScheduledRefWithPrismaDeletedAtEqualsParam) equals() {} + +type workflowTriggerScheduledRefWithPrismaDeletedAtEqualsUniqueParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerScheduledRefWithPrismaDeletedAtEqualsUniqueParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerScheduledRefWithPrismaDeletedAtEqualsUniqueParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerScheduledRefWithPrismaDeletedAtEqualsUniqueParam) workflowTriggerScheduledRefModel() { +} +func (p workflowTriggerScheduledRefWithPrismaDeletedAtEqualsUniqueParam) deletedAtField() {} + +func (workflowTriggerScheduledRefWithPrismaDeletedAtEqualsUniqueParam) unique() {} +func (workflowTriggerScheduledRefWithPrismaDeletedAtEqualsUniqueParam) equals() {} + type WorkflowTriggerScheduledRefWithPrismaParentEqualsSetParam interface { field() builder.Field getQuery() builder.Query @@ -231172,6 +234540,89 @@ func (p workflowTriggerScheduledRefWithPrismaTriggeredEqualsUniqueParam) trigger func (workflowTriggerScheduledRefWithPrismaTriggeredEqualsUniqueParam) unique() {} func (workflowTriggerScheduledRefWithPrismaTriggeredEqualsUniqueParam) equals() {} +type WorkflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsSetParam interface { + field() builder.Field + getQuery() builder.Query + equals() + workflowTriggerScheduledRefModel() + additionalMetadataField() +} + +type WorkflowTriggerScheduledRefWithPrismaAdditionalMetadataSetParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerScheduledRefModel() + additionalMetadataField() +} + +type workflowTriggerScheduledRefWithPrismaAdditionalMetadataSetParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerScheduledRefWithPrismaAdditionalMetadataSetParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerScheduledRefWithPrismaAdditionalMetadataSetParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerScheduledRefWithPrismaAdditionalMetadataSetParam) workflowTriggerScheduledRefModel() { +} + +func (p workflowTriggerScheduledRefWithPrismaAdditionalMetadataSetParam) additionalMetadataField() {} + +type WorkflowTriggerScheduledRefWithPrismaAdditionalMetadataWhereParam interface { + field() builder.Field + getQuery() builder.Query + workflowTriggerScheduledRefModel() + additionalMetadataField() +} + +type workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsParam) workflowTriggerScheduledRefModel() { +} + +func (p workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsParam) additionalMetadataField() { +} + +func (workflowTriggerScheduledRefWithPrismaAdditionalMetadataSetParam) settable() {} +func (workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsParam) equals() {} + +type workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsUniqueParam struct { + data builder.Field + query builder.Query +} + +func (p workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsUniqueParam) field() builder.Field { + return p.data +} + +func (p workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsUniqueParam) getQuery() builder.Query { + return p.query +} + +func (p workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsUniqueParam) workflowTriggerScheduledRefModel() { +} +func (p workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsUniqueParam) additionalMetadataField() { +} + +func (workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsUniqueParam) unique() {} +func (workflowTriggerScheduledRefWithPrismaAdditionalMetadataEqualsUniqueParam) equals() {} + type jobActions struct { // client holds the prisma client client *PrismaClient diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 24fb25457..ab903e8c9 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -653,7 +653,7 @@ model WorkflowTriggerCronRef { updatedAt DateTime @default(now()) @updatedAt deletedAt DateTime? // the cron expression - cron String + cron String // whether this cron is enabled or not enabled Boolean @default(true) From 1756214d7532f278064f42e8b02459e8a606ac1a Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Fri, 25 Oct 2024 07:24:01 -0400 Subject: [PATCH 12/30] feat: delete run --- api-contracts/openapi/openapi.yaml | 2 + .../openapi/paths/workflow/workflow.yaml | 94 +++++++ .../handlers/workflows/delete_scheduled.go | 26 ++ .../handlers/workflows/get_scheduled.go | 34 +++ api/v1/server/oas/gen/openapi.gen.go | 243 ++++++++++++++-- frontend/app/src/lib/api/generated/Api.ts | 34 +++ .../components/delete-scheduled-runs.tsx | 114 ++++++++ .../components/scheduled-runs-columns.tsx | 183 +++++++----- .../src/pages/main/scheduled-runs/index.tsx | 65 +++-- pkg/client/rest/gen.go | 264 ++++++++++++++++++ .../prisma/dbsqlc/workflow_runs.sql | 13 +- .../prisma/dbsqlc/workflow_runs.sql.go | 52 +++- pkg/repository/prisma/workflow_run.go | 31 ++ pkg/repository/workflow_run.go | 9 + 14 files changed, 1031 insertions(+), 133 deletions(-) create mode 100644 api/v1/server/handlers/workflows/delete_scheduled.go create mode 100644 api/v1/server/handlers/workflows/get_scheduled.go create mode 100644 frontend/app/src/pages/main/scheduled-runs/components/delete-scheduled-runs.tsx diff --git a/api-contracts/openapi/openapi.yaml b/api-contracts/openapi/openapi.yaml index e2c847fc2..8a4392be3 100644 --- a/api-contracts/openapi/openapi.yaml +++ b/api-contracts/openapi/openapi.yaml @@ -118,6 +118,8 @@ paths: $ref: "./paths/workflow/workflow.yaml#/withTenant" /api/v1/tenants/{tenant}/workflows/scheduled: $ref: "./paths/workflow/workflow.yaml#/scheduledList" + /api/v1/tenants/{tenant}/workflows/scheduled/{scheduledId}: + $ref: "./paths/workflow/workflow.yaml#/scheduled" /api/v1/tenants/{tenant}/workflows/crons: $ref: "./paths/workflow/workflow.yaml#/cronsList" /api/v1/tenants/{tenant}/workflows/cancel: diff --git a/api-contracts/openapi/paths/workflow/workflow.yaml b/api-contracts/openapi/paths/workflow/workflow.yaml index 6807f6fa1..e465ef601 100644 --- a/api-contracts/openapi/paths/workflow/workflow.yaml +++ b/api-contracts/openapi/paths/workflow/workflow.yaml @@ -910,6 +910,100 @@ scheduledList: tags: - Workflow +scheduled: + get: + x-resources: ["tenant"] + description: Get a scheduled workflow run for a tenant + operationId: workflow-scheduled:get + parameters: + - description: The tenant id + in: path + name: tenant + required: true + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + - description: The scheduled workflow id + in: path + name: scheduledId + required: true + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + responses: + "200": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/ScheduledWorkflows" + description: Successfully retrieved the workflow runs + "400": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: A malformed or bad request + "403": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: Forbidden + "404": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: Forbidden + summary: Get workflow runs + tags: + - Workflow + delete: + x-resources: ["tenant"] + description: Delete a scheduled workflow run for a tenant + operationId: workflow-scheduled:delete + parameters: + - description: The tenant id + in: path + name: tenant + required: true + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + - description: The scheduled workflow id + in: path + name: scheduledId + required: true + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + responses: + "204": + description: Successfully deleted the scheduled workflow run + "400": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: A malformed or bad request + "403": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIError" + description: Forbidden + summary: Delete tenant alert email group + tags: + - Workflow + cronsList: get: x-resources: ["tenant"] diff --git a/api/v1/server/handlers/workflows/delete_scheduled.go b/api/v1/server/handlers/workflows/delete_scheduled.go new file mode 100644 index 000000000..6cfcc414c --- /dev/null +++ b/api/v1/server/handlers/workflows/delete_scheduled.go @@ -0,0 +1,26 @@ +package workflows + +import ( + "context" + "time" + + "github.com/labstack/echo/v4" + + "github.com/hatchet-dev/hatchet/api/v1/server/oas/gen" + "github.com/hatchet-dev/hatchet/pkg/repository/prisma/db" +) + +func (t *WorkflowService) WorkflowScheduledDelete(ctx echo.Context, request gen.WorkflowScheduledDeleteRequestObject) (gen.WorkflowScheduledDeleteResponseObject, error) { + tenant := ctx.Get("tenant").(*db.TenantModel) + + dbCtx, cancel := context.WithTimeout(ctx.Request().Context(), 30*time.Second) + defer cancel() + + err := t.config.APIRepository.WorkflowRun().DeleteScheduledWorkflow(dbCtx, tenant.ID, request.ScheduledId.String()) + + if err != nil { + return nil, err + } + + return gen.WorkflowScheduledDelete204Response{}, nil +} diff --git a/api/v1/server/handlers/workflows/get_scheduled.go b/api/v1/server/handlers/workflows/get_scheduled.go new file mode 100644 index 000000000..35eb8901e --- /dev/null +++ b/api/v1/server/handlers/workflows/get_scheduled.go @@ -0,0 +1,34 @@ +package workflows + +import ( + "context" + "time" + + "github.com/labstack/echo/v4" + + "github.com/hatchet-dev/hatchet/api/v1/server/oas/apierrors" + "github.com/hatchet-dev/hatchet/api/v1/server/oas/gen" + "github.com/hatchet-dev/hatchet/api/v1/server/oas/transformers" + "github.com/hatchet-dev/hatchet/pkg/repository/prisma/db" +) + +func (t *WorkflowService) WorkflowScheduledGet(ctx echo.Context, request gen.WorkflowScheduledGetRequestObject) (gen.WorkflowScheduledGetResponseObject, error) { + tenant := ctx.Get("tenant").(*db.TenantModel) + + dbCtx, cancel := context.WithTimeout(ctx.Request().Context(), 30*time.Second) + defer cancel() + + scheduled, err := t.config.APIRepository.WorkflowRun().GetScheduledWorkflow(dbCtx, tenant.ID, request.ScheduledId.String()) + + if err != nil { + return nil, err + } + + if scheduled == nil { + return gen.WorkflowScheduledGet404JSONResponse(apierrors.NewAPIErrors("Scheduled workflow not found.")), nil + } + + return gen.WorkflowScheduledGet200JSONResponse( + *transformers.ToScheduledWorkflowsFromSQLC(scheduled), + ), nil +} diff --git a/api/v1/server/oas/gen/openapi.gen.go b/api/v1/server/oas/gen/openapi.gen.go index 53df14cdc..1c5ef45b5 100644 --- a/api/v1/server/oas/gen/openapi.gen.go +++ b/api/v1/server/oas/gen/openapi.gen.go @@ -1898,6 +1898,12 @@ type ServerInterface interface { // Get workflow runs // (GET /api/v1/tenants/{tenant}/workflows/scheduled) WorkflowScheduledList(ctx echo.Context, tenant openapi_types.UUID, params WorkflowScheduledListParams) error + // Delete tenant alert email group + // (DELETE /api/v1/tenants/{tenant}/workflows/scheduled/{scheduledId}) + WorkflowScheduledDelete(ctx echo.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID) error + // Get workflow runs + // (GET /api/v1/tenants/{tenant}/workflows/scheduled/{scheduledId}) + WorkflowScheduledGet(ctx echo.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID) error // Get workflow worker count // (GET /api/v1/tenants/{tenant}/workflows/{workflow}/worker-count) WorkflowGetWorkersCount(ctx echo.Context, tenant openapi_types.UUID, workflow openapi_types.UUID) error @@ -3688,6 +3694,62 @@ func (w *ServerInterfaceWrapper) WorkflowScheduledList(ctx echo.Context) error { return err } +// WorkflowScheduledDelete converts echo context to params. +func (w *ServerInterfaceWrapper) WorkflowScheduledDelete(ctx echo.Context) error { + var err error + // ------------- Path parameter "tenant" ------------- + var tenant openapi_types.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "tenant", runtime.ParamLocationPath, ctx.Param("tenant"), &tenant) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tenant: %s", err)) + } + + // ------------- Path parameter "scheduledId" ------------- + var scheduledId openapi_types.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "scheduledId", runtime.ParamLocationPath, ctx.Param("scheduledId"), &scheduledId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter scheduledId: %s", err)) + } + + ctx.Set(BearerAuthScopes, []string{}) + + ctx.Set(CookieAuthScopes, []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.WorkflowScheduledDelete(ctx, tenant, scheduledId) + return err +} + +// WorkflowScheduledGet converts echo context to params. +func (w *ServerInterfaceWrapper) WorkflowScheduledGet(ctx echo.Context) error { + var err error + // ------------- Path parameter "tenant" ------------- + var tenant openapi_types.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "tenant", runtime.ParamLocationPath, ctx.Param("tenant"), &tenant) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tenant: %s", err)) + } + + // ------------- Path parameter "scheduledId" ------------- + var scheduledId openapi_types.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "scheduledId", runtime.ParamLocationPath, ctx.Param("scheduledId"), &scheduledId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter scheduledId: %s", err)) + } + + ctx.Set(BearerAuthScopes, []string{}) + + ctx.Set(CookieAuthScopes, []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.WorkflowScheduledGet(ctx, tenant, scheduledId) + return err +} + // WorkflowGetWorkersCount converts echo context to params. func (w *ServerInterfaceWrapper) WorkflowGetWorkersCount(ctx echo.Context) error { var err error @@ -4185,6 +4247,8 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/runs", wrapper.WorkflowRunList) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/runs/metrics", wrapper.WorkflowRunGetMetrics) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/scheduled", wrapper.WorkflowScheduledList) + router.DELETE(baseURL+"/api/v1/tenants/:tenant/workflows/scheduled/:scheduledId", wrapper.WorkflowScheduledDelete) + router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/scheduled/:scheduledId", wrapper.WorkflowScheduledGet) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/:workflow/worker-count", wrapper.WorkflowGetWorkersCount) router.GET(baseURL+"/api/v1/users/current", wrapper.UserGetCurrent) router.GET(baseURL+"/api/v1/users/github/callback", wrapper.UserUpdateGithubOauthCallback) @@ -6498,6 +6562,86 @@ func (response WorkflowScheduledList403JSONResponse) VisitWorkflowScheduledListR return json.NewEncoder(w).Encode(response) } +type WorkflowScheduledDeleteRequestObject struct { + Tenant openapi_types.UUID `json:"tenant"` + ScheduledId openapi_types.UUID `json:"scheduledId"` +} + +type WorkflowScheduledDeleteResponseObject interface { + VisitWorkflowScheduledDeleteResponse(w http.ResponseWriter) error +} + +type WorkflowScheduledDelete204Response struct { +} + +func (response WorkflowScheduledDelete204Response) VisitWorkflowScheduledDeleteResponse(w http.ResponseWriter) error { + w.WriteHeader(204) + return nil +} + +type WorkflowScheduledDelete400JSONResponse APIErrors + +func (response WorkflowScheduledDelete400JSONResponse) VisitWorkflowScheduledDeleteResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(400) + + return json.NewEncoder(w).Encode(response) +} + +type WorkflowScheduledDelete403JSONResponse APIError + +func (response WorkflowScheduledDelete403JSONResponse) VisitWorkflowScheduledDeleteResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(403) + + return json.NewEncoder(w).Encode(response) +} + +type WorkflowScheduledGetRequestObject struct { + Tenant openapi_types.UUID `json:"tenant"` + ScheduledId openapi_types.UUID `json:"scheduledId"` +} + +type WorkflowScheduledGetResponseObject interface { + VisitWorkflowScheduledGetResponse(w http.ResponseWriter) error +} + +type WorkflowScheduledGet200JSONResponse ScheduledWorkflows + +func (response WorkflowScheduledGet200JSONResponse) VisitWorkflowScheduledGetResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type WorkflowScheduledGet400JSONResponse APIErrors + +func (response WorkflowScheduledGet400JSONResponse) VisitWorkflowScheduledGetResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(400) + + return json.NewEncoder(w).Encode(response) +} + +type WorkflowScheduledGet403JSONResponse APIErrors + +func (response WorkflowScheduledGet403JSONResponse) VisitWorkflowScheduledGetResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(403) + + return json.NewEncoder(w).Encode(response) +} + +type WorkflowScheduledGet404JSONResponse APIErrors + +func (response WorkflowScheduledGet404JSONResponse) VisitWorkflowScheduledGetResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(404) + + return json.NewEncoder(w).Encode(response) +} + type WorkflowGetWorkersCountRequestObject struct { Tenant openapi_types.UUID `json:"tenant"` Workflow openapi_types.UUID `json:"workflow"` @@ -7542,6 +7686,10 @@ type StrictServerInterface interface { WorkflowScheduledList(ctx echo.Context, request WorkflowScheduledListRequestObject) (WorkflowScheduledListResponseObject, error) + WorkflowScheduledDelete(ctx echo.Context, request WorkflowScheduledDeleteRequestObject) (WorkflowScheduledDeleteResponseObject, error) + + WorkflowScheduledGet(ctx echo.Context, request WorkflowScheduledGetRequestObject) (WorkflowScheduledGetResponseObject, error) + WorkflowGetWorkersCount(ctx echo.Context, request WorkflowGetWorkersCountRequestObject) (WorkflowGetWorkersCountResponseObject, error) UserGetCurrent(ctx echo.Context, request UserGetCurrentRequestObject) (UserGetCurrentResponseObject, error) @@ -9236,6 +9384,58 @@ func (sh *strictHandler) WorkflowScheduledList(ctx echo.Context, tenant openapi_ return nil } +// WorkflowScheduledDelete operation middleware +func (sh *strictHandler) WorkflowScheduledDelete(ctx echo.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID) error { + var request WorkflowScheduledDeleteRequestObject + + request.Tenant = tenant + request.ScheduledId = scheduledId + + handler := func(ctx echo.Context, request interface{}) (interface{}, error) { + return sh.ssi.WorkflowScheduledDelete(ctx, request.(WorkflowScheduledDeleteRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "WorkflowScheduledDelete") + } + + response, err := handler(ctx, request) + + if err != nil { + return err + } else if validResponse, ok := response.(WorkflowScheduledDeleteResponseObject); ok { + return validResponse.VisitWorkflowScheduledDeleteResponse(ctx.Response()) + } else if response != nil { + return fmt.Errorf("Unexpected response type: %T", response) + } + return nil +} + +// WorkflowScheduledGet operation middleware +func (sh *strictHandler) WorkflowScheduledGet(ctx echo.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID) error { + var request WorkflowScheduledGetRequestObject + + request.Tenant = tenant + request.ScheduledId = scheduledId + + handler := func(ctx echo.Context, request interface{}) (interface{}, error) { + return sh.ssi.WorkflowScheduledGet(ctx, request.(WorkflowScheduledGetRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "WorkflowScheduledGet") + } + + response, err := handler(ctx, request) + + if err != nil { + return err + } else if validResponse, ok := response.(WorkflowScheduledGetResponseObject); ok { + return validResponse.VisitWorkflowScheduledGetResponse(ctx.Response()) + } else if response != nil { + return fmt.Errorf("Unexpected response type: %T", response) + } + return nil +} + // WorkflowGetWorkersCount operation middleware func (sh *strictHandler) WorkflowGetWorkersCount(ctx echo.Context, tenant openapi_types.UUID, workflow openapi_types.UUID) error { var request WorkflowGetWorkersCountRequestObject @@ -10051,27 +10251,28 @@ var swaggerSpec = []string{ "GkUBbZgAkmJolcZftl3lNByzvuJcsgHuDoW+FVSsYWOQvqHQr4fm1StfBC2gA6YU0NLr+QPA0pldXYJ7", "fHh8tHdI/3d1ePiR/e9/DLgX3ft0Aj3x+oDAPQqFa1uVhkI8gdMogdsE+RObYZMwV2B5ikKE56vDLPvv", "FM+bAnqjmN7eZaKsub/Zq8Sy7thdJF7ZReLAJi0ccARo9KArsr+aJ87SE+Y1Fzbq1PBODd+9Gt7plp1u", - "+SI+cHjNQmBMAHUJK1/ofKcg+mlAj8Uaa2HWchW74Vh27qyH3QNW94C1nTtnxmTdK5YRI90N9LWdUJl/", - "tsyhsOdFaUhqLqOsjfT0lUkVwD1AAZgEkB1aclzjofUFEh77jk/YjK/eKbvOIfuVu1kWNmtFHuekwsmn", - "43UDrxeQtFqYRpH9UwwTfOClSQKrOZsXeBINHdpNW+LpCyQnYrAt0h0rZdSMzhjEXXqfl0/vY1vJitL9", - "ErkVK1mVyXiGyDydHHggCCZVBQRPIqqgEtigaNkXNjSrWnYih29cFMwT826jLFgBd3KBVYXAjOjbbLU3", - "BXGy3FtrSqk1q5ymQVgUzQK4HXpjQ//i9MbRt2F6yxH3y9EbCu8RgTbpPqU2zDtkdYJqj286Ai+NMhRz", - "bb0ED5+oaV3r4gI7fdH6WGURb0vYK5fFMdLeAfA8GJOK6hXsO84Mk2ISQ20qvvm8j7ud4Bc+OJ+oPh1l", - "BfXxlevor6sQnddkYEgq7b09fSWQBeJU5Kmj35vRF+/jbivrGx18A/TFV97RV01OfoqkFegriGaookjH", - "WTTDDgodwM7G/QoF44wNtB1aYkcwHX9HeXOt7tFBNJtB30Fdccp2XZ+LxzqlGtt7chDNopTUMEOUEjtu", - "iNKXt/UIGo1alkWqI9IaZZRRjy3ZLuBiAhM8R3GDK5DSye4axI+Q73k38XC+VQLXT9r8PqSiqLsTrXIn", - "UjFYT5IxwPghSnyzLOViUkhSR7avEqmXcszt6RgncxDOsonapGx4DDI/Q1Qnzl+ROOdkVaR0CyZK4IwK", - "sqTq0sdb4EqNJCvAsS22kWC0iWEk8rpnrlehp0sSstV5cAC8u628MIzpyC1+YKgRNQ1fHJYqZh38FD88", - "8xXSocprPYUcp7Wlf3hDGzcVWSrK6BCSTbRjf5CqcrQw3+OuUE4LC+Vw8rMolNPL6MuOOQ4Enm3uW7Kp", - "zJpXzTHiCMW2Xsmt5ZvN168SqFmlAF22XR17trQCXb5FTXk04032h01BDY1xg1OYZeEM4WxW5bvIpni9", - "5atW8FVsmXrdmrpVDcpW9STpsKKLgHjzCrNJJSHzVq+GlrdwK2UIKJwbVcWm6L1Domx39aUseY1D1nGa", - "ntMEQ6zDbEunybKTf/1NSE2GbBV81uBe1EpP+fdNbkYSwC7L946yfJ8bknoLYlUoZkU/+Z5VqRErTmig", - "cr2FgJEVg0Q63npp3lKjUdZhLBu1z567mumBrWCw7WX5ltVY7TJ8c62ryGW7Vg6tJMKyetjJA6OCuB5z", - "1qiJVjmJ6CYVkw9ljHcPE8xjmI0nZYMcRG3gZ03MPM+wuIEkjaunaNQDNkuiNGYR/DkIcqOMoLBO3+BT", - "AZiXUBvWTHgiSK/LedJGbSLbla0JLpKg2azKzeCKN3CAE8KH1WoJZj4Ir1NyXWnYZd8ZTpl1G6eUOqDf", - "E0W8CMQk4ymEnSkk3hz6pnwlueBvuSIlyEDZVVtlqlRl8CU0KZtSyyLBVVcWsQ0isXW14qUcrCkKaVv4", - "1UI0C9mAbcu7SqljJZb/4I1fkQnmV5DLW5ZyYlPXVAU7edcqFTAnxVVVwGUfsgkECUwyH7Ke1qsMJvdS", - "HqRJ4H503ecfz/8/AAD//z6iua4v2wEA", + "+SI+cHjNQmBMAHUJK1/ofKcg+mlAj8Uaa2HWchW74Vh27qyH3QNW94C1nTtnxmTdK5YRI90N9NWeUAc/", + "sz+Hvl0Nbv2Z1fDIeuV1uTU4MKYuy/G7+wrdlqW09VvaVUdbrm1tUR3Nhkd7lRafTbDXq0423n7e2uZh", + "2h2kryEM4WWP7yy8SqZA2vOiNCQ1tmTWRgbqyJxI4B6gAEwCyCSMHNcoYb5AwlPX4BM246uPqaqLp3rl", + "URKFzVpRsnBS4eTTqeoGXi8gabUoyyL7pxgm+MBLkwRWczavzygaOrSbtkLjF0hOxGBbpDtWibAZnTGI", + "u+x8L5+dz7YQJaX7JXIrFqIsk/EMkXk6OfBAEEyq6v+eRIuYatoNao5+YUOzoqMncvjGNT09Me82qnoW", + "cCcXWFXH04i+zRZrVRAnq7W2phJqs8KnGoRF0SyA26E3NvQvTm8cfRumtxxxvxy9ofAeEWiTrVtqw7xD", + "Vuav9vimI/DKZkMx19Yr6PGJrIy7AcKkWGlfYqTTF22PVRawvoS9clU7I+0dAM+DMakoPsW+48yKJCYx", + "lJbkm8/7uNuJXeWD84nqs0lXUB9fuY7+OhNmXlKJIam09/b0lUAWR1uRZpZ+b0ZfvI+7raStdPAN0Bdf", + "eUdfNSV1KJJWoK8gmqGKGltn0Qw7KHQAOxv3KxSMMzbQdmiJHcF0/B2lvbe6RwfRbAZ9B3W1pdt1fS4e", + "65RqbO/JQTSLUlLDDFFK7LghSl/e1iNoNGpZEsiOSGuUUUY9tmS7gIsJTPAcxQ2uQEonu2sQP0K+592E", + "39tWCVw/afP7kIqi7k60yp1IxWA9ScYA44co8c2ylItJIUkd2b5KpF7KMbenY5zMQTjLJmqTsuExyPwM", + "UZ04f0XinJNVkdItmCiBMyrIkqpLH2+BKzWSrH7WtthGgtEmhpHI6565XoWeLknIVufBAfDutvLCMKYj", + "t/iBoUbUNHxxWCp4efBT/GDhjGpRuc/ez1RWejQ6hGQT7dgfxNKHs6tz18I6d5nTdF2du15GX3bMcSDw", + "bHPfkk1l0ttqjhFHKLYNKmot32y+/KRAzSr1Y7Pt6tizpQVk8y1qyqMZb7I/bOphaYwbnMIs/baFs1mV", + "7yKb4vVWn1zBV7Fl6nVryk42qDrZk6TDaiYD4s0rzCaVhMxbvRpa3sKtlCGgcG5U1Yqk9w6Jst2Vh7Tk", + "NQ5Zx2l6ThMMsQ6zLZ0my07+VmF5mSeyVaRQg3tRKz3lm0S3ZQB20TE7io45N9TkEMSqUMyKfvI9q0ph", + "VpzQQOV6CwEjKwaJdLz10rylRqOsw1g2ap89dzXTA1vBYNsr0iGLqdsV6OBaV5HLdq0cWkmEZfWwkwdG", + "BXE95qxRE61SCtJNKuYOzBjvHiaYpyAxnpQNUgi2gZ81KW94guQN5FhePcOyHjCWSIAl4MlBkBtlBIV1", + "+gafCsC8hNqwZr4yQXpdyrI2ahPZrmxNcJEEzWZVbgZXvIEDnBA+rFYKOPNBeJ2S60rDLvvOcMqs2zil", + "1AH9nqjBSSAmGU8h7Ewh8ebQN6UbywV/yxUpQQbKrtoqU6UiwS+hSY3SsN7Niuen7Koat0Ek9tz3x//Y", + "zawjIUNFWkL46EHolx6spBysqelsW7fdQjQL2YBtq7NLqWMllv/gjV+RCeZXkMtblnJiU9dUBTt51yoV", + "MCfFVVXAZR+yCQQJTDIfsp7Wqwwm91IepEngfnTd5x/P/z8AAP//PplguO7iAQA=", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/frontend/app/src/lib/api/generated/Api.ts b/frontend/app/src/lib/api/generated/Api.ts index 2c04161e8..807831088 100644 --- a/frontend/app/src/lib/api/generated/Api.ts +++ b/frontend/app/src/lib/api/generated/Api.ts @@ -51,6 +51,7 @@ import { ReplayWorkflowRunsRequest, ReplayWorkflowRunsResponse, RerunStepRunRequest, + ScheduledWorkflows, ScheduledWorkflowsList, ScheduledWorkflowsOrderByField, SNSIntegration, @@ -1168,6 +1169,39 @@ export class Api extends HttpClient + this.request({ + path: `/api/v1/tenants/${tenant}/workflows/scheduled/${scheduledId}`, + method: 'GET', + secure: true, + format: 'json', + ...params, + }); + /** + * @description Delete a scheduled workflow run for a tenant + * + * @tags Workflow + * @name WorkflowScheduledDelete + * @summary Delete tenant alert email group + * @request DELETE:/api/v1/tenants/{tenant}/workflows/scheduled/{scheduledId} + * @secure + */ + workflowScheduledDelete = (tenant: string, scheduledId: string, params: RequestParams = {}) => + this.request({ + path: `/api/v1/tenants/${tenant}/workflows/scheduled/${scheduledId}`, + method: 'DELETE', + secure: true, + ...params, + }); /** * @description Get all cron job workflow runs for a tenant * diff --git a/frontend/app/src/pages/main/scheduled-runs/components/delete-scheduled-runs.tsx b/frontend/app/src/pages/main/scheduled-runs/components/delete-scheduled-runs.tsx new file mode 100644 index 000000000..8a6f93df7 --- /dev/null +++ b/frontend/app/src/pages/main/scheduled-runs/components/delete-scheduled-runs.tsx @@ -0,0 +1,114 @@ +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Spinner } from '@/components/ui/loading'; +import api, { ScheduledWorkflows } from '@/lib/api'; +import { useApiError } from '@/lib/hooks'; +import { useMutation } from '@tanstack/react-query'; + +interface DeleteScheduledRunFormProps { + isFutureRun: boolean; + className?: string; + onCancel: () => void; + isLoading: boolean; + onSubmit: () => void; +} + +export function DeleteScheduledRun({ + tenant, + scheduledRun, + setShowScheduledRunRevoke, + onSuccess, +}: { + tenant: string; + scheduledRun?: ScheduledWorkflows; + setShowScheduledRunRevoke: (show?: ScheduledWorkflows) => void; + onSuccess: () => void; +}) { + const { handleApiError } = useApiError({}); + + const deleteMutation = useMutation({ + mutationKey: ['scheduled-run:delete', tenant, scheduledRun], + mutationFn: async () => { + if (!scheduledRun) { + return; + } + await api.workflowScheduledDelete(tenant, scheduledRun.metadata.id); + }, + onSuccess: onSuccess, + onError: handleApiError, + }); + + return ( + + setShowScheduledRunRevoke(open ? scheduledRun : undefined) + } + > + deleteMutation.mutate()} + onCancel={() => setShowScheduledRunRevoke(undefined)} + isFutureRun={ + scheduledRun?.triggerAt + ? new Date(scheduledRun.triggerAt) > new Date() + : false + } + /> + + ); +} + +export function DeleteScheduledRunForm({ + className, + isFutureRun, + ...props +}: DeleteScheduledRunFormProps) { + return ( + + + Delete scheduled run + +
+
+ Are you sure you want to delete the scheduled run? + {isFutureRun ? ( + <> + This action will prevent the run from running in the future and + cannot be undone. + + ) : ( + <> + This action will delete the scheduled run trigger, but will not + affect the run itself and cannot be undone. + + )} +
+
+ + +
+
+
+ ); +} diff --git a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx index 620deeedd..3ab42933c 100644 --- a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx +++ b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-columns.tsx @@ -5,91 +5,120 @@ import RelativeDate from '@/components/molecules/relative-date'; import { AdditionalMetadata } from '../../events/components/additional-metadata'; import { RunStatus } from '../../workflow-runs/components/run-statuses'; import { Link } from 'react-router-dom'; - +import { DataTableRowActions } from '@/components/molecules/data-table/data-table-row-actions'; export type RateLimitRow = RateLimit & { metadata: { id: string; }; }; -export const columns: ColumnDef[] = [ - { - accessorKey: 'runId', - header: ({ column }) => ( - - ), - cell: ({ row }) => { - return row.original.workflowRunId ? ( - +export const columns = ({ + onDeleteClick, +}: { + onDeleteClick: (row: ScheduledWorkflows) => void; +}): ColumnDef[] => { + return [ + { + accessorKey: 'runId', + header: ({ column }) => ( + + ), + cell: ({ row }) => { + return row.original.workflowRunId ? ( + +
+ {row.original.workflowRunName} +
+ + ) : null; + }, + }, + { + accessorKey: 'status', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( + + ), + }, + { + accessorKey: 'triggerAt', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ +
+ ), + }, + { + accessorKey: 'Workflow', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
- {row.original.workflowRunName} + + {row.original.workflowName} +
- - ) : null; - }, - }, - { - accessorKey: 'status', - header: ({ column }) => ( - - ), - cell: ({ row }) => ( - - ), - }, - { - accessorKey: 'triggerAt', - header: ({ column }) => ( - - ), - cell: ({ row }) => ( -
- -
- ), - }, - { - accessorKey: 'Workflow', - header: ({ column }) => ( - - ), - cell: ({ row }) => ( - - ), - enableSorting: false, - enableHiding: true, - }, - { - accessorKey: 'Metadata', - header: ({ column }) => ( - - ), - cell: ({ row }) => { - if (!row.original.additionalMetadata) { - return
; - } + ), + enableSorting: false, + enableHiding: true, + }, + { + accessorKey: 'Metadata', + header: ({ column }) => ( + + ), + cell: ({ row }) => { + if (!row.original.additionalMetadata) { + return
; + } - return ; + return ( + + ); + }, + enableSorting: false, + }, + { + accessorKey: 'createdAt', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ +
+ ), + enableSorting: true, + enableHiding: true, }, - enableSorting: false, - }, - { - accessorKey: 'createdAt', - header: ({ column }) => ( - - ), - cell: ({ row }) => ( -
- -
- ), - enableSorting: true, - enableHiding: true, - }, -]; + { + accessorKey: 'actions', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ onDeleteClick(row.original), + }, + ]} + /> +
+ ), + enableHiding: true, + enableSorting: false, + }, + ]; +}; diff --git a/frontend/app/src/pages/main/scheduled-runs/index.tsx b/frontend/app/src/pages/main/scheduled-runs/index.tsx index 5c0388506..e0112f0b6 100644 --- a/frontend/app/src/pages/main/scheduled-runs/index.tsx +++ b/frontend/app/src/pages/main/scheduled-runs/index.tsx @@ -1,5 +1,6 @@ import { DataTable } from '../../../components/molecules/data-table/data-table'; import { columns } from './components/scheduled-runs-columns'; +import { DeleteScheduledRun } from './components/delete-scheduled-runs'; import { Separator } from '@/components/ui/separator'; import { useEffect, useMemo, useState } from 'react'; import { @@ -11,6 +12,7 @@ import { } from '@tanstack/react-table'; import { useQuery } from '@tanstack/react-query'; import { + ScheduledWorkflows, ScheduledWorkflowsOrderByField, WorkflowRunOrderByDirection, queries, @@ -147,29 +149,46 @@ function ScheduledRunsTable() { refetchInterval: 2000, }); + const [showScheduledRunRevoke, setShowScheduledRunRevoke] = + useState(); + return ( - row.metadata.id} - /> + <> + { + setShowScheduledRunRevoke(undefined); + }} + /> + { + setShowScheduledRunRevoke(row); + }, + })} + data={data?.rows || []} + filters={[]} + showColumnToggle={true} + columnVisibility={columnVisibility} + setColumnVisibility={setColumnVisibility} + sorting={sorting} + setSorting={setSorting} + search={search} + setSearch={setSearch} + columnFilters={columnFilters} + setColumnFilters={setColumnFilters} + pagination={pagination} + setPagination={setPagination} + onSetPageSize={setPageSize} + pageCount={data?.pagination?.num_pages || 0} + rowSelection={rowSelection} + setRowSelection={setRowSelection} + getRowId={(row) => row.metadata.id} + /> + ); } diff --git a/pkg/client/rest/gen.go b/pkg/client/rest/gen.go index d0940e417..2b6bd19f7 100644 --- a/pkg/client/rest/gen.go +++ b/pkg/client/rest/gen.go @@ -1998,6 +1998,12 @@ type ClientInterface interface { // WorkflowScheduledList request WorkflowScheduledList(ctx context.Context, tenant openapi_types.UUID, params *WorkflowScheduledListParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // WorkflowScheduledDelete request + WorkflowScheduledDelete(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) + + // WorkflowScheduledGet request + WorkflowScheduledGet(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) + // WorkflowGetWorkersCount request WorkflowGetWorkersCount(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -3014,6 +3020,30 @@ func (c *Client) WorkflowScheduledList(ctx context.Context, tenant openapi_types return c.Client.Do(req) } +func (c *Client) WorkflowScheduledDelete(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewWorkflowScheduledDeleteRequest(c.Server, tenant, scheduledId) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) WorkflowScheduledGet(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewWorkflowScheduledGetRequest(c.Server, tenant, scheduledId) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) WorkflowGetWorkersCount(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewWorkflowGetWorkersCountRequest(c.Server, tenant, workflow) if err != nil { @@ -6792,6 +6822,88 @@ func NewWorkflowScheduledListRequest(server string, tenant openapi_types.UUID, p return req, nil } +// NewWorkflowScheduledDeleteRequest generates requests for WorkflowScheduledDelete +func NewWorkflowScheduledDeleteRequest(server string, tenant openapi_types.UUID, scheduledId openapi_types.UUID) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "tenant", runtime.ParamLocationPath, tenant) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "scheduledId", runtime.ParamLocationPath, scheduledId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/api/v1/tenants/%s/workflows/scheduled/%s", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("DELETE", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewWorkflowScheduledGetRequest generates requests for WorkflowScheduledGet +func NewWorkflowScheduledGetRequest(server string, tenant openapi_types.UUID, scheduledId openapi_types.UUID) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "tenant", runtime.ParamLocationPath, tenant) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "scheduledId", runtime.ParamLocationPath, scheduledId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/api/v1/tenants/%s/workflows/scheduled/%s", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewWorkflowGetWorkersCountRequest generates requests for WorkflowGetWorkersCount func NewWorkflowGetWorkersCountRequest(server string, tenant openapi_types.UUID, workflow openapi_types.UUID) (*http.Request, error) { var err error @@ -7995,6 +8107,12 @@ type ClientWithResponsesInterface interface { // WorkflowScheduledListWithResponse request WorkflowScheduledListWithResponse(ctx context.Context, tenant openapi_types.UUID, params *WorkflowScheduledListParams, reqEditors ...RequestEditorFn) (*WorkflowScheduledListResponse, error) + // WorkflowScheduledDeleteWithResponse request + WorkflowScheduledDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowScheduledDeleteResponse, error) + + // WorkflowScheduledGetWithResponse request + WorkflowScheduledGetWithResponse(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowScheduledGetResponse, error) + // WorkflowGetWorkersCountWithResponse request WorkflowGetWorkersCountWithResponse(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowGetWorkersCountResponse, error) @@ -9558,6 +9676,54 @@ func (r WorkflowScheduledListResponse) StatusCode() int { return 0 } +type WorkflowScheduledDeleteResponse struct { + Body []byte + HTTPResponse *http.Response + JSON400 *APIErrors + JSON403 *APIError +} + +// Status returns HTTPResponse.Status +func (r WorkflowScheduledDeleteResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r WorkflowScheduledDeleteResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type WorkflowScheduledGetResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *ScheduledWorkflows + JSON400 *APIErrors + JSON403 *APIErrors + JSON404 *APIErrors +} + +// Status returns HTTPResponse.Status +func (r WorkflowScheduledGetResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r WorkflowScheduledGetResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type WorkflowGetWorkersCountResponse struct { Body []byte HTTPResponse *http.Response @@ -10829,6 +10995,24 @@ func (c *ClientWithResponses) WorkflowScheduledListWithResponse(ctx context.Cont return ParseWorkflowScheduledListResponse(rsp) } +// WorkflowScheduledDeleteWithResponse request returning *WorkflowScheduledDeleteResponse +func (c *ClientWithResponses) WorkflowScheduledDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowScheduledDeleteResponse, error) { + rsp, err := c.WorkflowScheduledDelete(ctx, tenant, scheduledId, reqEditors...) + if err != nil { + return nil, err + } + return ParseWorkflowScheduledDeleteResponse(rsp) +} + +// WorkflowScheduledGetWithResponse request returning *WorkflowScheduledGetResponse +func (c *ClientWithResponses) WorkflowScheduledGetWithResponse(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowScheduledGetResponse, error) { + rsp, err := c.WorkflowScheduledGet(ctx, tenant, scheduledId, reqEditors...) + if err != nil { + return nil, err + } + return ParseWorkflowScheduledGetResponse(rsp) +} + // WorkflowGetWorkersCountWithResponse request returning *WorkflowGetWorkersCountResponse func (c *ClientWithResponses) WorkflowGetWorkersCountWithResponse(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowGetWorkersCountResponse, error) { rsp, err := c.WorkflowGetWorkersCount(ctx, tenant, workflow, reqEditors...) @@ -13574,6 +13758,86 @@ func ParseWorkflowScheduledListResponse(rsp *http.Response) (*WorkflowScheduledL return response, nil } +// ParseWorkflowScheduledDeleteResponse parses an HTTP response from a WorkflowScheduledDeleteWithResponse call +func ParseWorkflowScheduledDeleteResponse(rsp *http.Response) (*WorkflowScheduledDeleteResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &WorkflowScheduledDeleteResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest APIError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + } + + return response, nil +} + +// ParseWorkflowScheduledGetResponse parses an HTTP response from a WorkflowScheduledGetWithResponse call +func ParseWorkflowScheduledGetResponse(rsp *http.Response) (*WorkflowScheduledGetResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &WorkflowScheduledGetResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest ScheduledWorkflows + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + } + + return response, nil +} + // ParseWorkflowGetWorkersCountResponse parses an HTTP response from a WorkflowGetWorkersCountWithResponse call func ParseWorkflowGetWorkersCountResponse(rsp *http.Response) (*WorkflowGetWorkersCountResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/pkg/repository/prisma/dbsqlc/workflow_runs.sql b/pkg/repository/prisma/dbsqlc/workflow_runs.sql index fec3fe15a..b7ca80873 100644 --- a/pkg/repository/prisma/dbsqlc/workflow_runs.sql +++ b/pkg/repository/prisma/dbsqlc/workflow_runs.sql @@ -1435,7 +1435,7 @@ LEFT JOIN "WorkflowRunTriggeredBy" tb ON t."id" = tb."scheduledId" LEFT JOIN "WorkflowRun" wr ON tb."parentId" = wr."id" WHERE v."deletedAt" IS NULL AND w."tenantId" = @tenantId::uuid - -- TODO page + AND (@scheduleId::uuid IS NULL OR t."id" = @scheduleId::uuid) ORDER BY case when @orderBy = 'triggerAt ASC' THEN t."triggerAt" END ASC , case when @orderBy = 'triggerAt DESC' THEN t."triggerAt" END DESC, @@ -1453,6 +1453,17 @@ OFFSET LIMIT COALESCE(sqlc.narg('limit'), 50); +-- name: UpdateScheduledWorkflow :exec +UPDATE "WorkflowTriggerScheduledRef" +SET "triggerAt" = @triggerAt::timestamp +WHERE + "id" = @scheduleId::uuid; + +-- name: DeleteScheduledWorkflow :exec +DELETE FROM "WorkflowTriggerScheduledRef" +WHERE + "id" = @scheduleId::uuid; + -- name: ListCronWorkflows :many SELECT w."name", diff --git a/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go b/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go index 9210bc848..f1777bb2f 100644 --- a/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go +++ b/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go @@ -1050,6 +1050,17 @@ type CreateWorkflowRunsParams struct { InsertOrder pgtype.Int4 `json:"insertOrder"` } +const deleteScheduledWorkflow = `-- name: DeleteScheduledWorkflow :exec +DELETE FROM "WorkflowTriggerScheduledRef" +WHERE + "id" = $1::uuid +` + +func (q *Queries) DeleteScheduledWorkflow(ctx context.Context, db DBTX, scheduleid pgtype.UUID) error { + _, err := db.Exec(ctx, deleteScheduledWorkflow, scheduleid) + return err +} + const getChildWorkflowRun = `-- name: GetChildWorkflowRun :one SELECT "createdAt", "updatedAt", "deletedAt", "tenantId", "workflowVersionId", status, error, "startedAt", "finishedAt", "concurrencyGroupId", "displayName", id, "childIndex", "childKey", "parentId", "parentStepRunId", "additionalMetadata", duration, priority, "insertOrder" @@ -2234,12 +2245,12 @@ LEFT JOIN "WorkflowRunTriggeredBy" tb ON t."id" = tb."scheduledId" LEFT JOIN "WorkflowRun" wr ON tb."parentId" = wr."id" WHERE v."deletedAt" IS NULL AND w."tenantId" = $1::uuid - -- TODO page + AND ($2::uuid IS NULL OR t."id" = $2::uuid) ORDER BY - case when $2 = 'triggerAt ASC' THEN t."triggerAt" END ASC , - case when $2 = 'triggerAt DESC' THEN t."triggerAt" END DESC, - case when $2 = 'createdAt ASC' THEN t."createdAt" END ASC , - case when $2 = 'createdAt DESC' THEN t."createdAt" END DESC, + case when $3 = 'triggerAt ASC' THEN t."triggerAt" END ASC , + case when $3 = 'triggerAt DESC' THEN t."triggerAt" END DESC, + case when $3 = 'createdAt ASC' THEN t."createdAt" END ASC , + case when $3 = 'createdAt DESC' THEN t."createdAt" END DESC, -- case when @orderBy = 'finishedAt ASC' THEN t."finishedAt" END ASC , -- case when @orderBy = 'finishedAt DESC' THEN t."finishedAt" END DESC, -- case when @orderBy = 'startedAt ASC' THEN t."startedAt" END ASC , @@ -2248,16 +2259,17 @@ ORDER BY -- case when @orderBy = 'duration DESC' THEN runs."duration" END DESC NULLS LAST, t."id" ASC OFFSET - COALESCE($3, 0) + COALESCE($4, 0) LIMIT - COALESCE($4, 50) + COALESCE($5, 50) ` type ListScheduledWorkflowsParams struct { - Tenantid pgtype.UUID `json:"tenantid"` - Orderby interface{} `json:"orderby"` - Offset interface{} `json:"offset"` - Limit interface{} `json:"limit"` + Tenantid pgtype.UUID `json:"tenantid"` + Scheduleid pgtype.UUID `json:"scheduleid"` + Orderby interface{} `json:"orderby"` + Offset interface{} `json:"offset"` + Limit interface{} `json:"limit"` } type ListScheduledWorkflowsRow struct { @@ -2287,6 +2299,7 @@ type ListScheduledWorkflowsRow struct { func (q *Queries) ListScheduledWorkflows(ctx context.Context, db DBTX, arg ListScheduledWorkflowsParams) ([]*ListScheduledWorkflowsRow, error) { rows, err := db.Query(ctx, listScheduledWorkflows, arg.Tenantid, + arg.Scheduleid, arg.Orderby, arg.Offset, arg.Limit, @@ -3064,6 +3077,23 @@ func (q *Queries) UpdateManyWorkflowRun(ctx context.Context, db DBTX, arg Update return items, nil } +const updateScheduledWorkflow = `-- name: UpdateScheduledWorkflow :exec +UPDATE "WorkflowTriggerScheduledRef" + SET "triggerAt" = $1::timestamp +WHERE + "id" = $2::uuid +` + +type UpdateScheduledWorkflowParams struct { + Triggerat pgtype.Timestamp `json:"triggerat"` + Scheduleid pgtype.UUID `json:"scheduleid"` +} + +func (q *Queries) UpdateScheduledWorkflow(ctx context.Context, db DBTX, arg UpdateScheduledWorkflowParams) error { + _, err := db.Exec(ctx, updateScheduledWorkflow, arg.Triggerat, arg.Scheduleid) + return err +} + const updateWorkflowRun = `-- name: UpdateWorkflowRun :one UPDATE "WorkflowRun" diff --git a/pkg/repository/prisma/workflow_run.go b/pkg/repository/prisma/workflow_run.go index 8b570e28e..fb1c9e59b 100644 --- a/pkg/repository/prisma/workflow_run.go +++ b/pkg/repository/prisma/workflow_run.go @@ -167,6 +167,37 @@ func (w *workflowRunAPIRepository) ListScheduledWorkflows(ctx context.Context, t return scheduledWorkflows, count, nil } +func (w *workflowRunAPIRepository) DeleteScheduledWorkflow(ctx context.Context, tenantId, scheduledWorkflowId string) error { + return w.queries.DeleteScheduledWorkflow(ctx, w.pool, sqlchelpers.UUIDFromStr(scheduledWorkflowId)) +} + +func (w *workflowRunAPIRepository) GetScheduledWorkflow(ctx context.Context, tenantId, scheduledWorkflowId string) (*dbsqlc.ListScheduledWorkflowsRow, error) { + + listOpts := dbsqlc.ListScheduledWorkflowsParams{ + Tenantid: sqlchelpers.UUIDFromStr(tenantId), + Scheduleid: sqlchelpers.UUIDFromStr(scheduledWorkflowId), + } + + scheduledWorkflows, err := w.queries.ListScheduledWorkflows(ctx, w.pool, listOpts) + if err != nil { + return nil, err + } + + if len(scheduledWorkflows) == 0 { + return nil, nil + } + + return scheduledWorkflows[0], nil + +} + +func (w *workflowRunAPIRepository) UpdateScheduledWorkflow(ctx context.Context, tenantId, scheduledWorkflowId string, triggerAt time.Time) error { + return w.queries.UpdateScheduledWorkflow(ctx, w.pool, dbsqlc.UpdateScheduledWorkflowParams{ + Scheduleid: sqlchelpers.UUIDFromStr(scheduledWorkflowId), + Triggerat: sqlchelpers.TimestampFromTime(triggerAt), + }) +} + func (w *workflowRunAPIRepository) ListCronWorkflows(ctx context.Context, tenantId string, opts *repository.ListCronWorkflowsOpts) ([]*dbsqlc.ListCronWorkflowsRow, int64, error) { ctx, cancel := context.WithTimeout(ctx, time.Second*30) diff --git a/pkg/repository/workflow_run.go b/pkg/repository/workflow_run.go index ea3410b31..bc992de0e 100644 --- a/pkg/repository/workflow_run.go +++ b/pkg/repository/workflow_run.go @@ -440,6 +440,15 @@ type WorkflowRunAPIRepository interface { // List ScheduledWorkflows lists workflows by scheduled trigger ListScheduledWorkflows(ctx context.Context, tenantId string, opts *ListScheduledWorkflowsOpts) ([]*dbsqlc.ListScheduledWorkflowsRow, int64, error) + // DeleteScheduledWorkflow deletes a scheduled workflow run + DeleteScheduledWorkflow(ctx context.Context, tenantId, scheduledWorkflowId string) error + + // GetScheduledWorkflow gets a scheduled workflow run + GetScheduledWorkflow(ctx context.Context, tenantId, scheduledWorkflowId string) (*dbsqlc.ListScheduledWorkflowsRow, error) + + // UpdateScheduledWorkflow updates a scheduled workflow run + UpdateScheduledWorkflow(ctx context.Context, tenantId, scheduledWorkflowId string, triggerAt time.Time) error + // List ScheduledWorkflows lists workflows by scheduled trigger ListCronWorkflows(ctx context.Context, tenantId string, opts *ListCronWorkflowsOpts) ([]*dbsqlc.ListCronWorkflowsRow, int64, error) From 3cae252e47d33632bdf7a74702cf2aeb01c4cc54 Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Fri, 25 Oct 2024 07:26:00 -0400 Subject: [PATCH 13/30] fix: remove search --- .../src/pages/main/scheduled-runs/index.tsx | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/frontend/app/src/pages/main/scheduled-runs/index.tsx b/frontend/app/src/pages/main/scheduled-runs/index.tsx index e0112f0b6..82ccf5e9f 100644 --- a/frontend/app/src/pages/main/scheduled-runs/index.tsx +++ b/frontend/app/src/pages/main/scheduled-runs/index.tsx @@ -41,9 +41,6 @@ function ScheduledRunsTable() { invariant(tenant); - const [search, setSearch] = useState( - searchParams.get('search') || undefined, - ); const [sorting, setSorting] = useState(() => { const sortParam = searchParams.get('sort'); if (sortParam) { @@ -75,11 +72,6 @@ function ScheduledRunsTable() { useEffect(() => { const newSearchParams = new URLSearchParams(searchParams); - if (search) { - newSearchParams.set('search', search); - } else { - newSearchParams.delete('search'); - } newSearchParams.set( 'sort', sorting.map((s) => `${s.id}:${s.desc ? 'desc' : 'asc'}`).join(','), @@ -88,14 +80,7 @@ function ScheduledRunsTable() { newSearchParams.set('pageIndex', pagination.pageIndex.toString()); newSearchParams.set('pageSize', pagination.pageSize.toString()); setSearchParams(newSearchParams); - }, [ - search, - sorting, - columnFilters, - pagination, - setSearchParams, - searchParams, - ]); + }, [sorting, columnFilters, pagination, setSearchParams, searchParams]); const orderByDirection = useMemo((): | WorkflowRunOrderByDirection @@ -177,8 +162,6 @@ function ScheduledRunsTable() { setColumnVisibility={setColumnVisibility} sorting={sorting} setSorting={setSorting} - search={search} - setSearch={setSearch} columnFilters={columnFilters} setColumnFilters={setColumnFilters} pagination={pagination} From 48dc2f9c3e8d0a862a545459099b70a2d524b128 Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Fri, 25 Oct 2024 08:25:35 -0400 Subject: [PATCH 14/30] feat: filterable scheduled --- .../openapi/components/schemas/_index.yaml | 2 + .../components/schemas/workflow_run.yaml | 11 + .../openapi/paths/workflow/workflow.yaml | 44 +- .../handlers/workflows/list_scheduled.go | 14 +- api/v1/server/oas/gen/openapi.gen.go | 455 ++++++++++-------- frontend/app/src/lib/api/generated/Api.ts | 25 +- .../src/lib/api/generated/data-contracts.ts | 10 + .../components/scheduled-runs-table.tsx | 365 ++++++++++++++ .../src/pages/main/scheduled-runs/index.tsx | 163 +------ pkg/client/rest/gen.go | 105 +++- .../prisma/dbsqlc/workflow_runs.sql | 54 ++- .../prisma/dbsqlc/workflow_runs.sql.go | 114 ++++- pkg/repository/prisma/workflow_run.go | 64 ++- pkg/repository/workflow_run.go | 12 + 14 files changed, 996 insertions(+), 442 deletions(-) create mode 100644 frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-table.tsx diff --git a/api-contracts/openapi/components/schemas/_index.yaml b/api-contracts/openapi/components/schemas/_index.yaml index 001f4fbea..6e6b9775c 100644 --- a/api-contracts/openapi/components/schemas/_index.yaml +++ b/api-contracts/openapi/components/schemas/_index.yaml @@ -158,6 +158,8 @@ ScheduledWorkflowsList: $ref: "./workflow_run.yaml#/ScheduledWorkflowsList" ScheduledWorkflowsOrderByField: $ref: "./workflow_run.yaml#/ScheduledWorkflowsOrderByField" +ScheduledRunStatus: + $ref: "./workflow_run.yaml#/ScheduledRunStatus" CronWorkflows: $ref: "./workflow_run.yaml#/CronWorkflows" CronWorkflowsList: diff --git a/api-contracts/openapi/components/schemas/workflow_run.yaml b/api-contracts/openapi/components/schemas/workflow_run.yaml index 9f7029265..36c58ee5a 100644 --- a/api-contracts/openapi/components/schemas/workflow_run.yaml +++ b/api-contracts/openapi/components/schemas/workflow_run.yaml @@ -316,6 +316,17 @@ WorkflowRunStatus: - CANCELLED - QUEUED +ScheduledRunStatus: + type: string + enum: + - PENDING + - RUNNING + - SUCCEEDED + - FAILED + - CANCELLED + - QUEUED + - SCHEDULED + WorkflowKind: type: string enum: diff --git a/api-contracts/openapi/paths/workflow/workflow.yaml b/api-contracts/openapi/paths/workflow/workflow.yaml index e465ef601..27df6a289 100644 --- a/api-contracts/openapi/paths/workflow/workflow.yaml +++ b/api-contracts/openapi/paths/workflow/workflow.yaml @@ -857,6 +857,18 @@ scheduledList: schema: type: integer format: int64 + - description: The order by field + in: query + name: orderByField + required: false + schema: + $ref: "../../components/schemas/_index.yaml#/ScheduledWorkflowsOrderByField" + - description: The order by direction + in: query + name: orderByDirection + required: false + schema: + $ref: "../../components/schemas/_index.yaml#/WorkflowRunOrderByDirection" - description: The workflow id to get runs for. in: query name: workflowId @@ -866,6 +878,24 @@ scheduledList: format: uuid minLength: 36 maxLength: 36 + - description: The parent workflow run id + in: query + name: parentWorkflowRunId + required: false + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + - description: The parent step run id + in: query + name: parentStepRunId + required: false + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 - description: A list of metadata key value pairs to filter by in: query name: additionalMetadata @@ -875,18 +905,14 @@ scheduledList: type: array items: type: string - - description: The order by field + - description: A list of scheduled run statuses to filter by in: query - name: orderByField - required: false - schema: - $ref: "../../components/schemas/_index.yaml#/ScheduledWorkflowsOrderByField" - - description: The order by direction - in: query - name: orderByDirection + name: statuses required: false schema: - $ref: "../../components/schemas/_index.yaml#/WorkflowRunOrderByDirection" + type: array + items: + $ref: "../../components/schemas/_index.yaml#/ScheduledRunStatus" responses: "200": content: diff --git a/api/v1/server/handlers/workflows/list_scheduled.go b/api/v1/server/handlers/workflows/list_scheduled.go index 1d4274829..cb766efbe 100644 --- a/api/v1/server/handlers/workflows/list_scheduled.go +++ b/api/v1/server/handlers/workflows/list_scheduled.go @@ -56,15 +56,15 @@ func (t *WorkflowService) WorkflowScheduledList(ctx echo.Context, request gen.Wo listOpts.WorkflowId = &workflowIdStr } - // if request.Params.Statuses != nil { - // statuses := make([]db.WorkflowRunStatus, len(*request.Params.Statuses)) + if request.Params.Statuses != nil { + statuses := make([]db.WorkflowRunStatus, len(*request.Params.Statuses)) - // for i, status := range *request.Params.Statuses { - // statuses[i] = db.WorkflowRunStatus(status) - // } + for i, status := range *request.Params.Statuses { + statuses[i] = db.WorkflowRunStatus(status) + } - // listOpts.Statuses = &statuses - // } + listOpts.Statuses = &statuses + } if request.Params.AdditionalMetadata != nil { additionalMetadata := make(map[string]interface{}, len(*request.Params.AdditionalMetadata)) diff --git a/api/v1/server/oas/gen/openapi.gen.go b/api/v1/server/oas/gen/openapi.gen.go index 1c5ef45b5..4222f9e34 100644 --- a/api/v1/server/oas/gen/openapi.gen.go +++ b/api/v1/server/oas/gen/openapi.gen.go @@ -83,6 +83,17 @@ const ( Value RateLimitOrderByField = "value" ) +// Defines values for ScheduledRunStatus. +const ( + ScheduledRunStatusCANCELLED ScheduledRunStatus = "CANCELLED" + ScheduledRunStatusFAILED ScheduledRunStatus = "FAILED" + ScheduledRunStatusPENDING ScheduledRunStatus = "PENDING" + ScheduledRunStatusQUEUED ScheduledRunStatus = "QUEUED" + ScheduledRunStatusRUNNING ScheduledRunStatus = "RUNNING" + ScheduledRunStatusSCHEDULED ScheduledRunStatus = "SCHEDULED" + ScheduledRunStatusSUCCEEDED ScheduledRunStatus = "SUCCEEDED" +) + // Defines values for ScheduledWorkflowsOrderByField. const ( ScheduledWorkflowsOrderByFieldCreatedAt ScheduledWorkflowsOrderByField = "createdAt" @@ -190,12 +201,12 @@ const ( // Defines values for WorkflowRunStatus. const ( - WorkflowRunStatusCANCELLED WorkflowRunStatus = "CANCELLED" - WorkflowRunStatusFAILED WorkflowRunStatus = "FAILED" - WorkflowRunStatusPENDING WorkflowRunStatus = "PENDING" - WorkflowRunStatusQUEUED WorkflowRunStatus = "QUEUED" - WorkflowRunStatusRUNNING WorkflowRunStatus = "RUNNING" - WorkflowRunStatusSUCCEEDED WorkflowRunStatus = "SUCCEEDED" + CANCELLED WorkflowRunStatus = "CANCELLED" + FAILED WorkflowRunStatus = "FAILED" + PENDING WorkflowRunStatus = "PENDING" + QUEUED WorkflowRunStatus = "QUEUED" + RUNNING WorkflowRunStatus = "RUNNING" + SUCCEEDED WorkflowRunStatus = "SUCCEEDED" ) // APIError defines model for APIError. @@ -643,6 +654,9 @@ type SNSIntegration struct { TopicArn string `json:"topicArn"` } +// ScheduledRunStatus defines model for ScheduledRunStatus. +type ScheduledRunStatus string + // ScheduledWorkflows defines model for ScheduledWorkflows. type ScheduledWorkflows struct { AdditionalMetadata *map[string]interface{} `json:"additionalMetadata,omitempty"` @@ -1607,17 +1621,26 @@ type WorkflowScheduledListParams struct { // Limit The number to limit by Limit *int64 `form:"limit,omitempty" json:"limit,omitempty"` + // OrderByField The order by field + OrderByField *ScheduledWorkflowsOrderByField `form:"orderByField,omitempty" json:"orderByField,omitempty"` + + // OrderByDirection The order by direction + OrderByDirection *WorkflowRunOrderByDirection `form:"orderByDirection,omitempty" json:"orderByDirection,omitempty"` + // WorkflowId The workflow id to get runs for. WorkflowId *openapi_types.UUID `form:"workflowId,omitempty" json:"workflowId,omitempty"` + // ParentWorkflowRunId The parent workflow run id + ParentWorkflowRunId *openapi_types.UUID `form:"parentWorkflowRunId,omitempty" json:"parentWorkflowRunId,omitempty"` + + // ParentStepRunId The parent step run id + ParentStepRunId *openapi_types.UUID `form:"parentStepRunId,omitempty" json:"parentStepRunId,omitempty"` + // AdditionalMetadata A list of metadata key value pairs to filter by AdditionalMetadata *[]string `form:"additionalMetadata,omitempty" json:"additionalMetadata,omitempty"` - // OrderByField The order by field - OrderByField *ScheduledWorkflowsOrderByField `form:"orderByField,omitempty" json:"orderByField,omitempty"` - - // OrderByDirection The order by direction - OrderByDirection *WorkflowRunOrderByDirection `form:"orderByDirection,omitempty" json:"orderByDirection,omitempty"` + // Statuses A list of scheduled run statuses to filter by + Statuses *[]ScheduledRunStatus `form:"statuses,omitempty" json:"statuses,omitempty"` } // WorkflowGetMetricsParams defines parameters for WorkflowGetMetrics. @@ -3661,6 +3684,20 @@ func (w *ServerInterfaceWrapper) WorkflowScheduledList(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } + // ------------- Optional query parameter "orderByField" ------------- + + err = runtime.BindQueryParameter("form", true, false, "orderByField", ctx.QueryParams(), ¶ms.OrderByField) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderByField: %s", err)) + } + + // ------------- Optional query parameter "orderByDirection" ------------- + + err = runtime.BindQueryParameter("form", true, false, "orderByDirection", ctx.QueryParams(), ¶ms.OrderByDirection) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderByDirection: %s", err)) + } + // ------------- Optional query parameter "workflowId" ------------- err = runtime.BindQueryParameter("form", true, false, "workflowId", ctx.QueryParams(), ¶ms.WorkflowId) @@ -3668,25 +3705,32 @@ func (w *ServerInterfaceWrapper) WorkflowScheduledList(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter workflowId: %s", err)) } - // ------------- Optional query parameter "additionalMetadata" ------------- + // ------------- Optional query parameter "parentWorkflowRunId" ------------- - err = runtime.BindQueryParameter("form", true, false, "additionalMetadata", ctx.QueryParams(), ¶ms.AdditionalMetadata) + err = runtime.BindQueryParameter("form", true, false, "parentWorkflowRunId", ctx.QueryParams(), ¶ms.ParentWorkflowRunId) if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter additionalMetadata: %s", err)) + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter parentWorkflowRunId: %s", err)) } - // ------------- Optional query parameter "orderByField" ------------- + // ------------- Optional query parameter "parentStepRunId" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderByField", ctx.QueryParams(), ¶ms.OrderByField) + err = runtime.BindQueryParameter("form", true, false, "parentStepRunId", ctx.QueryParams(), ¶ms.ParentStepRunId) if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderByField: %s", err)) + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter parentStepRunId: %s", err)) } - // ------------- Optional query parameter "orderByDirection" ------------- + // ------------- Optional query parameter "additionalMetadata" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderByDirection", ctx.QueryParams(), ¶ms.OrderByDirection) + err = runtime.BindQueryParameter("form", true, false, "additionalMetadata", ctx.QueryParams(), ¶ms.AdditionalMetadata) if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderByDirection: %s", err)) + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter additionalMetadata: %s", err)) + } + + // ------------- Optional query parameter "statuses" ------------- + + err = runtime.BindQueryParameter("form", true, false, "statuses", ctx.QueryParams(), ¶ms.Statuses) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter statuses: %s", err)) } // Invoke the callback with all the unmarshaled arguments @@ -10088,191 +10132,192 @@ func (sh *strictHandler) WorkflowVersionGet(ctx echo.Context, workflow openapi_t // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", + "X368/P8AAAD//14C8qdU5QEA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/frontend/app/src/lib/api/generated/Api.ts b/frontend/app/src/lib/api/generated/Api.ts index 807831088..fca7a1536 100644 --- a/frontend/app/src/lib/api/generated/Api.ts +++ b/frontend/app/src/lib/api/generated/Api.ts @@ -51,6 +51,7 @@ import { ReplayWorkflowRunsRequest, ReplayWorkflowRunsResponse, RerunStepRunRequest, + ScheduledRunStatus, ScheduledWorkflows, ScheduledWorkflowsList, ScheduledWorkflowsOrderByField, @@ -1142,6 +1143,10 @@ export class Api extends HttpClient extends HttpClient diff --git a/frontend/app/src/lib/api/generated/data-contracts.ts b/frontend/app/src/lib/api/generated/data-contracts.ts index e2360d7c1..1ca0db577 100644 --- a/frontend/app/src/lib/api/generated/data-contracts.ts +++ b/frontend/app/src/lib/api/generated/data-contracts.ts @@ -793,6 +793,16 @@ export enum ScheduledWorkflowsOrderByField { CreatedAt = 'createdAt', } +export enum ScheduledRunStatus { + PENDING = 'PENDING', + RUNNING = 'RUNNING', + SUCCEEDED = 'SUCCEEDED', + FAILED = 'FAILED', + CANCELLED = 'CANCELLED', + QUEUED = 'QUEUED', + SCHEDULED = 'SCHEDULED', +} + export interface CronWorkflows { metadata: APIResourceMeta; tenantId: string; diff --git a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-table.tsx b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-table.tsx new file mode 100644 index 000000000..3251f76a0 --- /dev/null +++ b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-table.tsx @@ -0,0 +1,365 @@ +import { DataTable } from '@/components/molecules/data-table/data-table.tsx'; +import { useEffect, useMemo, useState } from 'react'; +import { + ColumnFiltersState, + PaginationState, + RowSelectionState, + SortingState, + VisibilityState, +} from '@tanstack/react-table'; +import { useMutation, useQuery } from '@tanstack/react-query'; +import invariant from 'tiny-invariant'; +import api, { + ReplayWorkflowRunsRequest, + ScheduledRunStatus, + ScheduledWorkflows, + ScheduledWorkflowsOrderByField, + WorkflowRunOrderByDirection, + queries, +} from '@/lib/api'; +import { TenantContextType } from '@/lib/outlet'; +import { useOutletContext, useSearchParams } from 'react-router-dom'; +import { + FilterOption, + ToolbarFilters, + ToolbarType, +} from '@/components/molecules/data-table/data-table-toolbar'; +import { Button } from '@/components/ui/button'; +import { ArrowPathIcon } from '@heroicons/react/24/outline'; +import queryClient from '@/query-client'; +import { useApiError } from '@/lib/hooks'; +import { columns } from './scheduled-runs-columns'; +import { DeleteScheduledRun } from './delete-scheduled-runs'; + +export interface ScheduledWorkflowRunsTableProps { + createdAfter?: string; + createdBefore?: string; + workflowId?: string; + parentWorkflowRunId?: string; + parentStepRunId?: string; + initColumnVisibility?: VisibilityState; + filterVisibility?: { [key: string]: boolean }; + refetchInterval?: number; + showMetrics?: boolean; +} + +export function ScheduledRunsTable({ + workflowId, + initColumnVisibility = {}, + filterVisibility = {}, + parentWorkflowRunId, + parentStepRunId, + refetchInterval = 5000, +}: ScheduledWorkflowRunsTableProps) { + const [searchParams, setSearchParams] = useSearchParams(); + const { tenant } = useOutletContext(); + invariant(tenant); + + const [sorting, setSorting] = useState(() => { + const sortParam = searchParams.get('sort'); + if (sortParam) { + return sortParam.split(',').map((param) => { + const [id, desc] = param.split(':'); + return { id, desc: desc === 'desc' }; + }); + } + return []; + }); + + const [columnFilters, setColumnFilters] = useState(() => { + const filtersParam = searchParams.get('filters'); + if (filtersParam) { + return JSON.parse(filtersParam); + } + return []; + }); + + const [columnVisibility, setColumnVisibility] = + useState(initColumnVisibility); + + const [pagination, setPagination] = useState(() => { + const pageIndex = Number(searchParams.get('pageIndex')) || 0; + const pageSize = Number(searchParams.get('pageSize')) || 50; + return { pageIndex, pageSize }; + }); + + useEffect(() => { + const newSearchParams = new URLSearchParams(searchParams); + if (sorting.length) { + newSearchParams.set( + 'orderDirection', + sorting.map((s) => `${s.id}:${s.desc ? 'desc' : 'asc'}`).join(','), + ); + } else { + newSearchParams.delete('orderDirection'); + } + if (columnFilters.length) { + newSearchParams.set('filters', JSON.stringify(columnFilters)); + } else { + newSearchParams.delete('filters'); + } + newSearchParams.set('pageIndex', pagination.pageIndex.toString()); + newSearchParams.set('pageSize', pagination.pageSize.toString()); + + if (newSearchParams.toString() !== searchParams.toString()) { + setSearchParams(newSearchParams, { replace: true }); + } + }, [sorting, columnFilters, pagination, setSearchParams, searchParams]); + + const [pageSize, setPageSize] = useState(50); + + const offset = useMemo(() => { + if (!pagination) { + return; + } + + return pagination.pageIndex * pagination.pageSize; + }, [pagination]); + + const workflow = useMemo(() => { + if (workflowId) { + return workflowId; + } + + const filter = columnFilters.find((filter) => filter.id === 'Workflow'); + + if (!filter) { + return; + } + + const vals = filter?.value as Array; + return vals[0]; + }, [columnFilters, workflowId]); + + const statuses = useMemo(() => { + const filter = columnFilters.find((filter) => filter.id === 'status'); + + if (!filter) { + return; + } + + return filter?.value as Array; + }, [columnFilters]); + + const AdditionalMetadataFilter = useMemo(() => { + const filter = columnFilters.find((filter) => filter.id === 'Metadata'); + + if (!filter) { + return; + } + + return filter?.value as Array; + }, [columnFilters]); + + const orderByDirection = useMemo((): + | WorkflowRunOrderByDirection + | undefined => { + if (!sorting.length) { + return; + } + + return sorting[0]?.desc + ? WorkflowRunOrderByDirection.DESC + : WorkflowRunOrderByDirection.ASC; + }, [sorting]); + + const orderByField = useMemo((): + | ScheduledWorkflowsOrderByField + | undefined => { + if (!sorting.length) { + return; + } + + switch (sorting[0]?.id) { + case 'createdAt': + return ScheduledWorkflowsOrderByField.CreatedAt; + case 'triggerAt': + default: + return ScheduledWorkflowsOrderByField.TriggerAt; + } + }, [sorting]); + + const listWorkflowRunsQuery = useQuery({ + ...queries.scheduledRuns.list(tenant.metadata.id, { + offset, + limit: pageSize, + statuses, + workflowId: workflow, + parentWorkflowRunId, + parentStepRunId, + orderByDirection, + orderByField, + additionalMetadata: AdditionalMetadataFilter, + }), + placeholderData: (prev) => prev, + refetchInterval, + }); + + const { + data: workflowKeys, + isLoading: workflowKeysIsLoading, + error: workflowKeysError, + } = useQuery({ + ...queries.workflows.list(tenant.metadata.id), + }); + + const [rowSelection, setRowSelection] = useState({}); + + // const selectedRuns = useMemo(() => { + // return Object.entries(rowSelection) + // .filter(([, selected]) => !!selected) + // .map(([id]) => (listWorkflowRunsQuery.data?.rows || [])[Number(id)]); + // }, [listWorkflowRunsQuery.data?.rows, rowSelection]); + + // const { handleApiError } = useApiError({}); + + // const cancelWorkflowRunMutation = useMutation({ + // mutationKey: ['workflow-run:cancel', tenant.metadata.id, selectedRuns], + // mutationFn: async () => { + // const tenantId = tenant.metadata.id; + // const workflowRunIds = selectedRuns.map((wr) => wr.metadata.id); + + // invariant(tenantId, 'has tenantId'); + // invariant(workflowRunIds, 'has runIds'); + + // const res = await api.workflowRunCancel(tenantId, { + // workflowRunIds, + // }); + + // return res.data; + // }, + // onSuccess: () => { + // queryClient.invalidateQueries({ + // queryKey: queries.workflowRuns.list(tenant.metadata.id, {}).queryKey, + // }); + // }, + // onError: handleApiError, + // }); + + const workflowKeyFilters = useMemo((): FilterOption[] => { + return ( + workflowKeys?.rows?.map((key) => ({ + value: key.metadata.id, + label: key.name, + })) || [] + ); + }, [workflowKeys]); + + const workflowRunStatusFilters = useMemo((): FilterOption[] => { + return [ + { + value: ScheduledRunStatus.SCHEDULED, + label: 'Scheduled', + }, + { + value: ScheduledRunStatus.SUCCEEDED, + label: 'Succeeded', + }, + { + value: ScheduledRunStatus.FAILED, + label: 'Failed', + }, + { + value: ScheduledRunStatus.RUNNING, + label: 'Running', + }, + { + value: ScheduledRunStatus.QUEUED, + label: 'Queued', + }, + { + value: ScheduledRunStatus.PENDING, + label: 'Pending', + }, + ]; + }, []); + + const filters: ToolbarFilters = [ + { + columnId: 'Workflow', + title: 'Workflow', + options: workflowKeyFilters, + type: ToolbarType.Radio, + }, + { + columnId: 'status', + title: 'Status', + options: workflowRunStatusFilters, + }, + { + columnId: 'Metadata', + title: 'Metadata', + type: ToolbarType.KeyValue, + }, + ].filter((filter) => filterVisibility[filter.columnId] != false); + + const [rotate, setRotate] = useState(false); + + const refetch = () => { + listWorkflowRunsQuery.refetch(); + }; + + const actions = [ + , + ]; + + const [showScheduledRunRevoke, setShowScheduledRunRevoke] = useState< + ScheduledWorkflows | undefined + >(undefined); + + const isLoading = listWorkflowRunsQuery.isFetching || workflowKeysIsLoading; + + return ( + <> + { + refetch(); + setShowScheduledRunRevoke(undefined); + }} + /> + No workflow runs found with the given filters.} + error={workflowKeysError} + isLoading={isLoading} + columns={columns({ + onDeleteClick: (row) => { + setShowScheduledRunRevoke(row); + }, + })} + columnVisibility={columnVisibility} + setColumnVisibility={setColumnVisibility} + data={listWorkflowRunsQuery.data?.rows || []} + filters={filters} + actions={actions} + sorting={sorting} + setSorting={setSorting} + columnFilters={columnFilters} + setColumnFilters={setColumnFilters} + pagination={pagination} + setPagination={setPagination} + onSetPageSize={setPageSize} + rowSelection={rowSelection} + setRowSelection={setRowSelection} + pageCount={listWorkflowRunsQuery.data?.pagination?.num_pages || 0} + showColumnToggle={true} + /> + + ); +} diff --git a/frontend/app/src/pages/main/scheduled-runs/index.tsx b/frontend/app/src/pages/main/scheduled-runs/index.tsx index 82ccf5e9f..13128986d 100644 --- a/frontend/app/src/pages/main/scheduled-runs/index.tsx +++ b/frontend/app/src/pages/main/scheduled-runs/index.tsx @@ -1,25 +1,5 @@ -import { DataTable } from '../../../components/molecules/data-table/data-table'; -import { columns } from './components/scheduled-runs-columns'; -import { DeleteScheduledRun } from './components/delete-scheduled-runs'; import { Separator } from '@/components/ui/separator'; -import { useEffect, useMemo, useState } from 'react'; -import { - ColumnFiltersState, - PaginationState, - RowSelectionState, - SortingState, - VisibilityState, -} from '@tanstack/react-table'; -import { useQuery } from '@tanstack/react-query'; -import { - ScheduledWorkflows, - ScheduledWorkflowsOrderByField, - WorkflowRunOrderByDirection, - queries, -} from '@/lib/api'; -import invariant from 'tiny-invariant'; -import { useOutletContext, useSearchParams } from 'react-router-dom'; -import { TenantContextType } from '@/lib/outlet'; +import { ScheduledRunsTable } from './components/scheduled-runs-table'; export default function RateLimits() { return ( @@ -34,144 +14,3 @@ export default function RateLimits() {
); } - -function ScheduledRunsTable() { - const { tenant } = useOutletContext(); - const [searchParams, setSearchParams] = useSearchParams(); - - invariant(tenant); - - const [sorting, setSorting] = useState(() => { - const sortParam = searchParams.get('sort'); - if (sortParam) { - const [id, desc] = sortParam.split(':'); - return [{ id, desc: desc === 'desc' }]; - } - return []; - }); - const [columnFilters, setColumnFilters] = useState(() => { - const filtersParam = searchParams.get('filters'); - if (filtersParam) { - return JSON.parse(filtersParam); - } - return []; - }); - const [columnVisibility, setColumnVisibility] = useState({ - createdAt: false, - }); - - const [pagination, setPagination] = useState(() => { - const pageIndex = Number(searchParams.get('pageIndex')) || 0; - const pageSize = Number(searchParams.get('pageSize')) || 50; - return { pageIndex, pageSize }; - }); - const [pageSize, setPageSize] = useState( - Number(searchParams.get('pageSize')) || 50, - ); - const [rowSelection, setRowSelection] = useState({}); - - useEffect(() => { - const newSearchParams = new URLSearchParams(searchParams); - newSearchParams.set( - 'sort', - sorting.map((s) => `${s.id}:${s.desc ? 'desc' : 'asc'}`).join(','), - ); - newSearchParams.set('filters', JSON.stringify(columnFilters)); - newSearchParams.set('pageIndex', pagination.pageIndex.toString()); - newSearchParams.set('pageSize', pagination.pageSize.toString()); - setSearchParams(newSearchParams); - }, [sorting, columnFilters, pagination, setSearchParams, searchParams]); - - const orderByDirection = useMemo((): - | WorkflowRunOrderByDirection - | undefined => { - if (!sorting.length) { - return; - } - - return sorting[0]?.desc - ? WorkflowRunOrderByDirection.DESC - : WorkflowRunOrderByDirection.ASC; - }, [sorting]); - - const orderByField = useMemo((): - | ScheduledWorkflowsOrderByField - | undefined => { - if (!sorting.length) { - return; - } - - switch (sorting[0]?.id) { - case 'createdAt': - return ScheduledWorkflowsOrderByField.CreatedAt; - case 'triggerAt': - return ScheduledWorkflowsOrderByField.TriggerAt; - default: - return ScheduledWorkflowsOrderByField.TriggerAt; - } - }, [sorting]); - - const offset = useMemo(() => { - if (!pagination) { - return; - } - - return pagination.pageIndex * pagination.pageSize; - }, [pagination]); - - const { - data, - isLoading: queryIsLoading, - error: queryError, - } = useQuery({ - ...queries.scheduledRuns.list(tenant.metadata.id, { - // TODO: add filters - orderByField, - orderByDirection, - offset, - limit: pageSize, - }), - refetchInterval: 2000, - }); - - const [showScheduledRunRevoke, setShowScheduledRunRevoke] = - useState(); - - return ( - <> - { - setShowScheduledRunRevoke(undefined); - }} - /> - { - setShowScheduledRunRevoke(row); - }, - })} - data={data?.rows || []} - filters={[]} - showColumnToggle={true} - columnVisibility={columnVisibility} - setColumnVisibility={setColumnVisibility} - sorting={sorting} - setSorting={setSorting} - columnFilters={columnFilters} - setColumnFilters={setColumnFilters} - pagination={pagination} - setPagination={setPagination} - onSetPageSize={setPageSize} - pageCount={data?.pagination?.num_pages || 0} - rowSelection={rowSelection} - setRowSelection={setRowSelection} - getRowId={(row) => row.metadata.id} - /> - - ); -} diff --git a/pkg/client/rest/gen.go b/pkg/client/rest/gen.go index 2b6bd19f7..dd6ab5167 100644 --- a/pkg/client/rest/gen.go +++ b/pkg/client/rest/gen.go @@ -80,6 +80,17 @@ const ( Value RateLimitOrderByField = "value" ) +// Defines values for ScheduledRunStatus. +const ( + ScheduledRunStatusCANCELLED ScheduledRunStatus = "CANCELLED" + ScheduledRunStatusFAILED ScheduledRunStatus = "FAILED" + ScheduledRunStatusPENDING ScheduledRunStatus = "PENDING" + ScheduledRunStatusQUEUED ScheduledRunStatus = "QUEUED" + ScheduledRunStatusRUNNING ScheduledRunStatus = "RUNNING" + ScheduledRunStatusSCHEDULED ScheduledRunStatus = "SCHEDULED" + ScheduledRunStatusSUCCEEDED ScheduledRunStatus = "SUCCEEDED" +) + // Defines values for ScheduledWorkflowsOrderByField. const ( ScheduledWorkflowsOrderByFieldCreatedAt ScheduledWorkflowsOrderByField = "createdAt" @@ -187,12 +198,12 @@ const ( // Defines values for WorkflowRunStatus. const ( - WorkflowRunStatusCANCELLED WorkflowRunStatus = "CANCELLED" - WorkflowRunStatusFAILED WorkflowRunStatus = "FAILED" - WorkflowRunStatusPENDING WorkflowRunStatus = "PENDING" - WorkflowRunStatusQUEUED WorkflowRunStatus = "QUEUED" - WorkflowRunStatusRUNNING WorkflowRunStatus = "RUNNING" - WorkflowRunStatusSUCCEEDED WorkflowRunStatus = "SUCCEEDED" + CANCELLED WorkflowRunStatus = "CANCELLED" + FAILED WorkflowRunStatus = "FAILED" + PENDING WorkflowRunStatus = "PENDING" + QUEUED WorkflowRunStatus = "QUEUED" + RUNNING WorkflowRunStatus = "RUNNING" + SUCCEEDED WorkflowRunStatus = "SUCCEEDED" ) // APIError defines model for APIError. @@ -640,6 +651,9 @@ type SNSIntegration struct { TopicArn string `json:"topicArn"` } +// ScheduledRunStatus defines model for ScheduledRunStatus. +type ScheduledRunStatus string + // ScheduledWorkflows defines model for ScheduledWorkflows. type ScheduledWorkflows struct { AdditionalMetadata *map[string]interface{} `json:"additionalMetadata,omitempty"` @@ -1604,17 +1618,26 @@ type WorkflowScheduledListParams struct { // Limit The number to limit by Limit *int64 `form:"limit,omitempty" json:"limit,omitempty"` + // OrderByField The order by field + OrderByField *ScheduledWorkflowsOrderByField `form:"orderByField,omitempty" json:"orderByField,omitempty"` + + // OrderByDirection The order by direction + OrderByDirection *WorkflowRunOrderByDirection `form:"orderByDirection,omitempty" json:"orderByDirection,omitempty"` + // WorkflowId The workflow id to get runs for. WorkflowId *openapi_types.UUID `form:"workflowId,omitempty" json:"workflowId,omitempty"` + // ParentWorkflowRunId The parent workflow run id + ParentWorkflowRunId *openapi_types.UUID `form:"parentWorkflowRunId,omitempty" json:"parentWorkflowRunId,omitempty"` + + // ParentStepRunId The parent step run id + ParentStepRunId *openapi_types.UUID `form:"parentStepRunId,omitempty" json:"parentStepRunId,omitempty"` + // AdditionalMetadata A list of metadata key value pairs to filter by AdditionalMetadata *[]string `form:"additionalMetadata,omitempty" json:"additionalMetadata,omitempty"` - // OrderByField The order by field - OrderByField *ScheduledWorkflowsOrderByField `form:"orderByField,omitempty" json:"orderByField,omitempty"` - - // OrderByDirection The order by direction - OrderByDirection *WorkflowRunOrderByDirection `form:"orderByDirection,omitempty" json:"orderByDirection,omitempty"` + // Statuses A list of scheduled run statuses to filter by + Statuses *[]ScheduledRunStatus `form:"statuses,omitempty" json:"statuses,omitempty"` } // WorkflowGetMetricsParams defines parameters for WorkflowGetMetrics. @@ -6747,6 +6770,38 @@ func NewWorkflowScheduledListRequest(server string, tenant openapi_types.UUID, p } + if params.OrderByField != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "orderByField", runtime.ParamLocationQuery, *params.OrderByField); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.OrderByDirection != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "orderByDirection", runtime.ParamLocationQuery, *params.OrderByDirection); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + if params.WorkflowId != nil { if queryFrag, err := runtime.StyleParamWithLocation("form", true, "workflowId", runtime.ParamLocationQuery, *params.WorkflowId); err != nil { @@ -6763,9 +6818,9 @@ func NewWorkflowScheduledListRequest(server string, tenant openapi_types.UUID, p } - if params.AdditionalMetadata != nil { + if params.ParentWorkflowRunId != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "additionalMetadata", runtime.ParamLocationQuery, *params.AdditionalMetadata); err != nil { + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "parentWorkflowRunId", runtime.ParamLocationQuery, *params.ParentWorkflowRunId); err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err @@ -6779,9 +6834,9 @@ func NewWorkflowScheduledListRequest(server string, tenant openapi_types.UUID, p } - if params.OrderByField != nil { + if params.ParentStepRunId != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "orderByField", runtime.ParamLocationQuery, *params.OrderByField); err != nil { + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "parentStepRunId", runtime.ParamLocationQuery, *params.ParentStepRunId); err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err @@ -6795,9 +6850,25 @@ func NewWorkflowScheduledListRequest(server string, tenant openapi_types.UUID, p } - if params.OrderByDirection != nil { + if params.AdditionalMetadata != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "orderByDirection", runtime.ParamLocationQuery, *params.OrderByDirection); err != nil { + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "additionalMetadata", runtime.ParamLocationQuery, *params.AdditionalMetadata); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.Statuses != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "statuses", runtime.ParamLocationQuery, *params.Statuses); err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err diff --git a/pkg/repository/prisma/dbsqlc/workflow_runs.sql b/pkg/repository/prisma/dbsqlc/workflow_runs.sql index b7ca80873..c1c4ffd94 100644 --- a/pkg/repository/prisma/dbsqlc/workflow_runs.sql +++ b/pkg/repository/prisma/dbsqlc/workflow_runs.sql @@ -1436,23 +1436,54 @@ LEFT JOIN "WorkflowRun" wr ON tb."parentId" = wr."id" WHERE v."deletedAt" IS NULL AND w."tenantId" = @tenantId::uuid AND (@scheduleId::uuid IS NULL OR t."id" = @scheduleId::uuid) + AND (@workflowId::uuid IS NULL OR w."id" = @workflowId::uuid) + AND (@parentWorkflowRunId::uuid IS NULL OR t."id" = @parentWorkflowRunId::uuid) + AND (@parentStepRunId::uuid IS NULL OR t."parentStepRunId" = @parentStepRunId::uuid) + AND (sqlc.narg('additionalMetadata')::jsonb IS NULL OR + t."additionalMetadata" @> sqlc.narg('additionalMetadata')::jsonb) + AND ( + sqlc.narg('statuses')::text[] IS NULL OR + wr."status" = ANY(cast(sqlc.narg('statuses')::text[] as "WorkflowRunStatus"[])) + or ( + @includeScheduled::boolean IS TRUE AND + wr."status" IS NULL + ) + ) ORDER BY case when @orderBy = 'triggerAt ASC' THEN t."triggerAt" END ASC , case when @orderBy = 'triggerAt DESC' THEN t."triggerAt" END DESC, case when @orderBy = 'createdAt ASC' THEN t."createdAt" END ASC , case when @orderBy = 'createdAt DESC' THEN t."createdAt" END DESC, - -- case when @orderBy = 'finishedAt ASC' THEN t."finishedAt" END ASC , - -- case when @orderBy = 'finishedAt DESC' THEN t."finishedAt" END DESC, - -- case when @orderBy = 'startedAt ASC' THEN t."startedAt" END ASC , - -- case when @orderBy = 'startedAt DESC' THEN t."startedAt" END DESC, - -- case when @orderBy = 'duration ASC' THEN t."duration" END ASC NULLS FIRST, - -- case when @orderBy = 'duration DESC' THEN runs."duration" END DESC NULLS LAST, t."id" ASC OFFSET COALESCE(sqlc.narg('offset'), 0) LIMIT COALESCE(sqlc.narg('limit'), 50); +-- name: CountScheduledWorkflows :one +SELECT count(*) +FROM "WorkflowTriggerScheduledRef" t +JOIN "WorkflowVersion" v ON t."parentId" = v."id" +JOIN "Workflow" w on v."workflowId" = w."id" +LEFT JOIN "WorkflowRunTriggeredBy" tb ON t."id" = tb."scheduledId" +LEFT JOIN "WorkflowRun" wr ON tb."parentId" = wr."id" +WHERE v."deletedAt" IS NULL + AND w."tenantId" = @tenantId::uuid + AND (@scheduleId::uuid IS NULL OR t."id" = @scheduleId::uuid) + AND (@workflowId::uuid IS NULL OR w."id" = @workflowId::uuid) + AND (@parentWorkflowRunId::uuid IS NULL OR t."id" = @parentWorkflowRunId::uuid) + AND (@parentStepRunId::uuid IS NULL OR t."parentStepRunId" = @parentStepRunId::uuid) + AND (sqlc.narg('additionalMetadata')::jsonb IS NULL OR + t."additionalMetadata" @> sqlc.narg('additionalMetadata')::jsonb) + AND ( + sqlc.narg('statuses')::text[] IS NULL OR + wr."status" = ANY(cast(sqlc.narg('statuses')::text[] as "WorkflowRunStatus"[])) + or ( + @includeScheduled::boolean IS TRUE AND + wr."status" IS NULL + ) + ); + -- name: UpdateScheduledWorkflow :exec UPDATE "WorkflowTriggerScheduledRef" SET "triggerAt" = @triggerAt::timestamp @@ -1496,9 +1527,10 @@ OFFSET LIMIT COALESCE(sqlc.narg('limit'), 50); --- name: CountScheduledWorkflows :one -SELECT count(*) FROM "WorkflowTriggerScheduledRef" t -JOIN "WorkflowVersion" v ON t."parentId" = v."id" +-- name: CountCronWorkflows :one +SELECT count(*) +FROM "WorkflowTriggerCronRef" c +JOIN "WorkflowTriggers" t ON c."parentId" = t."id" +JOIN "WorkflowVersion" v ON t."workflowVersionId" = v."id" JOIN "Workflow" w on v."workflowId" = w."id" -WHERE v."deletedAt" IS NULL - AND w."tenantId" = @tenantId::uuid; +WHERE v."deletedAt" IS NULL AND w."tenantId" = @tenantId::uuid; diff --git a/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go b/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go index f1777bb2f..0c7bbd9c4 100644 --- a/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go +++ b/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go @@ -90,16 +90,69 @@ func (q *Queries) BulkCreateWorkflowRunEvent(ctx context.Context, db DBTX, arg B return err } +const countCronWorkflows = `-- name: CountCronWorkflows :one +SELECT count(*) +FROM "WorkflowTriggerCronRef" c +JOIN "WorkflowTriggers" t ON c."parentId" = t."id" +JOIN "WorkflowVersion" v ON t."workflowVersionId" = v."id" +JOIN "Workflow" w on v."workflowId" = w."id" +WHERE v."deletedAt" IS NULL AND w."tenantId" = $1::uuid +` + +func (q *Queries) CountCronWorkflows(ctx context.Context, db DBTX, tenantid pgtype.UUID) (int64, error) { + row := db.QueryRow(ctx, countCronWorkflows, tenantid) + var count int64 + err := row.Scan(&count) + return count, err +} + const countScheduledWorkflows = `-- name: CountScheduledWorkflows :one -SELECT count(*) FROM "WorkflowTriggerScheduledRef" t +SELECT count(*) +FROM "WorkflowTriggerScheduledRef" t JOIN "WorkflowVersion" v ON t."parentId" = v."id" JOIN "Workflow" w on v."workflowId" = w."id" +LEFT JOIN "WorkflowRunTriggeredBy" tb ON t."id" = tb."scheduledId" +LEFT JOIN "WorkflowRun" wr ON tb."parentId" = wr."id" WHERE v."deletedAt" IS NULL AND w."tenantId" = $1::uuid + AND ($2::uuid IS NULL OR t."id" = $2::uuid) + AND ($3::uuid IS NULL OR w."id" = $3::uuid) + AND ($4::uuid IS NULL OR t."id" = $4::uuid) + AND ($5::uuid IS NULL OR t."parentStepRunId" = $5::uuid) + AND ($6::jsonb IS NULL OR + t."additionalMetadata" @> $6::jsonb) + AND ( + $7::text[] IS NULL OR + wr."status" = ANY(cast($7::text[] as "WorkflowRunStatus"[])) + or ( + $8::boolean IS TRUE AND + wr."status" IS NULL + ) + ) ` -func (q *Queries) CountScheduledWorkflows(ctx context.Context, db DBTX, tenantid pgtype.UUID) (int64, error) { - row := db.QueryRow(ctx, countScheduledWorkflows, tenantid) +type CountScheduledWorkflowsParams struct { + Tenantid pgtype.UUID `json:"tenantid"` + Scheduleid pgtype.UUID `json:"scheduleid"` + Workflowid pgtype.UUID `json:"workflowid"` + Parentworkflowrunid pgtype.UUID `json:"parentworkflowrunid"` + Parentsteprunid pgtype.UUID `json:"parentsteprunid"` + AdditionalMetadata []byte `json:"additionalMetadata"` + Statuses []string `json:"statuses"` + Includescheduled bool `json:"includescheduled"` +} + +func (q *Queries) CountScheduledWorkflows(ctx context.Context, db DBTX, arg CountScheduledWorkflowsParams) (int64, error) { + row := db.QueryRow(ctx, countScheduledWorkflows, + arg.Tenantid, + arg.Scheduleid, + arg.Workflowid, + arg.Parentworkflowrunid, + arg.Parentsteprunid, + arg.AdditionalMetadata, + arg.Statuses, + arg.Includescheduled, + ) var count int64 err := row.Scan(&count) return count, err @@ -2246,30 +2299,43 @@ LEFT JOIN "WorkflowRun" wr ON tb."parentId" = wr."id" WHERE v."deletedAt" IS NULL AND w."tenantId" = $1::uuid AND ($2::uuid IS NULL OR t."id" = $2::uuid) + AND ($3::uuid IS NULL OR w."id" = $3::uuid) + AND ($4::uuid IS NULL OR t."id" = $4::uuid) + AND ($5::uuid IS NULL OR t."parentStepRunId" = $5::uuid) + AND ($6::jsonb IS NULL OR + t."additionalMetadata" @> $6::jsonb) + AND ( + $7::text[] IS NULL OR + wr."status" = ANY(cast($7::text[] as "WorkflowRunStatus"[])) + or ( + $8::boolean IS TRUE AND + wr."status" IS NULL + ) + ) ORDER BY - case when $3 = 'triggerAt ASC' THEN t."triggerAt" END ASC , - case when $3 = 'triggerAt DESC' THEN t."triggerAt" END DESC, - case when $3 = 'createdAt ASC' THEN t."createdAt" END ASC , - case when $3 = 'createdAt DESC' THEN t."createdAt" END DESC, - -- case when @orderBy = 'finishedAt ASC' THEN t."finishedAt" END ASC , - -- case when @orderBy = 'finishedAt DESC' THEN t."finishedAt" END DESC, - -- case when @orderBy = 'startedAt ASC' THEN t."startedAt" END ASC , - -- case when @orderBy = 'startedAt DESC' THEN t."startedAt" END DESC, - -- case when @orderBy = 'duration ASC' THEN t."duration" END ASC NULLS FIRST, - -- case when @orderBy = 'duration DESC' THEN runs."duration" END DESC NULLS LAST, + case when $9 = 'triggerAt ASC' THEN t."triggerAt" END ASC , + case when $9 = 'triggerAt DESC' THEN t."triggerAt" END DESC, + case when $9 = 'createdAt ASC' THEN t."createdAt" END ASC , + case when $9 = 'createdAt DESC' THEN t."createdAt" END DESC, t."id" ASC OFFSET - COALESCE($4, 0) + COALESCE($10, 0) LIMIT - COALESCE($5, 50) + COALESCE($11, 50) ` type ListScheduledWorkflowsParams struct { - Tenantid pgtype.UUID `json:"tenantid"` - Scheduleid pgtype.UUID `json:"scheduleid"` - Orderby interface{} `json:"orderby"` - Offset interface{} `json:"offset"` - Limit interface{} `json:"limit"` + Tenantid pgtype.UUID `json:"tenantid"` + Scheduleid pgtype.UUID `json:"scheduleid"` + Workflowid pgtype.UUID `json:"workflowid"` + Parentworkflowrunid pgtype.UUID `json:"parentworkflowrunid"` + Parentsteprunid pgtype.UUID `json:"parentsteprunid"` + AdditionalMetadata []byte `json:"additionalMetadata"` + Statuses []string `json:"statuses"` + Includescheduled bool `json:"includescheduled"` + Orderby interface{} `json:"orderby"` + Offset interface{} `json:"offset"` + Limit interface{} `json:"limit"` } type ListScheduledWorkflowsRow struct { @@ -2300,6 +2366,12 @@ func (q *Queries) ListScheduledWorkflows(ctx context.Context, db DBTX, arg ListS rows, err := db.Query(ctx, listScheduledWorkflows, arg.Tenantid, arg.Scheduleid, + arg.Workflowid, + arg.Parentworkflowrunid, + arg.Parentsteprunid, + arg.AdditionalMetadata, + arg.Statuses, + arg.Includescheduled, arg.Orderby, arg.Offset, arg.Limit, @@ -3079,7 +3151,7 @@ func (q *Queries) UpdateManyWorkflowRun(ctx context.Context, db DBTX, arg Update const updateScheduledWorkflow = `-- name: UpdateScheduledWorkflow :exec UPDATE "WorkflowTriggerScheduledRef" - SET "triggerAt" = $1::timestamp +SET "triggerAt" = $1::timestamp WHERE "id" = $2::uuid ` diff --git a/pkg/repository/prisma/workflow_run.go b/pkg/repository/prisma/workflow_run.go index fb1c9e59b..8e8b78bdb 100644 --- a/pkg/repository/prisma/workflow_run.go +++ b/pkg/repository/prisma/workflow_run.go @@ -121,16 +121,68 @@ func (w *workflowRunAPIRepository) ListScheduledWorkflows(ctx context.Context, t ctx, cancel := context.WithTimeout(ctx, time.Second*30) defer cancel() - count, err := w.queries.CountScheduledWorkflows(ctx, w.pool, sqlchelpers.UUIDFromStr(tenantId)) - - if err != nil { - return nil, 0, err + listOpts := dbsqlc.ListScheduledWorkflowsParams{ + Tenantid: sqlchelpers.UUIDFromStr(tenantId), } - listOpts := dbsqlc.ListScheduledWorkflowsParams{ + countParams := dbsqlc.CountScheduledWorkflowsParams{ Tenantid: sqlchelpers.UUIDFromStr(tenantId), } + if opts.WorkflowId != nil { + pgWorkflowId := sqlchelpers.UUIDFromStr(*opts.WorkflowId) + + listOpts.Workflowid = pgWorkflowId + countParams.Workflowid = pgWorkflowId + } + + if opts.AdditionalMetadata != nil { + additionalMetadataBytes, err := json.Marshal(opts.AdditionalMetadata) + if err != nil { + return nil, 0, err + } + + listOpts.AdditionalMetadata = additionalMetadataBytes + countParams.AdditionalMetadata = additionalMetadataBytes + } + + if opts.ParentWorkflowRunId != nil { + pgParentId := sqlchelpers.UUIDFromStr(*opts.ParentWorkflowRunId) + + listOpts.Parentworkflowrunid = pgParentId + countParams.Parentworkflowrunid = pgParentId + } + + if opts.ParentStepRunId != nil { + pgParentStepRunId := sqlchelpers.UUIDFromStr(*opts.ParentStepRunId) + + listOpts.Parentsteprunid = pgParentStepRunId + countParams.Parentsteprunid = pgParentStepRunId + } + + if opts.Statuses != nil { + statuses := make([]string, 0) + + for _, status := range *opts.Statuses { + if status == "SCHEDULED" { + listOpts.Includescheduled = true + countParams.Includescheduled = true + continue + } + + statuses = append(statuses, string(status)) + } + + listOpts.Statuses = statuses + countParams.Statuses = statuses + } + + count, err := w.queries.CountScheduledWorkflows(ctx, w.pool, countParams) + + if err != nil { + return nil, 0, err + } + if opts.Limit != nil { listOpts.Limit = pgtype.Int4{ Int32: int32(*opts.Limit), // nolint: gosec @@ -203,7 +255,7 @@ func (w *workflowRunAPIRepository) ListCronWorkflows(ctx context.Context, tenant ctx, cancel := context.WithTimeout(ctx, time.Second*30) defer cancel() - count, err := w.queries.CountScheduledWorkflows(ctx, w.pool, sqlchelpers.UUIDFromStr(tenantId)) + count, err := w.queries.CountCronWorkflows(ctx, w.pool, sqlchelpers.UUIDFromStr(tenantId)) if err != nil { return nil, 0, err diff --git a/pkg/repository/workflow_run.go b/pkg/repository/workflow_run.go index bc992de0e..d01dc2570 100644 --- a/pkg/repository/workflow_run.go +++ b/pkg/repository/workflow_run.go @@ -404,6 +404,18 @@ type ListScheduledWorkflowsOpts struct { // (optional) the workflow id WorkflowId *string `validate:"omitempty,uuid"` + // (optional) the parent workflow run id + ParentWorkflowRunId *string `validate:"omitempty,uuid"` + + // (optional) the parent step run id + ParentStepRunId *string `validate:"omitempty,uuid"` + + // (optional) statuses to filter by + Statuses *[]db.WorkflowRunStatus + + // (optional) include scheduled runs that are in the future + IncludeFuture *bool + // (optional) additional metadata for the workflow run AdditionalMetadata map[string]interface{} `validate:"omitempty"` } From 2eae6a047ce83182142cc1c32df2c07fbee5a45d Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Fri, 25 Oct 2024 08:30:43 -0400 Subject: [PATCH 15/30] fix: remove broken features --- .../recurring/components/recurring-table.tsx | 140 +++++++++++++++ .../app/src/pages/main/recurring/index.tsx | 167 +----------------- 2 files changed, 141 insertions(+), 166 deletions(-) create mode 100644 frontend/app/src/pages/main/recurring/components/recurring-table.tsx diff --git a/frontend/app/src/pages/main/recurring/components/recurring-table.tsx b/frontend/app/src/pages/main/recurring/components/recurring-table.tsx new file mode 100644 index 000000000..4eb8c860c --- /dev/null +++ b/frontend/app/src/pages/main/recurring/components/recurring-table.tsx @@ -0,0 +1,140 @@ +import { useEffect, useMemo, useState } from 'react'; +import { + ColumnFiltersState, + PaginationState, + RowSelectionState, + SortingState, + VisibilityState, +} from '@tanstack/react-table'; +import { useQuery } from '@tanstack/react-query'; +import { + CronWorkflowsOrderByField, + WorkflowRunOrderByDirection, + queries, +} from '@/lib/api'; +import invariant from 'tiny-invariant'; +import { useOutletContext, useSearchParams } from 'react-router-dom'; +import { TenantContextType } from '@/lib/outlet'; +import { DataTable } from '@/components/molecules/data-table/data-table'; +import { columns } from './recurring-columns'; + +export function CronsTable() { + const { tenant } = useOutletContext(); + const [searchParams, setSearchParams] = useSearchParams(); + + invariant(tenant); + + const [sorting, setSorting] = useState(() => { + const sortParam = searchParams.get('sort'); + if (sortParam) { + const [id, desc] = sortParam.split(':'); + return [{ id, desc: desc === 'desc' }]; + } + return []; + }); + const [columnFilters, setColumnFilters] = useState(() => { + const filtersParam = searchParams.get('filters'); + if (filtersParam) { + return JSON.parse(filtersParam); + } + return []; + }); + const [columnVisibility, setColumnVisibility] = useState({ + createdAt: false, + }); + + const [pagination, setPagination] = useState(() => { + const pageIndex = Number(searchParams.get('pageIndex')) || 0; + const pageSize = Number(searchParams.get('pageSize')) || 50; + return { pageIndex, pageSize }; + }); + const [pageSize, setPageSize] = useState( + Number(searchParams.get('pageSize')) || 50, + ); + const [rowSelection, setRowSelection] = useState({}); + + useEffect(() => { + const newSearchParams = new URLSearchParams(searchParams); + + newSearchParams.set( + 'sort', + sorting.map((s) => `${s.id}:${s.desc ? 'desc' : 'asc'}`).join(','), + ); + newSearchParams.set('filters', JSON.stringify(columnFilters)); + newSearchParams.set('pageIndex', pagination.pageIndex.toString()); + newSearchParams.set('pageSize', pagination.pageSize.toString()); + setSearchParams(newSearchParams); + }, [sorting, columnFilters, pagination, setSearchParams, searchParams]); + + const orderByDirection = useMemo((): + | WorkflowRunOrderByDirection + | undefined => { + if (!sorting.length) { + return; + } + + return sorting[0]?.desc + ? WorkflowRunOrderByDirection.DESC + : WorkflowRunOrderByDirection.ASC; + }, [sorting]); + + const orderByField = useMemo((): CronWorkflowsOrderByField | undefined => { + if (!sorting.length) { + return; + } + + switch (sorting[0]?.id) { + case 'triggerAt': + return CronWorkflowsOrderByField.CreatedAt; + default: + return CronWorkflowsOrderByField.CreatedAt; + } + }, [sorting]); + + const offset = useMemo(() => { + if (!pagination) { + return; + } + + return pagination.pageIndex * pagination.pageSize; + }, [pagination]); + + const { + data, + isLoading: queryIsLoading, + error: queryError, + } = useQuery({ + ...queries.cronRuns.list(tenant.metadata.id, { + // TODO: add filters + orderByField, + orderByDirection, + offset, + limit: pageSize, + }), + refetchInterval: 2000, + }); + + return ( + row.metadata.id} + /> + ); +} diff --git a/frontend/app/src/pages/main/recurring/index.tsx b/frontend/app/src/pages/main/recurring/index.tsx index ef081171e..81748c166 100644 --- a/frontend/app/src/pages/main/recurring/index.tsx +++ b/frontend/app/src/pages/main/recurring/index.tsx @@ -1,23 +1,5 @@ -import { DataTable } from '../../../components/molecules/data-table/data-table'; -import { columns } from './components/recurring-columns'; import { Separator } from '@/components/ui/separator'; -import { useEffect, useMemo, useState } from 'react'; -import { - ColumnFiltersState, - PaginationState, - RowSelectionState, - SortingState, - VisibilityState, -} from '@tanstack/react-table'; -import { useQuery } from '@tanstack/react-query'; -import { - CronWorkflowsOrderByField, - WorkflowRunOrderByDirection, - queries, -} from '@/lib/api'; -import invariant from 'tiny-invariant'; -import { useOutletContext, useSearchParams } from 'react-router-dom'; -import { TenantContextType } from '@/lib/outlet'; +import { CronsTable } from './components/recurring-table'; export default function Crons() { return ( @@ -32,150 +14,3 @@ export default function Crons() {
); } - -function CronsTable() { - const { tenant } = useOutletContext(); - const [searchParams, setSearchParams] = useSearchParams(); - - invariant(tenant); - - const [search, setSearch] = useState( - searchParams.get('search') || undefined, - ); - const [sorting, setSorting] = useState(() => { - const sortParam = searchParams.get('sort'); - if (sortParam) { - const [id, desc] = sortParam.split(':'); - return [{ id, desc: desc === 'desc' }]; - } - return []; - }); - const [columnFilters, setColumnFilters] = useState(() => { - const filtersParam = searchParams.get('filters'); - if (filtersParam) { - return JSON.parse(filtersParam); - } - return []; - }); - const [columnVisibility, setColumnVisibility] = useState({ - createdAt: false, - }); - - const [pagination, setPagination] = useState(() => { - const pageIndex = Number(searchParams.get('pageIndex')) || 0; - const pageSize = Number(searchParams.get('pageSize')) || 50; - return { pageIndex, pageSize }; - }); - const [pageSize, setPageSize] = useState( - Number(searchParams.get('pageSize')) || 50, - ); - const [rowSelection, setRowSelection] = useState({}); - - useEffect(() => { - const newSearchParams = new URLSearchParams(searchParams); - if (search) { - newSearchParams.set('search', search); - } else { - newSearchParams.delete('search'); - } - newSearchParams.set( - 'sort', - sorting.map((s) => `${s.id}:${s.desc ? 'desc' : 'asc'}`).join(','), - ); - newSearchParams.set('filters', JSON.stringify(columnFilters)); - newSearchParams.set('pageIndex', pagination.pageIndex.toString()); - newSearchParams.set('pageSize', pagination.pageSize.toString()); - setSearchParams(newSearchParams); - }, [ - search, - sorting, - columnFilters, - pagination, - setSearchParams, - searchParams, - ]); - - const orderByDirection = useMemo((): - | WorkflowRunOrderByDirection - | undefined => { - if (!sorting.length) { - return; - } - - return sorting[0]?.desc - ? WorkflowRunOrderByDirection.DESC - : WorkflowRunOrderByDirection.ASC; - }, [sorting]); - - const orderByField = useMemo((): CronWorkflowsOrderByField | undefined => { - if (!sorting.length) { - return; - } - - switch (sorting[0]?.id) { - case 'triggerAt': - return CronWorkflowsOrderByField.CreatedAt; - default: - return CronWorkflowsOrderByField.CreatedAt; - } - }, [sorting]); - - const offset = useMemo(() => { - if (!pagination) { - return; - } - - return pagination.pageIndex * pagination.pageSize; - }, [pagination]); - - const { - data, - isLoading: queryIsLoading, - error: queryError, - } = useQuery({ - ...queries.cronRuns.list(tenant.metadata.id, { - // TODO: add filters - orderByField, - orderByDirection, - offset, - limit: pageSize, - }), - refetchInterval: 2000, - }); - - // const tableData = - // data?.rows?.map( - // (row): CronWorkflows => ({ - // ...row, - // metadata: { - // id: row.key, - // }, - // }), - // ) || []; - - return ( - row.metadata.id} - /> - ); -} From 37b71f95846165649afc11d7bff7963ae3507c5e Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Fri, 25 Oct 2024 08:40:27 -0400 Subject: [PATCH 16/30] chore: lint --- .../components/scheduled-runs-table.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-table.tsx b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-table.tsx index 3251f76a0..fcd4b639d 100644 --- a/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-table.tsx +++ b/frontend/app/src/pages/main/scheduled-runs/components/scheduled-runs-table.tsx @@ -7,10 +7,9 @@ import { SortingState, VisibilityState, } from '@tanstack/react-table'; -import { useMutation, useQuery } from '@tanstack/react-query'; +import { useQuery } from '@tanstack/react-query'; import invariant from 'tiny-invariant'; -import api, { - ReplayWorkflowRunsRequest, +import { ScheduledRunStatus, ScheduledWorkflows, ScheduledWorkflowsOrderByField, @@ -26,8 +25,6 @@ import { } from '@/components/molecules/data-table/data-table-toolbar'; import { Button } from '@/components/ui/button'; import { ArrowPathIcon } from '@heroicons/react/24/outline'; -import queryClient from '@/query-client'; -import { useApiError } from '@/lib/hooks'; import { columns } from './scheduled-runs-columns'; import { DeleteScheduledRun } from './delete-scheduled-runs'; @@ -45,7 +42,9 @@ export interface ScheduledWorkflowRunsTableProps { export function ScheduledRunsTable({ workflowId, - initColumnVisibility = {}, + initColumnVisibility = { + createdAt: false, + }, filterVisibility = {}, parentWorkflowRunId, parentStepRunId, From 46313979bb7fbaf51a203e9215b50aeaf6a54fbd Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Mon, 28 Oct 2024 09:19:28 -0400 Subject: [PATCH 17/30] rm metadata for now --- .../components/recurring-columns.tsx | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx b/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx index d672999ee..ada012123 100644 --- a/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx +++ b/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx @@ -51,20 +51,20 @@ export const columns: ColumnDef[] = [ enableSorting: false, enableHiding: true, }, - { - accessorKey: 'Metadata', - header: ({ column }) => ( - - ), - cell: ({ row }) => { - if (!row.original.additionalMetadata) { - return
; - } + // { + // accessorKey: 'Metadata', + // header: ({ column }) => ( + // + // ), + // cell: ({ row }) => { + // if (!row.original.additionalMetadata) { + // return
; + // } - return ; - }, - enableSorting: false, - }, + // return ; + // }, + // enableSorting: false, + // }, { accessorKey: 'createdAt', header: ({ column }) => ( From 7dc03cce82e93fff14abfc387a52135ce22c8d6f Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Mon, 28 Oct 2024 09:19:41 -0400 Subject: [PATCH 18/30] chore: lint --- .../src/pages/main/recurring/components/recurring-columns.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx b/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx index ada012123..d61a512f5 100644 --- a/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx +++ b/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx @@ -2,7 +2,6 @@ import { ColumnDef } from '@tanstack/react-table'; import { DataTableColumnHeader } from '../../../../components/molecules/data-table/data-table-column-header'; import { CronWorkflows, RateLimit } from '@/lib/api'; import CronPrettifier from 'cronstrue'; -import { AdditionalMetadata } from '../../events/components/additional-metadata'; import RelativeDate from '@/components/molecules/relative-date'; export type RateLimitRow = RateLimit & { From 152452f98526909eb28788c54d01ee7ddb504d2b Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Mon, 28 Oct 2024 09:21:27 -0400 Subject: [PATCH 19/30] chore: recurring to cron job --- frontend/app/src/pages/main/index.tsx | 4 ++-- .../main/recurring/components/recurring-columns.tsx | 9 ++++++--- frontend/app/src/pages/main/recurring/index.tsx | 2 +- frontend/app/src/router.tsx | 2 +- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/frontend/app/src/pages/main/index.tsx b/frontend/app/src/pages/main/index.tsx index 587a90cdb..d6872486b 100644 --- a/frontend/app/src/pages/main/index.tsx +++ b/frontend/app/src/pages/main/index.tsx @@ -150,8 +150,8 @@ function Sidebar({ className, memberships, currTenant }: SidebarProps) { } />
diff --git a/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx b/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx index d61a512f5..2d3e22dad 100644 --- a/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx +++ b/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx @@ -3,6 +3,7 @@ import { DataTableColumnHeader } from '../../../../components/molecules/data-tab import { CronWorkflows, RateLimit } from '@/lib/api'; import CronPrettifier from 'cronstrue'; import RelativeDate from '@/components/molecules/relative-date'; +import { Link } from 'react-router-dom'; export type RateLimitRow = RateLimit & { metadata: { @@ -42,9 +43,11 @@ export const columns: ColumnDef[] = [ ), cell: ({ row }) => (
- - {row.original.workflowName} - +
+ + {row.original.workflowName} + +
), enableSorting: false, diff --git a/frontend/app/src/pages/main/recurring/index.tsx b/frontend/app/src/pages/main/recurring/index.tsx index 81748c166..619556595 100644 --- a/frontend/app/src/pages/main/recurring/index.tsx +++ b/frontend/app/src/pages/main/recurring/index.tsx @@ -6,7 +6,7 @@ export default function Crons() {

- Recurring Runs + Cron Jobs

diff --git a/frontend/app/src/router.tsx b/frontend/app/src/router.tsx index f9e5ef85a..683f23600 100644 --- a/frontend/app/src/router.tsx +++ b/frontend/app/src/router.tsx @@ -142,7 +142,7 @@ const routes: RouteObject[] = [ }), }, { - path: '/recurring', + path: '/cron-jobs', lazy: async () => import('./pages/main/recurring').then((res) => { return { From f79758f3c71d1f3325dfa8182c353b9cc0603361 Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Tue, 29 Oct 2024 08:23:35 -0400 Subject: [PATCH 20/30] fix: review comments --- .../openapi/paths/workflow/workflow.yaml | 10 +- .../server/handlers/workflows/list_crons.go | 10 - api/v1/server/oas/gen/openapi.gen.go | 382 +++++++++--------- frontend/app/src/lib/api/generated/Api.ts | 10 +- .../prisma/dbsqlc/workflow_runs.sql | 9 - .../prisma/dbsqlc/workflow_runs.sql.go | 9 - pkg/repository/prisma/workflow_run.go | 6 + 7 files changed, 207 insertions(+), 229 deletions(-) diff --git a/api-contracts/openapi/paths/workflow/workflow.yaml b/api-contracts/openapi/paths/workflow/workflow.yaml index 27df6a289..ac07a9f33 100644 --- a/api-contracts/openapi/paths/workflow/workflow.yaml +++ b/api-contracts/openapi/paths/workflow/workflow.yaml @@ -629,7 +629,7 @@ workflowRunsMetrics: schema: $ref: "../../components/schemas/_index.yaml#/APIErrors" description: Forbidden - summary: Get workflow runs + summary: Get workflow runs metrics tags: - Workflow workflowRun: @@ -932,7 +932,7 @@ scheduledList: schema: $ref: "../../components/schemas/_index.yaml#/APIErrors" description: Forbidden - summary: Get workflow runs + summary: Get scheduled workflow runs tags: - Workflow @@ -985,7 +985,7 @@ scheduled: schema: $ref: "../../components/schemas/_index.yaml#/APIErrors" description: Forbidden - summary: Get workflow runs + summary: Get scheduled workflow run tags: - Workflow delete: @@ -1026,7 +1026,7 @@ scheduled: schema: $ref: "../../components/schemas/_index.yaml#/APIError" description: Forbidden - summary: Delete tenant alert email group + summary: Delete scheduled workflow run tags: - Workflow @@ -1108,6 +1108,6 @@ cronsList: schema: $ref: "../../components/schemas/_index.yaml#/APIErrors" description: Forbidden - summary: Get workflow runs + summary: Get cron job workflows tags: - Workflow diff --git a/api/v1/server/handlers/workflows/list_crons.go b/api/v1/server/handlers/workflows/list_crons.go index 6dc0e5d55..692f4036d 100644 --- a/api/v1/server/handlers/workflows/list_crons.go +++ b/api/v1/server/handlers/workflows/list_crons.go @@ -56,16 +56,6 @@ func (t *WorkflowService) CronWorkflowList(ctx echo.Context, request gen.CronWor listOpts.WorkflowId = &workflowIdStr } - // if request.Params.Statuses != nil { - // statuses := make([]db.WorkflowRunStatus, len(*request.Params.Statuses)) - - // for i, status := range *request.Params.Statuses { - // statuses[i] = db.WorkflowRunStatus(status) - // } - - // listOpts.Statuses = &statuses - // } - if request.Params.AdditionalMetadata != nil { additionalMetadata := make(map[string]interface{}, len(*request.Params.AdditionalMetadata)) diff --git a/api/v1/server/oas/gen/openapi.gen.go b/api/v1/server/oas/gen/openapi.gen.go index 4222f9e34..9bc1c5b6f 100644 --- a/api/v1/server/oas/gen/openapi.gen.go +++ b/api/v1/server/oas/gen/openapi.gen.go @@ -1909,22 +1909,22 @@ type ServerInterface interface { // Cancel workflow runs // (POST /api/v1/tenants/{tenant}/workflows/cancel) WorkflowRunCancel(ctx echo.Context, tenant openapi_types.UUID) error - // Get workflow runs + // Get cron job workflows // (GET /api/v1/tenants/{tenant}/workflows/crons) CronWorkflowList(ctx echo.Context, tenant openapi_types.UUID, params CronWorkflowListParams) error // Get workflow runs // (GET /api/v1/tenants/{tenant}/workflows/runs) WorkflowRunList(ctx echo.Context, tenant openapi_types.UUID, params WorkflowRunListParams) error - // Get workflow runs + // Get workflow runs metrics // (GET /api/v1/tenants/{tenant}/workflows/runs/metrics) WorkflowRunGetMetrics(ctx echo.Context, tenant openapi_types.UUID, params WorkflowRunGetMetricsParams) error - // Get workflow runs + // Get scheduled workflow runs // (GET /api/v1/tenants/{tenant}/workflows/scheduled) WorkflowScheduledList(ctx echo.Context, tenant openapi_types.UUID, params WorkflowScheduledListParams) error - // Delete tenant alert email group + // Delete scheduled workflow run // (DELETE /api/v1/tenants/{tenant}/workflows/scheduled/{scheduledId}) WorkflowScheduledDelete(ctx echo.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID) error - // Get workflow runs + // Get scheduled workflow run // (GET /api/v1/tenants/{tenant}/workflows/scheduled/{scheduledId}) WorkflowScheduledGet(ctx echo.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID) error // Get workflow worker count @@ -10132,192 +10132,192 @@ func (sh *strictHandler) WorkflowVersionGet(ctx echo.Context, workflow openapi_t // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "X368/P8AAAD//14C8qdU5QEA", + "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/frontend/app/src/lib/api/generated/Api.ts b/frontend/app/src/lib/api/generated/Api.ts index fca7a1536..ddae67815 100644 --- a/frontend/app/src/lib/api/generated/Api.ts +++ b/frontend/app/src/lib/api/generated/Api.ts @@ -1126,7 +1126,7 @@ export class Api extends HttpClient extends HttpClient extends HttpClient extends HttpClient extends HttpClient Date: Tue, 29 Oct 2024 08:36:01 -0400 Subject: [PATCH 21/30] fix: populator --- .../openapi/paths/workflow/workflow.yaml | 2 +- .../handlers/workflows/delete_scheduled.go | 7 ++- api/v1/server/oas/gen/openapi.gen.go | 44 +++++++++---------- api/v1/server/run/run.go | 19 ++++++++ 4 files changed, 47 insertions(+), 25 deletions(-) diff --git a/api-contracts/openapi/paths/workflow/workflow.yaml b/api-contracts/openapi/paths/workflow/workflow.yaml index ac07a9f33..c0f9cd64c 100644 --- a/api-contracts/openapi/paths/workflow/workflow.yaml +++ b/api-contracts/openapi/paths/workflow/workflow.yaml @@ -989,7 +989,7 @@ scheduled: tags: - Workflow delete: - x-resources: ["tenant"] + x-resources: ["tenant", "scheduled-workflow-run"] description: Delete a scheduled workflow run for a tenant operationId: workflow-scheduled:delete parameters: diff --git a/api/v1/server/handlers/workflows/delete_scheduled.go b/api/v1/server/handlers/workflows/delete_scheduled.go index 6cfcc414c..190bce1d6 100644 --- a/api/v1/server/handlers/workflows/delete_scheduled.go +++ b/api/v1/server/handlers/workflows/delete_scheduled.go @@ -8,15 +8,18 @@ import ( "github.com/hatchet-dev/hatchet/api/v1/server/oas/gen" "github.com/hatchet-dev/hatchet/pkg/repository/prisma/db" + "github.com/hatchet-dev/hatchet/pkg/repository/prisma/dbsqlc" + "github.com/hatchet-dev/hatchet/pkg/repository/prisma/sqlchelpers" ) func (t *WorkflowService) WorkflowScheduledDelete(ctx echo.Context, request gen.WorkflowScheduledDeleteRequestObject) (gen.WorkflowScheduledDeleteResponseObject, error) { - tenant := ctx.Get("tenant").(*db.TenantModel) + _ = ctx.Get("tenant").(*db.TenantModel) + scheduled := ctx.Get("scheduled-workflow-run").(*dbsqlc.ListScheduledWorkflowsRow) dbCtx, cancel := context.WithTimeout(ctx.Request().Context(), 30*time.Second) defer cancel() - err := t.config.APIRepository.WorkflowRun().DeleteScheduledWorkflow(dbCtx, tenant.ID, request.ScheduledId.String()) + err := t.config.APIRepository.WorkflowRun().DeleteScheduledWorkflow(dbCtx, sqlchelpers.UUIDToStr(scheduled.TenantId), request.ScheduledId.String()) if err != nil { return nil, err diff --git a/api/v1/server/oas/gen/openapi.gen.go b/api/v1/server/oas/gen/openapi.gen.go index 3ca482892..8b12b50ad 100644 --- a/api/v1/server/oas/gen/openapi.gen.go +++ b/api/v1/server/oas/gen/openapi.gen.go @@ -10318,28 +10318,28 @@ var swaggerSpec = []string{ "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", - "XieEJ93mAQA=", + "lJYlTGd12KxWYtAAtquXHPzM/hz6dmXY9XA2VFReeWl2DQ6M2ety/O6+SLtlNXX9lnYF8pbLmxvw1Cyu", + "JhtkbynCpldpBtwE173qNPTtZ7ltnrbdSfsaAlSan+9bOd6zCDyZJWvPi9KQ1Lw0sDYylkumzQL3AAVg", + "EkAmauS4RlHzBRKe3QifsBlffdhdXcjdKw+kKWzWiiKGkwonn06pN5gaC0haLRC3yP4phgk+8NIkgdWc", + "zUt4ioYO7aYt4vkFkhMx2BbpjhWrbEZnDOIugePLJ3C0rVXKHHKL5FasVVom4xki83Ry4IEgmFSViD6J", + "FjHVxBuUpf3ChmZ1aU/k8I3Lvnpi3m0Ufi3gTi6wqtSrEX2breerIE4W9G1NsdxmtXE1CIuiWQC3Q29s", + "6F+c3jj6NkxvOeJ+OXpD4T0i0Cahu9SGeYesEmTt8U1H4MXvhmKurRdZ5BNZmYEDhOXGFBfY6YvWxyrL", + "abCEvXLhQyPtHQDPgzGpqE/GvuPMnCQmMVQf5ZvP+7jbCW/mg/OJ6hOOV1AfX7mO/joTZ151iyGptPf2", + "9JVAFmpdkYmYfm9GX7yPu628vnTwDdAXX3lHXzVVlyiSVqCvIJqhijJsZ9EMOyh0ADsb9ysUjDM20HZo", + "iR3BdPwdVUawukcH0WwGfQd15cfbdX0uHuuUamzvyUE0i1JSwwxRSuy4IUpf3tYjaDRqWZ7QjkhrlFFG", + "PbZku4CLCUzwHMUNrkBKJ7trED9CvufdhDfkVglcP2nz+5CKou5OtMqdSMVgPUnGAOOHKPHNspSLSSFJ", + "Hdm+SqReyjG3p2OczEE4yyZqk7LhMcj8DFGdOH9F4pyTVZHSLZgogTMqyJKqSx9vgSs1kqzE2rbYRoLR", + "JoaRyOueuV6Fni5JyFbnwQHw7rbywjCmI7f4gaFG1DR8cViqiXrwU/xg4axqUdzR3g9VFgM1OoRkE+3Y", + "H8TSx7MrhdjCUoiZU3VdKcReRl92zHEg8Gxz35JNZV7kao4RRyi2DTVrLd9svkKpQM0qJYaz7erYs6U1", + "hvMtasqjGW+yP2xKpmmMG5zCLB24hbNZle8im+L1FihdwVexZep1ayqTNihM2pOkw8pqA+LNK8wmlYTM", + "W70aWt7CrZQhoHBuVJUTpfcOibLdVRC15DUOWcdpek4TDLEOsy2dJstO/lZhe5knslXIUIN7USs95ZtE", + "v2UAdmEyOwqTOTeUbRHEqlDMin7yPaticlac0EDlegsBIysGiXS89dK8pUajrMNYNmqfPXc10wNbwWDb", + "q+Mi6+3b1XDhWleRy3atHFpJhGX1sJMHRgVxPeasUROtEk7STSpmlswY7x4mmCf/MZ6UDRJMtoGfNUle", + "eIqWDWTgXj3/th6wWRKlMcuck4MgN8oICuv0DT4VgHkJtWHNbHaC9LqEdm3UJlbKoNdIcJEEzWZVbgZX", + "vIEDnBA+rFYtOvNBeJ2S60rDLvvOcMqs2zil1AH9nijTSiAmGU8h7Ewh8ebQN+VXywV/yxUpQQbKrtoq", + "U6U60i+hSY3SsN7Nimcv7Qpft0Ek9tz3x//YzawjIUNFskr46EHolx6spBysyTBiW9rfQjQL2YBtC/hL", + "qWMllv/gjV+RCeZXkMtblnJiU9dUBTt51yoVMCfFVVXAZR+yCQQJTDIfsp7Wqwwm91IepEngfnTd5x/P", + "/z8AAP//eDS2D/bmAQA=", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/v1/server/run/run.go b/api/v1/server/run/run.go index 1687ee08f..241fffc10 100644 --- a/api/v1/server/run/run.go +++ b/api/v1/server/run/run.go @@ -252,6 +252,16 @@ func (t *APIServer) registerSpec(g *echo.Group, spec *openapi3.T) (*populator.Po return workflowRun, sqlchelpers.UUIDToStr(workflowRun.TenantId), nil }) + populatorMW.RegisterGetter("scheduled-workflow-run", func(config *server.ServerConfig, parentId, id string) (result interface{}, uniqueParentId string, err error) { + scheduled, err := config.APIRepository.WorkflowRun().GetScheduledWorkflow(context.Background(), parentId, id) + + if err != nil { + return nil, "", err + } + + return scheduled, sqlchelpers.UUIDToStr(scheduled.TenantId), nil + }) + populatorMW.RegisterGetter("step-run", func(config *server.ServerConfig, parentId, id string) (result interface{}, uniqueParentId string, err error) { stepRun, err := config.APIRepository.StepRun().GetStepRunById(id) @@ -295,6 +305,15 @@ func (t *APIServer) registerSpec(g *echo.Group, spec *openapi3.T) (*populator.Po return webhookWorker, webhookWorker.TenantID, nil }) + populatorMW.RegisterGetter("webhook", func(config *server.ServerConfig, parentId, id string) (result interface{}, uniqueParentId string, err error) { + webhookWorker, err := config.APIRepository.WebhookWorker().GetWebhookWorkerByID(id) + if err != nil { + return nil, "", err + } + + return webhookWorker, webhookWorker.TenantID, nil + }) + authnMW := authn.NewAuthN(t.config) authzMW := authz.NewAuthZ(t.config) From e6c5091504b123621b120e9719cf6561f4b316a3 Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Wed, 30 Oct 2024 10:15:53 -0400 Subject: [PATCH 22/30] wip cron changes --- api-contracts/openapi/openapi.yaml | 2 +- .../openapi/paths/workflow/workflow.yaml | 55 +- .../server/handlers/workflows/delete_cron.go | 34 ++ .../server/handlers/workflows/list_crons.go | 4 +- api/v1/server/oas/gen/openapi.gen.go | 499 +++++++++++------- api/v1/server/run/run.go | 10 + frontend/app/src/lib/api/generated/Api.ts | 33 ++ internal/services/ticker/cron.go | 16 +- pkg/client/rest/gen.go | 175 ++++++ pkg/repository/prisma/dbsqlc/copyfrom.go | 3 +- pkg/repository/prisma/dbsqlc/models.go | 2 + pkg/repository/prisma/dbsqlc/schema.sql | 9 +- pkg/repository/prisma/dbsqlc/tickers.sql.go | 4 +- .../prisma/dbsqlc/workflow_runs.sql | 33 +- .../prisma/dbsqlc/workflow_runs.sql.go | 127 +---- pkg/repository/prisma/dbsqlc/workflows.sql | 62 ++- pkg/repository/prisma/dbsqlc/workflows.sql.go | 172 +++++- pkg/repository/prisma/workflow.go | 113 ++++ pkg/repository/prisma/workflow_run.go | 61 +-- pkg/repository/workflow.go | 22 + pkg/repository/workflow_run.go | 6 +- .../20241030131339_tmp/migration.sql | 23 + .../20241030133040_tmp/migration.sql | 10 + prisma/schema.prisma | 6 +- sql/migrations/20241030131347_tmp.sql | 6 + sql/migrations/20241030133048_tmp.sql | 2 + sql/migrations/atlas.sum | 4 +- sql/schema/schema.sql | 9 +- 28 files changed, 1099 insertions(+), 403 deletions(-) create mode 100644 api/v1/server/handlers/workflows/delete_cron.go create mode 100644 prisma/migrations/20241030131339_tmp/migration.sql create mode 100644 prisma/migrations/20241030133040_tmp/migration.sql create mode 100644 sql/migrations/20241030131347_tmp.sql create mode 100644 sql/migrations/20241030133048_tmp.sql diff --git a/api-contracts/openapi/openapi.yaml b/api-contracts/openapi/openapi.yaml index 8a4392be3..b9e169d79 100644 --- a/api-contracts/openapi/openapi.yaml +++ b/api-contracts/openapi/openapi.yaml @@ -121,7 +121,7 @@ paths: /api/v1/tenants/{tenant}/workflows/scheduled/{scheduledId}: $ref: "./paths/workflow/workflow.yaml#/scheduled" /api/v1/tenants/{tenant}/workflows/crons: - $ref: "./paths/workflow/workflow.yaml#/cronsList" + $ref: "./paths/workflow/workflow.yaml#/crons" /api/v1/tenants/{tenant}/workflows/cancel: $ref: "./paths/workflow/workflow.yaml#/cancelWorkflowRuns" /api/v1/workflows/{workflow}: diff --git a/api-contracts/openapi/paths/workflow/workflow.yaml b/api-contracts/openapi/paths/workflow/workflow.yaml index c0f9cd64c..e50a8ddb5 100644 --- a/api-contracts/openapi/paths/workflow/workflow.yaml +++ b/api-contracts/openapi/paths/workflow/workflow.yaml @@ -1030,7 +1030,60 @@ scheduled: tags: - Workflow -cronsList: +crons: + delete: + x-resources: ["tenant", "cron-workflow"] + description: Delete a cron job workflow run for a tenant + operationId: workflow-cron:delete + parameters: + - description: The tenant id + in: path + name: tenant + required: true + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + - description: The cron job parent id + in: query + name: cronParentId + required: true + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + - description: The cron job name + in: query + name: cronName + required: false + schema: + type: string + - description: Cron schedule + in: query + name: cron + required: true + schema: + type: string + responses: + "204": + description: Successfully deleted the cron job workflow run + "400": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: A malformed or bad request + "403": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIError" + description: Forbidden + summary: Delete cron job workflow run + tags: + - Workflow get: x-resources: ["tenant"] description: Get all cron job workflow runs for a tenant diff --git a/api/v1/server/handlers/workflows/delete_cron.go b/api/v1/server/handlers/workflows/delete_cron.go new file mode 100644 index 000000000..bbe7c6ac8 --- /dev/null +++ b/api/v1/server/handlers/workflows/delete_cron.go @@ -0,0 +1,34 @@ +package workflows + +import ( + "context" + "time" + + "github.com/labstack/echo/v4" + + "github.com/hatchet-dev/hatchet/api/v1/server/oas/gen" + "github.com/hatchet-dev/hatchet/pkg/repository/prisma/db" + "github.com/hatchet-dev/hatchet/pkg/repository/prisma/dbsqlc" + "github.com/hatchet-dev/hatchet/pkg/repository/prisma/sqlchelpers" +) + +func (t *WorkflowService) WorkflowCronDelete(ctx echo.Context, request gen.WorkflowCronDeleteRequestObject) (gen.WorkflowCronDeleteResponseObject, error) { + _ = ctx.Get("tenant").(*db.TenantModel) + cron := ctx.Get("cron-workflow").(*dbsqlc.ListCronWorkflowsRow) + + dbCtx, cancel := context.WithTimeout(ctx.Request().Context(), 30*time.Second) + defer cancel() + + err := t.config.APIRepository.Workflow().DeleteCronWorkflow(dbCtx, + sqlchelpers.UUIDToStr(cron.TenantId), + request.Params.Cron, + request.Params.CronParentId.String(), + request.Params.CronName, + ) + + if err != nil { + return nil, err + } + + return gen.WorkflowCronDelete204Response{}, nil +} diff --git a/api/v1/server/handlers/workflows/list_crons.go b/api/v1/server/handlers/workflows/list_crons.go index 692f4036d..ff6617310 100644 --- a/api/v1/server/handlers/workflows/list_crons.go +++ b/api/v1/server/handlers/workflows/list_crons.go @@ -22,7 +22,7 @@ func (t *WorkflowService) CronWorkflowList(ctx echo.Context, request gen.CronWor limit := 50 offset := 0 orderDirection := "DESC" - orderBy := "triggerAt" + orderBy := "createdAt" listOpts := &repository.ListCronWorkflowsOpts{ Limit: &limit, @@ -76,7 +76,7 @@ func (t *WorkflowService) CronWorkflowList(ctx echo.Context, request gen.CronWor dbCtx, cancel := context.WithTimeout(ctx.Request().Context(), 30*time.Second) defer cancel() - scheduled, count, err := t.config.APIRepository.WorkflowRun().ListCronWorkflows(dbCtx, tenant.ID, listOpts) + scheduled, count, err := t.config.APIRepository.Workflow().ListCronWorkflows(dbCtx, tenant.ID, listOpts) if err != nil { return nil, err diff --git a/api/v1/server/oas/gen/openapi.gen.go b/api/v1/server/oas/gen/openapi.gen.go index 8b12b50ad..945155af6 100644 --- a/api/v1/server/oas/gen/openapi.gen.go +++ b/api/v1/server/oas/gen/openapi.gen.go @@ -1540,6 +1540,18 @@ type WorkflowRunListStepRunEventsParams struct { LastId *int32 `form:"lastId,omitempty" json:"lastId,omitempty"` } +// WorkflowCronDeleteParams defines parameters for WorkflowCronDelete. +type WorkflowCronDeleteParams struct { + // CronParentId The cron job parent id + CronParentId openapi_types.UUID `form:"cronParentId" json:"cronParentId"` + + // CronName The cron job name + CronName *string `form:"cronName,omitempty" json:"cronName,omitempty"` + + // Cron Cron schedule + Cron string `form:"cron" json:"cron"` +} + // CronWorkflowListParams defines parameters for CronWorkflowList. type CronWorkflowListParams struct { // Offset The number to skip @@ -1929,6 +1941,9 @@ type ServerInterface interface { // Cancel workflow runs // (POST /api/v1/tenants/{tenant}/workflows/cancel) WorkflowRunCancel(ctx echo.Context, tenant openapi_types.UUID) error + // Delete cron job workflow run + // (DELETE /api/v1/tenants/{tenant}/workflows/crons) + WorkflowCronDelete(ctx echo.Context, tenant openapi_types.UUID, params WorkflowCronDeleteParams) error // Get cron job workflows // (GET /api/v1/tenants/{tenant}/workflows/crons) CronWorkflowList(ctx echo.Context, tenant openapi_types.UUID, params CronWorkflowListParams) error @@ -3411,6 +3426,49 @@ func (w *ServerInterfaceWrapper) WorkflowRunCancel(ctx echo.Context) error { return err } +// WorkflowCronDelete converts echo context to params. +func (w *ServerInterfaceWrapper) WorkflowCronDelete(ctx echo.Context) error { + var err error + // ------------- Path parameter "tenant" ------------- + var tenant openapi_types.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "tenant", runtime.ParamLocationPath, ctx.Param("tenant"), &tenant) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tenant: %s", err)) + } + + ctx.Set(BearerAuthScopes, []string{}) + + ctx.Set(CookieAuthScopes, []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params WorkflowCronDeleteParams + // ------------- Required query parameter "cronParentId" ------------- + + err = runtime.BindQueryParameter("form", true, true, "cronParentId", ctx.QueryParams(), ¶ms.CronParentId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter cronParentId: %s", err)) + } + + // ------------- Optional query parameter "cronName" ------------- + + err = runtime.BindQueryParameter("form", true, false, "cronName", ctx.QueryParams(), ¶ms.CronName) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter cronName: %s", err)) + } + + // ------------- Required query parameter "cron" ------------- + + err = runtime.BindQueryParameter("form", true, true, "cron", ctx.QueryParams(), ¶ms.Cron) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter cron: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.WorkflowCronDelete(ctx, tenant, params) + return err +} + // CronWorkflowList converts echo context to params. func (w *ServerInterfaceWrapper) CronWorkflowList(ctx echo.Context) error { var err error @@ -4307,6 +4365,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/api/v1/tenants/:tenant/workflow-runs/:workflow-run/step-run-events", wrapper.WorkflowRunListStepRunEvents) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows", wrapper.WorkflowList) router.POST(baseURL+"/api/v1/tenants/:tenant/workflows/cancel", wrapper.WorkflowRunCancel) + router.DELETE(baseURL+"/api/v1/tenants/:tenant/workflows/crons", wrapper.WorkflowCronDelete) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/crons", wrapper.CronWorkflowList) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/runs", wrapper.WorkflowRunList) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/runs/metrics", wrapper.WorkflowRunGetMetrics) @@ -6482,6 +6541,41 @@ func (response WorkflowRunCancel403JSONResponse) VisitWorkflowRunCancelResponse( return json.NewEncoder(w).Encode(response) } +type WorkflowCronDeleteRequestObject struct { + Tenant openapi_types.UUID `json:"tenant"` + Params WorkflowCronDeleteParams +} + +type WorkflowCronDeleteResponseObject interface { + VisitWorkflowCronDeleteResponse(w http.ResponseWriter) error +} + +type WorkflowCronDelete204Response struct { +} + +func (response WorkflowCronDelete204Response) VisitWorkflowCronDeleteResponse(w http.ResponseWriter) error { + w.WriteHeader(204) + return nil +} + +type WorkflowCronDelete400JSONResponse APIErrors + +func (response WorkflowCronDelete400JSONResponse) VisitWorkflowCronDeleteResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(400) + + return json.NewEncoder(w).Encode(response) +} + +type WorkflowCronDelete403JSONResponse APIError + +func (response WorkflowCronDelete403JSONResponse) VisitWorkflowCronDeleteResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(403) + + return json.NewEncoder(w).Encode(response) +} + type CronWorkflowListRequestObject struct { Tenant openapi_types.UUID `json:"tenant"` Params CronWorkflowListParams @@ -7742,6 +7836,8 @@ type StrictServerInterface interface { WorkflowRunCancel(ctx echo.Context, request WorkflowRunCancelRequestObject) (WorkflowRunCancelResponseObject, error) + WorkflowCronDelete(ctx echo.Context, request WorkflowCronDeleteRequestObject) (WorkflowCronDeleteResponseObject, error) + CronWorkflowList(ctx echo.Context, request CronWorkflowListRequestObject) (CronWorkflowListResponseObject, error) WorkflowRunList(ctx echo.Context, request WorkflowRunListRequestObject) (WorkflowRunListResponseObject, error) @@ -9344,6 +9440,32 @@ func (sh *strictHandler) WorkflowRunCancel(ctx echo.Context, tenant openapi_type return nil } +// WorkflowCronDelete operation middleware +func (sh *strictHandler) WorkflowCronDelete(ctx echo.Context, tenant openapi_types.UUID, params WorkflowCronDeleteParams) error { + var request WorkflowCronDeleteRequestObject + + request.Tenant = tenant + request.Params = params + + handler := func(ctx echo.Context, request interface{}) (interface{}, error) { + return sh.ssi.WorkflowCronDelete(ctx, request.(WorkflowCronDeleteRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "WorkflowCronDelete") + } + + response, err := handler(ctx, request) + + if err != nil { + return err + } else if validResponse, ok := response.(WorkflowCronDeleteResponseObject); ok { + return validResponse.VisitWorkflowCronDeleteResponse(ctx.Response()) + } else if response != nil { + return fmt.Errorf("Unexpected response type: %T", response) + } + return nil +} + // CronWorkflowList operation middleware func (sh *strictHandler) CronWorkflowList(ctx echo.Context, tenant openapi_types.UUID, params CronWorkflowListParams) error { var request CronWorkflowListRequestObject @@ -10152,194 +10274,195 @@ func (sh *strictHandler) WorkflowVersionGet(ctx echo.Context, workflow openapi_t // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "/z8AAP//eDS2D/bmAQA=", + "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/v1/server/run/run.go b/api/v1/server/run/run.go index 241fffc10..c42a6039c 100644 --- a/api/v1/server/run/run.go +++ b/api/v1/server/run/run.go @@ -262,6 +262,16 @@ func (t *APIServer) registerSpec(g *echo.Group, spec *openapi3.T) (*populator.Po return scheduled, sqlchelpers.UUIDToStr(scheduled.TenantId), nil }) + populatorMW.RegisterGetter("cron-workflow", func(config *server.ServerConfig, parentId, id string) (result interface{}, uniqueParentId string, err error) { + scheduled, err := config.APIRepository.Workflow().GetCronWorkflow(context.Background(), parentId, id) + + if err != nil { + return nil, "", err + } + + return scheduled, sqlchelpers.UUIDToStr(scheduled.TenantId), nil + }) + populatorMW.RegisterGetter("step-run", func(config *server.ServerConfig, parentId, id string) (result interface{}, uniqueParentId string, err error) { stepRun, err := config.APIRepository.StepRun().GetStepRunById(id) diff --git a/frontend/app/src/lib/api/generated/Api.ts b/frontend/app/src/lib/api/generated/Api.ts index ddae67815..28cd5ce1f 100644 --- a/frontend/app/src/lib/api/generated/Api.ts +++ b/frontend/app/src/lib/api/generated/Api.ts @@ -1219,6 +1219,39 @@ export class Api extends HttpClient + this.request({ + path: `/api/v1/tenants/${tenant}/workflows/crons`, + method: 'DELETE', + query: query, + secure: true, + ...params, + }); /** * @description Get all cron job workflow runs for a tenant * diff --git a/internal/services/ticker/cron.go b/internal/services/ticker/cron.go index 176e6ab54..9049c0c19 100644 --- a/internal/services/ticker/cron.go +++ b/internal/services/ticker/cron.go @@ -2,6 +2,7 @@ package ticker import ( "context" + "encoding/json" "fmt" "time" @@ -79,11 +80,19 @@ func (t *TickerImpl) handleScheduleCron(ctx context.Context, cron *dbsqlc.PollCr workflowVersionId := sqlchelpers.UUIDToStr(cron.WorkflowVersionId) cronParentId := sqlchelpers.UUIDToStr(cron.ParentId) + var additionalMetadata map[string]interface{} + + if cron.AdditionalMetadata != nil { + if err := json.Unmarshal(cron.AdditionalMetadata, &additionalMetadata); err != nil { + return fmt.Errorf("could not unmarshal additional metadata: %w", err) + } + } + // schedule the cron _, err = s.NewJob( gocron.CronJob(cron.Cron, false), gocron.NewTask( - t.runCronWorkflow(tenantId, workflowVersionId, cron.Cron, cronParentId, cron.Input), + t.runCronWorkflow(tenantId, workflowVersionId, cron.Cron, cronParentId, &cron.Name.String, cron.Input, additionalMetadata), ), ) @@ -99,7 +108,7 @@ func (t *TickerImpl) handleScheduleCron(ctx context.Context, cron *dbsqlc.PollCr return nil } -func (t *TickerImpl) runCronWorkflow(tenantId, workflowVersionId, cron, cronParentId string, input []byte) func() { +func (t *TickerImpl) runCronWorkflow(tenantId, workflowVersionId, cron, cronParentId string, cronName *string, input []byte, additionalMetadata map[string]interface{}) func() { return func() { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() @@ -113,8 +122,7 @@ func (t *TickerImpl) runCronWorkflow(tenantId, workflowVersionId, cron, cronPare return } // create a new workflow run in the database - // FIXME additionalMetadata is not used for cron runs - createOpts, err := repository.GetCreateWorkflowRunOptsFromCron(cron, cronParentId, workflowVersion, input, nil) + createOpts, err := repository.GetCreateWorkflowRunOptsFromCron(cron, cronParentId, cronName, workflowVersion, input, additionalMetadata) if err != nil { t.l.Err(err).Msg("could not get create workflow run opts") diff --git a/pkg/client/rest/gen.go b/pkg/client/rest/gen.go index c9b6bcb94..4cfba2f10 100644 --- a/pkg/client/rest/gen.go +++ b/pkg/client/rest/gen.go @@ -1537,6 +1537,18 @@ type WorkflowRunListStepRunEventsParams struct { LastId *int32 `form:"lastId,omitempty" json:"lastId,omitempty"` } +// WorkflowCronDeleteParams defines parameters for WorkflowCronDelete. +type WorkflowCronDeleteParams struct { + // CronParentId The cron job parent id + CronParentId openapi_types.UUID `form:"cronParentId" json:"cronParentId"` + + // CronName The cron job name + CronName *string `form:"cronName,omitempty" json:"cronName,omitempty"` + + // Cron Cron schedule + Cron string `form:"cron" json:"cron"` +} + // CronWorkflowListParams defines parameters for CronWorkflowList. type CronWorkflowListParams struct { // Offset The number to skip @@ -2029,6 +2041,9 @@ type ClientInterface interface { WorkflowRunCancel(ctx context.Context, tenant openapi_types.UUID, body WorkflowRunCancelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // WorkflowCronDelete request + WorkflowCronDelete(ctx context.Context, tenant openapi_types.UUID, params *WorkflowCronDeleteParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // CronWorkflowList request CronWorkflowList(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -3015,6 +3030,18 @@ func (c *Client) WorkflowRunCancel(ctx context.Context, tenant openapi_types.UUI return c.Client.Do(req) } +func (c *Client) WorkflowCronDelete(ctx context.Context, tenant openapi_types.UUID, params *WorkflowCronDeleteParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewWorkflowCronDeleteRequest(c.Server, tenant, params) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) CronWorkflowList(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewCronWorkflowListRequest(c.Server, tenant, params) if err != nil { @@ -6161,6 +6188,86 @@ func NewWorkflowRunCancelRequestWithBody(server string, tenant openapi_types.UUI return req, nil } +// NewWorkflowCronDeleteRequest generates requests for WorkflowCronDelete +func NewWorkflowCronDeleteRequest(server string, tenant openapi_types.UUID, params *WorkflowCronDeleteParams) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "tenant", runtime.ParamLocationPath, tenant) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/api/v1/tenants/%s/workflows/crons", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + if params != nil { + queryValues := queryURL.Query() + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "cronParentId", runtime.ParamLocationQuery, params.CronParentId); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + if params.CronName != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "cronName", runtime.ParamLocationQuery, *params.CronName); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "cron", runtime.ParamLocationQuery, params.Cron); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + queryURL.RawQuery = queryValues.Encode() + } + + req, err := http.NewRequest("DELETE", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewCronWorkflowListRequest generates requests for CronWorkflowList func NewCronWorkflowListRequest(server string, tenant openapi_types.UUID, params *CronWorkflowListParams) (*http.Request, error) { var err error @@ -8186,6 +8293,9 @@ type ClientWithResponsesInterface interface { WorkflowRunCancelWithResponse(ctx context.Context, tenant openapi_types.UUID, body WorkflowRunCancelJSONRequestBody, reqEditors ...RequestEditorFn) (*WorkflowRunCancelResponse, error) + // WorkflowCronDeleteWithResponse request + WorkflowCronDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, params *WorkflowCronDeleteParams, reqEditors ...RequestEditorFn) (*WorkflowCronDeleteResponse, error) + // CronWorkflowListWithResponse request CronWorkflowListWithResponse(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*CronWorkflowListResponse, error) @@ -9671,6 +9781,29 @@ func (r WorkflowRunCancelResponse) StatusCode() int { return 0 } +type WorkflowCronDeleteResponse struct { + Body []byte + HTTPResponse *http.Response + JSON400 *APIErrors + JSON403 *APIError +} + +// Status returns HTTPResponse.Status +func (r WorkflowCronDeleteResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r WorkflowCronDeleteResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type CronWorkflowListResponse struct { Body []byte HTTPResponse *http.Response @@ -11050,6 +11183,15 @@ func (c *ClientWithResponses) WorkflowRunCancelWithResponse(ctx context.Context, return ParseWorkflowRunCancelResponse(rsp) } +// WorkflowCronDeleteWithResponse request returning *WorkflowCronDeleteResponse +func (c *ClientWithResponses) WorkflowCronDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, params *WorkflowCronDeleteParams, reqEditors ...RequestEditorFn) (*WorkflowCronDeleteResponse, error) { + rsp, err := c.WorkflowCronDelete(ctx, tenant, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseWorkflowCronDeleteResponse(rsp) +} + // CronWorkflowListWithResponse request returning *CronWorkflowListResponse func (c *ClientWithResponses) CronWorkflowListWithResponse(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*CronWorkflowListResponse, error) { rsp, err := c.CronWorkflowList(ctx, tenant, params, reqEditors...) @@ -13689,6 +13831,39 @@ func ParseWorkflowRunCancelResponse(rsp *http.Response) (*WorkflowRunCancelRespo return response, nil } +// ParseWorkflowCronDeleteResponse parses an HTTP response from a WorkflowCronDeleteWithResponse call +func ParseWorkflowCronDeleteResponse(rsp *http.Response) (*WorkflowCronDeleteResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &WorkflowCronDeleteResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest APIError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + } + + return response, nil +} + // ParseCronWorkflowListResponse parses an HTTP response from a CronWorkflowListWithResponse call func ParseCronWorkflowListResponse(rsp *http.Response) (*CronWorkflowListResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/pkg/repository/prisma/dbsqlc/copyfrom.go b/pkg/repository/prisma/dbsqlc/copyfrom.go index 953a92d7a..db902bbec 100644 --- a/pkg/repository/prisma/dbsqlc/copyfrom.go +++ b/pkg/repository/prisma/dbsqlc/copyfrom.go @@ -192,6 +192,7 @@ func (r iteratorForCreateWorkflowRunTriggeredBys) Values() ([]interface{}, error r.rows[0].EventId, r.rows[0].CronParentId, r.rows[0].CronSchedule, + r.rows[0].CronName, r.rows[0].ScheduledId, }, nil } @@ -201,7 +202,7 @@ func (r iteratorForCreateWorkflowRunTriggeredBys) Err() error { } func (q *Queries) CreateWorkflowRunTriggeredBys(ctx context.Context, db DBTX, arg []CreateWorkflowRunTriggeredBysParams) (int64, error) { - return db.CopyFrom(ctx, []string{"WorkflowRunTriggeredBy"}, []string{"id", "tenantId", "parentId", "eventId", "cronParentId", "cronSchedule", "scheduledId"}, &iteratorForCreateWorkflowRunTriggeredBys{rows: arg}) + return db.CopyFrom(ctx, []string{"WorkflowRunTriggeredBy"}, []string{"id", "tenantId", "parentId", "eventId", "cronParentId", "cronSchedule", "cronName", "scheduledId"}, &iteratorForCreateWorkflowRunTriggeredBys{rows: arg}) } // iteratorForCreateWorkflowRuns implements pgx.CopyFromSource. diff --git a/pkg/repository/prisma/dbsqlc/models.go b/pkg/repository/prisma/dbsqlc/models.go index fcc244fa4..46723d049 100644 --- a/pkg/repository/prisma/dbsqlc/models.go +++ b/pkg/repository/prisma/dbsqlc/models.go @@ -1699,6 +1699,7 @@ type WorkflowRunTriggeredBy struct { ScheduledId pgtype.UUID `json:"scheduledId"` Input []byte `json:"input"` ParentId pgtype.UUID `json:"parentId"` + CronName pgtype.Text `json:"cronName"` } type WorkflowTag struct { @@ -1725,6 +1726,7 @@ type WorkflowTriggerCronRef struct { CreatedAt pgtype.Timestamp `json:"createdAt"` DeletedAt pgtype.Timestamp `json:"deletedAt"` UpdatedAt pgtype.Timestamp `json:"updatedAt"` + Name pgtype.Text `json:"name"` } type WorkflowTriggerEventRef struct { diff --git a/pkg/repository/prisma/dbsqlc/schema.sql b/pkg/repository/prisma/dbsqlc/schema.sql index 665819895..bbb89b074 100644 --- a/pkg/repository/prisma/dbsqlc/schema.sql +++ b/pkg/repository/prisma/dbsqlc/schema.sql @@ -879,6 +879,7 @@ CREATE TABLE "WorkflowRunTriggeredBy" ( "scheduledId" UUID, "input" JSONB, "parentId" UUID NOT NULL, + "cronName" TEXT, CONSTRAINT "WorkflowRunTriggeredBy_pkey" PRIMARY KEY ("id") ); @@ -905,7 +906,8 @@ CREATE TABLE "WorkflowTriggerCronRef" ( "additionalMetadata" JSONB, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "deletedAt" TIMESTAMP(3), - "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "name" TEXT ); -- CreateTable @@ -1369,6 +1371,9 @@ CREATE UNIQUE INDEX "WorkflowTag_tenantId_name_key" ON "WorkflowTag"("tenantId" -- CreateIndex CREATE UNIQUE INDEX "WorkflowTriggerCronRef_parentId_cron_key" ON "WorkflowTriggerCronRef"("parentId" ASC, "cron" ASC); +-- CreateIndex +CREATE UNIQUE INDEX "WorkflowTriggerCronRef_parentId_cron_name_key" ON "WorkflowTriggerCronRef"("parentId" ASC, "cron" ASC, "name" ASC); + -- CreateIndex CREATE UNIQUE INDEX "WorkflowTriggerEventRef_parentId_eventKey_key" ON "WorkflowTriggerEventRef"("parentId" ASC, "eventKey" ASC); @@ -1577,7 +1582,7 @@ ALTER TABLE "WorkflowRun" ADD CONSTRAINT "WorkflowRun_parentStepRunId_fkey" FORE ALTER TABLE "WorkflowRunStickyState" ADD CONSTRAINT "WorkflowRunStickyState_workflowRunId_fkey" FOREIGN KEY ("workflowRunId") REFERENCES "WorkflowRun"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey -ALTER TABLE "WorkflowRunTriggeredBy" ADD CONSTRAINT "WorkflowRunTriggeredBy_cronParentId_cronSchedule_fkey" FOREIGN KEY ("cronParentId", "cronSchedule") REFERENCES "WorkflowTriggerCronRef"("parentId", "cron") ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE "WorkflowRunTriggeredBy" ADD CONSTRAINT "WorkflowRunTriggeredBy_cronParentId_cronSchedule_cronName_fkey" FOREIGN KEY ("cronParentId", "cronSchedule", "cronName") REFERENCES "WorkflowTriggerCronRef"("parentId", "cron", "name") ON DELETE SET NULL ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "WorkflowRunTriggeredBy" ADD CONSTRAINT "WorkflowRunTriggeredBy_scheduledId_fkey" FOREIGN KEY ("scheduledId") REFERENCES "WorkflowTriggerScheduledRef"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/pkg/repository/prisma/dbsqlc/tickers.sql.go b/pkg/repository/prisma/dbsqlc/tickers.sql.go index bcffe7861..8a4459f48 100644 --- a/pkg/repository/prisma/dbsqlc/tickers.sql.go +++ b/pkg/repository/prisma/dbsqlc/tickers.sql.go @@ -227,7 +227,7 @@ FROM active_cron_schedules WHERE cronSchedules."parentId" = active_cron_schedules."parentId" -RETURNING cronschedules."parentId", cronschedules.cron, cronschedules."tickerId", cronschedules.input, cronschedules.enabled, cronschedules."additionalMetadata", cronschedules."createdAt", cronschedules."deletedAt", cronschedules."updatedAt", active_cron_schedules."workflowVersionId", active_cron_schedules."tenantId" +RETURNING cronschedules."parentId", cronschedules.cron, cronschedules."tickerId", cronschedules.input, cronschedules.enabled, cronschedules."additionalMetadata", cronschedules."createdAt", cronschedules."deletedAt", cronschedules."updatedAt", cronschedules.name, active_cron_schedules."workflowVersionId", active_cron_schedules."tenantId" ` type PollCronSchedulesRow struct { @@ -240,6 +240,7 @@ type PollCronSchedulesRow struct { CreatedAt pgtype.Timestamp `json:"createdAt"` DeletedAt pgtype.Timestamp `json:"deletedAt"` UpdatedAt pgtype.Timestamp `json:"updatedAt"` + Name pgtype.Text `json:"name"` WorkflowVersionId pgtype.UUID `json:"workflowVersionId"` TenantId pgtype.UUID `json:"tenantId"` } @@ -263,6 +264,7 @@ func (q *Queries) PollCronSchedules(ctx context.Context, db DBTX, tickerid pgtyp &i.CreatedAt, &i.DeletedAt, &i.UpdatedAt, + &i.Name, &i.WorkflowVersionId, &i.TenantId, ); err != nil { diff --git a/pkg/repository/prisma/dbsqlc/workflow_runs.sql b/pkg/repository/prisma/dbsqlc/workflow_runs.sql index effacde47..30dd0a1d4 100644 --- a/pkg/repository/prisma/dbsqlc/workflow_runs.sql +++ b/pkg/repository/prisma/dbsqlc/workflow_runs.sql @@ -684,6 +684,7 @@ INSERT INTO "WorkflowRunTriggeredBy" ( "eventId", "cronParentId", "cronSchedule", + "cronName", "scheduledId" ) VALUES ( gen_random_uuid(), @@ -694,12 +695,12 @@ INSERT INTO "WorkflowRunTriggeredBy" ( @workflowRunId::uuid, sqlc.narg('eventId')::uuid, sqlc.narg('cronParentId')::uuid, - sqlc.narg('cron')::text, + sqlc.narg('cronSchedule')::text, + sqlc.narg('cronName')::text, sqlc.narg('scheduledId')::uuid ) RETURNING *; -- name: CreateWorkflowRunTriggeredBys :copyfrom - INSERT INTO "WorkflowRunTriggeredBy" ( "id", "tenantId", @@ -707,6 +708,7 @@ INSERT INTO "WorkflowRunTriggeredBy" ( "eventId", "cronParentId", "cronSchedule", + "cronName", "scheduledId" ) VALUES ( $1, @@ -715,8 +717,8 @@ INSERT INTO "WorkflowRunTriggeredBy" ( $4, $5, $6, - $7 - + $7, + $8 ); -- name: CreateGetGroupKeyRun :one @@ -1495,29 +1497,6 @@ DELETE FROM "WorkflowTriggerScheduledRef" WHERE "id" = @scheduleId::uuid; --- name: ListCronWorkflows :many -SELECT - w."name", - w."id" as "workflowId", - v."id" as "workflowVersionId", - w."tenantId", - t.*, - c.* -FROM "WorkflowTriggerCronRef" c -JOIN "WorkflowTriggers" t ON c."parentId" = t."id" -JOIN "WorkflowVersion" v ON t."workflowVersionId" = v."id" -JOIN "Workflow" w on v."workflowId" = w."id" -WHERE v."deletedAt" IS NULL - AND w."tenantId" = @tenantId::uuid -ORDER BY - case when @orderBy = 'createdAt ASC' THEN t."createdAt" END ASC , - case when @orderBy = 'createdAt DESC' THEN t."createdAt" END DESC, - t."id" ASC -OFFSET - COALESCE(sqlc.narg('offset'), 0) -LIMIT - COALESCE(sqlc.narg('limit'), 50); - -- name: CountCronWorkflows :one SELECT count(*) FROM "WorkflowTriggerCronRef" c diff --git a/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go b/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go index 8dc997988..3095a290b 100644 --- a/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go +++ b/pkg/repository/prisma/dbsqlc/workflow_runs.sql.go @@ -1028,6 +1028,7 @@ INSERT INTO "WorkflowRunTriggeredBy" ( "eventId", "cronParentId", "cronSchedule", + "cronName", "scheduledId" ) VALUES ( gen_random_uuid(), @@ -1039,8 +1040,9 @@ INSERT INTO "WorkflowRunTriggeredBy" ( $3::uuid, $4::uuid, $5::text, - $6::uuid -) RETURNING id, "createdAt", "updatedAt", "deletedAt", "tenantId", "eventId", "cronParentId", "cronSchedule", "scheduledId", input, "parentId" + $6::text, + $7::uuid +) RETURNING id, "createdAt", "updatedAt", "deletedAt", "tenantId", "eventId", "cronParentId", "cronSchedule", "scheduledId", input, "parentId", "cronName" ` type CreateWorkflowRunTriggeredByParams struct { @@ -1048,7 +1050,8 @@ type CreateWorkflowRunTriggeredByParams struct { Workflowrunid pgtype.UUID `json:"workflowrunid"` EventId pgtype.UUID `json:"eventId"` CronParentId pgtype.UUID `json:"cronParentId"` - Cron pgtype.Text `json:"cron"` + CronSchedule pgtype.Text `json:"cronSchedule"` + CronName pgtype.Text `json:"cronName"` ScheduledId pgtype.UUID `json:"scheduledId"` } @@ -1058,7 +1061,8 @@ func (q *Queries) CreateWorkflowRunTriggeredBy(ctx context.Context, db DBTX, arg arg.Workflowrunid, arg.EventId, arg.CronParentId, - arg.Cron, + arg.CronSchedule, + arg.CronName, arg.ScheduledId, ) var i WorkflowRunTriggeredBy @@ -1074,6 +1078,7 @@ func (q *Queries) CreateWorkflowRunTriggeredBy(ctx context.Context, db DBTX, arg &i.ScheduledId, &i.Input, &i.ParentId, + &i.CronName, ) return &i, err } @@ -1085,6 +1090,7 @@ type CreateWorkflowRunTriggeredBysParams struct { EventId pgtype.UUID `json:"eventId"` CronParentId pgtype.UUID `json:"cronParentId"` CronSchedule pgtype.Text `json:"cronSchedule"` + CronName pgtype.Text `json:"cronName"` ScheduledId pgtype.UUID `json:"scheduledId"` } @@ -1539,7 +1545,7 @@ func (q *Queries) GetStepsForWorkflowVersion(ctx context.Context, db DBTX, workf const getWorkflowRun = `-- name: GetWorkflowRun :many SELECT runs."createdAt", runs."updatedAt", runs."deletedAt", runs."tenantId", runs."workflowVersionId", runs.status, runs.error, runs."startedAt", runs."finishedAt", runs."concurrencyGroupId", runs."displayName", runs.id, runs."childIndex", runs."childKey", runs."parentId", runs."parentStepRunId", runs."additionalMetadata", runs.duration, runs.priority, runs."insertOrder", - runtriggers.id, runtriggers."createdAt", runtriggers."updatedAt", runtriggers."deletedAt", runtriggers."tenantId", runtriggers."eventId", runtriggers."cronParentId", runtriggers."cronSchedule", runtriggers."scheduledId", runtriggers.input, runtriggers."parentId", + runtriggers.id, runtriggers."createdAt", runtriggers."updatedAt", runtriggers."deletedAt", runtriggers."tenantId", runtriggers."eventId", runtriggers."cronParentId", runtriggers."cronSchedule", runtriggers."scheduledId", runtriggers.input, runtriggers."parentId", runtriggers."cronName", workflowversion.id, workflowversion."createdAt", workflowversion."updatedAt", workflowversion."deletedAt", workflowversion.version, workflowversion."order", workflowversion."workflowId", workflowversion.checksum, workflowversion."scheduleTimeout", workflowversion."onFailureJobId", workflowversion.sticky, workflowversion.kind, workflowversion."defaultPriority", workflow."name" as "workflowName", -- waiting on https://github.com/sqlc-dev/sqlc/pull/2858 for nullable fields @@ -1626,6 +1632,7 @@ func (q *Queries) GetWorkflowRun(ctx context.Context, db DBTX, arg GetWorkflowRu &i.WorkflowRunTriggeredBy.ScheduledId, &i.WorkflowRunTriggeredBy.Input, &i.WorkflowRunTriggeredBy.ParentId, + &i.WorkflowRunTriggeredBy.CronName, &i.WorkflowVersion.ID, &i.WorkflowVersion.CreatedAt, &i.WorkflowVersion.UpdatedAt, @@ -1689,7 +1696,7 @@ SELECT r."createdAt", r."updatedAt", r."deletedAt", r."tenantId", r."workflowVersionId", r.status, r.error, r."startedAt", r."finishedAt", r."concurrencyGroupId", r."displayName", r.id, r."childIndex", r."childKey", r."parentId", r."parentStepRunId", r."additionalMetadata", r.duration, r.priority, r."insertOrder", wv.id, wv."createdAt", wv."updatedAt", wv."deletedAt", wv.version, wv."order", wv."workflowId", wv.checksum, wv."scheduleTimeout", wv."onFailureJobId", wv.sticky, wv.kind, wv."defaultPriority", w.id, w."createdAt", w."updatedAt", w."deletedAt", w."tenantId", w.name, w.description, w."isPaused", - tb.id, tb."createdAt", tb."updatedAt", tb."deletedAt", tb."tenantId", tb."eventId", tb."cronParentId", tb."cronSchedule", tb."scheduledId", tb.input, tb."parentId" + tb.id, tb."createdAt", tb."updatedAt", tb."deletedAt", tb."tenantId", tb."eventId", tb."cronParentId", tb."cronSchedule", tb."scheduledId", tb.input, tb."parentId", tb."cronName" FROM "WorkflowRun" r JOIN @@ -1791,6 +1798,7 @@ func (q *Queries) GetWorkflowRunById(ctx context.Context, db DBTX, arg GetWorkfl &i.WorkflowRunTriggeredBy.ScheduledId, &i.WorkflowRunTriggeredBy.Input, &i.WorkflowRunTriggeredBy.ParentId, + &i.WorkflowRunTriggeredBy.CronName, ) return &i, err } @@ -1800,7 +1808,7 @@ SELECT r."createdAt", r."updatedAt", r."deletedAt", r."tenantId", r."workflowVersionId", r.status, r.error, r."startedAt", r."finishedAt", r."concurrencyGroupId", r."displayName", r.id, r."childIndex", r."childKey", r."parentId", r."parentStepRunId", r."additionalMetadata", r.duration, r.priority, r."insertOrder", wv.id, wv."createdAt", wv."updatedAt", wv."deletedAt", wv.version, wv."order", wv."workflowId", wv.checksum, wv."scheduleTimeout", wv."onFailureJobId", wv.sticky, wv.kind, wv."defaultPriority", w.id, w."createdAt", w."updatedAt", w."deletedAt", w."tenantId", w.name, w.description, w."isPaused", - tb.id, tb."createdAt", tb."updatedAt", tb."deletedAt", tb."tenantId", tb."eventId", tb."cronParentId", tb."cronSchedule", tb."scheduledId", tb.input, tb."parentId" + tb.id, tb."createdAt", tb."updatedAt", tb."deletedAt", tb."tenantId", tb."eventId", tb."cronParentId", tb."cronSchedule", tb."scheduledId", tb.input, tb."parentId", tb."cronName" FROM "WorkflowRun" r JOIN @@ -1908,6 +1916,7 @@ func (q *Queries) GetWorkflowRunByIds(ctx context.Context, db DBTX, arg GetWorkf &i.WorkflowRunTriggeredBy.ScheduledId, &i.WorkflowRunTriggeredBy.Input, &i.WorkflowRunTriggeredBy.ParentId, + &i.WorkflowRunTriggeredBy.CronName, ); err != nil { return nil, err } @@ -1966,7 +1975,7 @@ func (q *Queries) GetWorkflowRunStickyStateForUpdate(ctx context.Context, db DBT } const getWorkflowRunTrigger = `-- name: GetWorkflowRunTrigger :one -SELECT id, "createdAt", "updatedAt", "deletedAt", "tenantId", "eventId", "cronParentId", "cronSchedule", "scheduledId", input, "parentId" +SELECT id, "createdAt", "updatedAt", "deletedAt", "tenantId", "eventId", "cronParentId", "cronSchedule", "scheduledId", input, "parentId", "cronName" FROM "WorkflowRunTriggeredBy" WHERE @@ -1994,6 +2003,7 @@ func (q *Queries) GetWorkflowRunTrigger(ctx context.Context, db DBTX, arg GetWor &i.ScheduledId, &i.Input, &i.ParentId, + &i.CronName, ) return &i, err } @@ -2173,104 +2183,6 @@ func (q *Queries) ListChildWorkflowRunCounts(ctx context.Context, db DBTX, stepr return items, nil } -const listCronWorkflows = `-- name: ListCronWorkflows :many -SELECT - w."name", - w."id" as "workflowId", - v."id" as "workflowVersionId", - w."tenantId", - t.id, t."createdAt", t."updatedAt", t."deletedAt", t."workflowVersionId", t."tenantId", - c."parentId", c.cron, c."tickerId", c.input, c.enabled, c."additionalMetadata", c."createdAt", c."deletedAt", c."updatedAt" -FROM "WorkflowTriggerCronRef" c -JOIN "WorkflowTriggers" t ON c."parentId" = t."id" -JOIN "WorkflowVersion" v ON t."workflowVersionId" = v."id" -JOIN "Workflow" w on v."workflowId" = w."id" -WHERE v."deletedAt" IS NULL - AND w."tenantId" = $1::uuid -ORDER BY - case when $2 = 'createdAt ASC' THEN t."createdAt" END ASC , - case when $2 = 'createdAt DESC' THEN t."createdAt" END DESC, - t."id" ASC -OFFSET - COALESCE($3, 0) -LIMIT - COALESCE($4, 50) -` - -type ListCronWorkflowsParams struct { - Tenantid pgtype.UUID `json:"tenantid"` - Orderby interface{} `json:"orderby"` - Offset interface{} `json:"offset"` - Limit interface{} `json:"limit"` -} - -type ListCronWorkflowsRow struct { - Name string `json:"name"` - WorkflowId pgtype.UUID `json:"workflowId"` - WorkflowVersionId pgtype.UUID `json:"workflowVersionId"` - TenantId pgtype.UUID `json:"tenantId"` - ID pgtype.UUID `json:"id"` - CreatedAt pgtype.Timestamp `json:"createdAt"` - UpdatedAt pgtype.Timestamp `json:"updatedAt"` - DeletedAt pgtype.Timestamp `json:"deletedAt"` - WorkflowVersionId_2 pgtype.UUID `json:"workflowVersionId_2"` - TenantId_2 pgtype.UUID `json:"tenantId_2"` - ParentId pgtype.UUID `json:"parentId"` - Cron string `json:"cron"` - TickerId pgtype.UUID `json:"tickerId"` - Input []byte `json:"input"` - Enabled bool `json:"enabled"` - AdditionalMetadata []byte `json:"additionalMetadata"` - CreatedAt_2 pgtype.Timestamp `json:"createdAt_2"` - DeletedAt_2 pgtype.Timestamp `json:"deletedAt_2"` - UpdatedAt_2 pgtype.Timestamp `json:"updatedAt_2"` -} - -func (q *Queries) ListCronWorkflows(ctx context.Context, db DBTX, arg ListCronWorkflowsParams) ([]*ListCronWorkflowsRow, error) { - rows, err := db.Query(ctx, listCronWorkflows, - arg.Tenantid, - arg.Orderby, - arg.Offset, - arg.Limit, - ) - if err != nil { - return nil, err - } - defer rows.Close() - var items []*ListCronWorkflowsRow - for rows.Next() { - var i ListCronWorkflowsRow - if err := rows.Scan( - &i.Name, - &i.WorkflowId, - &i.WorkflowVersionId, - &i.TenantId, - &i.ID, - &i.CreatedAt, - &i.UpdatedAt, - &i.DeletedAt, - &i.WorkflowVersionId_2, - &i.TenantId_2, - &i.ParentId, - &i.Cron, - &i.TickerId, - &i.Input, - &i.Enabled, - &i.AdditionalMetadata, - &i.CreatedAt_2, - &i.DeletedAt_2, - &i.UpdatedAt_2, - ); err != nil { - return nil, err - } - items = append(items, &i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - const listScheduledWorkflows = `-- name: ListScheduledWorkflows :many SELECT w."name", @@ -2493,7 +2405,7 @@ const listWorkflowRuns = `-- name: ListWorkflowRuns :many SELECT runs."createdAt", runs."updatedAt", runs."deletedAt", runs."tenantId", runs."workflowVersionId", runs.status, runs.error, runs."startedAt", runs."finishedAt", runs."concurrencyGroupId", runs."displayName", runs.id, runs."childIndex", runs."childKey", runs."parentId", runs."parentStepRunId", runs."additionalMetadata", runs.duration, runs.priority, runs."insertOrder", workflow.id, workflow."createdAt", workflow."updatedAt", workflow."deletedAt", workflow."tenantId", workflow.name, workflow.description, workflow."isPaused", - runtriggers.id, runtriggers."createdAt", runtriggers."updatedAt", runtriggers."deletedAt", runtriggers."tenantId", runtriggers."eventId", runtriggers."cronParentId", runtriggers."cronSchedule", runtriggers."scheduledId", runtriggers.input, runtriggers."parentId", + runtriggers.id, runtriggers."createdAt", runtriggers."updatedAt", runtriggers."deletedAt", runtriggers."tenantId", runtriggers."eventId", runtriggers."cronParentId", runtriggers."cronSchedule", runtriggers."scheduledId", runtriggers.input, runtriggers."parentId", runtriggers."cronName", workflowversion.id, workflowversion."createdAt", workflowversion."updatedAt", workflowversion."deletedAt", workflowversion.version, workflowversion."order", workflowversion."workflowId", workflowversion.checksum, workflowversion."scheduleTimeout", workflowversion."onFailureJobId", workflowversion.sticky, workflowversion.kind, workflowversion."defaultPriority", -- waiting on https://github.com/sqlc-dev/sqlc/pull/2858 for nullable events field events.id, events.key, events."createdAt", events."updatedAt" @@ -2692,6 +2604,7 @@ func (q *Queries) ListWorkflowRuns(ctx context.Context, db DBTX, arg ListWorkflo &i.WorkflowRunTriggeredBy.ScheduledId, &i.WorkflowRunTriggeredBy.Input, &i.WorkflowRunTriggeredBy.ParentId, + &i.WorkflowRunTriggeredBy.CronName, &i.WorkflowVersion.ID, &i.WorkflowVersion.CreatedAt, &i.WorkflowVersion.UpdatedAt, diff --git a/pkg/repository/prisma/dbsqlc/workflows.sql b/pkg/repository/prisma/dbsqlc/workflows.sql index ccd7b7ddc..005cf67e3 100644 --- a/pkg/repository/prisma/dbsqlc/workflows.sql +++ b/pkg/repository/prisma/dbsqlc/workflows.sql @@ -331,11 +331,15 @@ INSERT INTO "WorkflowTriggerEventRef" ( INSERT INTO "WorkflowTriggerCronRef" ( "parentId", "cron", - "input" + "name", + "input", + "additionalMetadata" ) VALUES ( @workflowTriggersId::uuid, @cronTrigger::text, - sqlc.narg('input')::jsonb + sqlc.narg('name')::text, + sqlc.narg('input')::jsonb, + sqlc.narg('additionalMetadata')::jsonb ) RETURNING *; -- name: CreateWorkflowTriggerScheduledRef :one @@ -664,3 +668,57 @@ WHERE ORDER BY wv."order" DESC LIMIT 1; + + +-- name: ListCronWorkflows :many +-- Get all of the latest workflow versions for the tenant +WITH latest_versions AS ( + SELECT DISTINCT ON("workflowId") + workflowVersions."id" AS "workflowVersionId", + workflowVersions."workflowId" + FROM + "WorkflowVersion" as workflowVersions + JOIN + "Workflow" as workflow ON workflow."id" = workflowVersions."workflowId" + WHERE + workflow."tenantId" = @tenantId::uuid + AND workflowVersions."deletedAt" IS NULL + ORDER BY "workflowId", "order" DESC +) +SELECT + latest_versions."workflowVersionId", + w."name", + w."id" as "workflowId", + w."tenantId", + t.*, + c.* +FROM + latest_versions +JOIN + "WorkflowTriggers" as t ON t."workflowVersionId" = latest_versions."workflowVersionId" +JOIN + "WorkflowTriggerCronRef" as c ON c."parentId" = t."id" +JOIN + "Workflow" w on w."id" = latest_versions."workflowId" +WHERE + t."deletedAt" IS NULL + AND w."tenantId" = @tenantId::uuid + AND (@cronId::uuid IS NULL OR t."id" = @cronId::uuid) + AND (@workflowId::uuid IS NULL OR w."id" = @workflowId::uuid) + AND (sqlc.narg('additionalMetadata')::jsonb IS NULL OR + c."additionalMetadata" @> sqlc.narg('additionalMetadata')::jsonb) +ORDER BY + case when @orderBy = 'createdAt ASC' THEN t."createdAt" END ASC , + case when @orderBy = 'createdAt DESC' THEN t."createdAt" END DESC, + t."id" ASC +OFFSET + COALESCE(sqlc.narg('offset'), 0) +LIMIT + COALESCE(sqlc.narg('limit'), 50); + +-- name: DeleteWorkflowTriggerCronRef :exec +DELETE FROM "WorkflowTriggerCronRef" +WHERE + "parentId" = @parentId::uuid AND + "cron" = @cron::text AND + "name" = @name::text; diff --git a/pkg/repository/prisma/dbsqlc/workflows.sql.go b/pkg/repository/prisma/dbsqlc/workflows.sql.go index dcdf89393..6c1b622b5 100644 --- a/pkg/repository/prisma/dbsqlc/workflows.sql.go +++ b/pkg/repository/prisma/dbsqlc/workflows.sql.go @@ -567,22 +567,34 @@ const createWorkflowTriggerCronRef = `-- name: CreateWorkflowTriggerCronRef :one INSERT INTO "WorkflowTriggerCronRef" ( "parentId", "cron", - "input" + "name", + "input", + "additionalMetadata" ) VALUES ( $1::uuid, $2::text, - $3::jsonb -) RETURNING "parentId", cron, "tickerId", input, enabled, "additionalMetadata", "createdAt", "deletedAt", "updatedAt" + $3::text, + $4::jsonb, + $5::jsonb +) RETURNING "parentId", cron, "tickerId", input, enabled, "additionalMetadata", "createdAt", "deletedAt", "updatedAt", name ` type CreateWorkflowTriggerCronRefParams struct { Workflowtriggersid pgtype.UUID `json:"workflowtriggersid"` Crontrigger string `json:"crontrigger"` + Name pgtype.Text `json:"name"` Input []byte `json:"input"` + AdditionalMetadata []byte `json:"additionalMetadata"` } func (q *Queries) CreateWorkflowTriggerCronRef(ctx context.Context, db DBTX, arg CreateWorkflowTriggerCronRefParams) (*WorkflowTriggerCronRef, error) { - row := db.QueryRow(ctx, createWorkflowTriggerCronRef, arg.Workflowtriggersid, arg.Crontrigger, arg.Input) + row := db.QueryRow(ctx, createWorkflowTriggerCronRef, + arg.Workflowtriggersid, + arg.Crontrigger, + arg.Name, + arg.Input, + arg.AdditionalMetadata, + ) var i WorkflowTriggerCronRef err := row.Scan( &i.ParentId, @@ -594,6 +606,7 @@ func (q *Queries) CreateWorkflowTriggerCronRef(ctx context.Context, db DBTX, arg &i.CreatedAt, &i.DeletedAt, &i.UpdatedAt, + &i.Name, ) return &i, err } @@ -775,6 +788,25 @@ func (q *Queries) CreateWorkflowVersion(ctx context.Context, db DBTX, arg Create return &i, err } +const deleteWorkflowTriggerCronRef = `-- name: DeleteWorkflowTriggerCronRef :exec +DELETE FROM "WorkflowTriggerCronRef" +WHERE + "parentId" = $1::uuid AND + "cron" = $2::text AND + "name" = $3::text +` + +type DeleteWorkflowTriggerCronRefParams struct { + Parentid pgtype.UUID `json:"parentid"` + Cron string `json:"cron"` + Name string `json:"name"` +} + +func (q *Queries) DeleteWorkflowTriggerCronRef(ctx context.Context, db DBTX, arg DeleteWorkflowTriggerCronRefParams) error { + _, err := db.Exec(ctx, deleteWorkflowTriggerCronRef, arg.Parentid, arg.Cron, arg.Name) + return err +} + const getLatestWorkflowVersionForWorkflows = `-- name: GetLatestWorkflowVersionForWorkflows :many WITH latest_versions AS ( SELECT DISTINCT ON (workflowVersions."workflowId") @@ -981,7 +1013,7 @@ func (q *Queries) GetWorkflowVersionById(ctx context.Context, db DBTX, id pgtype const getWorkflowVersionCronTriggerRefs = `-- name: GetWorkflowVersionCronTriggerRefs :many SELECT - wtc."parentId", wtc.cron, wtc."tickerId", wtc.input, wtc.enabled, wtc."additionalMetadata", wtc."createdAt", wtc."deletedAt", wtc."updatedAt" + wtc."parentId", wtc.cron, wtc."tickerId", wtc.input, wtc.enabled, wtc."additionalMetadata", wtc."createdAt", wtc."deletedAt", wtc."updatedAt", wtc.name FROM "WorkflowTriggerCronRef" as wtc JOIN "WorkflowTriggers" as wt ON wt."id" = wtc."parentId" @@ -1008,6 +1040,7 @@ func (q *Queries) GetWorkflowVersionCronTriggerRefs(ctx context.Context, db DBTX &i.CreatedAt, &i.DeletedAt, &i.UpdatedAt, + &i.Name, ); err != nil { return nil, err } @@ -1333,6 +1366,135 @@ func (q *Queries) LinkOnFailureJob(ctx context.Context, db DBTX, arg LinkOnFailu return &i, err } +const listCronWorkflows = `-- name: ListCronWorkflows :many +WITH latest_versions AS ( + SELECT DISTINCT ON("workflowId") + workflowVersions."id" AS "workflowVersionId", + workflowVersions."workflowId" + FROM + "WorkflowVersion" as workflowVersions + JOIN + "Workflow" as workflow ON workflow."id" = workflowVersions."workflowId" + WHERE + workflow."tenantId" = $1::uuid + AND workflowVersions."deletedAt" IS NULL + ORDER BY "workflowId", "order" DESC +) +SELECT + latest_versions."workflowVersionId", + w."name", + w."id" as "workflowId", + w."tenantId", + t.id, t."createdAt", t."updatedAt", t."deletedAt", t."workflowVersionId", t."tenantId", + c."parentId", c.cron, c."tickerId", c.input, c.enabled, c."additionalMetadata", c."createdAt", c."deletedAt", c."updatedAt", c.name +FROM + latest_versions +JOIN + "WorkflowTriggers" as t ON t."workflowVersionId" = latest_versions."workflowVersionId" +JOIN + "WorkflowTriggerCronRef" as c ON c."parentId" = t."id" +JOIN + "Workflow" w on w."id" = latest_versions."workflowId" +WHERE + t."deletedAt" IS NULL + AND w."tenantId" = $1::uuid + AND ($2::uuid IS NULL OR t."id" = $2::uuid) + AND ($3::uuid IS NULL OR w."id" = $3::uuid) + AND ($4::jsonb IS NULL OR + c."additionalMetadata" @> $4::jsonb) +ORDER BY + case when $5 = 'createdAt ASC' THEN t."createdAt" END ASC , + case when $5 = 'createdAt DESC' THEN t."createdAt" END DESC, + t."id" ASC +OFFSET + COALESCE($6, 0) +LIMIT + COALESCE($7, 50) +` + +type ListCronWorkflowsParams struct { + Tenantid pgtype.UUID `json:"tenantid"` + Cronid pgtype.UUID `json:"cronid"` + Workflowid pgtype.UUID `json:"workflowid"` + AdditionalMetadata []byte `json:"additionalMetadata"` + Orderby interface{} `json:"orderby"` + Offset interface{} `json:"offset"` + Limit interface{} `json:"limit"` +} + +type ListCronWorkflowsRow struct { + WorkflowVersionId pgtype.UUID `json:"workflowVersionId"` + Name string `json:"name"` + WorkflowId pgtype.UUID `json:"workflowId"` + TenantId pgtype.UUID `json:"tenantId"` + ID pgtype.UUID `json:"id"` + CreatedAt pgtype.Timestamp `json:"createdAt"` + UpdatedAt pgtype.Timestamp `json:"updatedAt"` + DeletedAt pgtype.Timestamp `json:"deletedAt"` + WorkflowVersionId_2 pgtype.UUID `json:"workflowVersionId_2"` + TenantId_2 pgtype.UUID `json:"tenantId_2"` + ParentId pgtype.UUID `json:"parentId"` + Cron string `json:"cron"` + TickerId pgtype.UUID `json:"tickerId"` + Input []byte `json:"input"` + Enabled bool `json:"enabled"` + AdditionalMetadata []byte `json:"additionalMetadata"` + CreatedAt_2 pgtype.Timestamp `json:"createdAt_2"` + DeletedAt_2 pgtype.Timestamp `json:"deletedAt_2"` + UpdatedAt_2 pgtype.Timestamp `json:"updatedAt_2"` + Name_2 pgtype.Text `json:"name_2"` +} + +// Get all of the latest workflow versions for the tenant +func (q *Queries) ListCronWorkflows(ctx context.Context, db DBTX, arg ListCronWorkflowsParams) ([]*ListCronWorkflowsRow, error) { + rows, err := db.Query(ctx, listCronWorkflows, + arg.Tenantid, + arg.Cronid, + arg.Workflowid, + arg.AdditionalMetadata, + arg.Orderby, + arg.Offset, + arg.Limit, + ) + if err != nil { + return nil, err + } + defer rows.Close() + var items []*ListCronWorkflowsRow + for rows.Next() { + var i ListCronWorkflowsRow + if err := rows.Scan( + &i.WorkflowVersionId, + &i.Name, + &i.WorkflowId, + &i.TenantId, + &i.ID, + &i.CreatedAt, + &i.UpdatedAt, + &i.DeletedAt, + &i.WorkflowVersionId_2, + &i.TenantId_2, + &i.ParentId, + &i.Cron, + &i.TickerId, + &i.Input, + &i.Enabled, + &i.AdditionalMetadata, + &i.CreatedAt_2, + &i.DeletedAt_2, + &i.UpdatedAt_2, + &i.Name_2, + ); err != nil { + return nil, err + } + items = append(items, &i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const listPausedWorkflows = `-- name: ListPausedWorkflows :many SELECT "id" diff --git a/pkg/repository/prisma/workflow.go b/pkg/repository/prisma/workflow.go index ac1e5f4cb..ae486040b 100644 --- a/pkg/repository/prisma/workflow.go +++ b/pkg/repository/prisma/workflow.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "strings" + "time" "github.com/google/uuid" "github.com/jackc/pgx/v5" @@ -279,6 +280,118 @@ func (r *workflowAPIRepository) GetWorkflowMetrics(tenantId, workflowId string, }, nil } +func (w *workflowAPIRepository) ListCronWorkflows(ctx context.Context, tenantId string, opts *repository.ListCronWorkflowsOpts) ([]*dbsqlc.ListCronWorkflowsRow, int64, error) { + if err := w.v.Validate(opts); err != nil { + return nil, 0, err + } + + ctx, cancel := context.WithTimeout(ctx, time.Second*30) + defer cancel() + + count, err := w.queries.CountCronWorkflows(ctx, w.pool, sqlchelpers.UUIDFromStr(tenantId)) + + if err != nil { + return nil, 0, err + } + + listOpts := dbsqlc.ListCronWorkflowsParams{ + Tenantid: sqlchelpers.UUIDFromStr(tenantId), + } + + if opts.Limit != nil { + listOpts.Limit = pgtype.Int4{ + Int32: int32(*opts.Limit), // nolint: gosec + Valid: true, + } + } + + if opts.Offset != nil { + listOpts.Offset = pgtype.Int4{ + Int32: int32(*opts.Offset), // nolint: gosec + Valid: true, + } + } + + orderByField := "createdAt" + + if opts.OrderBy != nil { + orderByField = *opts.OrderBy + } + + orderByDirection := "DESC" + + if opts.OrderDirection != nil { + orderByDirection = *opts.OrderDirection + } + + listOpts.Orderby = orderByField + " " + orderByDirection + + cronWorkflows, err := w.queries.ListCronWorkflows(ctx, w.pool, listOpts) + if err != nil { + return nil, 0, err + } + + return cronWorkflows, count, nil +} + +func (w *workflowAPIRepository) GetCronWorkflow(ctx context.Context, tenantId, cronWorkflowId string) (*dbsqlc.ListCronWorkflowsRow, error) { + listOpts := dbsqlc.ListCronWorkflowsParams{ + Tenantid: sqlchelpers.UUIDFromStr(tenantId), + Cronid: sqlchelpers.UUIDFromStr(cronWorkflowId), + } + + cronWorkflows, err := w.queries.ListCronWorkflows(ctx, w.pool, listOpts) + + if err != nil { + return nil, err + } + + if len(cronWorkflows) == 0 { + return nil, nil + } + + return cronWorkflows[0], nil +} + +func (w *workflowAPIRepository) DeleteCronWorkflow(ctx context.Context, tenantId, cron, cronParentId string, cronName *string) error { + return w.queries.DeleteWorkflowTriggerCronRef(ctx, w.pool, dbsqlc.DeleteWorkflowTriggerCronRefParams{ + Parentid: sqlchelpers.UUIDFromStr(cronParentId), + Cron: cron, + Name: *cronName, + }) +} + +func (w *workflowAPIRepository) CreateCronWorkflow(ctx context.Context, tenantId string, opts *repository.CreateCronWorkflowTriggerOpts) (*dbsqlc.WorkflowRun, error) { + + workflow, err := w.queries.GetWorkflowByName(ctx, w.pool, dbsqlc.GetWorkflowByNameParams{ + Tenantid: sqlchelpers.UUIDFromStr(tenantId), + Name: opts.Name, + }) + + if err != nil { + return nil, err + } + + createParams := dbsqlc.CreateWorkflowTriggerCronRefParams{ + Workflowtriggersid: workflow.ID, + Crontrigger: opts.Cron, + Name: sqlchelpers.TextFromStr(opts.Name), + Input: opts.Input, + AdditionalMetadata: opts.AdditionalMetadata, + } + + _, err = w.queries.CreateWorkflowTriggerCronRef(ctx, w.pool, createParams) + + if err != nil { + return nil, err + } + + // TODO: return the cron workflow trigger + // cronWorkflow, err := w.GetCronWorkflow(ctx, tenantId, cronWorkflowTrigger.) + + return nil, nil +} + type workflowEngineRepository struct { pool *pgxpool.Pool v validator.Validator diff --git a/pkg/repository/prisma/workflow_run.go b/pkg/repository/prisma/workflow_run.go index f7d4c2beb..382e91d13 100644 --- a/pkg/repository/prisma/workflow_run.go +++ b/pkg/repository/prisma/workflow_run.go @@ -253,60 +253,6 @@ func (w *workflowRunAPIRepository) UpdateScheduledWorkflow(ctx context.Context, }) } -func (w *workflowRunAPIRepository) ListCronWorkflows(ctx context.Context, tenantId string, opts *repository.ListCronWorkflowsOpts) ([]*dbsqlc.ListCronWorkflowsRow, int64, error) { - if err := w.v.Validate(opts); err != nil { - return nil, 0, err - } - - ctx, cancel := context.WithTimeout(ctx, time.Second*30) - defer cancel() - - count, err := w.queries.CountCronWorkflows(ctx, w.pool, sqlchelpers.UUIDFromStr(tenantId)) - - if err != nil { - return nil, 0, err - } - - listOpts := dbsqlc.ListCronWorkflowsParams{ - Tenantid: sqlchelpers.UUIDFromStr(tenantId), - } - - if opts.Limit != nil { - listOpts.Limit = pgtype.Int4{ - Int32: int32(*opts.Limit), // nolint: gosec - Valid: true, - } - } - - if opts.Offset != nil { - listOpts.Offset = pgtype.Int4{ - Int32: int32(*opts.Offset), // nolint: gosec - Valid: true, - } - } - - orderByField := "createdAt" - - if opts.OrderBy != nil { - orderByField = *opts.OrderBy - } - - orderByDirection := "DESC" - - if opts.OrderDirection != nil { - orderByDirection = *opts.OrderDirection - } - - listOpts.Orderby = orderByField + " " + orderByDirection - - cronWorkflows, err := w.queries.ListCronWorkflows(ctx, w.pool, listOpts) - if err != nil { - return nil, 0, err - } - - return cronWorkflows, count, nil -} - func (w *workflowRunEngineRepository) GetWorkflowRunInputData(tenantId, workflowRunId string) (map[string]interface{}, error) { lookupData := datautils.JobRunLookupData{} @@ -1695,7 +1641,7 @@ func createNewWorkflowRuns(ctx context.Context, pool *pgxpool.Pool, queries *dbs var ( eventId, cronParentId, scheduledWorkflowId pgtype.UUID - cronSchedule pgtype.Text + cronSchedule, cronName pgtype.Text ) if opt.TriggeringEventId != nil { @@ -1710,6 +1656,10 @@ func createNewWorkflowRuns(ctx context.Context, pool *pgxpool.Pool, queries *dbs cronSchedule = sqlchelpers.TextFromStr(*opt.Cron) } + if opt.CronName != nil { + cronName = sqlchelpers.TextFromStr(*opt.CronName) + } + if opt.ScheduledWorkflowId != nil { scheduledWorkflowId = sqlchelpers.UUIDFromStr(*opt.ScheduledWorkflowId) } @@ -1722,6 +1672,7 @@ func createNewWorkflowRuns(ctx context.Context, pool *pgxpool.Pool, queries *dbs CronParentId: cronParentId, ScheduledId: scheduledWorkflowId, CronSchedule: cronSchedule, + CronName: cronName, } triggeredByParams = append(triggeredByParams, cp) diff --git a/pkg/repository/workflow.go b/pkg/repository/workflow.go index e4a135bba..e11f20492 100644 --- a/pkg/repository/workflow.go +++ b/pkg/repository/workflow.go @@ -58,6 +58,16 @@ type CreateWorkflowVersionOpts struct { DefaultPriority *int32 `validate:"omitempty,min=1,max=3"` } +type CreateCronWorkflowTriggerOpts struct { + // (required) the workflow name + Name string `validate:"required"` + + Cron string `validate:"required,cron"` + + Input []byte + AdditionalMetadata []byte +} + type CreateWorkflowConcurrencyOpts struct { // (optional) the action id for getting the concurrency group Action *string `validate:"omitempty,actionId"` @@ -265,6 +275,18 @@ type WorkflowAPIRepository interface { // GetWorkflowWorkerCount returns the number of workers for a given workflow. GetWorkflowWorkerCount(tenantId, workflowId string) (int, int, error) + + // CreateCronWorkflow creates a cron trigger + CreateCronWorkflow(ctx context.Context, tenantId string, opts *CreateCronWorkflowTriggerOpts) (*dbsqlc.WorkflowRun, error) + + // List ScheduledWorkflows lists workflows by scheduled trigger + ListCronWorkflows(ctx context.Context, tenantId string, opts *ListCronWorkflowsOpts) ([]*dbsqlc.ListCronWorkflowsRow, int64, error) + + // GetCronWorkflow gets a cron workflow run + GetCronWorkflow(ctx context.Context, tenantId, cronWorkflowId string) (*dbsqlc.ListCronWorkflowsRow, error) + + // DeleteCronWorkflow deletes a cron workflow run + DeleteCronWorkflow(ctx context.Context, tenantId, cron, cronParentId string, cronName *string) error } type WorkflowEngineRepository interface { diff --git a/pkg/repository/workflow_run.go b/pkg/repository/workflow_run.go index d01dc2570..26a027724 100644 --- a/pkg/repository/workflow_run.go +++ b/pkg/repository/workflow_run.go @@ -31,6 +31,7 @@ type CreateWorkflowRunOpts struct { // (optional) the cron schedule that triggered the workflow run Cron *string `validate:"omitnil,cron,required_without=ManualTriggerInput,required_without=TriggeringEventId,required_without=ScheduledWorkflowId,excluded_with=ManualTriggerInput,excluded_with=TriggeringEventId,excluded_with=ScheduledWorkflowId"` CronParentId *string `validate:"omitnil,uuid,required_without=ManualTriggerInput,required_without=TriggeringEventId,required_without=ScheduledWorkflowId,excluded_with=ManualTriggerInput,excluded_with=TriggeringEventId,excluded_with=ScheduledWorkflowId"` + CronName *string `validate:"omitnil,exclude_without=Cron"` // (optional) the scheduled trigger ScheduledWorkflowId *string `validate:"omitnil,uuid,required_without=ManualTriggerInput,required_without=TriggeringEventId,required_without=Cron,excluded_with=ManualTriggerInput,excluded_with=TriggeringEventId,excluded_with=Cron"` @@ -190,6 +191,7 @@ func GetCreateWorkflowRunOptsFromEvent( func GetCreateWorkflowRunOptsFromCron( cron, cronParentId string, + cronName *string, workflowVersion *dbsqlc.GetWorkflowVersionForEngineRow, input []byte, additionalMetadata map[string]interface{}, @@ -203,6 +205,7 @@ func GetCreateWorkflowRunOptsFromCron( WorkflowVersionId: sqlchelpers.UUIDToStr(workflowVersion.WorkflowVersion.ID), Cron: &cron, CronParentId: &cronParentId, + CronName: cronName, TriggeredBy: string(datautils.TriggeredByCron), InputData: input, AdditionalMetadata: additionalMetadata, @@ -461,9 +464,6 @@ type WorkflowRunAPIRepository interface { // UpdateScheduledWorkflow updates a scheduled workflow run UpdateScheduledWorkflow(ctx context.Context, tenantId, scheduledWorkflowId string, triggerAt time.Time) error - // List ScheduledWorkflows lists workflows by scheduled trigger - ListCronWorkflows(ctx context.Context, tenantId string, opts *ListCronWorkflowsOpts) ([]*dbsqlc.ListCronWorkflowsRow, int64, error) - // CreateNewWorkflowRun creates a new workflow run for a workflow version. CreateNewWorkflowRun(ctx context.Context, tenantId string, opts *CreateWorkflowRunOpts) (*dbsqlc.WorkflowRun, error) diff --git a/prisma/migrations/20241030131339_tmp/migration.sql b/prisma/migrations/20241030131339_tmp/migration.sql new file mode 100644 index 000000000..e994d5f0b --- /dev/null +++ b/prisma/migrations/20241030131339_tmp/migration.sql @@ -0,0 +1,23 @@ +/* + Warnings: + + - A unique constraint covering the columns `[parentId,cron,name]` on the table `WorkflowTriggerCronRef` will be added. If there are existing duplicate values, this will fail. + - The required column `id` was added to the `WorkflowTriggerCronRef` table with a prisma-level default value. This is not possible if the table is not empty. Please add this column as optional, then populate it before making it required. + +*/ +-- DropForeignKey +ALTER TABLE "WorkflowRunTriggeredBy" DROP CONSTRAINT "WorkflowRunTriggeredBy_cronParentId_cronSchedule_fkey"; + +-- AlterTable +ALTER TABLE "WorkflowRunTriggeredBy" ADD COLUMN "cronName" TEXT; + +-- AlterTable +ALTER TABLE "WorkflowTriggerCronRef" ADD COLUMN "id" UUID NOT NULL, +ADD COLUMN "name" TEXT, +ADD CONSTRAINT "WorkflowTriggerCronRef_pkey" PRIMARY KEY ("id"); + +-- CreateIndex +CREATE UNIQUE INDEX "WorkflowTriggerCronRef_parentId_cron_name_key" ON "WorkflowTriggerCronRef"("parentId", "cron", "name"); + +-- AddForeignKey +ALTER TABLE "WorkflowRunTriggeredBy" ADD CONSTRAINT "WorkflowRunTriggeredBy_cronParentId_cronSchedule_cronName_fkey" FOREIGN KEY ("cronParentId", "cronSchedule", "cronName") REFERENCES "WorkflowTriggerCronRef"("parentId", "cron", "name") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20241030133040_tmp/migration.sql b/prisma/migrations/20241030133040_tmp/migration.sql new file mode 100644 index 000000000..1465f196e --- /dev/null +++ b/prisma/migrations/20241030133040_tmp/migration.sql @@ -0,0 +1,10 @@ +/* + Warnings: + + - The primary key for the `WorkflowTriggerCronRef` table will be changed. If it partially fails, the table could be left without primary key constraint. + - You are about to drop the column `id` on the `WorkflowTriggerCronRef` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "WorkflowTriggerCronRef" DROP CONSTRAINT "WorkflowTriggerCronRef_pkey", +DROP COLUMN "id"; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 307ee46be..8245040e2 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -645,6 +645,8 @@ model WorkflowTriggerEventRef { } model WorkflowTriggerCronRef { + name String? + // the parent workflow parent WorkflowTriggers @relation(fields: [parentId], references: [id], onDelete: Cascade, onUpdate: Cascade) parentId String @db.Uuid @@ -671,6 +673,7 @@ model WorkflowTriggerCronRef { // cron references must be unique per workflow @@unique([parentId, cron]) + @@unique([parentId, cron, name]) } model WorkflowTriggerScheduledRef { @@ -1102,9 +1105,10 @@ model WorkflowRunTriggeredBy { eventId String? @db.Uuid // the cron reference that triggered this workflow - cron WorkflowTriggerCronRef? @relation(fields: [cronParentId, cronSchedule], references: [parentId, cron]) + cron WorkflowTriggerCronRef? @relation(fields: [cronParentId, cronSchedule, cronName], references: [parentId, cron, name]) cronParentId String? @db.Uuid cronSchedule String? + cronName String? // a specific time that triggered this workflow scheduled WorkflowTriggerScheduledRef? @relation(fields: [scheduledId], references: [id]) diff --git a/sql/migrations/20241030131347_tmp.sql b/sql/migrations/20241030131347_tmp.sql new file mode 100644 index 000000000..6f6e239cd --- /dev/null +++ b/sql/migrations/20241030131347_tmp.sql @@ -0,0 +1,6 @@ +-- Modify "WorkflowTriggerCronRef" table +ALTER TABLE "WorkflowTriggerCronRef" ADD COLUMN "id" uuid NOT NULL, ADD COLUMN "name" text NULL, ADD PRIMARY KEY ("id"); +-- Create index "WorkflowTriggerCronRef_parentId_cron_name_key" to table: "WorkflowTriggerCronRef" +CREATE UNIQUE INDEX "WorkflowTriggerCronRef_parentId_cron_name_key" ON "WorkflowTriggerCronRef" ("parentId", "cron", "name"); +-- Modify "WorkflowRunTriggeredBy" table +ALTER TABLE "WorkflowRunTriggeredBy" DROP CONSTRAINT "WorkflowRunTriggeredBy_cronParentId_cronSchedule_fkey", ADD COLUMN "cronName" text NULL, ADD CONSTRAINT "WorkflowRunTriggeredBy_cronParentId_cronSchedule_cronName_fkey" FOREIGN KEY ("cronParentId", "cronSchedule", "cronName") REFERENCES "WorkflowTriggerCronRef" ("parentId", "cron", "name") ON UPDATE CASCADE ON DELETE SET NULL; diff --git a/sql/migrations/20241030133048_tmp.sql b/sql/migrations/20241030133048_tmp.sql new file mode 100644 index 000000000..7efec8213 --- /dev/null +++ b/sql/migrations/20241030133048_tmp.sql @@ -0,0 +1,2 @@ +-- Modify "WorkflowTriggerCronRef" table +ALTER TABLE "WorkflowTriggerCronRef" DROP CONSTRAINT "WorkflowTriggerCronRef_pkey", DROP COLUMN "id"; diff --git a/sql/migrations/atlas.sum b/sql/migrations/atlas.sum index d83cc2ece..bea3957ee 100644 --- a/sql/migrations/atlas.sum +++ b/sql/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:y8lBsbOHVrTOEIGR+vDKOBwtZe5Tbkv+9juCrSYtd14= +h1:Qd8kaosQVxQXj9CxwoLtPrpmggU33rd/fqxrzwbDybg= 20240115180414_init.sql h1:Ef3ZyjAHkmJPdGF/dEWCahbwgcg6uGJKnDxW2JCRi2k= 20240122014727_v0_6_0.sql h1:o/LdlteAeFgoHJ3e/M4Xnghqt9826IE/Y/h0q95Acuo= 20240126235456_v0_7_0.sql h1:KiVzt/hXgQ6esbdC6OMJOOWuYEXmy1yeCpmsVAHTFKs= @@ -73,3 +73,5 @@ h1:y8lBsbOHVrTOEIGR+vDKOBwtZe5Tbkv+9juCrSYtd14= 20241023223039_v0.50.4.sql h1:eXJLlkM6ZzqzZ4RbAZtoTiW7WjJPIJ5L6UkIKy6w9Uk= 20241025162439_v0.50.5.sql h1:CIv/oSeiVR1D3rOb4z8uv2t0XUI62TyK+0UI0s6tQ/k= 20241029122625_v0.51.0.sql h1:nOa4FqmZxSh1yBOJyduX+j15gQavjizTn660wyXjhNk= +20241030131347_tmp.sql h1:48ydfY8fUk6nR6Av35gk57TfBbrwYYLwjtTAKch1TBg= +20241030133048_tmp.sql h1:dWSeXAsgIbUo1yCrxM6p/a2mPPDMfMP2j4s+R0ADZjE= diff --git a/sql/schema/schema.sql b/sql/schema/schema.sql index a2066d215..6bbb6a7c5 100644 --- a/sql/schema/schema.sql +++ b/sql/schema/schema.sql @@ -879,6 +879,7 @@ CREATE TABLE "WorkflowRunTriggeredBy" ( "scheduledId" UUID, "input" JSONB, "parentId" UUID NOT NULL, + "cronName" TEXT, CONSTRAINT "WorkflowRunTriggeredBy_pkey" PRIMARY KEY ("id") ); @@ -905,7 +906,8 @@ CREATE TABLE "WorkflowTriggerCronRef" ( "additionalMetadata" JSONB, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "deletedAt" TIMESTAMP(3), - "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "name" TEXT ); -- CreateTable @@ -1369,6 +1371,9 @@ CREATE UNIQUE INDEX "WorkflowTag_tenantId_name_key" ON "WorkflowTag"("tenantId" -- CreateIndex CREATE UNIQUE INDEX "WorkflowTriggerCronRef_parentId_cron_key" ON "WorkflowTriggerCronRef"("parentId" ASC, "cron" ASC); +-- CreateIndex +CREATE UNIQUE INDEX "WorkflowTriggerCronRef_parentId_cron_name_key" ON "WorkflowTriggerCronRef"("parentId" ASC, "cron" ASC, "name" ASC); + -- CreateIndex CREATE UNIQUE INDEX "WorkflowTriggerEventRef_parentId_eventKey_key" ON "WorkflowTriggerEventRef"("parentId" ASC, "eventKey" ASC); @@ -1577,7 +1582,7 @@ ALTER TABLE "WorkflowRun" ADD CONSTRAINT "WorkflowRun_parentStepRunId_fkey" FORE ALTER TABLE "WorkflowRunStickyState" ADD CONSTRAINT "WorkflowRunStickyState_workflowRunId_fkey" FOREIGN KEY ("workflowRunId") REFERENCES "WorkflowRun"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey -ALTER TABLE "WorkflowRunTriggeredBy" ADD CONSTRAINT "WorkflowRunTriggeredBy_cronParentId_cronSchedule_fkey" FOREIGN KEY ("cronParentId", "cronSchedule") REFERENCES "WorkflowTriggerCronRef"("parentId", "cron") ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE "WorkflowRunTriggeredBy" ADD CONSTRAINT "WorkflowRunTriggeredBy_cronParentId_cronSchedule_cronName_fkey" FOREIGN KEY ("cronParentId", "cronSchedule", "cronName") REFERENCES "WorkflowTriggerCronRef"("parentId", "cron", "name") ON DELETE SET NULL ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "WorkflowRunTriggeredBy" ADD CONSTRAINT "WorkflowRunTriggeredBy_scheduledId_fkey" FOREIGN KEY ("scheduledId") REFERENCES "WorkflowTriggerScheduledRef"("id") ON DELETE SET NULL ON UPDATE CASCADE; From a1f6d078e517c1278163823666312a20a3c6393a Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Wed, 30 Oct 2024 11:08:06 -0400 Subject: [PATCH 23/30] fix: ids are helpful --- api-contracts/openapi/openapi.yaml | 2 + .../openapi/paths/workflow/workflow.yaml | 67 +- .../server/handlers/workflows/delete_cron.go | 4 +- api/v1/server/handlers/workflows/get_cron.go | 34 + api/v1/server/oas/gen/openapi.gen.go | 618 ++++++++++-------- frontend/app/src/lib/api/generated/Api.ts | 67 +- pkg/client/rest/gen.go | 321 +++++---- pkg/repository/prisma/dbsqlc/models.go | 1 + pkg/repository/prisma/dbsqlc/schema.sql | 6 +- pkg/repository/prisma/dbsqlc/tickers.sql.go | 4 +- pkg/repository/prisma/dbsqlc/workflows.sql | 9 +- pkg/repository/prisma/dbsqlc/workflows.sql.go | 33 +- pkg/repository/prisma/workflow.go | 6 +- pkg/repository/workflow.go | 2 +- .../20241030150107_tmp/migration.sql | 12 + prisma/schema.prisma | 2 + sql/migrations/20241030150116_tmp.sql | 5 + sql/migrations/20241030150342_tmp.sql | 2 + sql/migrations/atlas.sum | 4 +- sql/schema/schema.sql | 6 +- 20 files changed, 748 insertions(+), 457 deletions(-) create mode 100644 api/v1/server/handlers/workflows/get_cron.go create mode 100644 prisma/migrations/20241030150107_tmp/migration.sql create mode 100644 sql/migrations/20241030150116_tmp.sql create mode 100644 sql/migrations/20241030150342_tmp.sql diff --git a/api-contracts/openapi/openapi.yaml b/api-contracts/openapi/openapi.yaml index b9e169d79..c2aea82a2 100644 --- a/api-contracts/openapi/openapi.yaml +++ b/api-contracts/openapi/openapi.yaml @@ -121,6 +121,8 @@ paths: /api/v1/tenants/{tenant}/workflows/scheduled/{scheduledId}: $ref: "./paths/workflow/workflow.yaml#/scheduled" /api/v1/tenants/{tenant}/workflows/crons: + $ref: "./paths/workflow/workflow.yaml#/cronsList" + /api/v1/tenants/{tenant}/workflows/crons/{cronId}: $ref: "./paths/workflow/workflow.yaml#/crons" /api/v1/tenants/{tenant}/workflows/cancel: $ref: "./paths/workflow/workflow.yaml#/cancelWorkflowRuns" diff --git a/api-contracts/openapi/paths/workflow/workflow.yaml b/api-contracts/openapi/paths/workflow/workflow.yaml index e50a8ddb5..141a39450 100644 --- a/api-contracts/openapi/paths/workflow/workflow.yaml +++ b/api-contracts/openapi/paths/workflow/workflow.yaml @@ -1031,10 +1031,10 @@ scheduled: - Workflow crons: - delete: + get: x-resources: ["tenant", "cron-workflow"] - description: Delete a cron job workflow run for a tenant - operationId: workflow-cron:delete + description: Get a cron job workflow run for a tenant + operationId: workflow-cron:get parameters: - description: The tenant id in: path @@ -1045,27 +1045,66 @@ crons: format: uuid minLength: 36 maxLength: 36 - - description: The cron job parent id - in: query - name: cronParentId + - description: The cron job id + in: path + name: cronId required: true schema: type: string format: uuid minLength: 36 maxLength: 36 - - description: The cron job name - in: query - name: cronName - required: false + responses: + "200": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/CronWorkflows" + description: Successfully retrieved the workflow runs + "400": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: A malformed or bad request + "403": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: Forbidden + "404": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: Forbidden + summary: Get cron job workflow run + tags: + - Workflow + delete: + x-resources: ["tenant", "cron-workflow"] + description: Delete a cron job workflow run for a tenant + operationId: workflow-cron:delete + parameters: + - description: The tenant id + in: path + name: tenant + required: true schema: type: string - - description: Cron schedule - in: query - name: cron + format: uuid + minLength: 36 + maxLength: 36 + - description: The cron job id + in: path + name: cronId required: true schema: type: string + format: uuid + minLength: 36 + maxLength: 36 responses: "204": description: Successfully deleted the cron job workflow run @@ -1084,6 +1123,8 @@ crons: summary: Delete cron job workflow run tags: - Workflow + +cronsList: get: x-resources: ["tenant"] description: Get all cron job workflow runs for a tenant diff --git a/api/v1/server/handlers/workflows/delete_cron.go b/api/v1/server/handlers/workflows/delete_cron.go index bbe7c6ac8..36012de0b 100644 --- a/api/v1/server/handlers/workflows/delete_cron.go +++ b/api/v1/server/handlers/workflows/delete_cron.go @@ -21,9 +21,7 @@ func (t *WorkflowService) WorkflowCronDelete(ctx echo.Context, request gen.Workf err := t.config.APIRepository.Workflow().DeleteCronWorkflow(dbCtx, sqlchelpers.UUIDToStr(cron.TenantId), - request.Params.Cron, - request.Params.CronParentId.String(), - request.Params.CronName, + sqlchelpers.UUIDToStr(cron.ID), ) if err != nil { diff --git a/api/v1/server/handlers/workflows/get_cron.go b/api/v1/server/handlers/workflows/get_cron.go new file mode 100644 index 000000000..e26338fc0 --- /dev/null +++ b/api/v1/server/handlers/workflows/get_cron.go @@ -0,0 +1,34 @@ +package workflows + +import ( + "context" + "time" + + "github.com/labstack/echo/v4" + + "github.com/hatchet-dev/hatchet/api/v1/server/oas/apierrors" + "github.com/hatchet-dev/hatchet/api/v1/server/oas/gen" + "github.com/hatchet-dev/hatchet/api/v1/server/oas/transformers" + "github.com/hatchet-dev/hatchet/pkg/repository/prisma/db" +) + +func (t *WorkflowService) WorkflowCronGet(ctx echo.Context, request gen.WorkflowCronGetRequestObject) (gen.WorkflowCronGetResponseObject, error) { + tenant := ctx.Get("tenant").(*db.TenantModel) + + dbCtx, cancel := context.WithTimeout(ctx.Request().Context(), 30*time.Second) + defer cancel() + + scheduled, err := t.config.APIRepository.Workflow().GetCronWorkflow(dbCtx, tenant.ID, request.CronId.String()) + + if err != nil { + return nil, err + } + + if scheduled == nil { + return gen.WorkflowCronGet404JSONResponse(apierrors.NewAPIErrors("Scheduled workflow not found.")), nil + } + + return gen.WorkflowCronGet200JSONResponse( + *transformers.ToCronWorkflowsFromSQLC(scheduled), + ), nil +} diff --git a/api/v1/server/oas/gen/openapi.gen.go b/api/v1/server/oas/gen/openapi.gen.go index 945155af6..2b47539ba 100644 --- a/api/v1/server/oas/gen/openapi.gen.go +++ b/api/v1/server/oas/gen/openapi.gen.go @@ -1540,18 +1540,6 @@ type WorkflowRunListStepRunEventsParams struct { LastId *int32 `form:"lastId,omitempty" json:"lastId,omitempty"` } -// WorkflowCronDeleteParams defines parameters for WorkflowCronDelete. -type WorkflowCronDeleteParams struct { - // CronParentId The cron job parent id - CronParentId openapi_types.UUID `form:"cronParentId" json:"cronParentId"` - - // CronName The cron job name - CronName *string `form:"cronName,omitempty" json:"cronName,omitempty"` - - // Cron Cron schedule - Cron string `form:"cron" json:"cron"` -} - // CronWorkflowListParams defines parameters for CronWorkflowList. type CronWorkflowListParams struct { // Offset The number to skip @@ -1941,12 +1929,15 @@ type ServerInterface interface { // Cancel workflow runs // (POST /api/v1/tenants/{tenant}/workflows/cancel) WorkflowRunCancel(ctx echo.Context, tenant openapi_types.UUID) error - // Delete cron job workflow run - // (DELETE /api/v1/tenants/{tenant}/workflows/crons) - WorkflowCronDelete(ctx echo.Context, tenant openapi_types.UUID, params WorkflowCronDeleteParams) error // Get cron job workflows // (GET /api/v1/tenants/{tenant}/workflows/crons) CronWorkflowList(ctx echo.Context, tenant openapi_types.UUID, params CronWorkflowListParams) error + // Delete cron job workflow run + // (DELETE /api/v1/tenants/{tenant}/workflows/crons/{cronId}) + WorkflowCronDelete(ctx echo.Context, tenant openapi_types.UUID, cronId openapi_types.UUID) error + // Get cron job workflow run + // (GET /api/v1/tenants/{tenant}/workflows/crons/{cronId}) + WorkflowCronGet(ctx echo.Context, tenant openapi_types.UUID, cronId openapi_types.UUID) error // Get workflow runs // (GET /api/v1/tenants/{tenant}/workflows/runs) WorkflowRunList(ctx echo.Context, tenant openapi_types.UUID, params WorkflowRunListParams) error @@ -3426,49 +3417,6 @@ func (w *ServerInterfaceWrapper) WorkflowRunCancel(ctx echo.Context) error { return err } -// WorkflowCronDelete converts echo context to params. -func (w *ServerInterfaceWrapper) WorkflowCronDelete(ctx echo.Context) error { - var err error - // ------------- Path parameter "tenant" ------------- - var tenant openapi_types.UUID - - err = runtime.BindStyledParameterWithLocation("simple", false, "tenant", runtime.ParamLocationPath, ctx.Param("tenant"), &tenant) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tenant: %s", err)) - } - - ctx.Set(BearerAuthScopes, []string{}) - - ctx.Set(CookieAuthScopes, []string{}) - - // Parameter object where we will unmarshal all parameters from the context - var params WorkflowCronDeleteParams - // ------------- Required query parameter "cronParentId" ------------- - - err = runtime.BindQueryParameter("form", true, true, "cronParentId", ctx.QueryParams(), ¶ms.CronParentId) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter cronParentId: %s", err)) - } - - // ------------- Optional query parameter "cronName" ------------- - - err = runtime.BindQueryParameter("form", true, false, "cronName", ctx.QueryParams(), ¶ms.CronName) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter cronName: %s", err)) - } - - // ------------- Required query parameter "cron" ------------- - - err = runtime.BindQueryParameter("form", true, true, "cron", ctx.QueryParams(), ¶ms.Cron) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter cron: %s", err)) - } - - // Invoke the callback with all the unmarshaled arguments - err = w.Handler.WorkflowCronDelete(ctx, tenant, params) - return err -} - // CronWorkflowList converts echo context to params. func (w *ServerInterfaceWrapper) CronWorkflowList(ctx echo.Context) error { var err error @@ -3533,6 +3481,62 @@ func (w *ServerInterfaceWrapper) CronWorkflowList(ctx echo.Context) error { return err } +// WorkflowCronDelete converts echo context to params. +func (w *ServerInterfaceWrapper) WorkflowCronDelete(ctx echo.Context) error { + var err error + // ------------- Path parameter "tenant" ------------- + var tenant openapi_types.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "tenant", runtime.ParamLocationPath, ctx.Param("tenant"), &tenant) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tenant: %s", err)) + } + + // ------------- Path parameter "cronId" ------------- + var cronId openapi_types.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "cronId", runtime.ParamLocationPath, ctx.Param("cronId"), &cronId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter cronId: %s", err)) + } + + ctx.Set(BearerAuthScopes, []string{}) + + ctx.Set(CookieAuthScopes, []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.WorkflowCronDelete(ctx, tenant, cronId) + return err +} + +// WorkflowCronGet converts echo context to params. +func (w *ServerInterfaceWrapper) WorkflowCronGet(ctx echo.Context) error { + var err error + // ------------- Path parameter "tenant" ------------- + var tenant openapi_types.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "tenant", runtime.ParamLocationPath, ctx.Param("tenant"), &tenant) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tenant: %s", err)) + } + + // ------------- Path parameter "cronId" ------------- + var cronId openapi_types.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "cronId", runtime.ParamLocationPath, ctx.Param("cronId"), &cronId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter cronId: %s", err)) + } + + ctx.Set(BearerAuthScopes, []string{}) + + ctx.Set(CookieAuthScopes, []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.WorkflowCronGet(ctx, tenant, cronId) + return err +} + // WorkflowRunList converts echo context to params. func (w *ServerInterfaceWrapper) WorkflowRunList(ctx echo.Context) error { var err error @@ -4365,8 +4369,9 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/api/v1/tenants/:tenant/workflow-runs/:workflow-run/step-run-events", wrapper.WorkflowRunListStepRunEvents) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows", wrapper.WorkflowList) router.POST(baseURL+"/api/v1/tenants/:tenant/workflows/cancel", wrapper.WorkflowRunCancel) - router.DELETE(baseURL+"/api/v1/tenants/:tenant/workflows/crons", wrapper.WorkflowCronDelete) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/crons", wrapper.CronWorkflowList) + router.DELETE(baseURL+"/api/v1/tenants/:tenant/workflows/crons/:cronId", wrapper.WorkflowCronDelete) + router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/crons/:cronId", wrapper.WorkflowCronGet) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/runs", wrapper.WorkflowRunList) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/runs/metrics", wrapper.WorkflowRunGetMetrics) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/scheduled", wrapper.WorkflowScheduledList) @@ -6541,9 +6546,45 @@ func (response WorkflowRunCancel403JSONResponse) VisitWorkflowRunCancelResponse( return json.NewEncoder(w).Encode(response) } +type CronWorkflowListRequestObject struct { + Tenant openapi_types.UUID `json:"tenant"` + Params CronWorkflowListParams +} + +type CronWorkflowListResponseObject interface { + VisitCronWorkflowListResponse(w http.ResponseWriter) error +} + +type CronWorkflowList200JSONResponse CronWorkflowsList + +func (response CronWorkflowList200JSONResponse) VisitCronWorkflowListResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type CronWorkflowList400JSONResponse APIErrors + +func (response CronWorkflowList400JSONResponse) VisitCronWorkflowListResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(400) + + return json.NewEncoder(w).Encode(response) +} + +type CronWorkflowList403JSONResponse APIErrors + +func (response CronWorkflowList403JSONResponse) VisitCronWorkflowListResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(403) + + return json.NewEncoder(w).Encode(response) +} + type WorkflowCronDeleteRequestObject struct { Tenant openapi_types.UUID `json:"tenant"` - Params WorkflowCronDeleteParams + CronId openapi_types.UUID `json:"cronId"` } type WorkflowCronDeleteResponseObject interface { @@ -6576,42 +6617,51 @@ func (response WorkflowCronDelete403JSONResponse) VisitWorkflowCronDeleteRespons return json.NewEncoder(w).Encode(response) } -type CronWorkflowListRequestObject struct { +type WorkflowCronGetRequestObject struct { Tenant openapi_types.UUID `json:"tenant"` - Params CronWorkflowListParams + CronId openapi_types.UUID `json:"cronId"` } -type CronWorkflowListResponseObject interface { - VisitCronWorkflowListResponse(w http.ResponseWriter) error +type WorkflowCronGetResponseObject interface { + VisitWorkflowCronGetResponse(w http.ResponseWriter) error } -type CronWorkflowList200JSONResponse CronWorkflowsList +type WorkflowCronGet200JSONResponse CronWorkflows -func (response CronWorkflowList200JSONResponse) VisitCronWorkflowListResponse(w http.ResponseWriter) error { +func (response WorkflowCronGet200JSONResponse) VisitWorkflowCronGetResponse(w http.ResponseWriter) error { w.Header().Set("Content-Type", "application/json") w.WriteHeader(200) return json.NewEncoder(w).Encode(response) } -type CronWorkflowList400JSONResponse APIErrors +type WorkflowCronGet400JSONResponse APIErrors -func (response CronWorkflowList400JSONResponse) VisitCronWorkflowListResponse(w http.ResponseWriter) error { +func (response WorkflowCronGet400JSONResponse) VisitWorkflowCronGetResponse(w http.ResponseWriter) error { w.Header().Set("Content-Type", "application/json") w.WriteHeader(400) return json.NewEncoder(w).Encode(response) } -type CronWorkflowList403JSONResponse APIErrors +type WorkflowCronGet403JSONResponse APIErrors -func (response CronWorkflowList403JSONResponse) VisitCronWorkflowListResponse(w http.ResponseWriter) error { +func (response WorkflowCronGet403JSONResponse) VisitWorkflowCronGetResponse(w http.ResponseWriter) error { w.Header().Set("Content-Type", "application/json") w.WriteHeader(403) return json.NewEncoder(w).Encode(response) } +type WorkflowCronGet404JSONResponse APIErrors + +func (response WorkflowCronGet404JSONResponse) VisitWorkflowCronGetResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(404) + + return json.NewEncoder(w).Encode(response) +} + type WorkflowRunListRequestObject struct { Tenant openapi_types.UUID `json:"tenant"` Params WorkflowRunListParams @@ -7836,9 +7886,11 @@ type StrictServerInterface interface { WorkflowRunCancel(ctx echo.Context, request WorkflowRunCancelRequestObject) (WorkflowRunCancelResponseObject, error) + CronWorkflowList(ctx echo.Context, request CronWorkflowListRequestObject) (CronWorkflowListResponseObject, error) + WorkflowCronDelete(ctx echo.Context, request WorkflowCronDeleteRequestObject) (WorkflowCronDeleteResponseObject, error) - CronWorkflowList(ctx echo.Context, request CronWorkflowListRequestObject) (CronWorkflowListResponseObject, error) + WorkflowCronGet(ctx echo.Context, request WorkflowCronGetRequestObject) (WorkflowCronGetResponseObject, error) WorkflowRunList(ctx echo.Context, request WorkflowRunListRequestObject) (WorkflowRunListResponseObject, error) @@ -9440,12 +9492,38 @@ func (sh *strictHandler) WorkflowRunCancel(ctx echo.Context, tenant openapi_type return nil } +// CronWorkflowList operation middleware +func (sh *strictHandler) CronWorkflowList(ctx echo.Context, tenant openapi_types.UUID, params CronWorkflowListParams) error { + var request CronWorkflowListRequestObject + + request.Tenant = tenant + request.Params = params + + handler := func(ctx echo.Context, request interface{}) (interface{}, error) { + return sh.ssi.CronWorkflowList(ctx, request.(CronWorkflowListRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "CronWorkflowList") + } + + response, err := handler(ctx, request) + + if err != nil { + return err + } else if validResponse, ok := response.(CronWorkflowListResponseObject); ok { + return validResponse.VisitCronWorkflowListResponse(ctx.Response()) + } else if response != nil { + return fmt.Errorf("Unexpected response type: %T", response) + } + return nil +} + // WorkflowCronDelete operation middleware -func (sh *strictHandler) WorkflowCronDelete(ctx echo.Context, tenant openapi_types.UUID, params WorkflowCronDeleteParams) error { +func (sh *strictHandler) WorkflowCronDelete(ctx echo.Context, tenant openapi_types.UUID, cronId openapi_types.UUID) error { var request WorkflowCronDeleteRequestObject request.Tenant = tenant - request.Params = params + request.CronId = cronId handler := func(ctx echo.Context, request interface{}) (interface{}, error) { return sh.ssi.WorkflowCronDelete(ctx, request.(WorkflowCronDeleteRequestObject)) @@ -9466,26 +9544,26 @@ func (sh *strictHandler) WorkflowCronDelete(ctx echo.Context, tenant openapi_typ return nil } -// CronWorkflowList operation middleware -func (sh *strictHandler) CronWorkflowList(ctx echo.Context, tenant openapi_types.UUID, params CronWorkflowListParams) error { - var request CronWorkflowListRequestObject +// WorkflowCronGet operation middleware +func (sh *strictHandler) WorkflowCronGet(ctx echo.Context, tenant openapi_types.UUID, cronId openapi_types.UUID) error { + var request WorkflowCronGetRequestObject request.Tenant = tenant - request.Params = params + request.CronId = cronId handler := func(ctx echo.Context, request interface{}) (interface{}, error) { - return sh.ssi.CronWorkflowList(ctx, request.(CronWorkflowListRequestObject)) + return sh.ssi.WorkflowCronGet(ctx, request.(WorkflowCronGetRequestObject)) } for _, middleware := range sh.middlewares { - handler = middleware(handler, "CronWorkflowList") + handler = middleware(handler, "WorkflowCronGet") } response, err := handler(ctx, request) if err != nil { return err - } else if validResponse, ok := response.(CronWorkflowListResponseObject); ok { - return validResponse.VisitCronWorkflowListResponse(ctx.Response()) + } else if validResponse, ok := response.(WorkflowCronGetResponseObject); ok { + return validResponse.VisitWorkflowCronGetResponse(ctx.Response()) } else if response != nil { return fmt.Errorf("Unexpected response type: %T", response) } @@ -10274,195 +10352,195 @@ func (sh *strictHandler) WorkflowVersionGet(ctx echo.Context, workflow openapi_t // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/frontend/app/src/lib/api/generated/Api.ts b/frontend/app/src/lib/api/generated/Api.ts index 28cd5ce1f..348a0c76f 100644 --- a/frontend/app/src/lib/api/generated/Api.ts +++ b/frontend/app/src/lib/api/generated/Api.ts @@ -24,6 +24,7 @@ import { CreateTenantAlertEmailGroupRequest, CreateTenantInviteRequest, CreateTenantRequest, + CronWorkflows, CronWorkflowsList, CronWorkflowsOrderByField, Event, @@ -1219,39 +1220,6 @@ export class Api extends HttpClient - this.request({ - path: `/api/v1/tenants/${tenant}/workflows/crons`, - method: 'DELETE', - query: query, - secure: true, - ...params, - }); /** * @description Get all cron job workflow runs for a tenant * @@ -1301,6 +1269,39 @@ export class Api extends HttpClient + this.request({ + path: `/api/v1/tenants/${tenant}/workflows/crons/${cronId}`, + method: 'GET', + secure: true, + format: 'json', + ...params, + }); + /** + * @description Delete a cron job workflow run for a tenant + * + * @tags Workflow + * @name WorkflowCronDelete + * @summary Delete cron job workflow run + * @request DELETE:/api/v1/tenants/{tenant}/workflows/crons/{cronId} + * @secure + */ + workflowCronDelete = (tenant: string, cronId: string, params: RequestParams = {}) => + this.request({ + path: `/api/v1/tenants/${tenant}/workflows/crons/${cronId}`, + method: 'DELETE', + secure: true, + ...params, + }); /** * @description Cancel a batch of workflow runs * diff --git a/pkg/client/rest/gen.go b/pkg/client/rest/gen.go index 4cfba2f10..aab89c07a 100644 --- a/pkg/client/rest/gen.go +++ b/pkg/client/rest/gen.go @@ -1537,18 +1537,6 @@ type WorkflowRunListStepRunEventsParams struct { LastId *int32 `form:"lastId,omitempty" json:"lastId,omitempty"` } -// WorkflowCronDeleteParams defines parameters for WorkflowCronDelete. -type WorkflowCronDeleteParams struct { - // CronParentId The cron job parent id - CronParentId openapi_types.UUID `form:"cronParentId" json:"cronParentId"` - - // CronName The cron job name - CronName *string `form:"cronName,omitempty" json:"cronName,omitempty"` - - // Cron Cron schedule - Cron string `form:"cron" json:"cron"` -} - // CronWorkflowListParams defines parameters for CronWorkflowList. type CronWorkflowListParams struct { // Offset The number to skip @@ -2041,12 +2029,15 @@ type ClientInterface interface { WorkflowRunCancel(ctx context.Context, tenant openapi_types.UUID, body WorkflowRunCancelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - // WorkflowCronDelete request - WorkflowCronDelete(ctx context.Context, tenant openapi_types.UUID, params *WorkflowCronDeleteParams, reqEditors ...RequestEditorFn) (*http.Response, error) - // CronWorkflowList request CronWorkflowList(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // WorkflowCronDelete request + WorkflowCronDelete(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) + + // WorkflowCronGet request + WorkflowCronGet(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) + // WorkflowRunList request WorkflowRunList(ctx context.Context, tenant openapi_types.UUID, params *WorkflowRunListParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -3030,8 +3021,8 @@ func (c *Client) WorkflowRunCancel(ctx context.Context, tenant openapi_types.UUI return c.Client.Do(req) } -func (c *Client) WorkflowCronDelete(ctx context.Context, tenant openapi_types.UUID, params *WorkflowCronDeleteParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewWorkflowCronDeleteRequest(c.Server, tenant, params) +func (c *Client) CronWorkflowList(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCronWorkflowListRequest(c.Server, tenant, params) if err != nil { return nil, err } @@ -3042,8 +3033,20 @@ func (c *Client) WorkflowCronDelete(ctx context.Context, tenant openapi_types.UU return c.Client.Do(req) } -func (c *Client) CronWorkflowList(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewCronWorkflowListRequest(c.Server, tenant, params) +func (c *Client) WorkflowCronDelete(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewWorkflowCronDeleteRequest(c.Server, tenant, cronId) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) WorkflowCronGet(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewWorkflowCronGetRequest(c.Server, tenant, cronId) if err != nil { return nil, err } @@ -6188,86 +6191,6 @@ func NewWorkflowRunCancelRequestWithBody(server string, tenant openapi_types.UUI return req, nil } -// NewWorkflowCronDeleteRequest generates requests for WorkflowCronDelete -func NewWorkflowCronDeleteRequest(server string, tenant openapi_types.UUID, params *WorkflowCronDeleteParams) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithLocation("simple", false, "tenant", runtime.ParamLocationPath, tenant) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/v1/tenants/%s/workflows/crons", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - queryValues := queryURL.Query() - - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "cronParentId", runtime.ParamLocationQuery, params.CronParentId); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - if params.CronName != nil { - - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "cronName", runtime.ParamLocationQuery, *params.CronName); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "cron", runtime.ParamLocationQuery, params.Cron); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - queryURL.RawQuery = queryValues.Encode() - } - - req, err := http.NewRequest("DELETE", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - // NewCronWorkflowListRequest generates requests for CronWorkflowList func NewCronWorkflowListRequest(server string, tenant openapi_types.UUID, params *CronWorkflowListParams) (*http.Request, error) { var err error @@ -6404,6 +6327,88 @@ func NewCronWorkflowListRequest(server string, tenant openapi_types.UUID, params return req, nil } +// NewWorkflowCronDeleteRequest generates requests for WorkflowCronDelete +func NewWorkflowCronDeleteRequest(server string, tenant openapi_types.UUID, cronId openapi_types.UUID) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "tenant", runtime.ParamLocationPath, tenant) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "cronId", runtime.ParamLocationPath, cronId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/api/v1/tenants/%s/workflows/crons/%s", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("DELETE", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewWorkflowCronGetRequest generates requests for WorkflowCronGet +func NewWorkflowCronGetRequest(server string, tenant openapi_types.UUID, cronId openapi_types.UUID) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "tenant", runtime.ParamLocationPath, tenant) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "cronId", runtime.ParamLocationPath, cronId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/api/v1/tenants/%s/workflows/crons/%s", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewWorkflowRunListRequest generates requests for WorkflowRunList func NewWorkflowRunListRequest(server string, tenant openapi_types.UUID, params *WorkflowRunListParams) (*http.Request, error) { var err error @@ -8293,12 +8298,15 @@ type ClientWithResponsesInterface interface { WorkflowRunCancelWithResponse(ctx context.Context, tenant openapi_types.UUID, body WorkflowRunCancelJSONRequestBody, reqEditors ...RequestEditorFn) (*WorkflowRunCancelResponse, error) - // WorkflowCronDeleteWithResponse request - WorkflowCronDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, params *WorkflowCronDeleteParams, reqEditors ...RequestEditorFn) (*WorkflowCronDeleteResponse, error) - // CronWorkflowListWithResponse request CronWorkflowListWithResponse(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*CronWorkflowListResponse, error) + // WorkflowCronDeleteWithResponse request + WorkflowCronDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowCronDeleteResponse, error) + + // WorkflowCronGetWithResponse request + WorkflowCronGetWithResponse(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowCronGetResponse, error) + // WorkflowRunListWithResponse request WorkflowRunListWithResponse(ctx context.Context, tenant openapi_types.UUID, params *WorkflowRunListParams, reqEditors ...RequestEditorFn) (*WorkflowRunListResponse, error) @@ -9781,6 +9789,30 @@ func (r WorkflowRunCancelResponse) StatusCode() int { return 0 } +type CronWorkflowListResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *CronWorkflowsList + JSON400 *APIErrors + JSON403 *APIErrors +} + +// Status returns HTTPResponse.Status +func (r CronWorkflowListResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r CronWorkflowListResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type WorkflowCronDeleteResponse struct { Body []byte HTTPResponse *http.Response @@ -9804,16 +9836,17 @@ func (r WorkflowCronDeleteResponse) StatusCode() int { return 0 } -type CronWorkflowListResponse struct { +type WorkflowCronGetResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *CronWorkflowsList + JSON200 *CronWorkflows JSON400 *APIErrors JSON403 *APIErrors + JSON404 *APIErrors } // Status returns HTTPResponse.Status -func (r CronWorkflowListResponse) Status() string { +func (r WorkflowCronGetResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -9821,7 +9854,7 @@ func (r CronWorkflowListResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r CronWorkflowListResponse) StatusCode() int { +func (r WorkflowCronGetResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } @@ -11183,22 +11216,31 @@ func (c *ClientWithResponses) WorkflowRunCancelWithResponse(ctx context.Context, return ParseWorkflowRunCancelResponse(rsp) } +// CronWorkflowListWithResponse request returning *CronWorkflowListResponse +func (c *ClientWithResponses) CronWorkflowListWithResponse(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*CronWorkflowListResponse, error) { + rsp, err := c.CronWorkflowList(ctx, tenant, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseCronWorkflowListResponse(rsp) +} + // WorkflowCronDeleteWithResponse request returning *WorkflowCronDeleteResponse -func (c *ClientWithResponses) WorkflowCronDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, params *WorkflowCronDeleteParams, reqEditors ...RequestEditorFn) (*WorkflowCronDeleteResponse, error) { - rsp, err := c.WorkflowCronDelete(ctx, tenant, params, reqEditors...) +func (c *ClientWithResponses) WorkflowCronDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowCronDeleteResponse, error) { + rsp, err := c.WorkflowCronDelete(ctx, tenant, cronId, reqEditors...) if err != nil { return nil, err } return ParseWorkflowCronDeleteResponse(rsp) } -// CronWorkflowListWithResponse request returning *CronWorkflowListResponse -func (c *ClientWithResponses) CronWorkflowListWithResponse(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*CronWorkflowListResponse, error) { - rsp, err := c.CronWorkflowList(ctx, tenant, params, reqEditors...) +// WorkflowCronGetWithResponse request returning *WorkflowCronGetResponse +func (c *ClientWithResponses) WorkflowCronGetWithResponse(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowCronGetResponse, error) { + rsp, err := c.WorkflowCronGet(ctx, tenant, cronId, reqEditors...) if err != nil { return nil, err } - return ParseCronWorkflowListResponse(rsp) + return ParseWorkflowCronGetResponse(rsp) } // WorkflowRunListWithResponse request returning *WorkflowRunListResponse @@ -13831,6 +13873,46 @@ func ParseWorkflowRunCancelResponse(rsp *http.Response) (*WorkflowRunCancelRespo return response, nil } +// ParseCronWorkflowListResponse parses an HTTP response from a CronWorkflowListWithResponse call +func ParseCronWorkflowListResponse(rsp *http.Response) (*CronWorkflowListResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &CronWorkflowListResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest CronWorkflowsList + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + } + + return response, nil +} + // ParseWorkflowCronDeleteResponse parses an HTTP response from a WorkflowCronDeleteWithResponse call func ParseWorkflowCronDeleteResponse(rsp *http.Response) (*WorkflowCronDeleteResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -13864,22 +13946,22 @@ func ParseWorkflowCronDeleteResponse(rsp *http.Response) (*WorkflowCronDeleteRes return response, nil } -// ParseCronWorkflowListResponse parses an HTTP response from a CronWorkflowListWithResponse call -func ParseCronWorkflowListResponse(rsp *http.Response) (*CronWorkflowListResponse, error) { +// ParseWorkflowCronGetResponse parses an HTTP response from a WorkflowCronGetWithResponse call +func ParseWorkflowCronGetResponse(rsp *http.Response) (*WorkflowCronGetResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &CronWorkflowListResponse{ + response := &WorkflowCronGetResponse{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest CronWorkflowsList + var dest CronWorkflows if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -13899,6 +13981,13 @@ func ParseCronWorkflowListResponse(rsp *http.Response) (*CronWorkflowListRespons } response.JSON403 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + } return response, nil diff --git a/pkg/repository/prisma/dbsqlc/models.go b/pkg/repository/prisma/dbsqlc/models.go index 46723d049..79470f663 100644 --- a/pkg/repository/prisma/dbsqlc/models.go +++ b/pkg/repository/prisma/dbsqlc/models.go @@ -1727,6 +1727,7 @@ type WorkflowTriggerCronRef struct { DeletedAt pgtype.Timestamp `json:"deletedAt"` UpdatedAt pgtype.Timestamp `json:"updatedAt"` Name pgtype.Text `json:"name"` + ID pgtype.UUID `json:"id"` } type WorkflowTriggerEventRef struct { diff --git a/pkg/repository/prisma/dbsqlc/schema.sql b/pkg/repository/prisma/dbsqlc/schema.sql index bbb89b074..1947f7128 100644 --- a/pkg/repository/prisma/dbsqlc/schema.sql +++ b/pkg/repository/prisma/dbsqlc/schema.sql @@ -907,7 +907,8 @@ CREATE TABLE "WorkflowTriggerCronRef" ( "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "deletedAt" TIMESTAMP(3), "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "name" TEXT + "name" TEXT, + "id" UUID NOT NULL ); -- CreateTable @@ -1368,6 +1369,9 @@ CREATE UNIQUE INDEX "WorkflowTag_id_key" ON "WorkflowTag"("id" ASC); -- CreateIndex CREATE UNIQUE INDEX "WorkflowTag_tenantId_name_key" ON "WorkflowTag"("tenantId" ASC, "name" ASC); +-- CreateIndex +CREATE UNIQUE INDEX "WorkflowTriggerCronRef_id_key" ON "WorkflowTriggerCronRef"("id" ASC); + -- CreateIndex CREATE UNIQUE INDEX "WorkflowTriggerCronRef_parentId_cron_key" ON "WorkflowTriggerCronRef"("parentId" ASC, "cron" ASC); diff --git a/pkg/repository/prisma/dbsqlc/tickers.sql.go b/pkg/repository/prisma/dbsqlc/tickers.sql.go index 8a4459f48..1aaa87cef 100644 --- a/pkg/repository/prisma/dbsqlc/tickers.sql.go +++ b/pkg/repository/prisma/dbsqlc/tickers.sql.go @@ -227,7 +227,7 @@ FROM active_cron_schedules WHERE cronSchedules."parentId" = active_cron_schedules."parentId" -RETURNING cronschedules."parentId", cronschedules.cron, cronschedules."tickerId", cronschedules.input, cronschedules.enabled, cronschedules."additionalMetadata", cronschedules."createdAt", cronschedules."deletedAt", cronschedules."updatedAt", cronschedules.name, active_cron_schedules."workflowVersionId", active_cron_schedules."tenantId" +RETURNING cronschedules."parentId", cronschedules.cron, cronschedules."tickerId", cronschedules.input, cronschedules.enabled, cronschedules."additionalMetadata", cronschedules."createdAt", cronschedules."deletedAt", cronschedules."updatedAt", cronschedules.name, cronschedules.id, active_cron_schedules."workflowVersionId", active_cron_schedules."tenantId" ` type PollCronSchedulesRow struct { @@ -241,6 +241,7 @@ type PollCronSchedulesRow struct { DeletedAt pgtype.Timestamp `json:"deletedAt"` UpdatedAt pgtype.Timestamp `json:"updatedAt"` Name pgtype.Text `json:"name"` + ID pgtype.UUID `json:"id"` WorkflowVersionId pgtype.UUID `json:"workflowVersionId"` TenantId pgtype.UUID `json:"tenantId"` } @@ -265,6 +266,7 @@ func (q *Queries) PollCronSchedules(ctx context.Context, db DBTX, tickerid pgtyp &i.DeletedAt, &i.UpdatedAt, &i.Name, + &i.ID, &i.WorkflowVersionId, &i.TenantId, ); err != nil { diff --git a/pkg/repository/prisma/dbsqlc/workflows.sql b/pkg/repository/prisma/dbsqlc/workflows.sql index 005cf67e3..7696b9c33 100644 --- a/pkg/repository/prisma/dbsqlc/workflows.sql +++ b/pkg/repository/prisma/dbsqlc/workflows.sql @@ -719,6 +719,9 @@ LIMIT -- name: DeleteWorkflowTriggerCronRef :exec DELETE FROM "WorkflowTriggerCronRef" WHERE - "parentId" = @parentId::uuid AND - "cron" = @cron::text AND - "name" = @name::text; + "id" = sqlc.narg('id')::uuid OR + ( + "parentId" = sqlc.narg('parentId')::uuid AND + "cron" = sqlc.narg('cron')::text AND + "name" = sqlc.narg('name')::text + ); diff --git a/pkg/repository/prisma/dbsqlc/workflows.sql.go b/pkg/repository/prisma/dbsqlc/workflows.sql.go index 6c1b622b5..3a5e796a5 100644 --- a/pkg/repository/prisma/dbsqlc/workflows.sql.go +++ b/pkg/repository/prisma/dbsqlc/workflows.sql.go @@ -576,7 +576,7 @@ INSERT INTO "WorkflowTriggerCronRef" ( $3::text, $4::jsonb, $5::jsonb -) RETURNING "parentId", cron, "tickerId", input, enabled, "additionalMetadata", "createdAt", "deletedAt", "updatedAt", name +) RETURNING "parentId", cron, "tickerId", input, enabled, "additionalMetadata", "createdAt", "deletedAt", "updatedAt", name, id ` type CreateWorkflowTriggerCronRefParams struct { @@ -607,6 +607,7 @@ func (q *Queries) CreateWorkflowTriggerCronRef(ctx context.Context, db DBTX, arg &i.DeletedAt, &i.UpdatedAt, &i.Name, + &i.ID, ) return &i, err } @@ -791,19 +792,28 @@ func (q *Queries) CreateWorkflowVersion(ctx context.Context, db DBTX, arg Create const deleteWorkflowTriggerCronRef = `-- name: DeleteWorkflowTriggerCronRef :exec DELETE FROM "WorkflowTriggerCronRef" WHERE - "parentId" = $1::uuid AND - "cron" = $2::text AND - "name" = $3::text + "id" = $1::uuid OR + ( + "parentId" = $2::uuid AND + "cron" = $3::text AND + "name" = $4::text + ) ` type DeleteWorkflowTriggerCronRefParams struct { - Parentid pgtype.UUID `json:"parentid"` - Cron string `json:"cron"` - Name string `json:"name"` + ID pgtype.UUID `json:"id"` + ParentId pgtype.UUID `json:"parentId"` + Cron pgtype.Text `json:"cron"` + Name pgtype.Text `json:"name"` } func (q *Queries) DeleteWorkflowTriggerCronRef(ctx context.Context, db DBTX, arg DeleteWorkflowTriggerCronRefParams) error { - _, err := db.Exec(ctx, deleteWorkflowTriggerCronRef, arg.Parentid, arg.Cron, arg.Name) + _, err := db.Exec(ctx, deleteWorkflowTriggerCronRef, + arg.ID, + arg.ParentId, + arg.Cron, + arg.Name, + ) return err } @@ -1013,7 +1023,7 @@ func (q *Queries) GetWorkflowVersionById(ctx context.Context, db DBTX, id pgtype const getWorkflowVersionCronTriggerRefs = `-- name: GetWorkflowVersionCronTriggerRefs :many SELECT - wtc."parentId", wtc.cron, wtc."tickerId", wtc.input, wtc.enabled, wtc."additionalMetadata", wtc."createdAt", wtc."deletedAt", wtc."updatedAt", wtc.name + wtc."parentId", wtc.cron, wtc."tickerId", wtc.input, wtc.enabled, wtc."additionalMetadata", wtc."createdAt", wtc."deletedAt", wtc."updatedAt", wtc.name, wtc.id FROM "WorkflowTriggerCronRef" as wtc JOIN "WorkflowTriggers" as wt ON wt."id" = wtc."parentId" @@ -1041,6 +1051,7 @@ func (q *Queries) GetWorkflowVersionCronTriggerRefs(ctx context.Context, db DBTX &i.DeletedAt, &i.UpdatedAt, &i.Name, + &i.ID, ); err != nil { return nil, err } @@ -1386,7 +1397,7 @@ SELECT w."id" as "workflowId", w."tenantId", t.id, t."createdAt", t."updatedAt", t."deletedAt", t."workflowVersionId", t."tenantId", - c."parentId", c.cron, c."tickerId", c.input, c.enabled, c."additionalMetadata", c."createdAt", c."deletedAt", c."updatedAt", c.name + c."parentId", c.cron, c."tickerId", c.input, c.enabled, c."additionalMetadata", c."createdAt", c."deletedAt", c."updatedAt", c.name, c.id FROM latest_versions JOIN @@ -1443,6 +1454,7 @@ type ListCronWorkflowsRow struct { DeletedAt_2 pgtype.Timestamp `json:"deletedAt_2"` UpdatedAt_2 pgtype.Timestamp `json:"updatedAt_2"` Name_2 pgtype.Text `json:"name_2"` + ID_2 pgtype.UUID `json:"id_2"` } // Get all of the latest workflow versions for the tenant @@ -1484,6 +1496,7 @@ func (q *Queries) ListCronWorkflows(ctx context.Context, db DBTX, arg ListCronWo &i.DeletedAt_2, &i.UpdatedAt_2, &i.Name_2, + &i.ID_2, ); err != nil { return nil, err } diff --git a/pkg/repository/prisma/workflow.go b/pkg/repository/prisma/workflow.go index ae486040b..879296f77 100644 --- a/pkg/repository/prisma/workflow.go +++ b/pkg/repository/prisma/workflow.go @@ -353,11 +353,9 @@ func (w *workflowAPIRepository) GetCronWorkflow(ctx context.Context, tenantId, c return cronWorkflows[0], nil } -func (w *workflowAPIRepository) DeleteCronWorkflow(ctx context.Context, tenantId, cron, cronParentId string, cronName *string) error { +func (w *workflowAPIRepository) DeleteCronWorkflow(ctx context.Context, tenantId, id string) error { return w.queries.DeleteWorkflowTriggerCronRef(ctx, w.pool, dbsqlc.DeleteWorkflowTriggerCronRefParams{ - Parentid: sqlchelpers.UUIDFromStr(cronParentId), - Cron: cron, - Name: *cronName, + ID: sqlchelpers.UUIDFromStr(id), }) } diff --git a/pkg/repository/workflow.go b/pkg/repository/workflow.go index e11f20492..2482f110d 100644 --- a/pkg/repository/workflow.go +++ b/pkg/repository/workflow.go @@ -286,7 +286,7 @@ type WorkflowAPIRepository interface { GetCronWorkflow(ctx context.Context, tenantId, cronWorkflowId string) (*dbsqlc.ListCronWorkflowsRow, error) // DeleteCronWorkflow deletes a cron workflow run - DeleteCronWorkflow(ctx context.Context, tenantId, cron, cronParentId string, cronName *string) error + DeleteCronWorkflow(ctx context.Context, tenantId, id string) error } type WorkflowEngineRepository interface { diff --git a/prisma/migrations/20241030150107_tmp/migration.sql b/prisma/migrations/20241030150107_tmp/migration.sql new file mode 100644 index 000000000..67a1cef29 --- /dev/null +++ b/prisma/migrations/20241030150107_tmp/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - A unique constraint covering the columns `[id]` on the table `WorkflowTriggerCronRef` will be added. If there are existing duplicate values, this will fail. + - The required column `id` was added to the `WorkflowTriggerCronRef` table with a prisma-level default value. This is not possible if the table is not empty. Please add this column as optional, then populate it before making it required. + +*/ +-- AlterTable +ALTER TABLE "WorkflowTriggerCronRef" ADD COLUMN "id" UUID NOT NULL; + +-- CreateIndex +CREATE UNIQUE INDEX "WorkflowTriggerCronRef_id_key" ON "WorkflowTriggerCronRef"("id"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 8245040e2..8718baa45 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -645,6 +645,8 @@ model WorkflowTriggerEventRef { } model WorkflowTriggerCronRef { + id String @unique @default(uuid()) @db.Uuid + name String? // the parent workflow diff --git a/sql/migrations/20241030150116_tmp.sql b/sql/migrations/20241030150116_tmp.sql new file mode 100644 index 000000000..3c5392d64 --- /dev/null +++ b/sql/migrations/20241030150116_tmp.sql @@ -0,0 +1,5 @@ +-- Modify "WorkflowTriggerCronRef" table +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; +ALTER TABLE "WorkflowTriggerCronRef" ADD COLUMN "id" uuid NOT NULL DEFAULT uuid_generate_v4(); +-- Create index "WorkflowTriggerCronRef_id_key" to table: "WorkflowTriggerCronRef" +CREATE UNIQUE INDEX "WorkflowTriggerCronRef_id_key" ON "WorkflowTriggerCronRef" ("id"); diff --git a/sql/migrations/20241030150342_tmp.sql b/sql/migrations/20241030150342_tmp.sql new file mode 100644 index 000000000..5eb64be46 --- /dev/null +++ b/sql/migrations/20241030150342_tmp.sql @@ -0,0 +1,2 @@ +-- Modify "WorkflowTriggerCronRef" table +ALTER TABLE "WorkflowTriggerCronRef" ALTER COLUMN "id" DROP DEFAULT; diff --git a/sql/migrations/atlas.sum b/sql/migrations/atlas.sum index bea3957ee..3fc2d766a 100644 --- a/sql/migrations/atlas.sum +++ b/sql/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:Qd8kaosQVxQXj9CxwoLtPrpmggU33rd/fqxrzwbDybg= +h1:n9zZZyeWzYmcejRQIs2QQUMbhtHA9YwDY5QZZy2Z+lM= 20240115180414_init.sql h1:Ef3ZyjAHkmJPdGF/dEWCahbwgcg6uGJKnDxW2JCRi2k= 20240122014727_v0_6_0.sql h1:o/LdlteAeFgoHJ3e/M4Xnghqt9826IE/Y/h0q95Acuo= 20240126235456_v0_7_0.sql h1:KiVzt/hXgQ6esbdC6OMJOOWuYEXmy1yeCpmsVAHTFKs= @@ -75,3 +75,5 @@ h1:Qd8kaosQVxQXj9CxwoLtPrpmggU33rd/fqxrzwbDybg= 20241029122625_v0.51.0.sql h1:nOa4FqmZxSh1yBOJyduX+j15gQavjizTn660wyXjhNk= 20241030131347_tmp.sql h1:48ydfY8fUk6nR6Av35gk57TfBbrwYYLwjtTAKch1TBg= 20241030133048_tmp.sql h1:dWSeXAsgIbUo1yCrxM6p/a2mPPDMfMP2j4s+R0ADZjE= +20241030150116_tmp.sql h1:LUy5JzLfjjUEO8cnUco26jKbqkdC7yIHAJ5xx2XLVqE= +20241030150342_tmp.sql h1:bDLmpmjBtYckGAIOhn7YRgEK32BLXGHA9sravMY135k= diff --git a/sql/schema/schema.sql b/sql/schema/schema.sql index 6bbb6a7c5..98748bcc3 100644 --- a/sql/schema/schema.sql +++ b/sql/schema/schema.sql @@ -907,7 +907,8 @@ CREATE TABLE "WorkflowTriggerCronRef" ( "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "deletedAt" TIMESTAMP(3), "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "name" TEXT + "name" TEXT, + "id" UUID NOT NULL ); -- CreateTable @@ -1368,6 +1369,9 @@ CREATE UNIQUE INDEX "WorkflowTag_id_key" ON "WorkflowTag"("id" ASC); -- CreateIndex CREATE UNIQUE INDEX "WorkflowTag_tenantId_name_key" ON "WorkflowTag"("tenantId" ASC, "name" ASC); +-- CreateIndex +CREATE UNIQUE INDEX "WorkflowTriggerCronRef_id_key" ON "WorkflowTriggerCronRef"("id" ASC); + -- CreateIndex CREATE UNIQUE INDEX "WorkflowTriggerCronRef_parentId_cron_key" ON "WorkflowTriggerCronRef"("parentId" ASC, "cron" ASC); From d489d39814a1453cea7ba632cb18cfddeec22c49 Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Fri, 1 Nov 2024 11:15:54 -0400 Subject: [PATCH 24/30] fix: populator --- api-contracts/openapi/openapi.yaml | 4 +- .../openapi/paths/workflow/workflow.yaml | 10 +- .../handlers/workflows/delete_scheduled.go | 4 +- api/v1/server/handlers/workflows/get_cron.go | 2 +- .../handlers/workflows/get_scheduled.go | 16 +- api/v1/server/oas/gen/openapi.gen.go | 474 +++++++++--------- frontend/app/src/lib/api/generated/Api.ts | 24 +- frontend/app/src/lib/api/queries.ts | 4 +- pkg/client/rest/gen.go | 64 +-- 9 files changed, 294 insertions(+), 308 deletions(-) diff --git a/api-contracts/openapi/openapi.yaml b/api-contracts/openapi/openapi.yaml index c2aea82a2..90a32b7d4 100644 --- a/api-contracts/openapi/openapi.yaml +++ b/api-contracts/openapi/openapi.yaml @@ -118,11 +118,11 @@ paths: $ref: "./paths/workflow/workflow.yaml#/withTenant" /api/v1/tenants/{tenant}/workflows/scheduled: $ref: "./paths/workflow/workflow.yaml#/scheduledList" - /api/v1/tenants/{tenant}/workflows/scheduled/{scheduledId}: + /api/v1/tenants/{tenant}/workflows/scheduled/{scheduled-workflow-run}: $ref: "./paths/workflow/workflow.yaml#/scheduled" /api/v1/tenants/{tenant}/workflows/crons: $ref: "./paths/workflow/workflow.yaml#/cronsList" - /api/v1/tenants/{tenant}/workflows/crons/{cronId}: + /api/v1/tenants/{tenant}/workflows/crons/{cron-workflow}: $ref: "./paths/workflow/workflow.yaml#/crons" /api/v1/tenants/{tenant}/workflows/cancel: $ref: "./paths/workflow/workflow.yaml#/cancelWorkflowRuns" diff --git a/api-contracts/openapi/paths/workflow/workflow.yaml b/api-contracts/openapi/paths/workflow/workflow.yaml index 141a39450..b00999a93 100644 --- a/api-contracts/openapi/paths/workflow/workflow.yaml +++ b/api-contracts/openapi/paths/workflow/workflow.yaml @@ -938,7 +938,7 @@ scheduledList: scheduled: get: - x-resources: ["tenant"] + x-resources: ["tenant", "scheduled-workflow-run"] description: Get a scheduled workflow run for a tenant operationId: workflow-scheduled:get parameters: @@ -953,7 +953,7 @@ scheduled: maxLength: 36 - description: The scheduled workflow id in: path - name: scheduledId + name: scheduled-workflow-run required: true schema: type: string @@ -1004,7 +1004,7 @@ scheduled: maxLength: 36 - description: The scheduled workflow id in: path - name: scheduledId + name: scheduled-workflow-run required: true schema: type: string @@ -1047,7 +1047,7 @@ crons: maxLength: 36 - description: The cron job id in: path - name: cronId + name: cron-workflow required: true schema: type: string @@ -1098,7 +1098,7 @@ crons: maxLength: 36 - description: The cron job id in: path - name: cronId + name: cron-workflow required: true schema: type: string diff --git a/api/v1/server/handlers/workflows/delete_scheduled.go b/api/v1/server/handlers/workflows/delete_scheduled.go index 190bce1d6..d30faa33d 100644 --- a/api/v1/server/handlers/workflows/delete_scheduled.go +++ b/api/v1/server/handlers/workflows/delete_scheduled.go @@ -7,19 +7,17 @@ import ( "github.com/labstack/echo/v4" "github.com/hatchet-dev/hatchet/api/v1/server/oas/gen" - "github.com/hatchet-dev/hatchet/pkg/repository/prisma/db" "github.com/hatchet-dev/hatchet/pkg/repository/prisma/dbsqlc" "github.com/hatchet-dev/hatchet/pkg/repository/prisma/sqlchelpers" ) func (t *WorkflowService) WorkflowScheduledDelete(ctx echo.Context, request gen.WorkflowScheduledDeleteRequestObject) (gen.WorkflowScheduledDeleteResponseObject, error) { - _ = ctx.Get("tenant").(*db.TenantModel) scheduled := ctx.Get("scheduled-workflow-run").(*dbsqlc.ListScheduledWorkflowsRow) dbCtx, cancel := context.WithTimeout(ctx.Request().Context(), 30*time.Second) defer cancel() - err := t.config.APIRepository.WorkflowRun().DeleteScheduledWorkflow(dbCtx, sqlchelpers.UUIDToStr(scheduled.TenantId), request.ScheduledId.String()) + err := t.config.APIRepository.WorkflowRun().DeleteScheduledWorkflow(dbCtx, sqlchelpers.UUIDToStr(scheduled.TenantId), request.ScheduledWorkflowRun.String()) if err != nil { return nil, err diff --git a/api/v1/server/handlers/workflows/get_cron.go b/api/v1/server/handlers/workflows/get_cron.go index e26338fc0..121870f71 100644 --- a/api/v1/server/handlers/workflows/get_cron.go +++ b/api/v1/server/handlers/workflows/get_cron.go @@ -18,7 +18,7 @@ func (t *WorkflowService) WorkflowCronGet(ctx echo.Context, request gen.Workflow dbCtx, cancel := context.WithTimeout(ctx.Request().Context(), 30*time.Second) defer cancel() - scheduled, err := t.config.APIRepository.Workflow().GetCronWorkflow(dbCtx, tenant.ID, request.CronId.String()) + scheduled, err := t.config.APIRepository.Workflow().GetCronWorkflow(dbCtx, tenant.ID, request.CronWorkflow.String()) if err != nil { return nil, err diff --git a/api/v1/server/handlers/workflows/get_scheduled.go b/api/v1/server/handlers/workflows/get_scheduled.go index 35eb8901e..6d7f47895 100644 --- a/api/v1/server/handlers/workflows/get_scheduled.go +++ b/api/v1/server/handlers/workflows/get_scheduled.go @@ -1,28 +1,16 @@ package workflows import ( - "context" - "time" - "github.com/labstack/echo/v4" "github.com/hatchet-dev/hatchet/api/v1/server/oas/apierrors" "github.com/hatchet-dev/hatchet/api/v1/server/oas/gen" "github.com/hatchet-dev/hatchet/api/v1/server/oas/transformers" - "github.com/hatchet-dev/hatchet/pkg/repository/prisma/db" + "github.com/hatchet-dev/hatchet/pkg/repository/prisma/dbsqlc" ) func (t *WorkflowService) WorkflowScheduledGet(ctx echo.Context, request gen.WorkflowScheduledGetRequestObject) (gen.WorkflowScheduledGetResponseObject, error) { - tenant := ctx.Get("tenant").(*db.TenantModel) - - dbCtx, cancel := context.WithTimeout(ctx.Request().Context(), 30*time.Second) - defer cancel() - - scheduled, err := t.config.APIRepository.WorkflowRun().GetScheduledWorkflow(dbCtx, tenant.ID, request.ScheduledId.String()) - - if err != nil { - return nil, err - } + scheduled := ctx.Get("scheduled").(*dbsqlc.ListScheduledWorkflowsRow) if scheduled == nil { return gen.WorkflowScheduledGet404JSONResponse(apierrors.NewAPIErrors("Scheduled workflow not found.")), nil diff --git a/api/v1/server/oas/gen/openapi.gen.go b/api/v1/server/oas/gen/openapi.gen.go index 2b47539ba..80bb0f34a 100644 --- a/api/v1/server/oas/gen/openapi.gen.go +++ b/api/v1/server/oas/gen/openapi.gen.go @@ -1933,11 +1933,11 @@ type ServerInterface interface { // (GET /api/v1/tenants/{tenant}/workflows/crons) CronWorkflowList(ctx echo.Context, tenant openapi_types.UUID, params CronWorkflowListParams) error // Delete cron job workflow run - // (DELETE /api/v1/tenants/{tenant}/workflows/crons/{cronId}) - WorkflowCronDelete(ctx echo.Context, tenant openapi_types.UUID, cronId openapi_types.UUID) error + // (DELETE /api/v1/tenants/{tenant}/workflows/crons/{cron-workflow}) + WorkflowCronDelete(ctx echo.Context, tenant openapi_types.UUID, cronWorkflow openapi_types.UUID) error // Get cron job workflow run - // (GET /api/v1/tenants/{tenant}/workflows/crons/{cronId}) - WorkflowCronGet(ctx echo.Context, tenant openapi_types.UUID, cronId openapi_types.UUID) error + // (GET /api/v1/tenants/{tenant}/workflows/crons/{cron-workflow}) + WorkflowCronGet(ctx echo.Context, tenant openapi_types.UUID, cronWorkflow openapi_types.UUID) error // Get workflow runs // (GET /api/v1/tenants/{tenant}/workflows/runs) WorkflowRunList(ctx echo.Context, tenant openapi_types.UUID, params WorkflowRunListParams) error @@ -1948,11 +1948,11 @@ type ServerInterface interface { // (GET /api/v1/tenants/{tenant}/workflows/scheduled) WorkflowScheduledList(ctx echo.Context, tenant openapi_types.UUID, params WorkflowScheduledListParams) error // Delete scheduled workflow run - // (DELETE /api/v1/tenants/{tenant}/workflows/scheduled/{scheduledId}) - WorkflowScheduledDelete(ctx echo.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID) error + // (DELETE /api/v1/tenants/{tenant}/workflows/scheduled/{scheduled-workflow-run}) + WorkflowScheduledDelete(ctx echo.Context, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID) error // Get scheduled workflow run - // (GET /api/v1/tenants/{tenant}/workflows/scheduled/{scheduledId}) - WorkflowScheduledGet(ctx echo.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID) error + // (GET /api/v1/tenants/{tenant}/workflows/scheduled/{scheduled-workflow-run}) + WorkflowScheduledGet(ctx echo.Context, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID) error // Get workflow worker count // (GET /api/v1/tenants/{tenant}/workflows/{workflow}/worker-count) WorkflowGetWorkersCount(ctx echo.Context, tenant openapi_types.UUID, workflow openapi_types.UUID) error @@ -3492,12 +3492,12 @@ func (w *ServerInterfaceWrapper) WorkflowCronDelete(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tenant: %s", err)) } - // ------------- Path parameter "cronId" ------------- - var cronId openapi_types.UUID + // ------------- Path parameter "cron-workflow" ------------- + var cronWorkflow openapi_types.UUID - err = runtime.BindStyledParameterWithLocation("simple", false, "cronId", runtime.ParamLocationPath, ctx.Param("cronId"), &cronId) + err = runtime.BindStyledParameterWithLocation("simple", false, "cron-workflow", runtime.ParamLocationPath, ctx.Param("cron-workflow"), &cronWorkflow) if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter cronId: %s", err)) + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter cron-workflow: %s", err)) } ctx.Set(BearerAuthScopes, []string{}) @@ -3505,7 +3505,7 @@ func (w *ServerInterfaceWrapper) WorkflowCronDelete(ctx echo.Context) error { ctx.Set(CookieAuthScopes, []string{}) // Invoke the callback with all the unmarshaled arguments - err = w.Handler.WorkflowCronDelete(ctx, tenant, cronId) + err = w.Handler.WorkflowCronDelete(ctx, tenant, cronWorkflow) return err } @@ -3520,12 +3520,12 @@ func (w *ServerInterfaceWrapper) WorkflowCronGet(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tenant: %s", err)) } - // ------------- Path parameter "cronId" ------------- - var cronId openapi_types.UUID + // ------------- Path parameter "cron-workflow" ------------- + var cronWorkflow openapi_types.UUID - err = runtime.BindStyledParameterWithLocation("simple", false, "cronId", runtime.ParamLocationPath, ctx.Param("cronId"), &cronId) + err = runtime.BindStyledParameterWithLocation("simple", false, "cron-workflow", runtime.ParamLocationPath, ctx.Param("cron-workflow"), &cronWorkflow) if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter cronId: %s", err)) + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter cron-workflow: %s", err)) } ctx.Set(BearerAuthScopes, []string{}) @@ -3533,7 +3533,7 @@ func (w *ServerInterfaceWrapper) WorkflowCronGet(ctx echo.Context) error { ctx.Set(CookieAuthScopes, []string{}) // Invoke the callback with all the unmarshaled arguments - err = w.Handler.WorkflowCronGet(ctx, tenant, cronId) + err = w.Handler.WorkflowCronGet(ctx, tenant, cronWorkflow) return err } @@ -3831,12 +3831,12 @@ func (w *ServerInterfaceWrapper) WorkflowScheduledDelete(ctx echo.Context) error return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tenant: %s", err)) } - // ------------- Path parameter "scheduledId" ------------- - var scheduledId openapi_types.UUID + // ------------- Path parameter "scheduled-workflow-run" ------------- + var scheduledWorkflowRun openapi_types.UUID - err = runtime.BindStyledParameterWithLocation("simple", false, "scheduledId", runtime.ParamLocationPath, ctx.Param("scheduledId"), &scheduledId) + err = runtime.BindStyledParameterWithLocation("simple", false, "scheduled-workflow-run", runtime.ParamLocationPath, ctx.Param("scheduled-workflow-run"), &scheduledWorkflowRun) if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter scheduledId: %s", err)) + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter scheduled-workflow-run: %s", err)) } ctx.Set(BearerAuthScopes, []string{}) @@ -3844,7 +3844,7 @@ func (w *ServerInterfaceWrapper) WorkflowScheduledDelete(ctx echo.Context) error ctx.Set(CookieAuthScopes, []string{}) // Invoke the callback with all the unmarshaled arguments - err = w.Handler.WorkflowScheduledDelete(ctx, tenant, scheduledId) + err = w.Handler.WorkflowScheduledDelete(ctx, tenant, scheduledWorkflowRun) return err } @@ -3859,12 +3859,12 @@ func (w *ServerInterfaceWrapper) WorkflowScheduledGet(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tenant: %s", err)) } - // ------------- Path parameter "scheduledId" ------------- - var scheduledId openapi_types.UUID + // ------------- Path parameter "scheduled-workflow-run" ------------- + var scheduledWorkflowRun openapi_types.UUID - err = runtime.BindStyledParameterWithLocation("simple", false, "scheduledId", runtime.ParamLocationPath, ctx.Param("scheduledId"), &scheduledId) + err = runtime.BindStyledParameterWithLocation("simple", false, "scheduled-workflow-run", runtime.ParamLocationPath, ctx.Param("scheduled-workflow-run"), &scheduledWorkflowRun) if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter scheduledId: %s", err)) + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter scheduled-workflow-run: %s", err)) } ctx.Set(BearerAuthScopes, []string{}) @@ -3872,7 +3872,7 @@ func (w *ServerInterfaceWrapper) WorkflowScheduledGet(ctx echo.Context) error { ctx.Set(CookieAuthScopes, []string{}) // Invoke the callback with all the unmarshaled arguments - err = w.Handler.WorkflowScheduledGet(ctx, tenant, scheduledId) + err = w.Handler.WorkflowScheduledGet(ctx, tenant, scheduledWorkflowRun) return err } @@ -4370,13 +4370,13 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/api/v1/tenants/:tenant/workflows", wrapper.WorkflowList) router.POST(baseURL+"/api/v1/tenants/:tenant/workflows/cancel", wrapper.WorkflowRunCancel) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/crons", wrapper.CronWorkflowList) - router.DELETE(baseURL+"/api/v1/tenants/:tenant/workflows/crons/:cronId", wrapper.WorkflowCronDelete) - router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/crons/:cronId", wrapper.WorkflowCronGet) + router.DELETE(baseURL+"/api/v1/tenants/:tenant/workflows/crons/:cron-workflow", wrapper.WorkflowCronDelete) + router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/crons/:cron-workflow", wrapper.WorkflowCronGet) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/runs", wrapper.WorkflowRunList) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/runs/metrics", wrapper.WorkflowRunGetMetrics) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/scheduled", wrapper.WorkflowScheduledList) - router.DELETE(baseURL+"/api/v1/tenants/:tenant/workflows/scheduled/:scheduledId", wrapper.WorkflowScheduledDelete) - router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/scheduled/:scheduledId", wrapper.WorkflowScheduledGet) + router.DELETE(baseURL+"/api/v1/tenants/:tenant/workflows/scheduled/:scheduled-workflow-run", wrapper.WorkflowScheduledDelete) + router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/scheduled/:scheduled-workflow-run", wrapper.WorkflowScheduledGet) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/:workflow/worker-count", wrapper.WorkflowGetWorkersCount) router.GET(baseURL+"/api/v1/users/current", wrapper.UserGetCurrent) router.GET(baseURL+"/api/v1/users/github/callback", wrapper.UserUpdateGithubOauthCallback) @@ -6583,8 +6583,8 @@ func (response CronWorkflowList403JSONResponse) VisitCronWorkflowListResponse(w } type WorkflowCronDeleteRequestObject struct { - Tenant openapi_types.UUID `json:"tenant"` - CronId openapi_types.UUID `json:"cronId"` + Tenant openapi_types.UUID `json:"tenant"` + CronWorkflow openapi_types.UUID `json:"cron-workflow"` } type WorkflowCronDeleteResponseObject interface { @@ -6618,8 +6618,8 @@ func (response WorkflowCronDelete403JSONResponse) VisitWorkflowCronDeleteRespons } type WorkflowCronGetRequestObject struct { - Tenant openapi_types.UUID `json:"tenant"` - CronId openapi_types.UUID `json:"cronId"` + Tenant openapi_types.UUID `json:"tenant"` + CronWorkflow openapi_types.UUID `json:"cron-workflow"` } type WorkflowCronGetResponseObject interface { @@ -6771,8 +6771,8 @@ func (response WorkflowScheduledList403JSONResponse) VisitWorkflowScheduledListR } type WorkflowScheduledDeleteRequestObject struct { - Tenant openapi_types.UUID `json:"tenant"` - ScheduledId openapi_types.UUID `json:"scheduledId"` + Tenant openapi_types.UUID `json:"tenant"` + ScheduledWorkflowRun openapi_types.UUID `json:"scheduled-workflow-run"` } type WorkflowScheduledDeleteResponseObject interface { @@ -6806,8 +6806,8 @@ func (response WorkflowScheduledDelete403JSONResponse) VisitWorkflowScheduledDel } type WorkflowScheduledGetRequestObject struct { - Tenant openapi_types.UUID `json:"tenant"` - ScheduledId openapi_types.UUID `json:"scheduledId"` + Tenant openapi_types.UUID `json:"tenant"` + ScheduledWorkflowRun openapi_types.UUID `json:"scheduled-workflow-run"` } type WorkflowScheduledGetResponseObject interface { @@ -9519,11 +9519,11 @@ func (sh *strictHandler) CronWorkflowList(ctx echo.Context, tenant openapi_types } // WorkflowCronDelete operation middleware -func (sh *strictHandler) WorkflowCronDelete(ctx echo.Context, tenant openapi_types.UUID, cronId openapi_types.UUID) error { +func (sh *strictHandler) WorkflowCronDelete(ctx echo.Context, tenant openapi_types.UUID, cronWorkflow openapi_types.UUID) error { var request WorkflowCronDeleteRequestObject request.Tenant = tenant - request.CronId = cronId + request.CronWorkflow = cronWorkflow handler := func(ctx echo.Context, request interface{}) (interface{}, error) { return sh.ssi.WorkflowCronDelete(ctx, request.(WorkflowCronDeleteRequestObject)) @@ -9545,11 +9545,11 @@ func (sh *strictHandler) WorkflowCronDelete(ctx echo.Context, tenant openapi_typ } // WorkflowCronGet operation middleware -func (sh *strictHandler) WorkflowCronGet(ctx echo.Context, tenant openapi_types.UUID, cronId openapi_types.UUID) error { +func (sh *strictHandler) WorkflowCronGet(ctx echo.Context, tenant openapi_types.UUID, cronWorkflow openapi_types.UUID) error { var request WorkflowCronGetRequestObject request.Tenant = tenant - request.CronId = cronId + request.CronWorkflow = cronWorkflow handler := func(ctx echo.Context, request interface{}) (interface{}, error) { return sh.ssi.WorkflowCronGet(ctx, request.(WorkflowCronGetRequestObject)) @@ -9649,11 +9649,11 @@ func (sh *strictHandler) WorkflowScheduledList(ctx echo.Context, tenant openapi_ } // WorkflowScheduledDelete operation middleware -func (sh *strictHandler) WorkflowScheduledDelete(ctx echo.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID) error { +func (sh *strictHandler) WorkflowScheduledDelete(ctx echo.Context, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID) error { var request WorkflowScheduledDeleteRequestObject request.Tenant = tenant - request.ScheduledId = scheduledId + request.ScheduledWorkflowRun = scheduledWorkflowRun handler := func(ctx echo.Context, request interface{}) (interface{}, error) { return sh.ssi.WorkflowScheduledDelete(ctx, request.(WorkflowScheduledDeleteRequestObject)) @@ -9675,11 +9675,11 @@ func (sh *strictHandler) WorkflowScheduledDelete(ctx echo.Context, tenant openap } // WorkflowScheduledGet operation middleware -func (sh *strictHandler) WorkflowScheduledGet(ctx echo.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID) error { +func (sh *strictHandler) WorkflowScheduledGet(ctx echo.Context, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID) error { var request WorkflowScheduledGetRequestObject request.Tenant = tenant - request.ScheduledId = scheduledId + request.ScheduledWorkflowRun = scheduledWorkflowRun handler := func(ctx echo.Context, request interface{}) (interface{}, error) { return sh.ssi.WorkflowScheduledGet(ctx, request.(WorkflowScheduledGetRequestObject)) @@ -10352,195 +10352,195 @@ func (sh *strictHandler) WorkflowVersionGet(ctx echo.Context, workflow openapi_t // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/frontend/app/src/lib/api/generated/Api.ts b/frontend/app/src/lib/api/generated/Api.ts index 348a0c76f..aad098201 100644 --- a/frontend/app/src/lib/api/generated/Api.ts +++ b/frontend/app/src/lib/api/generated/Api.ts @@ -1193,12 +1193,12 @@ export class Api extends HttpClient + workflowScheduledGet = (tenant: string, scheduledWorkflowRun: string, params: RequestParams = {}) => this.request({ - path: `/api/v1/tenants/${tenant}/workflows/scheduled/${scheduledId}`, + path: `/api/v1/tenants/${tenant}/workflows/scheduled/${scheduledWorkflowRun}`, method: 'GET', secure: true, format: 'json', @@ -1210,12 +1210,12 @@ export class Api extends HttpClient + workflowScheduledDelete = (tenant: string, scheduledWorkflowRun: string, params: RequestParams = {}) => this.request({ - path: `/api/v1/tenants/${tenant}/workflows/scheduled/${scheduledId}`, + path: `/api/v1/tenants/${tenant}/workflows/scheduled/${scheduledWorkflowRun}`, method: 'DELETE', secure: true, ...params, @@ -1275,12 +1275,12 @@ export class Api extends HttpClient + workflowCronGet = (tenant: string, cronWorkflow: string, params: RequestParams = {}) => this.request({ - path: `/api/v1/tenants/${tenant}/workflows/crons/${cronId}`, + path: `/api/v1/tenants/${tenant}/workflows/crons/${cronWorkflow}`, method: 'GET', secure: true, format: 'json', @@ -1292,12 +1292,12 @@ export class Api extends HttpClient + workflowCronDelete = (tenant: string, cronWorkflow: string, params: RequestParams = {}) => this.request({ - path: `/api/v1/tenants/${tenant}/workflows/crons/${cronId}`, + path: `/api/v1/tenants/${tenant}/workflows/crons/${cronWorkflow}`, method: 'DELETE', secure: true, ...params, diff --git a/frontend/app/src/lib/api/queries.ts b/frontend/app/src/lib/api/queries.ts index 87ef738f5..bfaef4b61 100644 --- a/frontend/app/src/lib/api/queries.ts +++ b/frontend/app/src/lib/api/queries.ts @@ -188,9 +188,9 @@ export const queries = createQueryKeyStore({ (await api.workflowScheduledList(tenant, query)).data, }), }, - cronRuns: { + cronJobs: { list: (tenant: string, query: CronWorkflowsQuery) => ({ - queryKey: ['cron-run:list', tenant, query], + queryKey: ['cron-job:list', tenant, query], queryFn: async () => (await api.cronWorkflowList(tenant, query)).data, }), }, diff --git a/pkg/client/rest/gen.go b/pkg/client/rest/gen.go index aab89c07a..09e00b0f7 100644 --- a/pkg/client/rest/gen.go +++ b/pkg/client/rest/gen.go @@ -2033,10 +2033,10 @@ type ClientInterface interface { CronWorkflowList(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*http.Response, error) // WorkflowCronDelete request - WorkflowCronDelete(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) + WorkflowCronDelete(ctx context.Context, tenant openapi_types.UUID, cronWorkflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) // WorkflowCronGet request - WorkflowCronGet(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) + WorkflowCronGet(ctx context.Context, tenant openapi_types.UUID, cronWorkflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) // WorkflowRunList request WorkflowRunList(ctx context.Context, tenant openapi_types.UUID, params *WorkflowRunListParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -2048,10 +2048,10 @@ type ClientInterface interface { WorkflowScheduledList(ctx context.Context, tenant openapi_types.UUID, params *WorkflowScheduledListParams, reqEditors ...RequestEditorFn) (*http.Response, error) // WorkflowScheduledDelete request - WorkflowScheduledDelete(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) + WorkflowScheduledDelete(ctx context.Context, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) // WorkflowScheduledGet request - WorkflowScheduledGet(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) + WorkflowScheduledGet(ctx context.Context, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) // WorkflowGetWorkersCount request WorkflowGetWorkersCount(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -3033,8 +3033,8 @@ func (c *Client) CronWorkflowList(ctx context.Context, tenant openapi_types.UUID return c.Client.Do(req) } -func (c *Client) WorkflowCronDelete(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewWorkflowCronDeleteRequest(c.Server, tenant, cronId) +func (c *Client) WorkflowCronDelete(ctx context.Context, tenant openapi_types.UUID, cronWorkflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewWorkflowCronDeleteRequest(c.Server, tenant, cronWorkflow) if err != nil { return nil, err } @@ -3045,8 +3045,8 @@ func (c *Client) WorkflowCronDelete(ctx context.Context, tenant openapi_types.UU return c.Client.Do(req) } -func (c *Client) WorkflowCronGet(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewWorkflowCronGetRequest(c.Server, tenant, cronId) +func (c *Client) WorkflowCronGet(ctx context.Context, tenant openapi_types.UUID, cronWorkflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewWorkflowCronGetRequest(c.Server, tenant, cronWorkflow) if err != nil { return nil, err } @@ -3093,8 +3093,8 @@ func (c *Client) WorkflowScheduledList(ctx context.Context, tenant openapi_types return c.Client.Do(req) } -func (c *Client) WorkflowScheduledDelete(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewWorkflowScheduledDeleteRequest(c.Server, tenant, scheduledId) +func (c *Client) WorkflowScheduledDelete(ctx context.Context, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewWorkflowScheduledDeleteRequest(c.Server, tenant, scheduledWorkflowRun) if err != nil { return nil, err } @@ -3105,8 +3105,8 @@ func (c *Client) WorkflowScheduledDelete(ctx context.Context, tenant openapi_typ return c.Client.Do(req) } -func (c *Client) WorkflowScheduledGet(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewWorkflowScheduledGetRequest(c.Server, tenant, scheduledId) +func (c *Client) WorkflowScheduledGet(ctx context.Context, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewWorkflowScheduledGetRequest(c.Server, tenant, scheduledWorkflowRun) if err != nil { return nil, err } @@ -6328,7 +6328,7 @@ func NewCronWorkflowListRequest(server string, tenant openapi_types.UUID, params } // NewWorkflowCronDeleteRequest generates requests for WorkflowCronDelete -func NewWorkflowCronDeleteRequest(server string, tenant openapi_types.UUID, cronId openapi_types.UUID) (*http.Request, error) { +func NewWorkflowCronDeleteRequest(server string, tenant openapi_types.UUID, cronWorkflow openapi_types.UUID) (*http.Request, error) { var err error var pathParam0 string @@ -6340,7 +6340,7 @@ func NewWorkflowCronDeleteRequest(server string, tenant openapi_types.UUID, cron var pathParam1 string - pathParam1, err = runtime.StyleParamWithLocation("simple", false, "cronId", runtime.ParamLocationPath, cronId) + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "cron-workflow", runtime.ParamLocationPath, cronWorkflow) if err != nil { return nil, err } @@ -6369,7 +6369,7 @@ func NewWorkflowCronDeleteRequest(server string, tenant openapi_types.UUID, cron } // NewWorkflowCronGetRequest generates requests for WorkflowCronGet -func NewWorkflowCronGetRequest(server string, tenant openapi_types.UUID, cronId openapi_types.UUID) (*http.Request, error) { +func NewWorkflowCronGetRequest(server string, tenant openapi_types.UUID, cronWorkflow openapi_types.UUID) (*http.Request, error) { var err error var pathParam0 string @@ -6381,7 +6381,7 @@ func NewWorkflowCronGetRequest(server string, tenant openapi_types.UUID, cronId var pathParam1 string - pathParam1, err = runtime.StyleParamWithLocation("simple", false, "cronId", runtime.ParamLocationPath, cronId) + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "cron-workflow", runtime.ParamLocationPath, cronWorkflow) if err != nil { return nil, err } @@ -7026,7 +7026,7 @@ func NewWorkflowScheduledListRequest(server string, tenant openapi_types.UUID, p } // NewWorkflowScheduledDeleteRequest generates requests for WorkflowScheduledDelete -func NewWorkflowScheduledDeleteRequest(server string, tenant openapi_types.UUID, scheduledId openapi_types.UUID) (*http.Request, error) { +func NewWorkflowScheduledDeleteRequest(server string, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID) (*http.Request, error) { var err error var pathParam0 string @@ -7038,7 +7038,7 @@ func NewWorkflowScheduledDeleteRequest(server string, tenant openapi_types.UUID, var pathParam1 string - pathParam1, err = runtime.StyleParamWithLocation("simple", false, "scheduledId", runtime.ParamLocationPath, scheduledId) + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "scheduled-workflow-run", runtime.ParamLocationPath, scheduledWorkflowRun) if err != nil { return nil, err } @@ -7067,7 +7067,7 @@ func NewWorkflowScheduledDeleteRequest(server string, tenant openapi_types.UUID, } // NewWorkflowScheduledGetRequest generates requests for WorkflowScheduledGet -func NewWorkflowScheduledGetRequest(server string, tenant openapi_types.UUID, scheduledId openapi_types.UUID) (*http.Request, error) { +func NewWorkflowScheduledGetRequest(server string, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID) (*http.Request, error) { var err error var pathParam0 string @@ -7079,7 +7079,7 @@ func NewWorkflowScheduledGetRequest(server string, tenant openapi_types.UUID, sc var pathParam1 string - pathParam1, err = runtime.StyleParamWithLocation("simple", false, "scheduledId", runtime.ParamLocationPath, scheduledId) + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "scheduled-workflow-run", runtime.ParamLocationPath, scheduledWorkflowRun) if err != nil { return nil, err } @@ -8302,10 +8302,10 @@ type ClientWithResponsesInterface interface { CronWorkflowListWithResponse(ctx context.Context, tenant openapi_types.UUID, params *CronWorkflowListParams, reqEditors ...RequestEditorFn) (*CronWorkflowListResponse, error) // WorkflowCronDeleteWithResponse request - WorkflowCronDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowCronDeleteResponse, error) + WorkflowCronDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, cronWorkflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowCronDeleteResponse, error) // WorkflowCronGetWithResponse request - WorkflowCronGetWithResponse(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowCronGetResponse, error) + WorkflowCronGetWithResponse(ctx context.Context, tenant openapi_types.UUID, cronWorkflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowCronGetResponse, error) // WorkflowRunListWithResponse request WorkflowRunListWithResponse(ctx context.Context, tenant openapi_types.UUID, params *WorkflowRunListParams, reqEditors ...RequestEditorFn) (*WorkflowRunListResponse, error) @@ -8317,10 +8317,10 @@ type ClientWithResponsesInterface interface { WorkflowScheduledListWithResponse(ctx context.Context, tenant openapi_types.UUID, params *WorkflowScheduledListParams, reqEditors ...RequestEditorFn) (*WorkflowScheduledListResponse, error) // WorkflowScheduledDeleteWithResponse request - WorkflowScheduledDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowScheduledDeleteResponse, error) + WorkflowScheduledDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowScheduledDeleteResponse, error) // WorkflowScheduledGetWithResponse request - WorkflowScheduledGetWithResponse(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowScheduledGetResponse, error) + WorkflowScheduledGetWithResponse(ctx context.Context, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowScheduledGetResponse, error) // WorkflowGetWorkersCountWithResponse request WorkflowGetWorkersCountWithResponse(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowGetWorkersCountResponse, error) @@ -11226,8 +11226,8 @@ func (c *ClientWithResponses) CronWorkflowListWithResponse(ctx context.Context, } // WorkflowCronDeleteWithResponse request returning *WorkflowCronDeleteResponse -func (c *ClientWithResponses) WorkflowCronDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowCronDeleteResponse, error) { - rsp, err := c.WorkflowCronDelete(ctx, tenant, cronId, reqEditors...) +func (c *ClientWithResponses) WorkflowCronDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, cronWorkflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowCronDeleteResponse, error) { + rsp, err := c.WorkflowCronDelete(ctx, tenant, cronWorkflow, reqEditors...) if err != nil { return nil, err } @@ -11235,8 +11235,8 @@ func (c *ClientWithResponses) WorkflowCronDeleteWithResponse(ctx context.Context } // WorkflowCronGetWithResponse request returning *WorkflowCronGetResponse -func (c *ClientWithResponses) WorkflowCronGetWithResponse(ctx context.Context, tenant openapi_types.UUID, cronId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowCronGetResponse, error) { - rsp, err := c.WorkflowCronGet(ctx, tenant, cronId, reqEditors...) +func (c *ClientWithResponses) WorkflowCronGetWithResponse(ctx context.Context, tenant openapi_types.UUID, cronWorkflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowCronGetResponse, error) { + rsp, err := c.WorkflowCronGet(ctx, tenant, cronWorkflow, reqEditors...) if err != nil { return nil, err } @@ -11271,8 +11271,8 @@ func (c *ClientWithResponses) WorkflowScheduledListWithResponse(ctx context.Cont } // WorkflowScheduledDeleteWithResponse request returning *WorkflowScheduledDeleteResponse -func (c *ClientWithResponses) WorkflowScheduledDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowScheduledDeleteResponse, error) { - rsp, err := c.WorkflowScheduledDelete(ctx, tenant, scheduledId, reqEditors...) +func (c *ClientWithResponses) WorkflowScheduledDeleteWithResponse(ctx context.Context, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowScheduledDeleteResponse, error) { + rsp, err := c.WorkflowScheduledDelete(ctx, tenant, scheduledWorkflowRun, reqEditors...) if err != nil { return nil, err } @@ -11280,8 +11280,8 @@ func (c *ClientWithResponses) WorkflowScheduledDeleteWithResponse(ctx context.Co } // WorkflowScheduledGetWithResponse request returning *WorkflowScheduledGetResponse -func (c *ClientWithResponses) WorkflowScheduledGetWithResponse(ctx context.Context, tenant openapi_types.UUID, scheduledId openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowScheduledGetResponse, error) { - rsp, err := c.WorkflowScheduledGet(ctx, tenant, scheduledId, reqEditors...) +func (c *ClientWithResponses) WorkflowScheduledGetWithResponse(ctx context.Context, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowScheduledGetResponse, error) { + rsp, err := c.WorkflowScheduledGet(ctx, tenant, scheduledWorkflowRun, reqEditors...) if err != nil { return nil, err } From 459398b5b636a7b0cef536a9dce962f417b73da3 Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Mon, 4 Nov 2024 14:20:09 -0500 Subject: [PATCH 25/30] wip --- .../components/schemas/workflow_run.yaml | 2 + .../server/handlers/workflows/delete_cron.go | 2 +- api/v1/server/oas/gen/openapi.gen.go | 330 +++++++++--------- .../server/oas/transformers/workflow_run.go | 3 +- .../src/lib/api/generated/data-contracts.ts | 1 + .../main/recurring/components/delete-cron.tsx | 92 +++++ .../components/recurring-columns.tsx | 179 ++++++---- .../recurring/components/recurring-table.tsx | 105 ++++-- pkg/client/rest/gen.go | 1 + pkg/repository/prisma/dbsqlc/workflows.sql | 17 +- pkg/repository/prisma/dbsqlc/workflows.sql.go | 45 +-- pkg/repository/prisma/workflow.go | 4 +- 12 files changed, 474 insertions(+), 307 deletions(-) create mode 100644 frontend/app/src/pages/main/recurring/components/delete-cron.tsx diff --git a/api-contracts/openapi/components/schemas/workflow_run.yaml b/api-contracts/openapi/components/schemas/workflow_run.yaml index 36c58ee5a..bb9b0ddb5 100644 --- a/api-contracts/openapi/components/schemas/workflow_run.yaml +++ b/api-contracts/openapi/components/schemas/workflow_run.yaml @@ -240,6 +240,8 @@ CronWorkflows: type: string cron: type: string + name: + type: string input: type: object additionalProperties: true diff --git a/api/v1/server/handlers/workflows/delete_cron.go b/api/v1/server/handlers/workflows/delete_cron.go index 36012de0b..d4d07f29d 100644 --- a/api/v1/server/handlers/workflows/delete_cron.go +++ b/api/v1/server/handlers/workflows/delete_cron.go @@ -21,7 +21,7 @@ func (t *WorkflowService) WorkflowCronDelete(ctx echo.Context, request gen.Workf err := t.config.APIRepository.Workflow().DeleteCronWorkflow(dbCtx, sqlchelpers.UUIDToStr(cron.TenantId), - sqlchelpers.UUIDToStr(cron.ID), + sqlchelpers.UUIDToStr(cron.CronId), ) if err != nil { diff --git a/api/v1/server/oas/gen/openapi.gen.go b/api/v1/server/oas/gen/openapi.gen.go index 80bb0f34a..a658ad11c 100644 --- a/api/v1/server/oas/gen/openapi.gen.go +++ b/api/v1/server/oas/gen/openapi.gen.go @@ -385,6 +385,7 @@ type CronWorkflows struct { Cron string `json:"cron"` Input *map[string]interface{} `json:"input,omitempty"` Metadata APIResourceMeta `json:"metadata"` + Name *string `json:"name,omitempty"` TenantId string `json:"tenantId"` WorkflowId string `json:"workflowId"` WorkflowName string `json:"workflowName"` @@ -10377,170 +10378,171 @@ var swaggerSpec = []string{ "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", + "7wEA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/v1/server/oas/transformers/workflow_run.go b/api/v1/server/oas/transformers/workflow_run.go index 454c001e8..597dcf0b1 100644 --- a/api/v1/server/oas/transformers/workflow_run.go +++ b/api/v1/server/oas/transformers/workflow_run.go @@ -560,10 +560,11 @@ func ToCronWorkflowsFromSQLC(cron *dbsqlc.ListCronWorkflowsRow) *gen.CronWorkflo Metadata: *toAPIMetadata(sqlchelpers.UUIDToStr(cron.ID), cron.CreatedAt.Time, cron.UpdatedAt.Time), WorkflowVersionId: sqlchelpers.UUIDToStr(cron.WorkflowVersionId), WorkflowId: sqlchelpers.UUIDToStr(cron.WorkflowId), - WorkflowName: cron.Name, + WorkflowName: cron.WorkflowName, TenantId: sqlchelpers.UUIDToStr(cron.TenantId), Cron: cron.Cron, AdditionalMetadata: &additionalMetadata, + Name: &cron.Name.String, } return res diff --git a/frontend/app/src/lib/api/generated/data-contracts.ts b/frontend/app/src/lib/api/generated/data-contracts.ts index 04f5403a6..b749aec23 100644 --- a/frontend/app/src/lib/api/generated/data-contracts.ts +++ b/frontend/app/src/lib/api/generated/data-contracts.ts @@ -810,6 +810,7 @@ export interface CronWorkflows { workflowId: string; workflowName: string; cron: string; + name?: string; input?: Record; additionalMetadata?: Record; } diff --git a/frontend/app/src/pages/main/recurring/components/delete-cron.tsx b/frontend/app/src/pages/main/recurring/components/delete-cron.tsx new file mode 100644 index 000000000..599bff651 --- /dev/null +++ b/frontend/app/src/pages/main/recurring/components/delete-cron.tsx @@ -0,0 +1,92 @@ +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Spinner } from '@/components/ui/loading'; +import api, { CronWorkflows } from '@/lib/api'; +import { useApiError } from '@/lib/hooks'; +import { useMutation } from '@tanstack/react-query'; + +interface DeleteCronFormProps { + className?: string; + onCancel: () => void; + isLoading: boolean; + onSubmit: () => void; +} + +export function DeleteCron({ + tenant, + cron, + setShowCronRevoke, + onSuccess, +}: { + tenant: string; + cron?: CronWorkflows; + setShowCronRevoke: (show?: CronWorkflows) => void; + onSuccess: () => void; +}) { + const { handleApiError } = useApiError({}); + + const deleteMutation = useMutation({ + mutationKey: ['cron-job:delete', tenant, cron], + mutationFn: async () => { + if (!cron) { + return; + } + await api.workflowCronDelete(tenant, cron.metadata.id); + }, + onSuccess: onSuccess, + onError: handleApiError, + }); + + return ( + setShowCronRevoke(open ? cron : undefined)} + > + deleteMutation.mutate()} + onCancel={() => setShowCronRevoke(undefined)} + /> + + ); +} + +export function DeleteCronForm({ className, ...props }: DeleteCronFormProps) { + return ( + + + Delete cron job + +
+
+ Are you sure you want to delete the cron job? This action will prevent + the run from running in the future and cannot be undone. +
+
+ + +
+
+
+ ); +} diff --git a/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx b/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx index 2d3e22dad..6d6e7e08d 100644 --- a/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx +++ b/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx @@ -1,83 +1,112 @@ import { ColumnDef } from '@tanstack/react-table'; import { DataTableColumnHeader } from '../../../../components/molecules/data-table/data-table-column-header'; -import { CronWorkflows, RateLimit } from '@/lib/api'; +import { CronWorkflows } from '@/lib/api'; import CronPrettifier from 'cronstrue'; import RelativeDate from '@/components/molecules/relative-date'; import { Link } from 'react-router-dom'; +import { DataTableRowActions } from '@/components/molecules/data-table/data-table-row-actions'; -export type RateLimitRow = RateLimit & { - metadata: { - id: string; - }; -}; - -export const columns: ColumnDef[] = [ - { - accessorKey: 'crons', - header: ({ column }) => ( - - ), - cell: ({ row }) => ( -
- {row.original.cron} -
- ), - enableSorting: false, - }, - { - accessorKey: 'readable', - header: ({ column }) => ( - - ), - cell: ({ row }) => ( -
- (runs {CronPrettifier.toString(row.original.cron).toLowerCase()} UTC) -
- ), - enableSorting: false, - }, - { - accessorKey: 'Workflow', - header: ({ column }) => ( - - ), - cell: ({ row }) => ( -
-
- - {row.original.workflowName} - +export const columns = ({ + onDeleteClick, +}: { + onDeleteClick: (row: CronWorkflows) => void; +}): ColumnDef[] => { + return [ + { + accessorKey: 'crons', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ {row.original.cron} +
+ ), + enableSorting: false, + }, + { + accessorKey: 'name', + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.original.name }
, + }, + { + accessorKey: 'readable', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ (runs {CronPrettifier.toString(row.original.cron).toLowerCase()} UTC) +
+ ), + enableSorting: false, + }, + { + accessorKey: 'Workflow', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+
+ + {row.original.workflowName} + +
-
- ), - enableSorting: false, - enableHiding: true, - }, - // { - // accessorKey: 'Metadata', - // header: ({ column }) => ( - // - // ), - // cell: ({ row }) => { - // if (!row.original.additionalMetadata) { - // return
; - // } + ), + enableSorting: false, + enableHiding: true, + }, + // { + // accessorKey: 'Metadata', + // header: ({ column }) => ( + // + // ), + // cell: ({ row }) => { + // if (!row.original.additionalMetadata) { + // return
; + // } - // return ; - // }, - // enableSorting: false, - // }, - { - accessorKey: 'createdAt', - header: ({ column }) => ( - - ), - cell: ({ row }) => ( -
- -
- ), - enableSorting: true, - enableHiding: true, - }, -]; + // return ; + // }, + // enableSorting: false, + // }, + { + accessorKey: 'createdAt', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ +
+ ), + enableSorting: true, + enableHiding: true, + }, + { + accessorKey: 'actions', + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ onDeleteClick(row.original), + }, + ]} + /> +
+ ), + enableHiding: true, + enableSorting: false, + }, + ]; +}; diff --git a/frontend/app/src/pages/main/recurring/components/recurring-table.tsx b/frontend/app/src/pages/main/recurring/components/recurring-table.tsx index 4eb8c860c..3266706e7 100644 --- a/frontend/app/src/pages/main/recurring/components/recurring-table.tsx +++ b/frontend/app/src/pages/main/recurring/components/recurring-table.tsx @@ -6,8 +6,9 @@ import { SortingState, VisibilityState, } from '@tanstack/react-table'; -import { useQuery } from '@tanstack/react-query'; +import { useQuery, useQueryClient } from '@tanstack/react-query'; import { + CronWorkflows, CronWorkflowsOrderByField, WorkflowRunOrderByDirection, queries, @@ -17,10 +18,14 @@ import { useOutletContext, useSearchParams } from 'react-router-dom'; import { TenantContextType } from '@/lib/outlet'; import { DataTable } from '@/components/molecules/data-table/data-table'; import { columns } from './recurring-columns'; +import { Button } from '@/components/ui/button'; +import { ArrowPathIcon } from '@heroicons/react/24/outline'; +import { DeleteCron } from './delete-cron'; export function CronsTable() { const { tenant } = useOutletContext(); const [searchParams, setSearchParams] = useSearchParams(); + const queryClient = useQueryClient(); invariant(tenant); @@ -32,6 +37,7 @@ export function CronsTable() { } return []; }); + const [columnFilters, setColumnFilters] = useState(() => { const filtersParam = searchParams.get('filters'); if (filtersParam) { @@ -39,6 +45,7 @@ export function CronsTable() { } return []; }); + const [columnVisibility, setColumnVisibility] = useState({ createdAt: false, }); @@ -48,6 +55,7 @@ export function CronsTable() { const pageSize = Number(searchParams.get('pageSize')) || 50; return { pageIndex, pageSize }; }); + const [pageSize, setPageSize] = useState( Number(searchParams.get('pageSize')) || 50, ); @@ -66,9 +74,9 @@ export function CronsTable() { setSearchParams(newSearchParams); }, [sorting, columnFilters, pagination, setSearchParams, searchParams]); - const orderByDirection = useMemo((): - | WorkflowRunOrderByDirection - | undefined => { + const orderByDirection = useMemo< + WorkflowRunOrderByDirection | undefined + >(() => { if (!sorting.length) { return; } @@ -78,7 +86,7 @@ export function CronsTable() { : WorkflowRunOrderByDirection.ASC; }, [sorting]); - const orderByField = useMemo((): CronWorkflowsOrderByField | undefined => { + const orderByField = useMemo(() => { if (!sorting.length) { return; } @@ -103,8 +111,9 @@ export function CronsTable() { data, isLoading: queryIsLoading, error: queryError, + refetch, } = useQuery({ - ...queries.cronRuns.list(tenant.metadata.id, { + ...queries.cronJobs.list(tenant.metadata.id, { // TODO: add filters orderByField, orderByDirection, @@ -114,27 +123,69 @@ export function CronsTable() { refetchInterval: 2000, }); + const [showDeleteCron, setShowDeleteCron] = useState< + CronWorkflows | undefined + >(); + + const handleDeleteClick = (cron: CronWorkflows) => { + setShowDeleteCron(cron); + }; + + const handleConfirmDelete = () => { + if (showDeleteCron) { + setShowDeleteCron(undefined); + } + }; + + const actions = [ + , + ]; + return ( - row.metadata.id} - /> + <> + {showDeleteCron && ( + + )} + row.metadata.id} + /> + ); } diff --git a/pkg/client/rest/gen.go b/pkg/client/rest/gen.go index 09e00b0f7..7998a0192 100644 --- a/pkg/client/rest/gen.go +++ b/pkg/client/rest/gen.go @@ -382,6 +382,7 @@ type CronWorkflows struct { Cron string `json:"cron"` Input *map[string]interface{} `json:"input,omitempty"` Metadata APIResourceMeta `json:"metadata"` + Name *string `json:"name,omitempty"` TenantId string `json:"tenantId"` WorkflowId string `json:"workflowId"` WorkflowName string `json:"workflowName"` diff --git a/pkg/repository/prisma/dbsqlc/workflows.sql b/pkg/repository/prisma/dbsqlc/workflows.sql index 7696b9c33..64376aef4 100644 --- a/pkg/repository/prisma/dbsqlc/workflows.sql +++ b/pkg/repository/prisma/dbsqlc/workflows.sql @@ -333,13 +333,15 @@ INSERT INTO "WorkflowTriggerCronRef" ( "cron", "name", "input", - "additionalMetadata" + "additionalMetadata", + "id" ) VALUES ( @workflowTriggersId::uuid, @cronTrigger::text, sqlc.narg('name')::text, sqlc.narg('input')::jsonb, - sqlc.narg('additionalMetadata')::jsonb + sqlc.narg('additionalMetadata')::jsonb, + gen_random_uuid() ) RETURNING *; -- name: CreateWorkflowTriggerScheduledRef :one @@ -687,9 +689,11 @@ WITH latest_versions AS ( ) SELECT latest_versions."workflowVersionId", - w."name", + w."name" as "workflowName", w."id" as "workflowId", w."tenantId", + t."id" as "triggerId", + c."id" as "cronId", t.*, c.* FROM @@ -719,9 +723,4 @@ LIMIT -- name: DeleteWorkflowTriggerCronRef :exec DELETE FROM "WorkflowTriggerCronRef" WHERE - "id" = sqlc.narg('id')::uuid OR - ( - "parentId" = sqlc.narg('parentId')::uuid AND - "cron" = sqlc.narg('cron')::text AND - "name" = sqlc.narg('name')::text - ); + "id" = @id::uuid; diff --git a/pkg/repository/prisma/dbsqlc/workflows.sql.go b/pkg/repository/prisma/dbsqlc/workflows.sql.go index 3a5e796a5..85fbe18da 100644 --- a/pkg/repository/prisma/dbsqlc/workflows.sql.go +++ b/pkg/repository/prisma/dbsqlc/workflows.sql.go @@ -569,13 +569,15 @@ INSERT INTO "WorkflowTriggerCronRef" ( "cron", "name", "input", - "additionalMetadata" + "additionalMetadata", + "id" ) VALUES ( $1::uuid, $2::text, $3::text, $4::jsonb, - $5::jsonb + $5::jsonb, + gen_random_uuid() ) RETURNING "parentId", cron, "tickerId", input, enabled, "additionalMetadata", "createdAt", "deletedAt", "updatedAt", name, id ` @@ -792,28 +794,11 @@ func (q *Queries) CreateWorkflowVersion(ctx context.Context, db DBTX, arg Create const deleteWorkflowTriggerCronRef = `-- name: DeleteWorkflowTriggerCronRef :exec DELETE FROM "WorkflowTriggerCronRef" WHERE - "id" = $1::uuid OR - ( - "parentId" = $2::uuid AND - "cron" = $3::text AND - "name" = $4::text - ) + "id" = $1::uuid ` -type DeleteWorkflowTriggerCronRefParams struct { - ID pgtype.UUID `json:"id"` - ParentId pgtype.UUID `json:"parentId"` - Cron pgtype.Text `json:"cron"` - Name pgtype.Text `json:"name"` -} - -func (q *Queries) DeleteWorkflowTriggerCronRef(ctx context.Context, db DBTX, arg DeleteWorkflowTriggerCronRefParams) error { - _, err := db.Exec(ctx, deleteWorkflowTriggerCronRef, - arg.ID, - arg.ParentId, - arg.Cron, - arg.Name, - ) +func (q *Queries) DeleteWorkflowTriggerCronRef(ctx context.Context, db DBTX, id pgtype.UUID) error { + _, err := db.Exec(ctx, deleteWorkflowTriggerCronRef, id) return err } @@ -1393,9 +1378,11 @@ WITH latest_versions AS ( ) SELECT latest_versions."workflowVersionId", - w."name", + w."name" as "workflowName", w."id" as "workflowId", w."tenantId", + t."id" as "triggerId", + c."id" as "cronId", t.id, t."createdAt", t."updatedAt", t."deletedAt", t."workflowVersionId", t."tenantId", c."parentId", c.cron, c."tickerId", c.input, c.enabled, c."additionalMetadata", c."createdAt", c."deletedAt", c."updatedAt", c.name, c.id FROM @@ -1435,9 +1422,11 @@ type ListCronWorkflowsParams struct { type ListCronWorkflowsRow struct { WorkflowVersionId pgtype.UUID `json:"workflowVersionId"` - Name string `json:"name"` + WorkflowName string `json:"workflowName"` WorkflowId pgtype.UUID `json:"workflowId"` TenantId pgtype.UUID `json:"tenantId"` + TriggerId pgtype.UUID `json:"triggerId"` + CronId pgtype.UUID `json:"cronId"` ID pgtype.UUID `json:"id"` CreatedAt pgtype.Timestamp `json:"createdAt"` UpdatedAt pgtype.Timestamp `json:"updatedAt"` @@ -1453,7 +1442,7 @@ type ListCronWorkflowsRow struct { CreatedAt_2 pgtype.Timestamp `json:"createdAt_2"` DeletedAt_2 pgtype.Timestamp `json:"deletedAt_2"` UpdatedAt_2 pgtype.Timestamp `json:"updatedAt_2"` - Name_2 pgtype.Text `json:"name_2"` + Name pgtype.Text `json:"name"` ID_2 pgtype.UUID `json:"id_2"` } @@ -1477,9 +1466,11 @@ func (q *Queries) ListCronWorkflows(ctx context.Context, db DBTX, arg ListCronWo var i ListCronWorkflowsRow if err := rows.Scan( &i.WorkflowVersionId, - &i.Name, + &i.WorkflowName, &i.WorkflowId, &i.TenantId, + &i.TriggerId, + &i.CronId, &i.ID, &i.CreatedAt, &i.UpdatedAt, @@ -1495,7 +1486,7 @@ func (q *Queries) ListCronWorkflows(ctx context.Context, db DBTX, arg ListCronWo &i.CreatedAt_2, &i.DeletedAt_2, &i.UpdatedAt_2, - &i.Name_2, + &i.Name, &i.ID_2, ); err != nil { return nil, err diff --git a/pkg/repository/prisma/workflow.go b/pkg/repository/prisma/workflow.go index 879296f77..b78cb7d2d 100644 --- a/pkg/repository/prisma/workflow.go +++ b/pkg/repository/prisma/workflow.go @@ -354,9 +354,7 @@ func (w *workflowAPIRepository) GetCronWorkflow(ctx context.Context, tenantId, c } func (w *workflowAPIRepository) DeleteCronWorkflow(ctx context.Context, tenantId, id string) error { - return w.queries.DeleteWorkflowTriggerCronRef(ctx, w.pool, dbsqlc.DeleteWorkflowTriggerCronRefParams{ - ID: sqlchelpers.UUIDFromStr(id), - }) + return w.queries.DeleteWorkflowTriggerCronRef(ctx, w.pool, sqlchelpers.UUIDFromStr(id)) } func (w *workflowAPIRepository) CreateCronWorkflow(ctx context.Context, tenantId string, opts *repository.CreateCronWorkflowTriggerOpts) (*dbsqlc.WorkflowRun, error) { From ff01f64ccbc06067c78b7c9eff2201ca357a282f Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Mon, 4 Nov 2024 16:03:08 -0500 Subject: [PATCH 26/30] wip: create crons, stub scheduled --- .../openapi/components/schemas/_index.yaml | 4 + .../components/schemas/workflow_run.yaml | 30 + api-contracts/openapi/openapi.yaml | 4 + .../openapi/paths/workflow/workflow.yaml | 152 +++- .../server/handlers/workflows/create_cron.go | 33 + .../handlers/workflows/create_scheduled.go | 16 + api/v1/server/oas/gen/openapi.gen.go | 680 +++++++++++++----- frontend/app/src/lib/api/generated/Api.ts | 72 +- .../src/lib/api/generated/data-contracts.ts | 14 + .../components/recurring-columns.tsx | 2 +- .../components/trigger-workflow-form.tsx | 208 +++++- pkg/client/rest/gen.go | 447 ++++++++++++ pkg/repository/prisma/dbsqlc/schema.sql | 3 - pkg/repository/prisma/dbsqlc/workflows.sql | 38 +- pkg/repository/prisma/dbsqlc/workflows.sql.go | 84 ++- pkg/repository/prisma/workflow.go | 47 +- pkg/repository/workflow.go | 9 +- pkg/repository/workflow_run.go | 2 +- .../20241104202817_tmp/migration.sql | 2 + prisma/schema.prisma | 1 - sql/migrations/20241104202826_tmp.sql | 2 + sql/migrations/atlas.sum | 7 +- sql/schema/schema.sql | 3 - 23 files changed, 1614 insertions(+), 246 deletions(-) create mode 100644 api/v1/server/handlers/workflows/create_cron.go create mode 100644 api/v1/server/handlers/workflows/create_scheduled.go create mode 100644 prisma/migrations/20241104202817_tmp/migration.sql create mode 100644 sql/migrations/20241104202826_tmp.sql diff --git a/api-contracts/openapi/components/schemas/_index.yaml b/api-contracts/openapi/components/schemas/_index.yaml index 7eec99e65..b6b669910 100644 --- a/api-contracts/openapi/components/schemas/_index.yaml +++ b/api-contracts/openapi/components/schemas/_index.yaml @@ -234,6 +234,10 @@ RerunStepRunRequest: $ref: "./workflow_run.yaml#/RerunStepRunRequest" TriggerWorkflowRunRequest: $ref: "./workflow_run.yaml#/TriggerWorkflowRunRequest" +ScheduleWorkflowRunRequest: + $ref: "./workflow_run.yaml#/ScheduleWorkflowRunRequest" +CreateCronWorkflowTriggerRequest: + $ref: "./workflow_run.yaml#/CreateCronWorkflowTriggerRequest" CreatePullRequestFromStepRun: $ref: "./workflow_run.yaml#/CreatePullRequestFromStepRun" GetStepRunDiffResponse: diff --git a/api-contracts/openapi/components/schemas/workflow_run.yaml b/api-contracts/openapi/components/schemas/workflow_run.yaml index bb9b0ddb5..d06e874cf 100644 --- a/api-contracts/openapi/components/schemas/workflow_run.yaml +++ b/api-contracts/openapi/components/schemas/workflow_run.yaml @@ -638,6 +638,36 @@ TriggerWorkflowRunRequest: required: - input +CreateCronWorkflowTriggerRequest: + properties: + input: + type: object + additionalMetadata: + type: object + cronName: + type: string + cronExpression: + type: string + required: + - input + - additionalMetadata + - cronName + - cronExpression + +ScheduleWorkflowRunRequest: + properties: + input: + type: object + additionalMetadata: + type: object + triggerAt: + type: string + format: date-time + required: + - input + - additionalMetadata + - triggerAt + CreatePullRequestFromStepRun: properties: branchName: diff --git a/api-contracts/openapi/openapi.yaml b/api-contracts/openapi/openapi.yaml index 90a32b7d4..86b156d5f 100644 --- a/api-contracts/openapi/openapi.yaml +++ b/api-contracts/openapi/openapi.yaml @@ -116,10 +116,14 @@ paths: $ref: "./paths/event/event.yaml#/keys" /api/v1/tenants/{tenant}/workflows: $ref: "./paths/workflow/workflow.yaml#/withTenant" + /api/v1/tenants/{tenant}/workflows/{workflow}/scheduled: + $ref: "./paths/workflow/workflow.yaml#/scheduledCreate" /api/v1/tenants/{tenant}/workflows/scheduled: $ref: "./paths/workflow/workflow.yaml#/scheduledList" /api/v1/tenants/{tenant}/workflows/scheduled/{scheduled-workflow-run}: $ref: "./paths/workflow/workflow.yaml#/scheduled" + /api/v1/tenants/{tenant}/workflows/{workflow}/crons: + $ref: "./paths/workflow/workflow.yaml#/cronsCreate" /api/v1/tenants/{tenant}/workflows/crons: $ref: "./paths/workflow/workflow.yaml#/cronsList" /api/v1/tenants/{tenant}/workflows/crons/{cron-workflow}: diff --git a/api-contracts/openapi/paths/workflow/workflow.yaml b/api-contracts/openapi/paths/workflow/workflow.yaml index b00999a93..dc9d8d89f 100644 --- a/api-contracts/openapi/paths/workflow/workflow.yaml +++ b/api-contracts/openapi/paths/workflow/workflow.yaml @@ -828,6 +828,81 @@ workflowWorkersCount: - Workflow +scheduledCreate: + post: + x-resources: ["tenant", "workflow"] + description: Schedule a new workflow run for a tenant + operationId: scheduled-workflow-run:create + parameters: + - description: The tenant id + in: path + name: tenant + required: true + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + - description: The workflow id + in: path + name: workflow + required: true + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + - description: The workflow version. If not supplied, the latest version is fetched. + in: query + name: version + required: false + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + requestBody: + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/ScheduleWorkflowRunRequest" + description: The input to the scheduled workflow run + required: true + responses: + "200": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/ScheduledWorkflows" + description: Successfully created the scheduled workflow run + "400": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: A malformed or bad request + "429": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: Resource limit exceeded + "403": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: Forbidden + "404": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: Not found + summary: Trigger workflow run + tags: + - Workflow Run + scheduledList: get: x-resources: ["tenant"] @@ -1124,10 +1199,85 @@ crons: tags: - Workflow +cronsCreate: + post: + x-resources: ["tenant", "workflow"] + description: Create a new cron job workflow trigger for a tenant + operationId: cron-workflow-trigger:create + parameters: + - description: The tenant id + in: path + name: tenant + required: true + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + - description: The workflow id + in: path + name: workflow + required: true + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + - description: The workflow version. If not supplied, the latest version is fetched. + in: query + name: version + required: false + schema: + type: string + format: uuid + minLength: 36 + maxLength: 36 + requestBody: + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/CreateCronWorkflowTriggerRequest" + description: The input to the cron job workflow trigger + required: true + responses: + "200": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/CronWorkflows" + description: Successfully created the cron job workflow trigger + "400": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: A malformed or bad request + "429": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: Resource limit exceeded + "403": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: Forbidden + "404": + content: + application/json: + schema: + $ref: "../../components/schemas/_index.yaml#/APIErrors" + description: Not found + summary: Create cron job workflow trigger + tags: + - Workflow Run + cronsList: get: x-resources: ["tenant"] - description: Get all cron job workflow runs for a tenant + description: Get all cron job workflow triggers for a tenant operationId: cron-workflow:list parameters: - description: The tenant id diff --git a/api/v1/server/handlers/workflows/create_cron.go b/api/v1/server/handlers/workflows/create_cron.go new file mode 100644 index 000000000..5d925379b --- /dev/null +++ b/api/v1/server/handlers/workflows/create_cron.go @@ -0,0 +1,33 @@ +package workflows + +import ( + "github.com/labstack/echo/v4" + + "github.com/hatchet-dev/hatchet/api/v1/server/oas/apierrors" + "github.com/hatchet-dev/hatchet/api/v1/server/oas/gen" + "github.com/hatchet-dev/hatchet/api/v1/server/oas/transformers" + "github.com/hatchet-dev/hatchet/pkg/repository" + "github.com/hatchet-dev/hatchet/pkg/repository/prisma/db" +) + +func (t *WorkflowService) CronWorkflowTriggerCreate(ctx echo.Context, request gen.CronWorkflowTriggerCreateRequestObject) (gen.CronWorkflowTriggerCreateResponseObject, error) { + tenant := ctx.Get("tenant").(*db.TenantModel) + + cronTrigger, err := t.config.APIRepository.Workflow().CreateCronWorkflow( + ctx.Request().Context(), tenant.ID, &repository.CreateCronWorkflowTriggerOpts{ + Name: request.Body.CronName, + Cron: request.Body.CronExpression, + Input: request.Body.Input, + AdditionalMetadata: request.Body.AdditionalMetadata, + WorkflowId: request.Workflow.String(), + }, + ) + + if err != nil { + return gen.CronWorkflowTriggerCreate400JSONResponse(apierrors.NewAPIErrors(err.Error())), err + } + + return gen.CronWorkflowTriggerCreate200JSONResponse( + *transformers.ToCronWorkflowsFromSQLC(cronTrigger), + ), nil +} diff --git a/api/v1/server/handlers/workflows/create_scheduled.go b/api/v1/server/handlers/workflows/create_scheduled.go new file mode 100644 index 000000000..7e9ca8a48 --- /dev/null +++ b/api/v1/server/handlers/workflows/create_scheduled.go @@ -0,0 +1,16 @@ +package workflows + +import ( + "github.com/labstack/echo/v4" + + "github.com/hatchet-dev/hatchet/api/v1/server/oas/gen" +) + +func (t *WorkflowService) ScheduledWorkflowRunCreate(ctx echo.Context, request gen.ScheduledWorkflowRunCreateRequestObject) (gen.ScheduledWorkflowRunCreateResponseObject, error) { + + // t. + + return gen.ScheduledWorkflowRunCreate200JSONResponse( + gen.ScheduledWorkflows{}, + ), nil +} diff --git a/api/v1/server/oas/gen/openapi.gen.go b/api/v1/server/oas/gen/openapi.gen.go index a658ad11c..7ca71134b 100644 --- a/api/v1/server/oas/gen/openapi.gen.go +++ b/api/v1/server/oas/gen/openapi.gen.go @@ -339,6 +339,14 @@ type CreateAPITokenResponse struct { Token string `json:"token"` } +// CreateCronWorkflowTriggerRequest defines model for CreateCronWorkflowTriggerRequest. +type CreateCronWorkflowTriggerRequest struct { + AdditionalMetadata map[string]interface{} `json:"additionalMetadata"` + CronExpression string `json:"cronExpression"` + CronName string `json:"cronName"` + Input map[string]interface{} `json:"input"` +} + // CreateEventRequest defines model for CreateEventRequest. type CreateEventRequest struct { // AdditionalMetadata Additional metadata for the event. @@ -662,6 +670,13 @@ type SNSIntegration struct { TopicArn string `json:"topicArn"` } +// ScheduleWorkflowRunRequest defines model for ScheduleWorkflowRunRequest. +type ScheduleWorkflowRunRequest struct { + AdditionalMetadata map[string]interface{} `json:"additionalMetadata"` + Input map[string]interface{} `json:"input"` + TriggerAt time.Time `json:"triggerAt"` +} + // ScheduledRunStatus defines model for ScheduledRunStatus. type ScheduledRunStatus string @@ -1664,6 +1679,18 @@ type WorkflowScheduledListParams struct { Statuses *[]ScheduledRunStatus `form:"statuses,omitempty" json:"statuses,omitempty"` } +// CronWorkflowTriggerCreateParams defines parameters for CronWorkflowTriggerCreate. +type CronWorkflowTriggerCreateParams struct { + // Version The workflow version. If not supplied, the latest version is fetched. + Version *openapi_types.UUID `form:"version,omitempty" json:"version,omitempty"` +} + +// ScheduledWorkflowRunCreateParams defines parameters for ScheduledWorkflowRunCreate. +type ScheduledWorkflowRunCreateParams struct { + // Version The workflow version. If not supplied, the latest version is fetched. + Version *openapi_types.UUID `form:"version,omitempty" json:"version,omitempty"` +} + // WorkflowGetMetricsParams defines parameters for WorkflowGetMetrics. type WorkflowGetMetricsParams struct { // Status A status of workflow run statuses to filter by @@ -1733,6 +1760,12 @@ type WorkflowRunUpdateReplayJSONRequestBody = ReplayWorkflowRunsRequest // WorkflowRunCancelJSONRequestBody defines body for WorkflowRunCancel for application/json ContentType. type WorkflowRunCancelJSONRequestBody = WorkflowRunsCancelRequest +// CronWorkflowTriggerCreateJSONRequestBody defines body for CronWorkflowTriggerCreate for application/json ContentType. +type CronWorkflowTriggerCreateJSONRequestBody = CreateCronWorkflowTriggerRequest + +// ScheduledWorkflowRunCreateJSONRequestBody defines body for ScheduledWorkflowRunCreate for application/json ContentType. +type ScheduledWorkflowRunCreateJSONRequestBody = ScheduleWorkflowRunRequest + // TenantInviteAcceptJSONRequestBody defines body for TenantInviteAccept for application/json ContentType. type TenantInviteAcceptJSONRequestBody = AcceptInviteRequest @@ -1954,6 +1987,12 @@ type ServerInterface interface { // Get scheduled workflow run // (GET /api/v1/tenants/{tenant}/workflows/scheduled/{scheduled-workflow-run}) WorkflowScheduledGet(ctx echo.Context, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID) error + // Create cron job workflow trigger + // (POST /api/v1/tenants/{tenant}/workflows/{workflow}/crons) + CronWorkflowTriggerCreate(ctx echo.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params CronWorkflowTriggerCreateParams) error + // Trigger workflow run + // (POST /api/v1/tenants/{tenant}/workflows/{workflow}/scheduled) + ScheduledWorkflowRunCreate(ctx echo.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params ScheduledWorkflowRunCreateParams) error // Get workflow worker count // (GET /api/v1/tenants/{tenant}/workflows/{workflow}/worker-count) WorkflowGetWorkersCount(ctx echo.Context, tenant openapi_types.UUID, workflow openapi_types.UUID) error @@ -3877,6 +3916,80 @@ func (w *ServerInterfaceWrapper) WorkflowScheduledGet(ctx echo.Context) error { return err } +// CronWorkflowTriggerCreate converts echo context to params. +func (w *ServerInterfaceWrapper) CronWorkflowTriggerCreate(ctx echo.Context) error { + var err error + // ------------- Path parameter "tenant" ------------- + var tenant openapi_types.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "tenant", runtime.ParamLocationPath, ctx.Param("tenant"), &tenant) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tenant: %s", err)) + } + + // ------------- Path parameter "workflow" ------------- + var workflow openapi_types.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "workflow", runtime.ParamLocationPath, ctx.Param("workflow"), &workflow) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter workflow: %s", err)) + } + + ctx.Set(BearerAuthScopes, []string{}) + + ctx.Set(CookieAuthScopes, []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params CronWorkflowTriggerCreateParams + // ------------- Optional query parameter "version" ------------- + + err = runtime.BindQueryParameter("form", true, false, "version", ctx.QueryParams(), ¶ms.Version) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter version: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.CronWorkflowTriggerCreate(ctx, tenant, workflow, params) + return err +} + +// ScheduledWorkflowRunCreate converts echo context to params. +func (w *ServerInterfaceWrapper) ScheduledWorkflowRunCreate(ctx echo.Context) error { + var err error + // ------------- Path parameter "tenant" ------------- + var tenant openapi_types.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "tenant", runtime.ParamLocationPath, ctx.Param("tenant"), &tenant) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tenant: %s", err)) + } + + // ------------- Path parameter "workflow" ------------- + var workflow openapi_types.UUID + + err = runtime.BindStyledParameterWithLocation("simple", false, "workflow", runtime.ParamLocationPath, ctx.Param("workflow"), &workflow) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter workflow: %s", err)) + } + + ctx.Set(BearerAuthScopes, []string{}) + + ctx.Set(CookieAuthScopes, []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params ScheduledWorkflowRunCreateParams + // ------------- Optional query parameter "version" ------------- + + err = runtime.BindQueryParameter("form", true, false, "version", ctx.QueryParams(), ¶ms.Version) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter version: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.ScheduledWorkflowRunCreate(ctx, tenant, workflow, params) + return err +} + // WorkflowGetWorkersCount converts echo context to params. func (w *ServerInterfaceWrapper) WorkflowGetWorkersCount(ctx echo.Context) error { var err error @@ -4378,6 +4491,8 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/scheduled", wrapper.WorkflowScheduledList) router.DELETE(baseURL+"/api/v1/tenants/:tenant/workflows/scheduled/:scheduled-workflow-run", wrapper.WorkflowScheduledDelete) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/scheduled/:scheduled-workflow-run", wrapper.WorkflowScheduledGet) + router.POST(baseURL+"/api/v1/tenants/:tenant/workflows/:workflow/crons", wrapper.CronWorkflowTriggerCreate) + router.POST(baseURL+"/api/v1/tenants/:tenant/workflows/:workflow/scheduled", wrapper.ScheduledWorkflowRunCreate) router.GET(baseURL+"/api/v1/tenants/:tenant/workflows/:workflow/worker-count", wrapper.WorkflowGetWorkersCount) router.GET(baseURL+"/api/v1/users/current", wrapper.UserGetCurrent) router.GET(baseURL+"/api/v1/users/github/callback", wrapper.UserUpdateGithubOauthCallback) @@ -6851,6 +6966,118 @@ func (response WorkflowScheduledGet404JSONResponse) VisitWorkflowScheduledGetRes return json.NewEncoder(w).Encode(response) } +type CronWorkflowTriggerCreateRequestObject struct { + Tenant openapi_types.UUID `json:"tenant"` + Workflow openapi_types.UUID `json:"workflow"` + Params CronWorkflowTriggerCreateParams + Body *CronWorkflowTriggerCreateJSONRequestBody +} + +type CronWorkflowTriggerCreateResponseObject interface { + VisitCronWorkflowTriggerCreateResponse(w http.ResponseWriter) error +} + +type CronWorkflowTriggerCreate200JSONResponse CronWorkflows + +func (response CronWorkflowTriggerCreate200JSONResponse) VisitCronWorkflowTriggerCreateResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type CronWorkflowTriggerCreate400JSONResponse APIErrors + +func (response CronWorkflowTriggerCreate400JSONResponse) VisitCronWorkflowTriggerCreateResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(400) + + return json.NewEncoder(w).Encode(response) +} + +type CronWorkflowTriggerCreate403JSONResponse APIErrors + +func (response CronWorkflowTriggerCreate403JSONResponse) VisitCronWorkflowTriggerCreateResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(403) + + return json.NewEncoder(w).Encode(response) +} + +type CronWorkflowTriggerCreate404JSONResponse APIErrors + +func (response CronWorkflowTriggerCreate404JSONResponse) VisitCronWorkflowTriggerCreateResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(404) + + return json.NewEncoder(w).Encode(response) +} + +type CronWorkflowTriggerCreate429JSONResponse APIErrors + +func (response CronWorkflowTriggerCreate429JSONResponse) VisitCronWorkflowTriggerCreateResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(429) + + return json.NewEncoder(w).Encode(response) +} + +type ScheduledWorkflowRunCreateRequestObject struct { + Tenant openapi_types.UUID `json:"tenant"` + Workflow openapi_types.UUID `json:"workflow"` + Params ScheduledWorkflowRunCreateParams + Body *ScheduledWorkflowRunCreateJSONRequestBody +} + +type ScheduledWorkflowRunCreateResponseObject interface { + VisitScheduledWorkflowRunCreateResponse(w http.ResponseWriter) error +} + +type ScheduledWorkflowRunCreate200JSONResponse ScheduledWorkflows + +func (response ScheduledWorkflowRunCreate200JSONResponse) VisitScheduledWorkflowRunCreateResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type ScheduledWorkflowRunCreate400JSONResponse APIErrors + +func (response ScheduledWorkflowRunCreate400JSONResponse) VisitScheduledWorkflowRunCreateResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(400) + + return json.NewEncoder(w).Encode(response) +} + +type ScheduledWorkflowRunCreate403JSONResponse APIErrors + +func (response ScheduledWorkflowRunCreate403JSONResponse) VisitScheduledWorkflowRunCreateResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(403) + + return json.NewEncoder(w).Encode(response) +} + +type ScheduledWorkflowRunCreate404JSONResponse APIErrors + +func (response ScheduledWorkflowRunCreate404JSONResponse) VisitScheduledWorkflowRunCreateResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(404) + + return json.NewEncoder(w).Encode(response) +} + +type ScheduledWorkflowRunCreate429JSONResponse APIErrors + +func (response ScheduledWorkflowRunCreate429JSONResponse) VisitScheduledWorkflowRunCreateResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(429) + + return json.NewEncoder(w).Encode(response) +} + type WorkflowGetWorkersCountRequestObject struct { Tenant openapi_types.UUID `json:"tenant"` Workflow openapi_types.UUID `json:"workflow"` @@ -7903,6 +8130,10 @@ type StrictServerInterface interface { WorkflowScheduledGet(ctx echo.Context, request WorkflowScheduledGetRequestObject) (WorkflowScheduledGetResponseObject, error) + CronWorkflowTriggerCreate(ctx echo.Context, request CronWorkflowTriggerCreateRequestObject) (CronWorkflowTriggerCreateResponseObject, error) + + ScheduledWorkflowRunCreate(ctx echo.Context, request ScheduledWorkflowRunCreateRequestObject) (ScheduledWorkflowRunCreateResponseObject, error) + WorkflowGetWorkersCount(ctx echo.Context, request WorkflowGetWorkersCountRequestObject) (WorkflowGetWorkersCountResponseObject, error) UserGetCurrent(ctx echo.Context, request UserGetCurrentRequestObject) (UserGetCurrentResponseObject, error) @@ -9701,6 +9932,72 @@ func (sh *strictHandler) WorkflowScheduledGet(ctx echo.Context, tenant openapi_t return nil } +// CronWorkflowTriggerCreate operation middleware +func (sh *strictHandler) CronWorkflowTriggerCreate(ctx echo.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params CronWorkflowTriggerCreateParams) error { + var request CronWorkflowTriggerCreateRequestObject + + request.Tenant = tenant + request.Workflow = workflow + request.Params = params + + var body CronWorkflowTriggerCreateJSONRequestBody + if err := ctx.Bind(&body); err != nil { + return err + } + request.Body = &body + + handler := func(ctx echo.Context, request interface{}) (interface{}, error) { + return sh.ssi.CronWorkflowTriggerCreate(ctx, request.(CronWorkflowTriggerCreateRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "CronWorkflowTriggerCreate") + } + + response, err := handler(ctx, request) + + if err != nil { + return err + } else if validResponse, ok := response.(CronWorkflowTriggerCreateResponseObject); ok { + return validResponse.VisitCronWorkflowTriggerCreateResponse(ctx.Response()) + } else if response != nil { + return fmt.Errorf("Unexpected response type: %T", response) + } + return nil +} + +// ScheduledWorkflowRunCreate operation middleware +func (sh *strictHandler) ScheduledWorkflowRunCreate(ctx echo.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params ScheduledWorkflowRunCreateParams) error { + var request ScheduledWorkflowRunCreateRequestObject + + request.Tenant = tenant + request.Workflow = workflow + request.Params = params + + var body ScheduledWorkflowRunCreateJSONRequestBody + if err := ctx.Bind(&body); err != nil { + return err + } + request.Body = &body + + handler := func(ctx echo.Context, request interface{}) (interface{}, error) { + return sh.ssi.ScheduledWorkflowRunCreate(ctx, request.(ScheduledWorkflowRunCreateRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "ScheduledWorkflowRunCreate") + } + + response, err := handler(ctx, request) + + if err != nil { + return err + } else if validResponse, ok := response.(ScheduledWorkflowRunCreateResponseObject); ok { + return validResponse.VisitScheduledWorkflowRunCreateResponse(ctx.Response()) + } else if response != nil { + return fmt.Errorf("Unexpected response type: %T", response) + } + return nil +} + // WorkflowGetWorkersCount operation middleware func (sh *strictHandler) WorkflowGetWorkersCount(ctx echo.Context, tenant openapi_types.UUID, workflow openapi_types.UUID) error { var request WorkflowGetWorkersCountRequestObject @@ -10353,196 +10650,199 @@ func (sh *strictHandler) WorkflowVersionGet(ctx echo.Context, workflow openapi_t // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "7wEA", + "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/frontend/app/src/lib/api/generated/Api.ts b/frontend/app/src/lib/api/generated/Api.ts index aad098201..2b2d1d8e5 100644 --- a/frontend/app/src/lib/api/generated/Api.ts +++ b/frontend/app/src/lib/api/generated/Api.ts @@ -19,6 +19,7 @@ import { CancelEventRequest, CreateAPITokenRequest, CreateAPITokenResponse, + CreateCronWorkflowTriggerRequest, CreateEventRequest, CreateSNSIntegrationRequest, CreateTenantAlertEmailGroupRequest, @@ -56,6 +57,7 @@ import { ScheduledWorkflows, ScheduledWorkflowsList, ScheduledWorkflowsOrderByField, + ScheduleWorkflowRunRequest, SNSIntegration, StepRun, StepRunArchiveList, @@ -1122,6 +1124,40 @@ export class Api extends HttpClient + this.request({ + path: `/api/v1/tenants/${tenant}/workflows/${workflow}/scheduled`, + method: 'POST', + query: query, + body: data, + secure: true, + type: ContentType.Json, + format: 'json', + ...params, + }); /** * @description Get all scheduled workflow runs for a tenant * @@ -1221,7 +1257,41 @@ export class Api extends HttpClient + this.request({ + path: `/api/v1/tenants/${tenant}/workflows/${workflow}/crons`, + method: 'POST', + query: query, + body: data, + secure: true, + type: ContentType.Json, + format: 'json', + ...params, + }); + /** + * @description Get all cron job workflow triggers for a tenant * * @tags Workflow * @name CronWorkflowList diff --git a/frontend/app/src/lib/api/generated/data-contracts.ts b/frontend/app/src/lib/api/generated/data-contracts.ts index b749aec23..a59011521 100644 --- a/frontend/app/src/lib/api/generated/data-contracts.ts +++ b/frontend/app/src/lib/api/generated/data-contracts.ts @@ -1196,6 +1196,20 @@ export interface TriggerWorkflowRunRequest { additionalMetadata?: object; } +export interface ScheduleWorkflowRunRequest { + input: object; + additionalMetadata: object; + /** @format date-time */ + triggerAt: string; +} + +export interface CreateCronWorkflowTriggerRequest { + input: object; + additionalMetadata: object; + cronName: string; + cronExpression: string; +} + export interface CreatePullRequestFromStepRun { branchName: string; } diff --git a/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx b/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx index 6d6e7e08d..59da1d0cf 100644 --- a/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx +++ b/frontend/app/src/pages/main/recurring/components/recurring-columns.tsx @@ -29,7 +29,7 @@ export const columns = ({ header: ({ column }) => ( ), - cell: ({ row }) =>
{row.original.name }
, + cell: ({ row }) =>
{row.original.name}
, }, { accessorKey: 'readable', diff --git a/frontend/app/src/pages/main/workflows/$workflow/components/trigger-workflow-form.tsx b/frontend/app/src/pages/main/workflows/$workflow/components/trigger-workflow-form.tsx index 98e680db0..a5e396c1e 100644 --- a/frontend/app/src/pages/main/workflows/$workflow/components/trigger-workflow-form.tsx +++ b/frontend/app/src/pages/main/workflows/$workflow/components/trigger-workflow-form.tsx @@ -5,8 +5,13 @@ import { DialogHeader, DialogTitle, } from '@/components/ui/dialog'; -import api, { Workflow, WorkflowRun } from '@/lib/api'; -import { useState } from 'react'; +import api, { + CronWorkflows, + ScheduledWorkflows, + Workflow, + WorkflowRun, +} from '@/lib/api'; +import { useMemo, useState } from 'react'; import { Button } from '@/components/ui/button'; import invariant from 'tiny-invariant'; import { useApiError } from '@/lib/hooks'; @@ -16,6 +21,9 @@ import { cn } from '@/lib/utils'; import { useNavigate, useOutletContext } from 'react-router-dom'; import { TenantContextType } from '@/lib/outlet'; import { CodeEditor } from '@/components/ui/code-editor'; +import { Input } from '@/components/ui/input'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import CronPrettifier from 'cronstrue'; export function TriggerWorkflowForm({ workflow, @@ -35,11 +43,28 @@ export function TriggerWorkflowForm({ const [addlMeta, setAddlMeta] = useState('{}'); const [errors, setErrors] = useState([]); + const [timingOption, setTimingOption] = useState<'now' | 'schedule' | 'cron'>( + 'now', + ); + const [scheduleTime, setScheduleTime] = useState(''); + const [cronExpression, setCronExpression] = useState('* * * * *'); + + const cronPretty = useMemo(() => { + try { + return { + pretty: CronPrettifier.toString(cronExpression || '').toLowerCase(), + }; + } catch (e) { + console.error(e); + return { error: e as string }; + } + }, [cronExpression]); + const { handleApiError } = useApiError({ setErrors, }); - const triggerWorkflowMutation = useMutation({ + const triggerNowMutation = useMutation({ mutationKey: ['workflow-run:create', workflow?.metadata.id], mutationFn: async (data: { input: object; addlMeta: object }) => { if (!workflow) { @@ -66,6 +91,112 @@ export function TriggerWorkflowForm({ onError: handleApiError, }); + const triggerScheduleMutation = useMutation({ + mutationKey: ['workflow-run:schedule', workflow?.metadata.id], + mutationFn: async (data: { + input: object; + addlMeta: object; + scheduledAt: string; + }) => { + if (!workflow) { + return; + } + + const res = await api.scheduledWorkflowRunCreate( + tenant.metadata.id, + workflow?.metadata.id, + { + input: data.input, + additionalMetadata: data.addlMeta, + triggerAt: data.scheduledAt, + }, + ); + + return res.data; + }, + onMutate: () => { + setErrors([]); + }, + onSuccess: (workflowRun: ScheduledWorkflows | undefined) => { + if (!workflowRun) { + return; + } + + // TODO: navigate to the scheduled workflow runs page + // navigate(`/workflow-runs/${workflowRun.metadata.id}`); + }, + onError: handleApiError, + }); + + const triggerCronMutation = useMutation({ + mutationKey: ['workflow-run:cron', workflow?.metadata.id], + mutationFn: async (data: { + input: object; + addlMeta: object; + cron: string; + }) => { + if (!workflow) { + return; + } + + const res = await api.cronWorkflowTriggerCreate( + tenant.metadata.id, + workflow?.metadata.id, + { + input: data.input, + additionalMetadata: data.addlMeta, + cronName: 'helloworld', + cronExpression: data.cron, + }, + ); + + return res.data; + }, + onMutate: () => { + setErrors([]); + }, + onSuccess: (workflowRun: CronWorkflows | undefined) => { + if (!workflowRun) { + return; + } + // TODO: navigate to the cron workflow runs page + // navigate(`/workflow-runs/${workflowRun.metadata.id}`); + }, + onError: handleApiError, + }); + + const handleSubmit = () => { + const inputObj = JSON.parse(input || '{}'); + const addlMetaObj = JSON.parse(addlMeta || '{}'); + + if (timingOption === 'now') { + triggerNowMutation.mutate({ + input: inputObj, + addlMeta: addlMetaObj, + }); + } else if (timingOption === 'schedule') { + if (!scheduleTime) { + setErrors(['Please select a date and time for scheduling.']); + return; + } + triggerScheduleMutation.mutate({ + input: inputObj, + addlMeta: addlMetaObj, + scheduledAt: scheduleTime, + }); + } else if (timingOption === 'cron') { + if (!cronExpression) { + setErrors(['Please enter a valid cron expression.']); + return; + } + triggerCronMutation.mutate({ + input: inputObj, + addlMeta: addlMetaObj, + cron: cronExpression, + }); + } + }; + return ( +
+
Timing
+ + setTimingOption(value as 'now' | 'schedule' | 'cron') + } + > + + Now + Schedule + Cron + + + +
+
Select Date and Time
+ setScheduleTime(e.target.value)} + className="w-full" + /> +
+
+ +
+
Cron Expression
+ setCronExpression(e.target.value)} + placeholder="e.g., 0 0 * * *" + className="w-full" + /> +
+ {cronPretty?.error || `(runs ${cronPretty?.pretty} UTC)`} +
+
+
+
+
+ - {errors.length > 0 && ( + {(errors.length > 0 || + triggerNowMutation.error || + triggerScheduleMutation.error || + triggerCronMutation.error) && (
{errors.map((error, index) => (
diff --git a/pkg/client/rest/gen.go b/pkg/client/rest/gen.go index 7998a0192..c26db8b76 100644 --- a/pkg/client/rest/gen.go +++ b/pkg/client/rest/gen.go @@ -336,6 +336,14 @@ type CreateAPITokenResponse struct { Token string `json:"token"` } +// CreateCronWorkflowTriggerRequest defines model for CreateCronWorkflowTriggerRequest. +type CreateCronWorkflowTriggerRequest struct { + AdditionalMetadata map[string]interface{} `json:"additionalMetadata"` + CronExpression string `json:"cronExpression"` + CronName string `json:"cronName"` + Input map[string]interface{} `json:"input"` +} + // CreateEventRequest defines model for CreateEventRequest. type CreateEventRequest struct { // AdditionalMetadata Additional metadata for the event. @@ -659,6 +667,13 @@ type SNSIntegration struct { TopicArn string `json:"topicArn"` } +// ScheduleWorkflowRunRequest defines model for ScheduleWorkflowRunRequest. +type ScheduleWorkflowRunRequest struct { + AdditionalMetadata map[string]interface{} `json:"additionalMetadata"` + Input map[string]interface{} `json:"input"` + TriggerAt time.Time `json:"triggerAt"` +} + // ScheduledRunStatus defines model for ScheduledRunStatus. type ScheduledRunStatus string @@ -1661,6 +1676,18 @@ type WorkflowScheduledListParams struct { Statuses *[]ScheduledRunStatus `form:"statuses,omitempty" json:"statuses,omitempty"` } +// CronWorkflowTriggerCreateParams defines parameters for CronWorkflowTriggerCreate. +type CronWorkflowTriggerCreateParams struct { + // Version The workflow version. If not supplied, the latest version is fetched. + Version *openapi_types.UUID `form:"version,omitempty" json:"version,omitempty"` +} + +// ScheduledWorkflowRunCreateParams defines parameters for ScheduledWorkflowRunCreate. +type ScheduledWorkflowRunCreateParams struct { + // Version The workflow version. If not supplied, the latest version is fetched. + Version *openapi_types.UUID `form:"version,omitempty" json:"version,omitempty"` +} + // WorkflowGetMetricsParams defines parameters for WorkflowGetMetrics. type WorkflowGetMetricsParams struct { // Status A status of workflow run statuses to filter by @@ -1730,6 +1757,12 @@ type WorkflowRunUpdateReplayJSONRequestBody = ReplayWorkflowRunsRequest // WorkflowRunCancelJSONRequestBody defines body for WorkflowRunCancel for application/json ContentType. type WorkflowRunCancelJSONRequestBody = WorkflowRunsCancelRequest +// CronWorkflowTriggerCreateJSONRequestBody defines body for CronWorkflowTriggerCreate for application/json ContentType. +type CronWorkflowTriggerCreateJSONRequestBody = CreateCronWorkflowTriggerRequest + +// ScheduledWorkflowRunCreateJSONRequestBody defines body for ScheduledWorkflowRunCreate for application/json ContentType. +type ScheduledWorkflowRunCreateJSONRequestBody = ScheduleWorkflowRunRequest + // TenantInviteAcceptJSONRequestBody defines body for TenantInviteAccept for application/json ContentType. type TenantInviteAcceptJSONRequestBody = AcceptInviteRequest @@ -2054,6 +2087,16 @@ type ClientInterface interface { // WorkflowScheduledGet request WorkflowScheduledGet(ctx context.Context, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) + // CronWorkflowTriggerCreateWithBody request with any body + CronWorkflowTriggerCreateWithBody(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *CronWorkflowTriggerCreateParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + CronWorkflowTriggerCreate(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *CronWorkflowTriggerCreateParams, body CronWorkflowTriggerCreateJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // ScheduledWorkflowRunCreateWithBody request with any body + ScheduledWorkflowRunCreateWithBody(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *ScheduledWorkflowRunCreateParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + ScheduledWorkflowRunCreate(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *ScheduledWorkflowRunCreateParams, body ScheduledWorkflowRunCreateJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // WorkflowGetWorkersCount request WorkflowGetWorkersCount(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -3118,6 +3161,54 @@ func (c *Client) WorkflowScheduledGet(ctx context.Context, tenant openapi_types. return c.Client.Do(req) } +func (c *Client) CronWorkflowTriggerCreateWithBody(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *CronWorkflowTriggerCreateParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCronWorkflowTriggerCreateRequestWithBody(c.Server, tenant, workflow, params, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) CronWorkflowTriggerCreate(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *CronWorkflowTriggerCreateParams, body CronWorkflowTriggerCreateJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCronWorkflowTriggerCreateRequest(c.Server, tenant, workflow, params, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) ScheduledWorkflowRunCreateWithBody(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *ScheduledWorkflowRunCreateParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewScheduledWorkflowRunCreateRequestWithBody(c.Server, tenant, workflow, params, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) ScheduledWorkflowRunCreate(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *ScheduledWorkflowRunCreateParams, body ScheduledWorkflowRunCreateJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewScheduledWorkflowRunCreateRequest(c.Server, tenant, workflow, params, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) WorkflowGetWorkersCount(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewWorkflowGetWorkersCountRequest(c.Server, tenant, workflow) if err != nil { @@ -7108,6 +7199,158 @@ func NewWorkflowScheduledGetRequest(server string, tenant openapi_types.UUID, sc return req, nil } +// NewCronWorkflowTriggerCreateRequest calls the generic CronWorkflowTriggerCreate builder with application/json body +func NewCronWorkflowTriggerCreateRequest(server string, tenant openapi_types.UUID, workflow openapi_types.UUID, params *CronWorkflowTriggerCreateParams, body CronWorkflowTriggerCreateJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewCronWorkflowTriggerCreateRequestWithBody(server, tenant, workflow, params, "application/json", bodyReader) +} + +// NewCronWorkflowTriggerCreateRequestWithBody generates requests for CronWorkflowTriggerCreate with any type of body +func NewCronWorkflowTriggerCreateRequestWithBody(server string, tenant openapi_types.UUID, workflow openapi_types.UUID, params *CronWorkflowTriggerCreateParams, contentType string, body io.Reader) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "tenant", runtime.ParamLocationPath, tenant) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "workflow", runtime.ParamLocationPath, workflow) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/api/v1/tenants/%s/workflows/%s/crons", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + if params != nil { + queryValues := queryURL.Query() + + if params.Version != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "version", runtime.ParamLocationQuery, *params.Version); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + queryURL.RawQuery = queryValues.Encode() + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + +// NewScheduledWorkflowRunCreateRequest calls the generic ScheduledWorkflowRunCreate builder with application/json body +func NewScheduledWorkflowRunCreateRequest(server string, tenant openapi_types.UUID, workflow openapi_types.UUID, params *ScheduledWorkflowRunCreateParams, body ScheduledWorkflowRunCreateJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewScheduledWorkflowRunCreateRequestWithBody(server, tenant, workflow, params, "application/json", bodyReader) +} + +// NewScheduledWorkflowRunCreateRequestWithBody generates requests for ScheduledWorkflowRunCreate with any type of body +func NewScheduledWorkflowRunCreateRequestWithBody(server string, tenant openapi_types.UUID, workflow openapi_types.UUID, params *ScheduledWorkflowRunCreateParams, contentType string, body io.Reader) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "tenant", runtime.ParamLocationPath, tenant) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "workflow", runtime.ParamLocationPath, workflow) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/api/v1/tenants/%s/workflows/%s/scheduled", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + if params != nil { + queryValues := queryURL.Query() + + if params.Version != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "version", runtime.ParamLocationQuery, *params.Version); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + queryURL.RawQuery = queryValues.Encode() + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + // NewWorkflowGetWorkersCountRequest generates requests for WorkflowGetWorkersCount func NewWorkflowGetWorkersCountRequest(server string, tenant openapi_types.UUID, workflow openapi_types.UUID) (*http.Request, error) { var err error @@ -8323,6 +8566,16 @@ type ClientWithResponsesInterface interface { // WorkflowScheduledGetWithResponse request WorkflowScheduledGetWithResponse(ctx context.Context, tenant openapi_types.UUID, scheduledWorkflowRun openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowScheduledGetResponse, error) + // CronWorkflowTriggerCreateWithBodyWithResponse request with any body + CronWorkflowTriggerCreateWithBodyWithResponse(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *CronWorkflowTriggerCreateParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CronWorkflowTriggerCreateResponse, error) + + CronWorkflowTriggerCreateWithResponse(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *CronWorkflowTriggerCreateParams, body CronWorkflowTriggerCreateJSONRequestBody, reqEditors ...RequestEditorFn) (*CronWorkflowTriggerCreateResponse, error) + + // ScheduledWorkflowRunCreateWithBodyWithResponse request with any body + ScheduledWorkflowRunCreateWithBodyWithResponse(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *ScheduledWorkflowRunCreateParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ScheduledWorkflowRunCreateResponse, error) + + ScheduledWorkflowRunCreateWithResponse(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *ScheduledWorkflowRunCreateParams, body ScheduledWorkflowRunCreateJSONRequestBody, reqEditors ...RequestEditorFn) (*ScheduledWorkflowRunCreateResponse, error) + // WorkflowGetWorkersCountWithResponse request WorkflowGetWorkersCountWithResponse(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowGetWorkersCountResponse, error) @@ -9982,6 +10235,58 @@ func (r WorkflowScheduledGetResponse) StatusCode() int { return 0 } +type CronWorkflowTriggerCreateResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *CronWorkflows + JSON400 *APIErrors + JSON403 *APIErrors + JSON404 *APIErrors + JSON429 *APIErrors +} + +// Status returns HTTPResponse.Status +func (r CronWorkflowTriggerCreateResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r CronWorkflowTriggerCreateResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type ScheduledWorkflowRunCreateResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *ScheduledWorkflows + JSON400 *APIErrors + JSON403 *APIErrors + JSON404 *APIErrors + JSON429 *APIErrors +} + +// Status returns HTTPResponse.Status +func (r ScheduledWorkflowRunCreateResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r ScheduledWorkflowRunCreateResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type WorkflowGetWorkersCountResponse struct { Body []byte HTTPResponse *http.Response @@ -11289,6 +11594,40 @@ func (c *ClientWithResponses) WorkflowScheduledGetWithResponse(ctx context.Conte return ParseWorkflowScheduledGetResponse(rsp) } +// CronWorkflowTriggerCreateWithBodyWithResponse request with arbitrary body returning *CronWorkflowTriggerCreateResponse +func (c *ClientWithResponses) CronWorkflowTriggerCreateWithBodyWithResponse(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *CronWorkflowTriggerCreateParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CronWorkflowTriggerCreateResponse, error) { + rsp, err := c.CronWorkflowTriggerCreateWithBody(ctx, tenant, workflow, params, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCronWorkflowTriggerCreateResponse(rsp) +} + +func (c *ClientWithResponses) CronWorkflowTriggerCreateWithResponse(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *CronWorkflowTriggerCreateParams, body CronWorkflowTriggerCreateJSONRequestBody, reqEditors ...RequestEditorFn) (*CronWorkflowTriggerCreateResponse, error) { + rsp, err := c.CronWorkflowTriggerCreate(ctx, tenant, workflow, params, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCronWorkflowTriggerCreateResponse(rsp) +} + +// ScheduledWorkflowRunCreateWithBodyWithResponse request with arbitrary body returning *ScheduledWorkflowRunCreateResponse +func (c *ClientWithResponses) ScheduledWorkflowRunCreateWithBodyWithResponse(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *ScheduledWorkflowRunCreateParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ScheduledWorkflowRunCreateResponse, error) { + rsp, err := c.ScheduledWorkflowRunCreateWithBody(ctx, tenant, workflow, params, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseScheduledWorkflowRunCreateResponse(rsp) +} + +func (c *ClientWithResponses) ScheduledWorkflowRunCreateWithResponse(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, params *ScheduledWorkflowRunCreateParams, body ScheduledWorkflowRunCreateJSONRequestBody, reqEditors ...RequestEditorFn) (*ScheduledWorkflowRunCreateResponse, error) { + rsp, err := c.ScheduledWorkflowRunCreate(ctx, tenant, workflow, params, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseScheduledWorkflowRunCreateResponse(rsp) +} + // WorkflowGetWorkersCountWithResponse request returning *WorkflowGetWorkersCountResponse func (c *ClientWithResponses) WorkflowGetWorkersCountWithResponse(ctx context.Context, tenant openapi_types.UUID, workflow openapi_types.UUID, reqEditors ...RequestEditorFn) (*WorkflowGetWorkersCountResponse, error) { rsp, err := c.WorkflowGetWorkersCount(ctx, tenant, workflow, reqEditors...) @@ -14194,6 +14533,114 @@ func ParseWorkflowScheduledGetResponse(rsp *http.Response) (*WorkflowScheduledGe return response, nil } +// ParseCronWorkflowTriggerCreateResponse parses an HTTP response from a CronWorkflowTriggerCreateWithResponse call +func ParseCronWorkflowTriggerCreateResponse(rsp *http.Response) (*CronWorkflowTriggerCreateResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &CronWorkflowTriggerCreateResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest CronWorkflows + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + } + + return response, nil +} + +// ParseScheduledWorkflowRunCreateResponse parses an HTTP response from a ScheduledWorkflowRunCreateWithResponse call +func ParseScheduledWorkflowRunCreateResponse(rsp *http.Response) (*ScheduledWorkflowRunCreateResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &ScheduledWorkflowRunCreateResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest ScheduledWorkflows + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest APIErrors + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + } + + return response, nil +} + // ParseWorkflowGetWorkersCountResponse parses an HTTP response from a WorkflowGetWorkersCountWithResponse call func ParseWorkflowGetWorkersCountResponse(rsp *http.Response) (*WorkflowGetWorkersCountResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/pkg/repository/prisma/dbsqlc/schema.sql b/pkg/repository/prisma/dbsqlc/schema.sql index 1947f7128..2b7f1a129 100644 --- a/pkg/repository/prisma/dbsqlc/schema.sql +++ b/pkg/repository/prisma/dbsqlc/schema.sql @@ -1372,9 +1372,6 @@ CREATE UNIQUE INDEX "WorkflowTag_tenantId_name_key" ON "WorkflowTag"("tenantId" -- CreateIndex CREATE UNIQUE INDEX "WorkflowTriggerCronRef_id_key" ON "WorkflowTriggerCronRef"("id" ASC); --- CreateIndex -CREATE UNIQUE INDEX "WorkflowTriggerCronRef_parentId_cron_key" ON "WorkflowTriggerCronRef"("parentId" ASC, "cron" ASC); - -- CreateIndex CREATE UNIQUE INDEX "WorkflowTriggerCronRef_parentId_cron_name_key" ON "WorkflowTriggerCronRef"("parentId" ASC, "cron" ASC, "name" ASC); diff --git a/pkg/repository/prisma/dbsqlc/workflows.sql b/pkg/repository/prisma/dbsqlc/workflows.sql index 64376aef4..d1560b8b8 100644 --- a/pkg/repository/prisma/dbsqlc/workflows.sql +++ b/pkg/repository/prisma/dbsqlc/workflows.sql @@ -344,19 +344,49 @@ INSERT INTO "WorkflowTriggerCronRef" ( gen_random_uuid() ) RETURNING *; + +-- name: CreateWorkflowTriggerCronRefForWorkflow :one +WITH latest_version AS ( + SELECT "id" FROM "WorkflowVersion" + WHERE "workflowId" = @workflowId::uuid + ORDER BY "order" DESC + LIMIT 1 +), +latest_trigger AS ( + SELECT "id" FROM "WorkflowTriggers" + WHERE "workflowVersionId" = (SELECT "id" FROM latest_version) + ORDER BY "createdAt" DESC + LIMIT 1 +) +INSERT INTO "WorkflowTriggerCronRef" ( + "parentId", + "cron", + "name", + "input", + "additionalMetadata", + "id" +) VALUES ( + (SELECT "id" FROM latest_trigger), + @cronTrigger::text, + sqlc.narg('name')::text, + sqlc.narg('input')::jsonb, + sqlc.narg('additionalMetadata')::jsonb, + gen_random_uuid() +) RETURNING *; + -- name: CreateWorkflowTriggerScheduledRef :one INSERT INTO "WorkflowTriggerScheduledRef" ( "id", "parentId", "triggerAt", - "tickerId", - "input" + "input", + "additionalMetadata" ) VALUES ( gen_random_uuid(), @workflowVersionId::uuid, @scheduledTrigger::timestamp, - NULL, -- or provide a tickerId if applicable - NULL -- or provide input if applicable + @input::jsonb, + @additionalMetadata::jsonb ) RETURNING *; -- name: ListWorkflowsForEvent :many diff --git a/pkg/repository/prisma/dbsqlc/workflows.sql.go b/pkg/repository/prisma/dbsqlc/workflows.sql.go index 85fbe18da..c1e86113b 100644 --- a/pkg/repository/prisma/dbsqlc/workflows.sql.go +++ b/pkg/repository/prisma/dbsqlc/workflows.sql.go @@ -614,6 +614,69 @@ func (q *Queries) CreateWorkflowTriggerCronRef(ctx context.Context, db DBTX, arg return &i, err } +const createWorkflowTriggerCronRefForWorkflow = `-- name: CreateWorkflowTriggerCronRefForWorkflow :one +WITH latest_version AS ( + SELECT "id" FROM "WorkflowVersion" + WHERE "workflowId" = $5::uuid + ORDER BY "order" DESC + LIMIT 1 +), +latest_trigger AS ( + SELECT "id" FROM "WorkflowTriggers" + WHERE "workflowVersionId" = (SELECT "id" FROM latest_version) + ORDER BY "createdAt" DESC + LIMIT 1 +) +INSERT INTO "WorkflowTriggerCronRef" ( + "parentId", + "cron", + "name", + "input", + "additionalMetadata", + "id" +) VALUES ( + (SELECT "id" FROM latest_trigger), + $1::text, + $2::text, + $3::jsonb, + $4::jsonb, + gen_random_uuid() +) RETURNING "parentId", cron, "tickerId", input, enabled, "additionalMetadata", "createdAt", "deletedAt", "updatedAt", name, id +` + +type CreateWorkflowTriggerCronRefForWorkflowParams struct { + Crontrigger string `json:"crontrigger"` + Name pgtype.Text `json:"name"` + Input []byte `json:"input"` + AdditionalMetadata []byte `json:"additionalMetadata"` + Workflowid pgtype.UUID `json:"workflowid"` +} + +func (q *Queries) CreateWorkflowTriggerCronRefForWorkflow(ctx context.Context, db DBTX, arg CreateWorkflowTriggerCronRefForWorkflowParams) (*WorkflowTriggerCronRef, error) { + row := db.QueryRow(ctx, createWorkflowTriggerCronRefForWorkflow, + arg.Crontrigger, + arg.Name, + arg.Input, + arg.AdditionalMetadata, + arg.Workflowid, + ) + var i WorkflowTriggerCronRef + err := row.Scan( + &i.ParentId, + &i.Cron, + &i.TickerId, + &i.Input, + &i.Enabled, + &i.AdditionalMetadata, + &i.CreatedAt, + &i.DeletedAt, + &i.UpdatedAt, + &i.Name, + &i.ID, + ) + return &i, err +} + const createWorkflowTriggerEventRef = `-- name: CreateWorkflowTriggerEventRef :one INSERT INTO "WorkflowTriggerEventRef" ( "parentId", @@ -641,24 +704,31 @@ INSERT INTO "WorkflowTriggerScheduledRef" ( "id", "parentId", "triggerAt", - "tickerId", - "input" + "input", + "additionalMetadata" ) VALUES ( gen_random_uuid(), $1::uuid, $2::timestamp, - NULL, -- or provide a tickerId if applicable - NULL -- or provide input if applicable + $3::jsonb, + $4::jsonb ) RETURNING id, "parentId", "triggerAt", "tickerId", input, "childIndex", "childKey", "parentStepRunId", "parentWorkflowRunId", "additionalMetadata", "createdAt", "deletedAt", "updatedAt" ` type CreateWorkflowTriggerScheduledRefParams struct { - Workflowversionid pgtype.UUID `json:"workflowversionid"` - Scheduledtrigger pgtype.Timestamp `json:"scheduledtrigger"` + Workflowversionid pgtype.UUID `json:"workflowversionid"` + Scheduledtrigger pgtype.Timestamp `json:"scheduledtrigger"` + Input []byte `json:"input"` + Additionalmetadata []byte `json:"additionalmetadata"` } func (q *Queries) CreateWorkflowTriggerScheduledRef(ctx context.Context, db DBTX, arg CreateWorkflowTriggerScheduledRefParams) (*WorkflowTriggerScheduledRef, error) { - row := db.QueryRow(ctx, createWorkflowTriggerScheduledRef, arg.Workflowversionid, arg.Scheduledtrigger) + row := db.QueryRow(ctx, createWorkflowTriggerScheduledRef, + arg.Workflowversionid, + arg.Scheduledtrigger, + arg.Input, + arg.Additionalmetadata, + ) var i WorkflowTriggerScheduledRef err := row.Scan( &i.ID, diff --git a/pkg/repository/prisma/workflow.go b/pkg/repository/prisma/workflow.go index b78cb7d2d..b1fda1a41 100644 --- a/pkg/repository/prisma/workflow.go +++ b/pkg/repository/prisma/workflow.go @@ -2,6 +2,7 @@ package prisma import ( "context" + "encoding/json" "errors" "fmt" "strings" @@ -357,35 +358,51 @@ func (w *workflowAPIRepository) DeleteCronWorkflow(ctx context.Context, tenantId return w.queries.DeleteWorkflowTriggerCronRef(ctx, w.pool, sqlchelpers.UUIDFromStr(id)) } -func (w *workflowAPIRepository) CreateCronWorkflow(ctx context.Context, tenantId string, opts *repository.CreateCronWorkflowTriggerOpts) (*dbsqlc.WorkflowRun, error) { +func (w *workflowAPIRepository) CreateCronWorkflow(ctx context.Context, tenantId string, opts *repository.CreateCronWorkflowTriggerOpts) (*dbsqlc.ListCronWorkflowsRow, error) { - workflow, err := w.queries.GetWorkflowByName(ctx, w.pool, dbsqlc.GetWorkflowByNameParams{ - Tenantid: sqlchelpers.UUIDFromStr(tenantId), - Name: opts.Name, - }) + var input, additionalMetadata []byte + var err error - if err != nil { - return nil, err + if opts.Input != nil { + input, err = json.Marshal(opts.Input) + + if err != nil { + return nil, err + } + } + + if opts.AdditionalMetadata != nil { + additionalMetadata, err = json.Marshal(opts.AdditionalMetadata) + + if err != nil { + return nil, err + } } - createParams := dbsqlc.CreateWorkflowTriggerCronRefParams{ - Workflowtriggersid: workflow.ID, + createParams := dbsqlc.CreateWorkflowTriggerCronRefForWorkflowParams{ + Workflowid: sqlchelpers.UUIDFromStr(opts.WorkflowId), Crontrigger: opts.Cron, Name: sqlchelpers.TextFromStr(opts.Name), - Input: opts.Input, - AdditionalMetadata: opts.AdditionalMetadata, + Input: input, + AdditionalMetadata: additionalMetadata, } - _, err = w.queries.CreateWorkflowTriggerCronRef(ctx, w.pool, createParams) + cronTrigger, err := w.queries.CreateWorkflowTriggerCronRefForWorkflow(ctx, w.pool, createParams) if err != nil { return nil, err } - // TODO: return the cron workflow trigger - // cronWorkflow, err := w.GetCronWorkflow(ctx, tenantId, cronWorkflowTrigger.) + row, err := w.queries.ListCronWorkflows(ctx, w.pool, dbsqlc.ListCronWorkflowsParams{ + Tenantid: sqlchelpers.UUIDFromStr(tenantId), + Cronid: cronTrigger.ID, + }) + + if err != nil { + return nil, err + } - return nil, nil + return row[0], nil } type workflowEngineRepository struct { diff --git a/pkg/repository/workflow.go b/pkg/repository/workflow.go index 2482f110d..f7dcc581b 100644 --- a/pkg/repository/workflow.go +++ b/pkg/repository/workflow.go @@ -59,13 +59,16 @@ type CreateWorkflowVersionOpts struct { } type CreateCronWorkflowTriggerOpts struct { + // (required) the workflow id + WorkflowId string `validate:"required,uuid"` + // (required) the workflow name Name string `validate:"required"` Cron string `validate:"required,cron"` - Input []byte - AdditionalMetadata []byte + Input map[string]interface{} + AdditionalMetadata map[string]interface{} } type CreateWorkflowConcurrencyOpts struct { @@ -277,7 +280,7 @@ type WorkflowAPIRepository interface { GetWorkflowWorkerCount(tenantId, workflowId string) (int, int, error) // CreateCronWorkflow creates a cron trigger - CreateCronWorkflow(ctx context.Context, tenantId string, opts *CreateCronWorkflowTriggerOpts) (*dbsqlc.WorkflowRun, error) + CreateCronWorkflow(ctx context.Context, tenantId string, opts *CreateCronWorkflowTriggerOpts) (*dbsqlc.ListCronWorkflowsRow, error) // List ScheduledWorkflows lists workflows by scheduled trigger ListCronWorkflows(ctx context.Context, tenantId string, opts *ListCronWorkflowsOpts) ([]*dbsqlc.ListCronWorkflowsRow, int64, error) diff --git a/pkg/repository/workflow_run.go b/pkg/repository/workflow_run.go index 19304d03e..355d69688 100644 --- a/pkg/repository/workflow_run.go +++ b/pkg/repository/workflow_run.go @@ -31,7 +31,7 @@ type CreateWorkflowRunOpts struct { // (optional) the cron schedule that triggered the workflow run Cron *string `validate:"omitnil,cron,required_without=ManualTriggerInput,required_without=TriggeringEventId,required_without=ScheduledWorkflowId,excluded_with=ManualTriggerInput,excluded_with=TriggeringEventId,excluded_with=ScheduledWorkflowId"` CronParentId *string `validate:"omitnil,uuid,required_without=ManualTriggerInput,required_without=TriggeringEventId,required_without=ScheduledWorkflowId,excluded_with=ManualTriggerInput,excluded_with=TriggeringEventId,excluded_with=ScheduledWorkflowId"` - CronName *string `validate:"omitnil,exclude_without=Cron"` + CronName *string `validate:"omitnil"` // (optional) the scheduled trigger ScheduledWorkflowId *string `validate:"omitnil,uuid,required_without=ManualTriggerInput,required_without=TriggeringEventId,required_without=Cron,excluded_with=ManualTriggerInput,excluded_with=TriggeringEventId,excluded_with=Cron"` diff --git a/prisma/migrations/20241104202817_tmp/migration.sql b/prisma/migrations/20241104202817_tmp/migration.sql new file mode 100644 index 000000000..a64493312 --- /dev/null +++ b/prisma/migrations/20241104202817_tmp/migration.sql @@ -0,0 +1,2 @@ +-- DropIndex +DROP INDEX "WorkflowTriggerCronRef_parentId_cron_key"; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 8718baa45..ebeb38784 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -674,7 +674,6 @@ model WorkflowTriggerCronRef { additionalMetadata Json? // cron references must be unique per workflow - @@unique([parentId, cron]) @@unique([parentId, cron, name]) } diff --git a/sql/migrations/20241104202826_tmp.sql b/sql/migrations/20241104202826_tmp.sql new file mode 100644 index 000000000..c092ab7fb --- /dev/null +++ b/sql/migrations/20241104202826_tmp.sql @@ -0,0 +1,2 @@ +-- Drop index "WorkflowTriggerCronRef_parentId_cron_key" from table: "WorkflowTriggerCronRef" +DROP INDEX "WorkflowTriggerCronRef_parentId_cron_key"; diff --git a/sql/migrations/atlas.sum b/sql/migrations/atlas.sum index b9ff733fc..58f74699e 100644 --- a/sql/migrations/atlas.sum +++ b/sql/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:n9zZZyeWzYmcejRQIs2QQUMbhtHA9YwDY5QZZy2Z+lM= +h1:huS/xWxyq+fGX7e8YorWJjiQgcGa0BCkUMVTuyY52K4= 20240115180414_init.sql h1:Ef3ZyjAHkmJPdGF/dEWCahbwgcg6uGJKnDxW2JCRi2k= 20240122014727_v0_6_0.sql h1:o/LdlteAeFgoHJ3e/M4Xnghqt9826IE/Y/h0q95Acuo= 20240126235456_v0_7_0.sql h1:KiVzt/hXgQ6esbdC6OMJOOWuYEXmy1yeCpmsVAHTFKs= @@ -73,3 +73,8 @@ h1:n9zZZyeWzYmcejRQIs2QQUMbhtHA9YwDY5QZZy2Z+lM= 20241023223039_v0.50.4.sql h1:eXJLlkM6ZzqzZ4RbAZtoTiW7WjJPIJ5L6UkIKy6w9Uk= 20241025162439_v0.50.5.sql h1:CIv/oSeiVR1D3rOb4z8uv2t0XUI62TyK+0UI0s6tQ/k= 20241029122625_v0.51.0.sql h1:nOa4FqmZxSh1yBOJyduX+j15gQavjizTn660wyXjhNk= +20241030131347_tmp.sql h1:48ydfY8fUk6nR6Av35gk57TfBbrwYYLwjtTAKch1TBg= +20241030133048_tmp.sql h1:dWSeXAsgIbUo1yCrxM6p/a2mPPDMfMP2j4s+R0ADZjE= +20241030150116_tmp.sql h1:LUy5JzLfjjUEO8cnUco26jKbqkdC7yIHAJ5xx2XLVqE= +20241030150342_tmp.sql h1:bDLmpmjBtYckGAIOhn7YRgEK32BLXGHA9sravMY135k= +20241104202826_tmp.sql h1:sCDs68edZmeRw0+NSSaBUS+k273WTaT7DrSKjER6tww= diff --git a/sql/schema/schema.sql b/sql/schema/schema.sql index 98748bcc3..07826f84d 100644 --- a/sql/schema/schema.sql +++ b/sql/schema/schema.sql @@ -1372,9 +1372,6 @@ CREATE UNIQUE INDEX "WorkflowTag_tenantId_name_key" ON "WorkflowTag"("tenantId" -- CreateIndex CREATE UNIQUE INDEX "WorkflowTriggerCronRef_id_key" ON "WorkflowTriggerCronRef"("id" ASC); --- CreateIndex -CREATE UNIQUE INDEX "WorkflowTriggerCronRef_parentId_cron_key" ON "WorkflowTriggerCronRef"("parentId" ASC, "cron" ASC); - -- CreateIndex CREATE UNIQUE INDEX "WorkflowTriggerCronRef_parentId_cron_name_key" ON "WorkflowTriggerCronRef"("parentId" ASC, "cron" ASC, "name" ASC); From 12aa0d4fee0f4e92a1d6cc7208093bab7b883e60 Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Mon, 4 Nov 2024 16:50:02 -0500 Subject: [PATCH 27/30] wip: create schedule --- .../handlers/workflows/create_scheduled.go | 20 +++++- .../components/trigger-workflow-form.tsx | 20 +++--- pkg/repository/prisma/dbsqlc/workflows.sql | 27 ++++++++ pkg/repository/prisma/dbsqlc/workflows.sql.go | 61 +++++++++++++++++++ pkg/repository/prisma/workflow.go | 45 ++++++++++++++ pkg/repository/workflow.go | 12 ++++ 6 files changed, 174 insertions(+), 11 deletions(-) diff --git a/api/v1/server/handlers/workflows/create_scheduled.go b/api/v1/server/handlers/workflows/create_scheduled.go index 7e9ca8a48..fddd154d0 100644 --- a/api/v1/server/handlers/workflows/create_scheduled.go +++ b/api/v1/server/handlers/workflows/create_scheduled.go @@ -3,14 +3,30 @@ package workflows import ( "github.com/labstack/echo/v4" + "github.com/hatchet-dev/hatchet/api/v1/server/oas/apierrors" "github.com/hatchet-dev/hatchet/api/v1/server/oas/gen" + "github.com/hatchet-dev/hatchet/api/v1/server/oas/transformers" + "github.com/hatchet-dev/hatchet/pkg/repository" + "github.com/hatchet-dev/hatchet/pkg/repository/prisma/db" ) func (t *WorkflowService) ScheduledWorkflowRunCreate(ctx echo.Context, request gen.ScheduledWorkflowRunCreateRequestObject) (gen.ScheduledWorkflowRunCreateResponseObject, error) { + tenant := ctx.Get("tenant").(*db.TenantModel) - // t. + scheduled, err := t.config.APIRepository.Workflow().CreateScheduledWorkflow(ctx.Request().Context(), tenant.ID, &repository.CreateScheduledWorkflowRunForWorkflowOpts{ + ScheduledTrigger: request.Body.TriggerAt, + Input: request.Body.Input, + AdditionalMetadata: request.Body.AdditionalMetadata, + WorkflowId: request.Workflow.String(), + }) + + if err != nil { + return gen.ScheduledWorkflowRunCreate400JSONResponse( + apierrors.NewAPIErrors(err.Error()), + ), nil + } return gen.ScheduledWorkflowRunCreate200JSONResponse( - gen.ScheduledWorkflows{}, + *transformers.ToScheduledWorkflowsFromSQLC(scheduled), ), nil } diff --git a/frontend/app/src/pages/main/workflows/$workflow/components/trigger-workflow-form.tsx b/frontend/app/src/pages/main/workflows/$workflow/components/trigger-workflow-form.tsx index a5e396c1e..47b2d00a2 100644 --- a/frontend/app/src/pages/main/workflows/$workflow/components/trigger-workflow-form.tsx +++ b/frontend/app/src/pages/main/workflows/$workflow/components/trigger-workflow-form.tsx @@ -24,6 +24,7 @@ import { CodeEditor } from '@/components/ui/code-editor'; import { Input } from '@/components/ui/input'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import CronPrettifier from 'cronstrue'; +import { DateTimePicker } from '@/components/molecules/time-picker/date-time-picker'; export function TriggerWorkflowForm({ workflow, @@ -46,7 +47,9 @@ export function TriggerWorkflowForm({ const [timingOption, setTimingOption] = useState<'now' | 'schedule' | 'cron'>( 'now', ); - const [scheduleTime, setScheduleTime] = useState(''); + const [scheduleTime, setScheduleTime] = useState( + new Date(), + ); const [cronExpression, setCronExpression] = useState('* * * * *'); const cronPretty = useMemo(() => { @@ -123,7 +126,7 @@ export function TriggerWorkflowForm({ } // TODO: navigate to the scheduled workflow runs page - // navigate(`/workflow-runs/${workflowRun.metadata.id}`); + navigate(`/scheduled`); }, onError: handleApiError, }); @@ -160,7 +163,7 @@ export function TriggerWorkflowForm({ return; } // TODO: navigate to the cron workflow runs page - // navigate(`/workflow-runs/${workflowRun.metadata.id}`); + navigate(`/cron-jobs`); }, onError: handleApiError, }); @@ -182,7 +185,7 @@ export function TriggerWorkflowForm({ triggerScheduleMutation.mutate({ input: inputObj, addlMeta: addlMetaObj, - scheduledAt: scheduleTime, + scheduledAt: scheduleTime.toISOString(), }); } else if (timingOption === 'cron') { if (!cronExpression) { @@ -244,11 +247,10 @@ export function TriggerWorkflowForm({
Select Date and Time
- setScheduleTime(e.target.value)} - className="w-full" +
diff --git a/pkg/repository/prisma/dbsqlc/workflows.sql b/pkg/repository/prisma/dbsqlc/workflows.sql index d1560b8b8..b9daf5936 100644 --- a/pkg/repository/prisma/dbsqlc/workflows.sql +++ b/pkg/repository/prisma/dbsqlc/workflows.sql @@ -374,6 +374,33 @@ INSERT INTO "WorkflowTriggerCronRef" ( gen_random_uuid() ) RETURNING *; +-- name: CreateWorkflowTriggerScheduledRefForWorkflow :one +WITH latest_version AS ( + SELECT "id" FROM "WorkflowVersion" + WHERE "workflowId" = @workflowId::uuid + ORDER BY "order" DESC + LIMIT 1 +), +latest_trigger AS ( + SELECT "id" FROM "WorkflowTriggers" + WHERE "workflowVersionId" = (SELECT "id" FROM latest_version) + ORDER BY "createdAt" DESC + LIMIT 1 +) +INSERT INTO "WorkflowTriggerScheduledRef" ( + "id", + "parentId", + "triggerAt", + "input", + "additionalMetadata" +) VALUES ( + gen_random_uuid(), + (SELECT "id" FROM latest_version), + @scheduledTrigger::timestamp, + @input::jsonb, + @additionalMetadata::jsonb +) RETURNING *; + -- name: CreateWorkflowTriggerScheduledRef :one INSERT INTO "WorkflowTriggerScheduledRef" ( "id", diff --git a/pkg/repository/prisma/dbsqlc/workflows.sql.go b/pkg/repository/prisma/dbsqlc/workflows.sql.go index c1e86113b..3eb9815dc 100644 --- a/pkg/repository/prisma/dbsqlc/workflows.sql.go +++ b/pkg/repository/prisma/dbsqlc/workflows.sql.go @@ -748,6 +748,67 @@ func (q *Queries) CreateWorkflowTriggerScheduledRef(ctx context.Context, db DBTX return &i, err } +const createWorkflowTriggerScheduledRefForWorkflow = `-- name: CreateWorkflowTriggerScheduledRefForWorkflow :one +WITH latest_version AS ( + SELECT "id" FROM "WorkflowVersion" + WHERE "workflowId" = $4::uuid + ORDER BY "order" DESC + LIMIT 1 +), +latest_trigger AS ( + SELECT "id" FROM "WorkflowTriggers" + WHERE "workflowVersionId" = (SELECT "id" FROM latest_version) + ORDER BY "createdAt" DESC + LIMIT 1 +) +INSERT INTO "WorkflowTriggerScheduledRef" ( + "id", + "parentId", + "triggerAt", + "input", + "additionalMetadata" +) VALUES ( + gen_random_uuid(), + (SELECT "id" FROM latest_version), + $1::timestamp, + $2::jsonb, + $3::jsonb +) RETURNING id, "parentId", "triggerAt", "tickerId", input, "childIndex", "childKey", "parentStepRunId", "parentWorkflowRunId", "additionalMetadata", "createdAt", "deletedAt", "updatedAt" +` + +type CreateWorkflowTriggerScheduledRefForWorkflowParams struct { + Scheduledtrigger pgtype.Timestamp `json:"scheduledtrigger"` + Input []byte `json:"input"` + Additionalmetadata []byte `json:"additionalmetadata"` + Workflowid pgtype.UUID `json:"workflowid"` +} + +func (q *Queries) CreateWorkflowTriggerScheduledRefForWorkflow(ctx context.Context, db DBTX, arg CreateWorkflowTriggerScheduledRefForWorkflowParams) (*WorkflowTriggerScheduledRef, error) { + row := db.QueryRow(ctx, createWorkflowTriggerScheduledRefForWorkflow, + arg.Scheduledtrigger, + arg.Input, + arg.Additionalmetadata, + arg.Workflowid, + ) + var i WorkflowTriggerScheduledRef + err := row.Scan( + &i.ID, + &i.ParentId, + &i.TriggerAt, + &i.TickerId, + &i.Input, + &i.ChildIndex, + &i.ChildKey, + &i.ParentStepRunId, + &i.ParentWorkflowRunId, + &i.AdditionalMetadata, + &i.CreatedAt, + &i.DeletedAt, + &i.UpdatedAt, + ) + return &i, err +} + const createWorkflowTriggers = `-- name: CreateWorkflowTriggers :one INSERT INTO "WorkflowTriggers" ( "id", diff --git a/pkg/repository/prisma/workflow.go b/pkg/repository/prisma/workflow.go index b1fda1a41..b2f508ef0 100644 --- a/pkg/repository/prisma/workflow.go +++ b/pkg/repository/prisma/workflow.go @@ -631,6 +631,51 @@ func (r *workflowEngineRepository) CreateSchedules( return r.queries.CreateSchedules(ctx, r.pool, createParams) } +func (r *workflowAPIRepository) CreateScheduledWorkflow(ctx context.Context, tenantId string, opts *repository.CreateScheduledWorkflowRunForWorkflowOpts) (*dbsqlc.ListScheduledWorkflowsRow, error) { + if err := r.v.Validate(opts); err != nil { + return nil, err + } + + var input, additionalMetadata []byte + var err error + + if opts.Input != nil { + input, err = json.Marshal(opts.Input) + } + + if opts.AdditionalMetadata != nil { + additionalMetadata, err = json.Marshal(opts.AdditionalMetadata) + } + + if err != nil { + return nil, err + } + + createParams := dbsqlc.CreateWorkflowTriggerScheduledRefForWorkflowParams{ + Workflowid: sqlchelpers.UUIDFromStr(opts.WorkflowId), + Scheduledtrigger: sqlchelpers.TimestampFromTime(opts.ScheduledTrigger), + Input: input, + Additionalmetadata: additionalMetadata, + } + + created, err := r.queries.CreateWorkflowTriggerScheduledRefForWorkflow(ctx, r.pool, createParams) + + if err != nil { + return nil, err + } + + scheduled, err := r.queries.ListScheduledWorkflows(ctx, r.pool, dbsqlc.ListScheduledWorkflowsParams{ + Tenantid: sqlchelpers.UUIDFromStr(tenantId), + Scheduleid: created.ID, + }) + + if err != nil { + return nil, err + } + + return scheduled[0], nil +} + func (r *workflowEngineRepository) GetLatestWorkflowVersions(ctx context.Context, tenantId string, workflowIds []string) ([]*dbsqlc.GetWorkflowVersionForEngineRow, error) { var workflowVersionIds = make([]pgtype.UUID, len(workflowIds)) diff --git a/pkg/repository/workflow.go b/pkg/repository/workflow.go index f7dcc581b..df9c20d9d 100644 --- a/pkg/repository/workflow.go +++ b/pkg/repository/workflow.go @@ -109,6 +109,15 @@ type CreateWorkflowSchedulesOpts struct { AdditionalMetadata []byte } +type CreateScheduledWorkflowRunForWorkflowOpts struct { + WorkflowId string `validate:"required,uuid"` + + ScheduledTrigger time.Time + + Input map[string]interface{} + AdditionalMetadata map[string]interface{} +} + type CreateWorkflowTagOpts struct { // (required) the tag name Name string `validate:"required"` @@ -290,6 +299,9 @@ type WorkflowAPIRepository interface { // DeleteCronWorkflow deletes a cron workflow run DeleteCronWorkflow(ctx context.Context, tenantId, id string) error + + // CreateScheduledWorkflow creates a scheduled workflow run + CreateScheduledWorkflow(ctx context.Context, tenantId string, opts *CreateScheduledWorkflowRunForWorkflowOpts) (*dbsqlc.ListScheduledWorkflowsRow, error) } type WorkflowEngineRepository interface { From dd20790f00fbf7f29212dd841056a6d1254d1989 Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Mon, 4 Nov 2024 17:08:00 -0500 Subject: [PATCH 28/30] wip add trigger buttons to all the pages --- .../app/src/pages/main/recurring/index.tsx | 14 +++ .../src/pages/main/scheduled-runs/index.tsx | 14 +++ .../src/pages/main/workflow-runs/index.tsx | 13 ++ .../components/trigger-workflow-form.tsx | 112 ++++++++++++++++-- .../pages/main/workflows/$workflow/index.tsx | 2 +- 5 files changed, 142 insertions(+), 13 deletions(-) diff --git a/frontend/app/src/pages/main/recurring/index.tsx b/frontend/app/src/pages/main/recurring/index.tsx index 619556595..2b5f64f22 100644 --- a/frontend/app/src/pages/main/recurring/index.tsx +++ b/frontend/app/src/pages/main/recurring/index.tsx @@ -1,13 +1,27 @@ import { Separator } from '@/components/ui/separator'; import { CronsTable } from './components/recurring-table'; +import { TriggerWorkflowForm } from '../workflows/$workflow/components/trigger-workflow-form'; +import { useState } from 'react'; +import { Button } from '@/components/ui/button'; export default function Crons() { + const [triggerWorkflow, setTriggerWorkflow] = useState(false); + return (

Cron Jobs

+ + setTriggerWorkflow(false)} + />
diff --git a/frontend/app/src/pages/main/scheduled-runs/index.tsx b/frontend/app/src/pages/main/scheduled-runs/index.tsx index 13128986d..b356178e1 100644 --- a/frontend/app/src/pages/main/scheduled-runs/index.tsx +++ b/frontend/app/src/pages/main/scheduled-runs/index.tsx @@ -1,13 +1,27 @@ import { Separator } from '@/components/ui/separator'; import { ScheduledRunsTable } from './components/scheduled-runs-table'; +import { TriggerWorkflowForm } from '../workflows/$workflow/components/trigger-workflow-form'; +import { useState } from 'react'; +import { Button } from '@/components/ui/button'; export default function RateLimits() { + const [triggerWorkflow, setTriggerWorkflow] = useState(false); + return (

Scheduled Runs

+ + setTriggerWorkflow(false)} + />
diff --git a/frontend/app/src/pages/main/workflow-runs/index.tsx b/frontend/app/src/pages/main/workflow-runs/index.tsx index 2ae335262..4321081ea 100644 --- a/frontend/app/src/pages/main/workflow-runs/index.tsx +++ b/frontend/app/src/pages/main/workflow-runs/index.tsx @@ -1,13 +1,26 @@ import { Separator } from '@/components/ui/separator'; import { WorkflowRunsTable } from './components/workflow-runs-table'; +import { Button } from '@/components/ui/button'; +import { TriggerWorkflowForm } from '../workflows/$workflow/components/trigger-workflow-form'; +import { useState } from 'react'; export default function WorkflowRuns() { + const [triggerWorkflow, setTriggerWorkflow] = useState(false); + return (

Workflow Runs

+ + setTriggerWorkflow(false)} + />
diff --git a/frontend/app/src/pages/main/workflows/$workflow/components/trigger-workflow-form.tsx b/frontend/app/src/pages/main/workflows/$workflow/components/trigger-workflow-form.tsx index 47b2d00a2..3ac2899fe 100644 --- a/frontend/app/src/pages/main/workflows/$workflow/components/trigger-workflow-form.tsx +++ b/frontend/app/src/pages/main/workflows/$workflow/components/trigger-workflow-form.tsx @@ -7,6 +7,7 @@ import { } from '@/components/ui/dialog'; import api, { CronWorkflows, + queries, ScheduledWorkflows, Workflow, WorkflowRun, @@ -15,7 +16,7 @@ import { useMemo, useState } from 'react'; import { Button } from '@/components/ui/button'; import invariant from 'tiny-invariant'; import { useApiError } from '@/lib/hooks'; -import { useMutation } from '@tanstack/react-query'; +import { useMutation, useQuery } from '@tanstack/react-query'; import { PlusIcon } from '@heroicons/react/24/outline'; import { cn } from '@/lib/utils'; import { useNavigate, useOutletContext } from 'react-router-dom'; @@ -26,14 +27,18 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import CronPrettifier from 'cronstrue'; import { DateTimePicker } from '@/components/molecules/time-picker/date-time-picker'; +type TimingOption = 'now' | 'schedule' | 'cron'; + export function TriggerWorkflowForm({ - workflow, + defaultWorkflow, show, onClose, + defaultTimingOption = 'now', }: { - workflow: Workflow; + defaultWorkflow?: Workflow; show: boolean; onClose: () => void; + defaultTimingOption?: TimingOption; }) { const { tenant } = useOutletContext(); invariant(tenant); @@ -44,9 +49,8 @@ export function TriggerWorkflowForm({ const [addlMeta, setAddlMeta] = useState('{}'); const [errors, setErrors] = useState([]); - const [timingOption, setTimingOption] = useState<'now' | 'schedule' | 'cron'>( - 'now', - ); + const [timingOption, setTimingOption] = + useState(defaultTimingOption); const [scheduleTime, setScheduleTime] = useState( new Date(), ); @@ -67,6 +71,24 @@ export function TriggerWorkflowForm({ setErrors, }); + const { + data: workflowKeys, + isLoading: workflowKeysIsLoading, + error: workflowKeysError, + } = useQuery({ + ...queries.workflows.list(tenant.metadata.id), + }); + + const workflow = useMemo(() => { + if (!defaultWorkflow) { + return (workflowKeys?.rows || [])[0]; + } + + return workflowKeys?.rows?.find( + (w) => w.metadata.id === defaultWorkflow?.metadata.id, + ); + }, [workflowKeys, defaultWorkflow]); + const triggerNowMutation = useMutation({ mutationKey: ['workflow-run:create', workflow?.metadata.id], mutationFn: async (data: { input: object; addlMeta: object }) => { @@ -211,7 +233,7 @@ export function TriggerWorkflowForm({ > - Trigger this workflow + Trigger {workflow?.name} You can change the input to your workflow here. @@ -247,11 +269,77 @@ export function TriggerWorkflowForm({
Select Date and Time
- +
+ + +
+
+ + + + + +
diff --git a/frontend/app/src/pages/main/workflows/$workflow/index.tsx b/frontend/app/src/pages/main/workflows/$workflow/index.tsx index 7b3389280..0d95b1190 100644 --- a/frontend/app/src/pages/main/workflows/$workflow/index.tsx +++ b/frontend/app/src/pages/main/workflows/$workflow/index.tsx @@ -171,7 +171,7 @@ export default function ExpandedWorkflow() {
setTriggerWorkflow(false)} />
From 3bd1b236a9e2c6a7ebe5b206dc061750745a5a8d Mon Sep 17 00:00:00 2001 From: gabriel ruttner Date: Mon, 4 Nov 2024 17:19:19 -0500 Subject: [PATCH 29/30] wip: reusable trigger form --- .../src/pages/main/workers/webhooks/index.tsx | 2 +- .../components/trigger-workflow-form.tsx | 67 ++++++++++++++++--- 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/frontend/app/src/pages/main/workers/webhooks/index.tsx b/frontend/app/src/pages/main/workers/webhooks/index.tsx index b5588946f..84e765948 100644 --- a/frontend/app/src/pages/main/workers/webhooks/index.tsx +++ b/frontend/app/src/pages/main/workers/webhooks/index.tsx @@ -74,7 +74,7 @@ export default function Webhooks() { {worker.name} - + + + + {workflowKeysIsLoading && ( + Loading workflows... + )} + {workflowKeysError && ( + + Error loading workflows + + )} + {workflowKeys?.rows?.map((w) => ( + setSelectedWorkflowId(w.metadata.id)} + > + {w.name} + + ))} + + +
Input
Date: Fri, 8 Nov 2024 12:18:40 -0500 Subject: [PATCH 30/30] fix: hash --- sql/migrations/atlas.sum | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sql/migrations/atlas.sum b/sql/migrations/atlas.sum index 316166001..b8cd6e06d 100644 --- a/sql/migrations/atlas.sum +++ b/sql/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:1+kD2Z/AiXWbeuM4UBpvslzVJmdhDxyLXInlAEOhY8U= +h1:1vMj0p3TGNHFWD3my+BQNZsHWFL/8Ur/EYUncIPbk08= 20240115180414_init.sql h1:Ef3ZyjAHkmJPdGF/dEWCahbwgcg6uGJKnDxW2JCRi2k= 20240122014727_v0_6_0.sql h1:o/LdlteAeFgoHJ3e/M4Xnghqt9826IE/Y/h0q95Acuo= 20240126235456_v0_7_0.sql h1:KiVzt/hXgQ6esbdC6OMJOOWuYEXmy1yeCpmsVAHTFKs= @@ -73,4 +73,9 @@ h1:1+kD2Z/AiXWbeuM4UBpvslzVJmdhDxyLXInlAEOhY8U= 20241023223039_v0.50.4.sql h1:eXJLlkM6ZzqzZ4RbAZtoTiW7WjJPIJ5L6UkIKy6w9Uk= 20241025162439_v0.50.5.sql h1:CIv/oSeiVR1D3rOb4z8uv2t0XUI62TyK+0UI0s6tQ/k= 20241029122625_v0.51.0.sql h1:nOa4FqmZxSh1yBOJyduX+j15gQavjizTn660wyXjhNk= -20241107162939_v0.51.2.sql h1:qtnUITelb0kzAazo99gdTzejmQeOiE8NTP8b8bpQuF0= +20241030131347_tmp.sql h1:48ydfY8fUk6nR6Av35gk57TfBbrwYYLwjtTAKch1TBg= +20241030133048_tmp.sql h1:dWSeXAsgIbUo1yCrxM6p/a2mPPDMfMP2j4s+R0ADZjE= +20241030150116_tmp.sql h1:LUy5JzLfjjUEO8cnUco26jKbqkdC7yIHAJ5xx2XLVqE= +20241030150342_tmp.sql h1:bDLmpmjBtYckGAIOhn7YRgEK32BLXGHA9sravMY135k= +20241104202826_tmp.sql h1:sCDs68edZmeRw0+NSSaBUS+k273WTaT7DrSKjER6tww= +20241107162939_v0.51.2.sql h1:PbfbTcggw9x6EAhOHuAiXuk0NCLXfWPZWpp4mXyCApc=