Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add create run on cron trigger option #2892

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions lib/lightning_web/live/job_live/cron_run_component.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
defmodule LightningWeb.JobLive.CronRunButton do
@moduledoc """
Displays and manages cron runs in a form.
"""
use LightningWeb, :live_component

import Ecto.Query

alias Lightning.Repo
alias Lightning.Run
alias Lightning.WorkOrder

require Run

@impl true
def render(assigns) do
~H"""
<div id="run-buttons" class="inline-flex shadow-sm">
<div>
<.button
id={@id}
phx-target={@myself}
phx-click={@selected_option}
phx-hook="DefaultRunViaCtrlEnter"
class={cron_trigger_bt_classes(assigns)}
disabled={@disabled}
>
<%= if processing(@follow_run) do %>
<.icon name="hero-arrow-path" class="w-4 h-4 animate-spin mr-1" />
Processing
<% else %>
<.icon name="hero-play-mini" class="w-4 h-4 mr-1" /> <%= button_text(
@selected_option
) %>
<% end %>
</.button>
</div>
</div>
"""
end

@impl true
def update(
%{follow_run: follow_run} = assigns,
socket
) do
snapshot_version_tag = "latest"
disabled = processing(follow_run) or snapshot_version_tag != "latest"

{:ok,
socket
|> assign(assigns)
|> assign(
disabled: disabled,
follow_run: nil,
selected_option: "clear_and_run"
)}
end

@impl true
def handle_event("clear_and_run", _params, socket) do
cron_trigger =
Enum.find(socket.assigns.workflow.triggers, &(&1.type == :cron))

dataclip_id =
Repo.one(
from(wo in WorkOrder,
where: wo.trigger_id == ^cron_trigger.id,
select: wo.dataclip_id,
limit: 1,
order_by: [desc: :inserted_at]
)
)

send(
self(),
{__MODULE__, "cron_trigger_manual_run", %{dataclip_id: dataclip_id}}
)

{:noreply, socket}
end

# @impl true
# def handle_info(
# %RunUpdated{run: run},
# %{assigns: %{follow_run: %{id: follow_run_id}}} = socket
# )
# when run.id === follow_run_id do
# {:noreply,
# socket
# |> assign(follow_run: run)}
# end

defp cron_trigger_bt_classes(_assigns) do
["relative inline-flex"]
end

def button_text(selected) do
case selected do
"clear_and_run" -> "Run now"
"run_last_state" -> "Run with last state"
"run_custom_state" -> "Run with custom state"
end
end

defp processing(%{state: state}), do: state not in Run.final_states()
defp processing(_run), do: false
end
179 changes: 104 additions & 75 deletions lib/lightning_web/live/workflow_live/edit.ex
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ defmodule LightningWeb.WorkflowLive.Edit do
/>
<:footer>
<div class="flex flex-row">
<div class="flex items-center">
<div class={["grow", @show_cron_run_button && "mt-2"]}>
<.input
type="toggle"
field={tf[:enabled]}
Expand All @@ -562,6 +562,15 @@ defmodule LightningWeb.WorkflowLive.Edit do
label="Enabled"
/>
</div>
<div :if={@show_cron_run_button}>
<.live_component
id="cron-run-button"
module={LightningWeb.JobLive.CronRunButton}
workflow={@workflow}
follow_run={@follow_run}
snapshot_version_tag={@snapshot_version_tag}
/>
</div>
</div>
</:footer>
</.panel>
Expand Down Expand Up @@ -1114,6 +1123,7 @@ defmodule LightningWeb.WorkflowLive.Edit do
selected_job: nil,
selected_run: nil,
selected_trigger: nil,
show_cron_run_button: false,
selection_mode: nil,
query_params: %{
"s" => nil,
Expand Down Expand Up @@ -1663,80 +1673,7 @@ defmodule LightningWeb.WorkflowLive.Edit do
# The manual_run_submit event is for create a new work order from a dataclip and
# a job.
def handle_event("manual_run_submit", params, socket) do
%{
project: project,
selected_job: selected_job,
current_user: current_user,
workflow_params: workflow_params,
has_presence_edit_priority: has_presence_edit_priority,
workflow: workflow,
manual_run_form: form
} = socket.assigns

manual_params = Map.get(params, "manual", %{})

params =
case form do
nil -> manual_params
%{params: form_params} -> Map.merge(form_params, manual_params)
end

socket = socket |> apply_params(workflow_params, :workflow)

workflow_or_changeset =
if has_presence_edit_priority do
socket.assigns.changeset
else
get_workflow_by_id(workflow.id)
end

with :ok <- check_user_can_manual_run_workflow(socket) do
case Helpers.run_workflow(
workflow_or_changeset,
params,
project: project,
selected_job: selected_job,
created_by: current_user
) do
{:ok, %{workorder: workorder, workflow: workflow}} ->
%{runs: [run]} = workorder

Runs.subscribe(run)

snapshot = snapshot_by_version(workflow.id, workflow.lock_version)

{:noreply,
socket
|> assign_workflow(workflow, snapshot)
|> follow_run(run)
|> push_event("push-hash", %{"hash" => "log"})}

{:error, %Ecto.Changeset{data: %WorkOrders.Manual{}} = changeset} ->
{:noreply,
socket
|> assign_manual_run_form(changeset)}

{:error, %Ecto.Changeset{data: %Workflow{}} = changeset} ->
{
:noreply,
socket
|> assign_changeset(changeset)
|> mark_validated()
|> put_flash(:error, "Workflow could not be saved")
}

{:error, %{text: message}} ->
{:noreply, put_flash(socket, :error, message)}

{:error, :workflow_deleted} ->
{:noreply,
put_flash(
socket,
:error,
"Oops! You cannot modify a deleted workflow"
)}
end
end
handle_manual_run_submit(socket, params)
end

def handle_event("toggle_workflow_state", %{"workflow_state" => state}, socket) do
Expand Down Expand Up @@ -1793,6 +1730,15 @@ defmodule LightningWeb.WorkflowLive.Edit do
end
end

def handle_info(
{LightningWeb.JobLive.CronRunButton, "cron_trigger_manual_run",
dataclip_id},
socket
) do
params = %{"manual" => %{"dataclip_id" => dataclip_id}}
handle_manual_run_submit(socket, params)
end

def handle_info({"form_changed", %{"workflow" => params}}, socket) do
{:noreply, handle_new_params(socket, params, :workflow)}
end
Expand Down Expand Up @@ -2156,6 +2102,10 @@ defmodule LightningWeb.WorkflowLive.Edit do
WorkflowParams.apply_form_params(socket.assigns.workflow_params, params)

socket
|> assign(
:show_cron_run_button,
get_in(params, ["triggers", "0", "type"]) == "cron"
)
|> apply_params(next_params, type)
|> mark_validated()
|> push_patches_applied(initial_params)
Expand Down Expand Up @@ -2626,4 +2576,83 @@ defmodule LightningWeb.WorkflowLive.Edit do
end

defp loaded?(%Workflow{} = workflow), do: workflow.__meta__.state == :loaded

defp handle_manual_run_submit(socket, params) do
IO.inspect(params)

%{
project: project,
selected_job: selected_job,
current_user: current_user,
workflow_params: workflow_params,
has_presence_edit_priority: has_presence_edit_priority,
workflow: workflow,
manual_run_form: form
} = socket.assigns

manual_params = Map.get(params, "manual", %{})

params =
case form do
nil -> manual_params
%{params: form_params} -> Map.merge(form_params, manual_params)
end

socket = socket |> apply_params(workflow_params, :workflow)

workflow_or_changeset =
if has_presence_edit_priority do
socket.assigns.changeset
else
get_workflow_by_id(workflow.id)
end

with :ok <- check_user_can_manual_run_workflow(socket) do
case Helpers.run_workflow(
workflow_or_changeset,
params,
project: project,
selected_job: selected_job,
created_by: current_user
) do
{:ok, %{workorder: workorder, workflow: workflow}} ->
%{runs: [run]} = workorder

Runs.subscribe(run)

snapshot = snapshot_by_version(workflow.id, workflow.lock_version)

{:noreply,
socket
|> assign_workflow(workflow, snapshot)
|> follow_run(run)
|> push_event("push-hash", %{"hash" => "log"})}

{:error, %Ecto.Changeset{data: %WorkOrders.Manual{}} = changeset} ->
{:noreply,
socket
|> assign_manual_run_form(changeset)}

{:error, %Ecto.Changeset{data: %Workflow{}} = changeset} ->
{
:noreply,
socket
|> assign_changeset(changeset)
|> mark_validated()
|> put_flash(:error, "Workflow could not be saved")
}

{:error, %{text: message}} ->
{:noreply, put_flash(socket, :error, message)}

{:error, :workflow_deleted} ->
{:noreply,
put_flash(
socket,
:error,
"Oops! You cannot modify a deleted workflow"
)}
end
end
end
end