fix: fix cyclical loop in apps

This commit is contained in:
Ruben Fiszel
2023-08-30 17:12:55 +02:00
parent a002b242fc
commit 61df339343
7 changed files with 128 additions and 94 deletions
+17 -17
View File
@@ -511,26 +511,26 @@ pub async fn run_worker<R: rsmq_async::RsmqConnection + Send + Sync + Clone + 's
(copy_cache_from_bucket_handle.is_none() || copy_cache_from_bucket_handle.as_ref().unwrap().is_finished()) {
last_sync = Instant::now();
if (crate::global_cache::worker_s3_bucket_sync_enabled(&db).await) {
if crate::global_cache::worker_s3_bucket_sync_enabled(&db).await {
tracing::debug!("CAN PULL LOCK START");
let _lock = CAN_PULL.write().await;
tracing::debug!("CAN PULL LOCK START");
let _lock = CAN_PULL.write().await;
tracing::info!("Started syncing cache");
// if num_workers > 1 {
// create_barrier_for_all_workers(num_workers, sync_barrier.clone()).await;
// }
if let Err(e) = copy_cache_to_tmp_cache().await {
tracing::error!("failed to copy cache to tmp cache: {}", e);
} else {
copy_cache_from_bucket_handle = Some(tokio::task::spawn(async move {
if let Some(ref s) = S3_CACHE_BUCKET.clone() {
if let Err(e) = cache_global(s, copy_tx).await {
tracing::error!("failed to sync cache: {}", e);
tracing::info!("Started syncing cache");
// if num_workers > 1 {
// create_barrier_for_all_workers(num_workers, sync_barrier.clone()).await;
// }
if let Err(e) = copy_cache_to_tmp_cache().await {
tracing::error!("failed to copy cache to tmp cache: {}", e);
} else {
copy_cache_from_bucket_handle = Some(tokio::task::spawn(async move {
if let Some(ref s) = S3_CACHE_BUCKET.clone() {
if let Err(e) = cache_global(s, copy_tx).await {
tracing::error!("failed to sync cache: {}", e);
}
}
}
}));
}
}));
}
}
}
}
@@ -77,8 +77,11 @@
const debounce_ms = 50
export async function computeExpr() {
value = await evalExpr(lastInput as EvalAppInput)
return value
const nvalue = await evalExpr(lastInput as EvalAppInput)
if (!deepEqual(nvalue, value)) {
value = nvalue
}
return nvalue
}
function debounce(cb: () => Promise<void>) {
@@ -423,6 +423,7 @@
let p: Partial<CancelablePromise<void>> = new Promise<void>((resolve, reject) => {
rejectCb = reject
donePromise = resolve
executeComponent(true, inlineScript).catch(reject)
})
p.cancel = () => {
@@ -0,0 +1,53 @@
<script lang="ts">
import Toggle from '$lib/components/Toggle.svelte'
import { Button, Popup, SecondsInput } from '$lib/components/common'
import { autoPlacement } from '@floating-ui/core'
export let cache_ttl: number | undefined
</script>
<Popup
floatingConfig={{
middleware: [
autoPlacement({
allowedPlacements: ['bottom-start', 'bottom-end', 'top-start', 'top-end', 'top', 'bottom']
})
]
}}
>
<svelte:fragment slot="button">
<Button
nonCaptureEvent={true}
btnClasses={Boolean(cache_ttl)
? 'bg-blue-100 text-blue-800 border border-blue-300 hover:bg-blue-200 dark:bg-frost-700 dark:text-frost-100 dark:border-frost-600'
: 'bg-surface text-primay hover:bg-hover'}
color="light"
variant="border"
size="xs">Cache</Button
>
</svelte:fragment>
<div class="block text-primary">
<Toggle
checked={Boolean(cache_ttl)}
on:change={() => {
if (cache_ttl != undefined) {
cache_ttl = undefined
} else {
cache_ttl = 600
}
}}
options={{
right: 'Cache the results for each possible inputs'
}}
/>
<div class="mb-4">
<span class="text-xs font-bold">How long to keep cache valid</span>
{#if cache_ttl}
<SecondsInput bind:seconds={cache_ttl} />
{:else}
<SecondsInput disabled />
{/if}
</div>
</div>
</Popup>
@@ -20,10 +20,8 @@
import { scriptLangToEditorLang } from '$lib/scripts'
import ScriptGen from '$lib/components/codeGen/ScriptGen.svelte'
import DiffEditor from '$lib/components/DiffEditor.svelte'
import { autoPlacement } from '@floating-ui/core'
import { Popup, SecondsInput } from '$lib/components/common'
import Toggle from '$lib/components/Toggle.svelte'
import { userStore } from '$lib/stores'
import CacheTtlPopup from './CacheTtlPopup.svelte'
let inlineScriptEditorDrawer: InlineScriptEditorDrawer
@@ -190,60 +188,7 @@
<Badge color="red" baseClass="!text-2xs">Invalid</Badge>
{/if}
{#if inlineScript}
<Popup
floatingConfig={{
middleware: [
autoPlacement({
allowedPlacements: [
'bottom-start',
'bottom-end',
'top-start',
'top-end',
'top',
'bottom'
]
})
]
}}
>
<svelte:fragment slot="button">
<Button
nonCaptureEvent={true}
btnClasses={Boolean(inlineScript.cache_ttl)
? 'bg-blue-100 text-blue-800 border border-blue-300 hover:bg-blue-200 dark:bg-frost-700 dark:text-frost-100 dark:border-frost-600'
: 'bg-surface text-primay hover:bg-hover'}
color="light"
variant="border"
size="xs">Cache</Button
>
</svelte:fragment>
<div class="block text-primary">
<Toggle
checked={Boolean(inlineScript.cache_ttl)}
on:change={() => {
if (inlineScript) {
if (inlineScript.cache_ttl != undefined) {
inlineScript.cache_ttl = undefined
} else {
inlineScript.cache_ttl = 600
}
}
}}
options={{
right: 'Cache the results for each possible inputs'
}}
/>
<div class="mb-4">
<span class="text-xs font-bold">How long to keep cache valid</span>
{#if inlineScript.cache_ttl}
<SecondsInput bind:seconds={inlineScript.cache_ttl} />
{:else}
<SecondsInput disabled />
{/if}
</div>
</div>
</Popup>
<CacheTtlPopup bind:cache_ttl={inlineScript.cache_ttl} />
{/if}
<ScriptGen
lang={inlineScript?.language}
@@ -37,22 +37,33 @@
let drawerFlowViewer: Drawer
let flowPath: string = ''
let notFound = false
const dispatch = createEventDispatcher()
async function refreshScript(x: RunnableByPath) {
let { schema } = await getScriptByPath(x.path)
if (!deepEqual(x.schema, schema)) {
x.schema = schema
fields = computeFields(schema, false, fields)
try {
let { schema } = await getScriptByPath(x.path)
if (!deepEqual(x.schema, schema)) {
x.schema = schema
fields = computeFields(schema, false, fields)
}
} catch (e) {
notFound = true
console.error(e)
}
}
async function refreshFlow(x: RunnableByPath) {
const { schema } = (await loadSchema($workspaceStore ?? '', x.path, 'flow')) ?? emptySchema()
if (!deepEqual(x.schema, schema)) {
x.schema = schema
fields = computeFields(schema, false, fields)
try {
const { schema } = (await loadSchema($workspaceStore ?? '', x.path, 'flow')) ?? emptySchema()
if (!deepEqual(x.schema, schema)) {
x.schema = schema
fields = computeFields(schema, false, fields)
}
} catch (e) {
notFound = true
console.error(e)
}
}
@@ -74,14 +85,20 @@
})
}
function refresh() {
let lastRunnable: RunnableByPath | undefined = undefined
function refresh(runnable) {
if (deepEqual(runnable, lastRunnable)) {
return
}
notFound = false
if (runnable.runType == 'script') {
refreshScript(runnable)
} else if (runnable.runType == 'flow') {
refreshFlow(runnable)
}
lastRunnable = runnable
}
$: runnable.runType && refresh()
$: refresh(runnable)
</script>
<Drawer bind:this={drawerFlowViewer} size="1200px">
@@ -100,7 +117,7 @@
startIcon={{ icon: faRefresh }}
on:click={async () => {
sendUserToast('Refreshing inputs')
refresh()
refresh(runnable)
$stateId = $stateId + 1
await tick()
}}
@@ -169,7 +186,11 @@
</div>
<div class="w-full">
{#key $stateId}
{#if runnable.runType == 'script' || runnable.runType == 'hubscript'}
{#if notFound}
<div class="text-red-400"
>{runnable.runType} not found at {runnable.path} in workspace {$workspaceStore}</div
>
{:else if runnable.runType == 'script' || runnable.runType == 'hubscript'}
<div class="border">
<FlowModuleScript path={runnable.path} />
</div>
@@ -11,17 +11,28 @@
let code: string
let language: SupportedLanguage
let notFound = false
async function loadCode(path: string, hash: string | undefined) {
const script = hash
? await ScriptService.getScriptByHash({ workspace: $workspaceStore!, hash })
: await getScriptByPath(path!)
code = script.content
language = script.language
try {
notFound = false
const script = hash
? await ScriptService.getScriptByHash({ workspace: $workspaceStore!, hash })
: await getScriptByPath(path!)
code = script.content
language = script.language
} catch (e) {
notFound = true
console.error(e)
}
}
$: path && loadCode(path, hash)
</script>
<div class="flex flex-col flex-1 h-full overflow-auto p-2">
<HighlightCode {language} {code} />
{#if notFound}
<div class="text-red-400">script not found at {path} in workspace {$workspaceStore}</div>
{:else}
<HighlightCode {language} {code} />
{/if}
</div>