diff --git a/frontend/src/lib/components/apps/components/buttons/AppButton.svelte b/frontend/src/lib/components/apps/components/buttons/AppButton.svelte index 51ae40c21a..946a15c0f7 100644 --- a/frontend/src/lib/components/apps/components/buttons/AppButton.svelte +++ b/frontend/src/lib/components/apps/components/buttons/AppButton.svelte @@ -78,7 +78,8 @@ let outputs = initOutput($worldStore, id, { result: undefined, loading: false, - jobId: undefined + jobId: undefined, + submitted: undefined }) if (controls) { @@ -197,6 +198,21 @@ $effect.pre(() => { resolvedConfig.afterIcon && afterIconComponent && untrack(() => handleAfterIcon()) }) + let hasTriggeredBackgroundSuccess = $state(false) + + $effect(() => { + // For background jobs, trigger success handler immediately when job is submitted + if (resolvedConfig.runInBackground && outputs.submitted?.peak() === true && !hasTriggeredBackgroundSuccess) { + hasTriggeredBackgroundSuccess = true + untrack(() => { + runnableWrapper?.handleSideEffect(true) + }) + } + // Reset the flag when submitted becomes undefined (new run) + if (outputs.submitted?.peak() === undefined) { + hasTriggeredBackgroundSuccess = false + } + }) let errorsMessage = $derived( Object.values(errors) .filter((x) => x != '') @@ -244,6 +260,7 @@ {outputs} {extraKey} allowConcurentRequests={resolvedConfig.runInBackground} + skipSideEffectOnSuccess={resolvedConfig.runInBackground} onSuccess={(r) => { let inputOutput = { result: r, loading: false } if (rowContext && rowInputs) { diff --git a/frontend/src/lib/components/apps/components/helpers/RunnableComponent.svelte b/frontend/src/lib/components/apps/components/helpers/RunnableComponent.svelte index 261bf922fe..64d657815a 100644 --- a/frontend/src/lib/components/apps/components/helpers/RunnableComponent.svelte +++ b/frontend/src/lib/components/apps/components/helpers/RunnableComponent.svelte @@ -47,6 +47,7 @@ result: Output loading: Output jobId?: Output | undefined + submitted?: Output | undefined } extraKey?: string initializing?: boolean @@ -176,6 +177,7 @@ console.log('started', id) loading = true outputs.jobId?.set(id) + outputs.submitted?.set(true) dispatch('started', id) }, doneWithoutCompute(r: any) { @@ -349,6 +351,9 @@ dynamicArgsOverride?: Record, callbacks?: RunnableCallback ): Promise { + // Reset submitted flag for new execution + outputs.submitted?.set(undefined) + let jobId: string | undefined console.debug(`Executing ${id}`) if (iterContext && $iterContext.disabled) { diff --git a/frontend/src/lib/components/apps/components/helpers/RunnableWrapper.svelte b/frontend/src/lib/components/apps/components/helpers/RunnableWrapper.svelte index 2874422d2f..138c77e2b7 100644 --- a/frontend/src/lib/components/apps/components/helpers/RunnableWrapper.svelte +++ b/frontend/src/lib/components/apps/components/helpers/RunnableWrapper.svelte @@ -83,11 +83,13 @@ result: Output loading: Output jobId?: Output | undefined + submitted?: Output | undefined } extraKey?: string | undefined refreshOnStart?: boolean errorHandledByComponent?: boolean allowConcurentRequests?: boolean + skipSideEffectOnSuccess?: boolean onSuccess?: (result: any) => void children?: import('svelte').Snippet nonRenderedPlaceholder?: import('svelte').Snippet @@ -120,6 +122,7 @@ refreshOnStart = false, errorHandledByComponent = false, allowConcurentRequests = false, + skipSideEffectOnSuccess = false, onSuccess = () => {}, children, nonRenderedPlaceholder @@ -355,7 +358,9 @@ }} on:success={(e) => { onSuccess(e.detail) - handleSideEffect(true) + if (!skipSideEffectOnSuccess) { + handleSideEffect(true) + } }} on:handleError={(e) => handleSideEffect(false, e.detail)} {outputs}