feat: Tag override for scheduled scripts (#2998)

* feat: Tag override for scheduled scripts

* Refactor WorkerTagPicker to component

* Fix test
This commit is contained in:
Guillaume Bouvignies
2024-01-13 00:06:54 +01:00
committed by GitHub
parent 22f502d2a8
commit 2edba18038
32 changed files with 231 additions and 168 deletions
@@ -125,6 +125,11 @@
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
},
{
"ordinal": 25,
"name": "jobs",
"type_info": "JsonArray"
}
@@ -161,6 +166,7 @@
true,
true,
false,
true,
null
]
},
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO schedule (workspace_id, path, schedule, timezone, edited_by, script_path, is_flow, args, enabled, email, on_failure, on_failure_times, on_failure_exact, on_failure_extra_args, on_recovery, on_recovery_times, on_recovery_extra_args, ws_error_handler_muted, retry, summary, no_flow_overlap ) VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21 ) RETURNING *",
"query": "INSERT INTO schedule (workspace_id, path, schedule, timezone, edited_by, script_path, is_flow, args, enabled, email, on_failure, on_failure_times, on_failure_exact, on_failure_extra_args, on_recovery, on_recovery_times, on_recovery_extra_args, ws_error_handler_muted, retry, summary, no_flow_overlap, tag ) VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22 ) RETURNING *",
"describe": {
"columns": [
{
@@ -122,6 +122,11 @@
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
@@ -146,7 +151,8 @@
"Bool",
"Jsonb",
"Varchar",
"Bool"
"Bool",
"Varchar"
]
},
"nullable": [
@@ -173,8 +179,9 @@
false,
true,
true,
false
false,
true
]
},
"hash": "6bb9e6cab7034bf28ef2597445dc617b60c49b42568fdb975cf2d2dc8702167e"
"hash": "597335a4a1eda7799303e0d930b5468af2364f5d2075aab48787b93e5774336d"
}
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE schedule SET schedule = $1, timezone = $2, args = $3, on_failure = $4, on_failure_times = $5, on_failure_exact = $6, on_failure_extra_args = $7, on_recovery = $8, on_recovery_times = $9, on_recovery_extra_args = $10, ws_error_handler_muted = $11, retry = $12, summary = $13, no_flow_overlap = $14 WHERE path = $15 AND workspace_id = $16 RETURNING *",
"query": "UPDATE schedule SET schedule = $1, timezone = $2, args = $3, on_failure = $4, on_failure_times = $5, on_failure_exact = $6, on_failure_extra_args = $7, on_recovery = $8, on_recovery_times = $9, on_recovery_extra_args = $10, ws_error_handler_muted = $11, retry = $12, summary = $13, no_flow_overlap = $14, tag = $15\n WHERE path = $16 AND workspace_id = $17 RETURNING *",
"describe": {
"columns": [
{
@@ -122,6 +122,11 @@
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
@@ -140,6 +145,7 @@
"Jsonb",
"Varchar",
"Bool",
"Varchar",
"Text",
"Text"
]
@@ -168,8 +174,9 @@
false,
true,
true,
false
false,
true
]
},
"hash": "b7ed211ec7611c994a49565e46e5893788bcf49b2c9357fbc45a8353a7c84f48"
"hash": "90435687152ccd37db7e0a6a5baeb558db50f5f96b1e8eff0b10e4398566f325"
}
@@ -122,6 +122,11 @@
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
@@ -155,7 +160,8 @@
false,
true,
true,
false
false,
true
]
},
"hash": "911b1e1f2a5ba6d5159916e5598020e680c45043b0736ad0153ee261a151dd90"
@@ -122,6 +122,11 @@
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
@@ -156,7 +161,8 @@
false,
true,
true,
false
false,
true
]
},
"hash": "96dc1cd308f3c21cfb50b88048054dc03f93e261d25969d66aa48e9d0502960f"
@@ -122,6 +122,11 @@
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
@@ -154,7 +159,8 @@
false,
true,
true,
false
false,
true
]
},
"hash": "aa2800113a8a8805f47cdc1dd0f29d94c546fe531e7edd3e91da4978af5442fb"
@@ -122,6 +122,11 @@
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
@@ -155,7 +160,8 @@
false,
true,
true,
false
false,
true
]
},
"hash": "c10348d26e3e3dc9e345d9044db35db9906617eb9c98aaf58a55d9681ffb85e3"
@@ -122,6 +122,11 @@
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
@@ -155,7 +160,8 @@
false,
true,
true,
false
false,
true
]
},
"hash": "dd74fa9468b5fe8c8ad657ded06076c11a78d0206af2af20685c691d4d9520bb"
@@ -122,6 +122,11 @@
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
@@ -155,7 +160,8 @@
false,
true,
true,
false
false,
true
]
},
"hash": "eced0a09ba547ce1dccb54a5419b22373603c9d01f77047b3553bde125bf71e8"
@@ -122,6 +122,11 @@
"ordinal": 23,
"name": "no_flow_overlap",
"type_info": "Bool"
},
{
"ordinal": 24,
"name": "tag",
"type_info": "Varchar"
}
],
"parameters": {
@@ -153,7 +158,8 @@
false,
true,
true,
false
false,
true
]
},
"hash": "fdd3710a381dac33ef5ee5ec5564a4874e6d7807d43fa6ea7b8408cad9e97480"
@@ -0,0 +1,2 @@
-- Add down migration script here
ALTER TABLE schedule DROP COLUMN tag;
@@ -0,0 +1,2 @@
-- Add up migration script here
ALTER TABLE schedule ADD COLUMN tag VARCHAR(50);
+6 -3
View File
@@ -2873,7 +2873,7 @@ async fn test_script_schedule_handlers(db: Pool<Postgres>) {
retry: None,
no_flow_overlap: None,
summary: None,
tag: None,
};
let _ = client.create_schedule("test-workspace", &schedule).await;
@@ -2936,7 +2936,8 @@ async fn test_script_schedule_handlers(db: Pool<Postgres>) {
ws_error_handler_muted: None,
retry: None,
summary: None,
no_flow_overlap: None
no_flow_overlap: None,
tag: None,
},
)
.await
@@ -3016,6 +3017,7 @@ async fn test_flow_schedule_handlers(db: Pool<Postgres>) {
retry: None,
no_flow_overlap: None,
summary: None,
tag: None,
};
let _ = client.create_schedule("test-workspace", &schedule).await;
@@ -3079,7 +3081,8 @@ async fn test_flow_schedule_handlers(db: Pool<Postgres>) {
ws_error_handler_muted: None,
retry: None,
summary: None,
no_flow_overlap: None
no_flow_overlap: None,
tag: None,
},
)
.await
+6
View File
@@ -8250,6 +8250,8 @@ paths:
type: boolean
summary:
type: string
tag:
type: string
required: &ref_148
- path
- schedule
@@ -8319,6 +8321,8 @@ paths:
type: boolean
summary:
type: string
tag:
type: string
required: &ref_150
- schedule
- timezone
@@ -8464,6 +8468,8 @@ paths:
type: string
no_flow_overlap:
type: boolean
tag:
type: string
required: &ref_80
- path
- edited_by
+6
View File
@@ -8587,6 +8587,8 @@ components:
type: string
no_flow_overlap:
type: boolean
tag:
type: string
required:
- path
- edited_by
@@ -8660,6 +8662,8 @@ components:
type: boolean
summary:
type: string
tag:
type: string
required:
- path
- schedule
@@ -8700,6 +8704,8 @@ components:
type: boolean
summary:
type: string
tag:
type: string
required:
- schedule
- timezone
+6 -2
View File
@@ -880,6 +880,7 @@ mod tests {
)]
.into(),
hash: None,
tag_override: None,
},
stop_after_if: None,
summary: None,
@@ -948,6 +949,7 @@ mod tests {
path: "test".to_string(),
input_transforms: HashMap::new(),
hash: None,
tag_override: None,
},
stop_after_if: Some(StopAfterIf {
expr: "previous.isEmpty()".to_string(),
@@ -983,7 +985,8 @@ mod tests {
}
},
"type": "script",
"path": "test"
"path": "test",
"tag_override": Option::<String>::None,
},
},
{
@@ -1026,7 +1029,8 @@ mod tests {
"value": {
"input_transforms": {},
"type": "script",
"path": "test"
"path": "test",
"tag_override": Option::<String>::None,
},
"stop_after_if": {
"expr": "previous.isEmpty()",
+10 -4
View File
@@ -69,6 +69,7 @@ pub struct NewSchedule {
pub on_recovery_extra_args: Option<serde_json::Value>,
pub ws_error_handler_muted: Option<bool>,
pub retry: Option<serde_json::Value>,
pub tag: Option<String>,
}
#[derive(Serialize, Deserialize)]
@@ -155,9 +156,9 @@ async fn create_schedule(
"INSERT INTO schedule (workspace_id, path, schedule, timezone, edited_by, script_path, \
is_flow, args, enabled, email, on_failure, on_failure_times, on_failure_exact, \
on_failure_extra_args, on_recovery, on_recovery_times, on_recovery_extra_args, \
ws_error_handler_muted, retry, summary, no_flow_overlap \
ws_error_handler_muted, retry, summary, no_flow_overlap, tag \
) VALUES ( \
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21 \
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22 \
) RETURNING *",
w_id,
ns.path,
@@ -180,6 +181,7 @@ async fn create_schedule(
ns.retry,
ns.summary,
ns.no_flow_overlap.unwrap_or(false),
ns.tag,
)
.fetch_one(&mut tx)
.await
@@ -233,8 +235,9 @@ async fn edit_schedule(
Schedule,
"UPDATE schedule SET schedule = $1, timezone = $2, args = $3, on_failure = $4, on_failure_times = $5, \
on_failure_exact = $6, on_failure_extra_args = $7, on_recovery = $8, on_recovery_times = $9, \
on_recovery_extra_args = $10, ws_error_handler_muted = $11, retry = $12, summary = $13, no_flow_overlap = $14 \
WHERE path = $15 AND workspace_id = $16 RETURNING *",
on_recovery_extra_args = $10, ws_error_handler_muted = $11, retry = $12, summary = $13, \
no_flow_overlap = $14, tag = $15
WHERE path = $16 AND workspace_id = $17 RETURNING *",
es.schedule,
es.timezone,
es.args,
@@ -249,6 +252,7 @@ async fn edit_schedule(
es.retry,
es.summary,
es.no_flow_overlap.unwrap_or(false),
es.tag,
path,
w_id,
)
@@ -344,6 +348,7 @@ pub struct ScheduleWJobs {
pub jobs: Option<Vec<serde_json::Value>>,
pub summary: Option<String>,
pub no_flow_overlap: bool,
pub tag: Option<String>,
}
async fn list_schedule_with_jobs(
@@ -692,6 +697,7 @@ pub struct EditSchedule {
pub ws_error_handler_muted: Option<bool>,
pub retry: Option<serde_json::Value>,
pub no_flow_overlap: Option<bool>,
pub tag: Option<String>,
}
pub async fn clear_schedule<'c>(
+1
View File
@@ -292,6 +292,7 @@ pub enum FlowModuleValue {
path: String,
#[serde(skip_serializing_if = "Option::is_none")]
hash: Option<ScriptHash>,
tag_override: Option<String>,
},
Flow {
#[serde(default)]
+1
View File
@@ -317,6 +317,7 @@ pub enum JobPayload {
concurrency_time_window_s: Option<i32>,
cache_ttl: Option<i32>,
priority: Option<i16>,
tag_override: Option<String>,
},
DeploymentCallback {
path: String,
+1
View File
@@ -39,6 +39,7 @@ pub struct Schedule {
pub retry: Option<serde_json::Value>,
pub no_flow_overlap: bool,
pub summary: Option<String>,
pub tag: Option<String>,
}
impl Schedule {
+3
View File
@@ -1005,6 +1005,7 @@ pub async fn handle_maybe_scheduled_job<'c, R: rsmq_async::RsmqConnection + Clon
retry: schedule.retry,
summary: schedule.summary,
no_flow_overlap: schedule.no_flow_overlap,
tag: schedule.tag,
},
)
.await;
@@ -2616,6 +2617,7 @@ pub async fn push<'c, T: Serialize + Send + Sync, R: rsmq_async::RsmqConnection
concurrency_time_window_s,
cache_ttl,
priority,
tag_override,
} => {
let mut input_transforms = HashMap::<String, InputTransform>::new();
for (arg_name, arg_value) in args {
@@ -2628,6 +2630,7 @@ pub async fn push<'c, T: Serialize + Send + Sync, R: rsmq_async::RsmqConnection
input_transforms: input_transforms,
path: path.clone(),
hash: Some(hash),
tag_override: tag_override,
},
stop_after_if: None,
summary: None,
+2 -1
View File
@@ -130,6 +130,7 @@ pub async fn push_scheduled_job<'c, R: rsmq_async::RsmqConnection + Send + 'c>(
concurrency_time_window_s: concurrency_time_window_s,
cache_ttl: cache_ttl,
priority: priority,
tag_override: schedule.tag.clone(),
},
Some("flow".to_string()),
timeout,
@@ -146,7 +147,7 @@ pub async fn push_scheduled_job<'c, R: rsmq_async::RsmqConnection + Send + 'c>(
language,
priority,
},
tag,
schedule.tag.or(tag),
timeout,
)
}
+9 -5
View File
@@ -2310,8 +2310,10 @@ async fn compute_next_flow_transform(
NextStatus::NextStep,
))
}
FlowModuleValue::Script { path: script_path, hash: script_hash, .. } => {
let payload = script_to_payload(script_hash, script_path, db, flow_job, module).await?;
FlowModuleValue::Script { path: script_path, hash: script_hash, tag_override, .. } => {
let payload =
script_to_payload(script_hash, script_path, db, flow_job, module, tag_override)
.await?;
Ok(NextFlowTransform::Continue(
ContinuePayload::SingleJob(payload),
NextStatus::NextStep,
@@ -2809,8 +2811,8 @@ async fn payload_from_simple_module(
let delete_after_use = module.delete_after_use.unwrap_or(false);
Ok(match value {
FlowModuleValue::Flow { path, .. } => flow_to_payload(path, &delete_after_use),
FlowModuleValue::Script { path: script_path, hash: script_hash, .. } => {
script_to_payload(script_hash, script_path, db, flow_job, module).await?
FlowModuleValue::Script { path: script_path, hash: script_hash, tag_override, .. } => {
script_to_payload(script_hash, script_path, db, flow_job, module, tag_override).await?
}
FlowModuleValue::RawScript {
path,
@@ -2875,7 +2877,9 @@ async fn script_to_payload(
db: &sqlx::Pool<sqlx::Postgres>,
flow_job: &QueuedJob,
module: &FlowModule,
tag_override: &Option<String>,
) -> Result<JobPayloadWithTag, Error> {
tracing::warn!("Script tag override: {:?}", tag_override);
let (payload, tag, delete_after_use, script_timeout) = if script_hash.is_none() {
script_path_to_payload(script_path, &db, &flow_job.workspace_id).await?
} else {
@@ -2903,7 +2907,7 @@ async fn script_to_payload(
dedicated_worker,
priority,
},
tag,
tag_override.to_owned().or(tag),
delete_after_use,
script_timeout,
)
@@ -35,7 +35,7 @@ resource "aws_ecs_task_definition" "windmill_cluster_windmill_server_td" {
value = "true"
}, {
name = "DATABASE_URL"
value = "postgres://${aws_db_instance.windmill_cluster_rds.username}:${aws_db_instance.windmill_cluster_rds.password}@${aws_db_instance.windmill_cluster_rds.endpoint}/${aws_db_instance.windmill_cluster_rds.db_name}"
value = "postgres://${aws_db_instance.windmill_cluster_rds.username}:${aws_db_instance.windmill_cluster_rds.password}@${aws_db_instance.windmill_cluster_rds.endpoint}/${aws_db_instance.windmill_cluster_rds.db_name}?sslmode=disable"
}, {
name = "MODE"
value = "server"
@@ -26,7 +26,7 @@ resource "aws_ecs_task_definition" "windmill_cluster_windmill_worker_td" {
value = "true"
}, {
name = "DATABASE_URL"
value = "postgres://${aws_db_instance.windmill_cluster_rds.username}:${aws_db_instance.windmill_cluster_rds.password}@${aws_db_instance.windmill_cluster_rds.endpoint}/${aws_db_instance.windmill_cluster_rds.db_name}"
value = "postgres://${aws_db_instance.windmill_cluster_rds.username}:${aws_db_instance.windmill_cluster_rds.password}@${aws_db_instance.windmill_cluster_rds.endpoint}/${aws_db_instance.windmill_cluster_rds.db_name}?sslmode=disable"
}, {
name = "MODE"
value = "worker"
@@ -101,7 +101,7 @@ resource "aws_ecs_task_definition" "windmill_cluster_windmill_high_performance_w
value = "true"
}, {
name = "DATABASE_URL"
value = "postgres://${aws_db_instance.windmill_cluster_rds.username}:${aws_db_instance.windmill_cluster_rds.password}@${aws_db_instance.windmill_cluster_rds.endpoint}/${aws_db_instance.windmill_cluster_rds.db_name}"
value = "postgres://${aws_db_instance.windmill_cluster_rds.username}:${aws_db_instance.windmill_cluster_rds.password}@${aws_db_instance.windmill_cluster_rds.endpoint}/${aws_db_instance.windmill_cluster_rds.db_name}?sslmode=disable"
}, {
name = "MODE"
value = "worker"
@@ -26,7 +26,7 @@ resource "aws_ecs_task_definition" "windmill_cluster_windmill_native_worker_td"
value = "true"
}, {
name = "DATABASE_URL"
value = "postgres://${aws_db_instance.windmill_cluster_rds.username}:${aws_db_instance.windmill_cluster_rds.password}@${aws_db_instance.windmill_cluster_rds.endpoint}/${aws_db_instance.windmill_cluster_rds.db_name}"
value = "postgres://${aws_db_instance.windmill_cluster_rds.username}:${aws_db_instance.windmill_cluster_rds.password}@${aws_db_instance.windmill_cluster_rds.endpoint}/${aws_db_instance.windmill_cluster_rds.db_name}?sslmode=disable"
}, {
name = "MODE"
value = "worker"
@@ -11,6 +11,7 @@
let newTag: string = ''
export let customTags: string[] | undefined = undefined
export let placement: 'bottom-end' | 'top-end' = 'bottom-end'
async function loadCustomTags() {
try {
@@ -26,7 +27,7 @@
</script>
<Popup
floatingConfig={{ strategy: 'absolute', placement: 'bottom-end' }}
floatingConfig={{ strategy: 'absolute', placement: placement }}
containerClasses="border rounded-lg shadow-lg p-4 bg-surface"
>
<svelte:fragment slot="button">
@@ -26,6 +26,7 @@
import Section from '$lib/components/Section.svelte'
import { List, Save } from 'lucide-svelte'
import FlowRetries from './flows/content/FlowRetries.svelte'
import WorkerTagPicker from './WorkerTagPicker.svelte'
let optionTabSelected: 'error_handler' | 'recovery_handler' | 'retries' = 'error_handler'
@@ -144,6 +145,7 @@
let pathError = ''
let summary = ''
let no_flow_overlap = false
let tag: string | undefined = undefined
let validCRON = true
$: allowSchedule = isValid && validCRON && script_path != ''
@@ -271,6 +273,7 @@
}
args = s.args ?? {}
can_write = canWrite(s.path, s.extra_perms, $userStore)
tag = s.tag
} catch (err) {
sendUserToast(`Could not load schedule: ${err}`, true)
}
@@ -303,7 +306,8 @@
ws_error_handler_muted: wsErrorHandlerMuted,
retry: retry,
summary: summary != '' ? summary : undefined,
no_flow_overlap: no_flow_overlap
no_flow_overlap: no_flow_overlap,
tag: tag
}
})
sendUserToast(`Schedule ${path} updated`)
@@ -330,7 +334,8 @@
ws_error_handler_muted: wsErrorHandlerMuted,
retry: retry,
summary: summary != '' ? summary : undefined,
no_flow_overlap: no_flow_overlap
no_flow_overlap: no_flow_overlap,
tag: tag
}
})
sendUserToast(`Schedule ${path} created`)
@@ -533,12 +538,15 @@
</div>
</Section>
{#if !is_flow}{/if}
<div class="flex flex-col gap-2">
<Tabs bind:selected={optionTabSelected}>
<Tab value="error_handler">Error Handler</Tab>
<Tab value="recovery_handler">Recovery Handler</Tab>
{#if itemKind === 'script'}
<Tab value="retries">Retries</Tab>
<Tab value="tag">Custom tag</Tab>
{/if}
</Tabs>
<div class="pt-0.5" />
@@ -744,6 +752,13 @@
</svelte:fragment>
<FlowRetries bind:flowModuleRetry={retry} disabled={itemKind !== 'script'} />
</Section>
{:else if optionTabSelected === 'tag'}
<Section
label="Custom script tag"
tooltip="When set, the script tag will be overridden by this tag"
>
<WorkerTagPicker bind:tag popupPlacement="top-end" />
</Section>
{/if}
</div>
</div>
@@ -1,17 +1,10 @@
<script lang="ts">
import {
DraftService,
NewScript,
Script,
ScriptService,
WorkerService,
type NewScriptWithDraft
} from '$lib/gen'
import { DraftService, NewScript, Script, ScriptService, type NewScriptWithDraft } from '$lib/gen'
import { goto } from '$app/navigation'
import { page } from '$app/stores'
import { inferArgs } from '$lib/infer'
import { initialCode } from '$lib/script_helpers'
import { enterpriseLicense, userStore, workerTags, workspaceStore } from '$lib/stores'
import { enterpriseLicense, userStore, workspaceStore } from '$lib/stores'
import {
cleanValueProperties,
emptySchema,
@@ -34,12 +27,9 @@
CheckCircle,
Code,
DiffIcon,
ExternalLink,
Loader2,
Pen,
Plus,
Rocket,
RotateCw,
Save,
Settings,
X
@@ -59,7 +49,7 @@
import type DiffDrawer from './DiffDrawer.svelte'
import { cloneDeep } from 'lodash'
import type Editor from './Editor.svelte'
import AssignableTags from './AssignableTags.svelte'
import WorkerTagPicker from './WorkerTagPicker.svelte'
export let script: NewScript
export let initialPath: string = ''
@@ -81,14 +71,6 @@
const enterpriseLangs = ['bigquery', 'snowflake', 'mssql']
loadWorkerGroups()
async function loadWorkerGroups() {
if (!$workerTags) {
$workerTags = await WorkerService.getCustomTags()
}
}
export function setCode(code: string): void {
editor?.setCode(code)
}
@@ -599,59 +581,7 @@
group tag (queue). For instance, you could setup an "highmem", or "gpu" tag.
</Tooltip>
</svelte:fragment>
<div class="flex gap-2 items-center">
<div class="max-w-sm grow">
{#if $workerTags}
{#if $workerTags?.length > 0}
<select
bind:value={script.tag}
on:change={(e) => {
if (script.tag == '') {
script.tag = undefined
}
}}
>
{#if script.tag}
<option value="">reset to default</option>
{:else}
<option value="" disabled selected>Worker Group Tag</option>
{/if}
{#each $workerTags ?? [] as tag (tag)}
<option value={tag}>{tag}</option>
{/each}
</select>
{:else}
<div class="text-sm text-secondary flex flex-row gap-2">
No custom worker group tag defined on this instance in "Workers {'->'} Assignable
Tags"
<a
href="https://www.windmill.dev/docs/core_concepts/worker_groups"
target="_blank"
class="hover:underline"
>
<div class="flex flex-row gap-2 items-center">
See documentation
<ExternalLink size="12" />
</div>
</a>
</div>
{/if}
{:else}
<Loader2 class="animate-spin" />
{/if}
</div>
<Button
variant="border"
color="light"
on:click={() => {
$workerTags = undefined
loadWorkerGroups()
}}
startIcon={{ icon: RotateCw }}
/>
<AssignableTags />
</div>
<WorkerTagPicker bind:tag={script.tag} />
</Section>
<Section label="Cache">
<div class="flex gap-2 shrink flex-col">
@@ -0,0 +1,70 @@
<script lang="ts">
import { Button } from '$lib/components/common'
import { ExternalLink, RotateCw, Loader2 } from 'lucide-svelte'
import { workerTags } from '$lib/stores'
import AssignableTags from './AssignableTags.svelte'
import { WorkerService } from '$lib/gen'
export let tag: string | undefined
export let popupPlacement: 'bottom-end' | 'top-end' = 'bottom-end'
loadWorkerGroups()
async function loadWorkerGroups() {
if (!$workerTags) {
$workerTags = await WorkerService.getCustomTags()
}
}
</script>
<div class="flex gap-2 items-center">
<div class="max-w-sm grow">
{#if workerTags}
{#if $workerTags?.length ?? 0 > 0}
<select
bind:value={tag}
on:change={(e) => {
if (tag == '') {
tag = undefined
}
}}
>
{#if tag}
<option value="">reset to default</option>
{:else}
<option value="" disabled selected>Worker Group Tag</option>
{/if}
{#each $workerTags ?? [] as tag (tag)}
<option value={tag}>{tag}</option>
{/each}
</select>
{:else}
<div class="text-sm text-secondary flex flex-row gap-2">
No custom worker group tag defined on this instance in "Workers {'->'} Assignable Tags"
<a
href="https://www.windmill.dev/docs/core_concepts/worker_groups"
target="_blank"
class="hover:underline"
>
<div class="flex flex-row gap-2 items-center">
See documentation
<ExternalLink size="12" />
</div>
</a>
</div>
{/if}
{:else}
<Loader2 class="animate-spin" />
{/if}
</div>
<Button
variant="border"
color="light"
on:click={() => {
$workerTags = undefined
loadWorkerGroups()
}}
startIcon={{ icon: RotateCw }}
/>
<AssignableTags placement={popupPlacement} />
</div>
@@ -17,34 +17,26 @@
import { isCloudHosted } from '$lib/cloud'
import { copyToClipboard } from '$lib/utils'
import Tooltip from '$lib/components/Tooltip.svelte'
import { WorkerService } from '$lib/gen'
import { AlertTriangle, Clipboard, Loader2, RotateCw } from 'lucide-svelte'
import { AlertTriangle, Clipboard } from 'lucide-svelte'
import SimpleEditor from '$lib/components/SimpleEditor.svelte'
import { schemaToObject } from '$lib/schema'
import type { Schema } from '$lib/common'
import Section from '$lib/components/Section.svelte'
import Label from '$lib/components/Label.svelte'
import ErrorHandlerToggleButton from '$lib/components/details/ErrorHandlerToggleButton.svelte'
import AssignableTags from '$lib/components/AssignableTags.svelte'
import WorkerTagPicker from '$lib/components/WorkerTagPicker.svelte'
export let noEditor: boolean
const { selectedId, flowStore, initialPath, previewArgs, pathStore } =
getContext<FlowEditorContext>('FlowEditorContext')
async function loadWorkerGroups() {
if (!$workerTags) {
$workerTags = await WorkerService.getCustomTags()
}
}
let hostname = BROWSER ? window.location.protocol + '//' + window.location.host : 'SSR'
$: url = `${hostname}/api/w/${$workspaceStore}/jobs/run/f/${$pathStore}`
$: syncedUrl = `${hostname}/api/w/${$workspaceStore}/jobs/run_wait_result/f/${$pathStore}`
$: if ($selectedId == 'settings-worker-group') {
$workerTags = undefined
loadWorkerGroups()
}
function asSchema(x: any) {
@@ -327,54 +319,7 @@
'flow' and the steps will be executed with their respective tag
</Alert>
<span class="my-4 text-lg font-bold">Worker Group Tag (Queue)</span>
<div class="flex gap-2 items-center">
{#if $workerTags}
{#if $workerTags?.length > 0}
<div class="max-w-sm grow">
<select
placeholder="Worker group tag"
bind:value={$flowStore.tag}
on:change={(e) => {
if ($flowStore.tag == '') {
$flowStore.tag = undefined
}
}}
>
{#if $flowStore.tag}
<option value="">reset to default</option>
{:else}
<option value="" disabled selected>Worker Group Tag</option>
{/if}
{#each $workerTags ?? [] as tag (tag)}
<option value={tag}>{tag}</option>
{/each}
</select>
</div>
{:else}
<div class="text-sm text-secondary italic mb-2">
No custom worker group tag defined on this instance in "Workers {'->'} Assignable
Tags". See
<a
href="https://www.windmill.dev/docs/core_concepts/worker_groups"
target="_blank">documentation</a
>
</div>
{/if}
{:else}
<Loader2 class="animate-spin" />
{/if}
<Button
variant="border"
color="light"
on:click={() => {
$workerTags = undefined
loadWorkerGroups()
}}
startIcon={{ icon: RotateCw }}
/>
<AssignableTags />
</div>
<WorkerTagPicker bind:tag={$flowStore.tag} />
<div class="py-6" />
<span class="my-4 text-lg font-bold flex items-baseline gap-8"