feat: perpetual scripts

This commit is contained in:
Ruben Fiszel
2023-12-04 19:46:43 +01:00
parent df865380bc
commit bea0da3d6f
8 changed files with 127 additions and 10 deletions
@@ -0,0 +1,23 @@
{
"db_name": "PostgreSQL",
"query": "SELECT restart_unless_cancelled FROM script WHERE hash = $1 AND workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "restart_unless_cancelled",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Int8",
"Text"
]
},
"nullable": [
true
]
},
"hash": "1d27895aa42ccbb542479b19baefd62790205b529ab0d8af36f18c470e8bb838"
}
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO script (workspace_id, hash, path, parent_hashes, summary, description, content, created_by, schema, is_template, extra_perms, lock, language, kind, tag, draft_only, envs, concurrent_limit, concurrency_time_window_s, cache_ttl, dedicated_worker, ws_error_handler_muted, priority) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9::text::json, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23)",
"query": "INSERT INTO script (workspace_id, hash, path, parent_hashes, summary, description, content, created_by, schema, is_template, extra_perms, lock, language, kind, tag, draft_only, envs, concurrent_limit, concurrency_time_window_s, cache_ttl, dedicated_worker, ws_error_handler_muted, priority, restart_unless_cancelled) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9::text::json, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24)",
"describe": {
"columns": [],
"parameters": {
@@ -61,10 +61,11 @@
"Int4",
"Bool",
"Bool",
"Int2"
"Int2",
"Bool"
]
},
"nullable": []
},
"hash": "52ad1773a9f5a1b6be1bb16af408f051f27d3f21b615c468b85aa75b64d943db"
"hash": "cc916f88edb1ac791cdfb24c37691db9048e7d921a628a1ff5b71fead1de5e3a"
}
@@ -2,4 +2,4 @@
ALTER TABLE script ADD COLUMN timeout INTEGER;
ALTER TABLE flow ADD COLUMN timeout INTEGER;
ALTER TABLE script ADD COLUMN delete_after_use BOOLEAN;
ALTER TABLE script ADD COLUMN restart_unless_cancelled SMALLINT;
ALTER TABLE script ADD COLUMN restart_unless_cancelled BOOLEAN;
+3 -2
View File
@@ -465,8 +465,8 @@ async fn create_script(
"INSERT INTO script (workspace_id, hash, path, parent_hashes, summary, description, \
content, created_by, schema, is_template, extra_perms, lock, language, kind, tag, \
draft_only, envs, concurrent_limit, concurrency_time_window_s, cache_ttl, \
dedicated_worker, ws_error_handler_muted, priority) \
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9::text::json, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23)",
dedicated_worker, ws_error_handler_muted, priority, restart_unless_cancelled) \
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9::text::json, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24)",
&w_id,
&hash.0,
ns.path,
@@ -490,6 +490,7 @@ async fn create_script(
ns.dedicated_worker,
ns.ws_error_handler_muted.unwrap_or(false),
ns.priority,
ns.restart_unless_cancelled
)
.execute(&mut tx)
.await?;
+57
View File
@@ -559,6 +559,63 @@ pub async fn add_completed_job<
}
}
if !queued_job.is_flow_step && queued_job.job_kind == JobKind::Script && canceled_by.is_none() {
if let Some(hash) = queued_job.script_hash {
let p = sqlx::query_scalar!(
"SELECT restart_unless_cancelled FROM script WHERE hash = $1 AND workspace_id = $2",
hash.0,
&queued_job.workspace_id
)
.fetch_optional(db)
.await?
.flatten()
.unwrap_or(false);
if p {
let tx = PushIsolationLevel::IsolatedRoot(db.clone(), rsmq);
let (_uuid, tx) = push(
db,
tx,
&queued_job.workspace_id,
JobPayload::ScriptHash {
hash,
path: queued_job.script_path().to_string(),
concurrent_limit: queued_job.concurrent_limit,
concurrency_time_window_s: queued_job.concurrency_time_window_s,
cache_ttl: queued_job.cache_ttl,
dedicated_worker: None,
language: queued_job
.language
.clone()
.unwrap_or_else(|| ScriptLang::Deno),
priority: queued_job.priority,
},
queued_job.args.clone(),
&queued_job.created_by,
&queued_job.email,
queued_job.permissioned_as.clone(),
None,
queued_job.schedule_path.clone(),
None,
None,
None,
false,
false,
None,
queued_job.visible_to_owner,
Some(queued_job.tag.clone()),
queued_job.timeout,
None,
queued_job.priority,
)
.await?;
if let Err(e) = tx.commit().await {
tracing::error!("Could not restart job {}: {}", queued_job.id, e);
}
}
}
}
// tracing::error!("4 {:?}", start.elapsed());
Ok(queued_job.id)
@@ -210,7 +210,8 @@
concurrency_time_window_s: script.concurrency_time_window_s,
cache_ttl: script.cache_ttl,
ws_error_handler_muted: script.ws_error_handler_muted,
priority: script.priority
priority: script.priority,
restart_unless_cancelled: script.restart_unless_cancelled
}
})
savedScript = cloneDeep(script) as NewScriptWithDraft
@@ -643,6 +644,24 @@
{/if}
</div>
</Section>
<Section label="Perpetual Script">
<div class="flex gap-2 shrink flex-col">
<Toggle
size="sm"
checked={Boolean(script.restart_unless_cancelled)}
on:change={() => {
if (script.restart_unless_cancelled) {
script.restart_unless_cancelled = undefined
} else {
script.restart_unless_cancelled = true
}
}}
options={{
right: 'Restart upon ending unless cancelled'
}}
/>
</div>
</Section>
<Section label="Dedicated Workers" eeOnly>
<Toggle
disabled={!$enterpriseLicense ||
@@ -682,7 +701,7 @@
</svelte:fragment>
</Section>
{#if !isCloudHosted()}
<Section label="High priority script">
<Section label="High priority script" eeOnly>
<Toggle
disabled={!$enterpriseLicense || isCloudHosted()}
size="sm"
@@ -64,7 +64,6 @@ const display: ComponentSet = {
'displaycomponent',
'jobidlogcomponent',
'jobidflowstatuscomponent',
'customcomponent',
'statcomponent',
'menucomponent'
]
@@ -20,7 +20,8 @@
superadmin,
usageStore,
userStore,
workspaceStore
workspaceStore,
type UserExt
} from '$lib/stores'
import CenteredModal from '$lib/components/CenteredModal.svelte'
import { afterNavigate, beforeNavigate, goto } from '$app/navigation'
@@ -168,6 +169,22 @@
}
let devOnly = $page.url.pathname.startsWith('/scripts/dev')
$: onUserStore($userStore)
let timeout: NodeJS.Timeout | undefined
async function onUserStore(u: UserExt | undefined) {
if (u && timeout) {
clearTimeout(timeout)
timeout = undefined
} else if (!u) {
timeout = setTimeout(async () => {
if (!$userStore && $workspaceStore) {
$userStore = await getUserExt($workspaceStore)
}
}, 5000)
}
}
</script>
<svelte:window bind:innerWidth />