Compare commits
39 Commits
rf/pythonI
...
alp/teams_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88c9710fba | ||
|
|
c1e0a4345f | ||
|
|
ec69a60e8b | ||
|
|
da084aacd5 | ||
|
|
5c10fcda73 | ||
|
|
1b9c33a0fb | ||
|
|
14109a832f | ||
|
|
f7d276c558 | ||
|
|
0b00d7b4ff | ||
|
|
19bf8775d8 | ||
|
|
58838c75a9 | ||
|
|
a1be0f2039 | ||
|
|
3dc3f78c40 | ||
|
|
7c7cf6436c | ||
|
|
fe77410a89 | ||
|
|
afdc10c538 | ||
|
|
ad75a5d03c | ||
|
|
e12d0291f4 | ||
|
|
ce026e0adc | ||
|
|
74d0d2f331 | ||
|
|
6b6220ebc1 | ||
|
|
c49cafae95 | ||
|
|
eea16d5d55 | ||
|
|
217aac0243 | ||
|
|
13ca5ed18d | ||
|
|
80bcf05fa6 | ||
|
|
db17d75e60 | ||
|
|
9275875a36 | ||
|
|
c111ad775d | ||
|
|
58350db089 | ||
|
|
bee9ed5acc | ||
|
|
35e95c6f64 | ||
|
|
ef28300a4f | ||
|
|
d6d1361a3d | ||
|
|
3ff79c53be | ||
|
|
e07a0ad722 | ||
|
|
1c2b14d939 | ||
|
|
40c71b0a61 | ||
|
|
3f042a9d50 |
@@ -1,40 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n DELETE\n FROM parallel_monitor_lock\n WHERE last_ping IS NOT NULL AND last_ping < NOW() - ($1 || ' seconds')::interval\n RETURNING parent_flow_id, job_id, last_ping, (SELECT workspace_id FROM v2_job_queue q\n WHERE q.id = parent_flow_id AND q.running = true AND q.canceled_by IS NULL\n ) AS workspace_id\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "parent_flow_id",
|
||||
"type_info": "Uuid"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "job_id",
|
||||
"type_info": "Uuid"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "last_ping",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "workspace_id",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "00c4a602aa6a50f2f922851ce63b5216e915c7649698687a00d47da55c70349f"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO metrics (id, value)\n VALUES ($1, to_jsonb((\n SELECT EXTRACT(EPOCH FROM now() - scheduled_for)\n FROM v2_job_queue\n WHERE tag = $2 AND running = false AND scheduled_for <= now() - ('3 seconds')::interval\n ORDER BY priority DESC NULLS LAST, scheduled_for LIMIT 1\n )))",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Varchar",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "00e63eab76d26e148b77e932848de74e8b0943d30481465da453942e299a128f"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT suspend > 0 AS \"r!\" FROM v2_job_queue WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "r!",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "12828c9b2964f2b484a68de1e01b65cdcd277257192ee0a6d18a00f41bce49d4"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO job_logs (job_id, logs)\n VALUES ($1, $2)\n ON CONFLICT (job_id) DO UPDATE SET logs = job_logs.logs || '\n' || EXCLUDED.logs\n WHERE job_logs.job_id = $1",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "1ab0d1ba1fbfad31ffb28a01a6c9640d0ac142aabee8d288a4f9c56ad9dbeac4"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT SUBSTRING(name, 9) as \"name!\", (config.config->'min_alive_workers_alert_threshold')::INT as \"threshold!\" \n FROM config \n WHERE name LIKE 'worker__%' AND config->'min_alive_workers_alert_threshold' IS NOT NULL",
|
||||
"query": "SELECT SUBSTRING(name, 9) as \"name!\", (config.config->'min_alive_workers_alert_threshold')::INT as \"threshold!\"\n FROM config\n WHERE name LIKE 'worker__%' AND config->'min_alive_workers_alert_threshold' IS NOT NULL",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -22,5 +22,5 @@
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "354f88b23d20f92c6b6d5bdd8d6c69b08c6a86116cbfd0ecad8f112f7f49d8d1"
|
||||
"hash": "1d0cd1c29ad48e31b4a3237cd34cc5c157241fbf274a3c525c6891c361293942"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM v2_job_completed c\n USING v2_job j\n WHERE\n created_at <= now() - ($1::bigint::text || ' s')::interval\n AND completed_at + ($1::bigint::text || ' s')::interval <= now()\n AND c.id = j.id\n RETURNING c.id",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Uuid"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "1d819b829cd92995c39d29540df8cffbcc3334bada244a331a0bd8db06029d42"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT script_path FROM v2_as_completed_job WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "script_path",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "280a361076d1c6317610765960f543252891c53351bdc98da66cc30ffc895866"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM job_logs WHERE job_id = ANY($1) RETURNING log_file_index",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "log_file_index",
|
||||
"type_info": "TextArray"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"UuidArray"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "288e99211bbd45a337fc9b79c43c5139ee535e23c8b3362c52eef49998349f15"
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM pip_resolution_cache WHERE expiration <= now() RETURNING hash",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "hash",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "399a8337a2488fa2ce3da2ef3281a34f8f96ee0d833c2fe3c22a0aa43e306f09"
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT worker, array_agg(v2_job_queue.id) as ids FROM v2_job_queue LEFT JOIN v2_job ON v2_job_queue.id = v2_job.id LEFT JOIN v2_job_runtime ON v2_job_queue.id = v2_job_runtime.id WHERE v2_job_queue.created_at < now() - ('60 seconds')::interval\n AND running = true AND ping IS NULL AND same_worker = true AND worker IS NOT NULL GROUP BY worker",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "worker",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "ids",
|
||||
"type_info": "UuidArray"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "3e261911cc4c5289da49865f54350613f9e651540a279bd7d75e5e7d79f676a8"
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_queue SET running = false, started_at = null\n WHERE id = $1 AND canceled_by IS NULL",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "3e55d027327bd3c76810fbe22d3ccb1bbbf83c8cff69d8f5907d1417a2522e69"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM metrics WHERE created_at < NOW() - INTERVAL '180 day'",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "45dde0dc2da12fe46b5975ed53b520fc4160c008c3d29fe7d99e609c0b6e3e6d"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO healthchecks (check_type, healthy) \n SELECT 'min_alive_workers_' || $1, true \n WHERE NOT EXISTS (\n SELECT 1 FROM healthchecks \n WHERE check_type = 'min_alive_workers_' || $1 AND created_at > NOW() - INTERVAL '2 minutes'\n )\n RETURNING id",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "4cfa57b2a836242d55071ef237855b21bbc487b80bda7fd6250ac12e93938577"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "WITH worker_ids AS (SELECT unnest($1::text[]) as worker)\n SELECT worker_ids.worker FROM worker_ids\n LEFT JOIN worker_ping ON worker_ids.worker = worker_ping.worker\n WHERE worker_ping.worker IS NULL OR worker_ping.ping_at < now() - ('60 seconds')::interval",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "worker",
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"TextArray"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "5a219a2532517869578c4504ff3153c43903f929ae5d62fbba12610f89c36d55"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO healthchecks (check_type, healthy) \n SELECT 'min_alive_workers_' || $1, false\n WHERE NOT EXISTS (\n SELECT 1 FROM healthchecks \n WHERE check_type = 'min_alive_workers_' || $1 AND created_at > NOW() - INTERVAL '2 minutes'\n )\n RETURNING id",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "5f22a7c9170f035779782591b4bfb1d462d5c796f08c7481c42154f9bfacf388"
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM job_stats WHERE job_id = ANY($1)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"UuidArray"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "6c0f74c56789ac51ccb06cd8a14986071ccc94df0de137b56d63d673db11d8aa"
|
||||
}
|
||||
22
backend/.sqlx/query-72cea8e73e1974534163ef6515afed378e69232fb38bbfc44c4edeeb27574947.json
generated
Normal file
22
backend/.sqlx/query-72cea8e73e1974534163ef6515afed378e69232fb38bbfc44c4edeeb27574947.json
generated
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO healthchecks (check_type, healthy)\n SELECT 'min_alive_workers_' || $1, true\n WHERE NOT EXISTS (\n SELECT 1 FROM healthchecks\n WHERE check_type = 'min_alive_workers_' || $1 AND created_at > NOW() - INTERVAL '2 minutes'\n )\n RETURNING id",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "72cea8e73e1974534163ef6515afed378e69232fb38bbfc44c4edeeb27574947"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM metrics WHERE id LIKE 'queue_%' AND created_at < NOW() - INTERVAL '14 day'",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "7c9a464ac807051b99fe37f2078f1b17f824e6d9b1124db618855a15a98e31f6"
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT created_at FROM metrics WHERE id LIKE 'queue_count_%' ORDER BY created_at DESC LIMIT 1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "created_at",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "82f6674f19e8ad51a992505a46f46fc4a48172f104e9e849f755ac041c3eef92"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT workflow_as_code_status FROM v2_job_completed WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "workflow_as_code_status",
|
||||
"type_info": "Jsonb"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "867d5c75ddc6c5d20136880c7294844b4c1a38701190795a801fa43c74a0beeb"
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM resource WHERE resource_type = 'cache' AND to_timestamp((value->>'expire')::int) < now() RETURNING path",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "path",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "873fde22f7947882edae7d15bc54e8df105d5e241eeb842a83e3444be0d2736d"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO metrics (id, value) VALUES ($1, $2)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Varchar",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "8824b382c4e98dfa17b4aa656af3a6c1ff99973e778d71bd598a50d022da8f15"
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO log_file (hostname, mode, worker_group, log_ts, file_path, ok_lines, err_lines, json_fmt)\n VALUES ($1, $2::text::LOG_MODE, $3, $4, $5, $6, $7, $8)\n ON CONFLICT (hostname, log_ts) DO UPDATE SET ok_lines = log_file.ok_lines + $6, err_lines = log_file.err_lines + $7",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Varchar",
|
||||
"Text",
|
||||
"Varchar",
|
||||
"Timestamp",
|
||||
"Varchar",
|
||||
"Int8",
|
||||
"Int8",
|
||||
"Bool"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "92faee8714a45a403b623e04d789f7f99067a05e9dfe270223164db8a1df2e4b"
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM log_file WHERE log_ts <= now() - ($1::bigint::text || ' s')::interval RETURNING file_path, hostname",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "file_path",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "hostname",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "94da1e7feb4f58cc7ebe99752736f956d47810a94cb052fdcffb5cfe440f8033"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT id FROM v2_job WHERE parent_job = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Uuid"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "99f74bf675120daf965e063e5eaff808ba646f4f99d0c8837097e747b481f03a"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT labels FROM v2_job WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "labels",
|
||||
"type_info": "TextArray"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "9d518842a9ad90ff9c28dc39690deb0ee6b62cf1d8ae1a02b28c23255d377b3d"
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM concurrency_key WHERE ended_at <= now() - ($1::bigint::text || ' s')::interval ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "9da0cea2a5d0464ca78cfeccf6cedf2b1c0e6e6cb3c9183a937a68465debdb06"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO global_settings (name, value) VALUES ($1, $2) ON CONFLICT (name) DO UPDATE SET value = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Varchar",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "a00e61e770e20157bbd9e4cdedf7fb5f9de7c8c9e50282e3ecf2e3ce917ec37a"
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT count(*) AS \"count!\" FROM resume_job",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "count!",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "a0c35cb515a842067b294343c90f1bfbe4e2db85da9a478a07460733999e9beb"
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT preprocessed, script_entrypoint_override FROM v2_job WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "preprocessed",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "script_entrypoint_override",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "a56eef5f5ecbe1a8d309ff65d9a8c456a3c165f7f2a107cf7fa6a4cdd30d55c0"
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM variable WHERE expires_at IS NOT NULL AND expires_at < now() RETURNING path",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "path",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "b0c2f470f7d2df567eca550db1ae638fcb554622b61a5f4fb6b6696f6283516a"
|
||||
}
|
||||
@@ -18,8 +18,8 @@
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
true
|
||||
true,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "b3dbdfb50ee8118bdaed3164b210cb549a34b96554ae1872355b90304f5dcb76"
|
||||
|
||||
22
backend/.sqlx/query-bb31ee7266192f0df19fbf972bab2d94e8377509f3da999f41537b6598ace5f2.json
generated
Normal file
22
backend/.sqlx/query-bb31ee7266192f0df19fbf972bab2d94e8377509f3da999f41537b6598ace5f2.json
generated
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO healthchecks (check_type, healthy)\n SELECT 'min_alive_workers_' || $1, false\n WHERE NOT EXISTS (\n SELECT 1 FROM healthchecks\n WHERE check_type = 'min_alive_workers_' || $1 AND created_at > NOW() - INTERVAL '2 minutes'\n )\n RETURNING id",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "bb31ee7266192f0df19fbf972bab2d94e8377509f3da999f41537b6598ace5f2"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job SET labels = $2 WHERE id = $1 AND $2::TEXT[] IS NOT NULL",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"TextArray"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "bd5a0c06e2f2361c9fc670eb0b975b58d65ca93d68b29124d04bd526239b9df2"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT COUNT(*) as count, \n MIN(scheduled_for) as oldest_job\n FROM v2_job_queue \n WHERE tag = $1 \n AND scheduled_for <= NOW() - $2::interval \n AND running = false\n ",
|
||||
"query": "\n SELECT COUNT(*) as count,\n MIN(scheduled_for) as oldest_job\n FROM v2_job_queue\n WHERE tag = $1\n AND scheduled_for <= NOW() - $2::interval\n AND running = false\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -25,5 +25,5 @@
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "9e2810312302b36d3b4d761481c00296ee84c9536228496e19b4ec5df1781bc5"
|
||||
"hash": "c67b5ad3869bbeb53cc06ca7fb2f1000d512c95f3b74ba9aafee684670aff5f4"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT preprocessed FROM v2_job WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "preprocessed",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "cd5f02cf10cbf92dd1df53a54f2110efa11a7731ad0f0e5509f55efabdf535cd"
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM audit WHERE timestamp <= now() - ($1::bigint::text || ' s')::interval",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "d8186f0cee285aa50db7626409aec7e0504b068ffa8bb185d9384ce1422fd3d1"
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "WITH to_update AS (\n SELECT q.id, q.workspace_id, r.ping, COALESCE(zjc.counter, 0) as counter\n FROM v2_job_queue q\n JOIN v2_job j ON j.id = q.id\n JOIN v2_job_runtime r ON r.id = j.id\n LEFT JOIN zombie_job_counter zjc ON zjc.job_id = q.id\n WHERE ping < now() - ($1 || ' seconds')::interval\n AND running = true\n AND kind NOT IN ('flow', 'flowpreview', 'flownode', 'singlescriptflow')\n AND same_worker = false\n AND (zjc.counter IS NULL OR zjc.counter <= $2)\n FOR UPDATE of q SKIP LOCKED\n ),\n zombie_jobs AS (\n UPDATE v2_job_queue q\n SET running = false, started_at = null\n FROM to_update tu\n WHERE q.id = tu.id AND (tu.counter IS NULL OR tu.counter < $2)\n RETURNING q.id, q.workspace_id, ping, tu.counter\n ),\n update_ping AS (\n UPDATE v2_job_runtime r\n SET ping = null\n FROM zombie_jobs zj\n WHERE r.id = zj.id\n ),\n increment_counter AS (\n INSERT INTO zombie_job_counter (job_id, counter)\n SELECT id, 1 FROM to_update WHERE counter < $2\n ON CONFLICT (job_id) DO UPDATE\n SET counter = zombie_job_counter.counter + 1\n ),\n update_concurrency AS (\n UPDATE concurrency_counter cc\n SET job_uuids = job_uuids - zj.id::text\n FROM zombie_jobs zj\n INNER JOIN concurrency_key ck ON ck.job_id = zj.id\n WHERE cc.concurrency_id = ck.key\n )\n SELECT id AS \"id!\", workspace_id AS \"workspace_id!\", ping, counter + 1 AS counter FROM to_update",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id!",
|
||||
"type_info": "Uuid"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "workspace_id!",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "ping",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "counter",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "daf9674838fb3e3653a356c7434c719616a614d77e726433737e5f5d9bd60134"
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT version()",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "version",
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "df1f1d15d442789a5b9c81cdddf44d88d5748499cc48865023ddc1ff1587d0f6"
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT\n id AS \"id!\", workspace_id AS \"workspace_id!\", parent_job, is_flow_step,\n flow_status AS \"flow_status: Box<str>\", last_ping, same_worker\n FROM v2_as_queue\n WHERE running = true AND suspend = 0 AND suspend_until IS null AND scheduled_for <= now()\n AND (job_kind = 'flow' OR job_kind = 'flowpreview' OR job_kind = 'flownode')\n AND last_ping IS NOT NULL AND last_ping < NOW() - ($1 || ' seconds')::interval\n AND canceled = false\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id!",
|
||||
"type_info": "Uuid"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "workspace_id!",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "parent_job",
|
||||
"type_info": "Uuid"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "is_flow_step",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "flow_status: Box<str>",
|
||||
"type_info": "Jsonb"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "last_ping",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "same_worker",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "e653d36b607a16c0dfc0324690942ab25883b53a81ebb581fe019af2ec5eb567"
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM v2_job WHERE id = ANY($1)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"UuidArray"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "ecd62c48fe2fba2fc2582e9e7ae5590d5dea8c67f6ae7b14743ac4f265dd89a3"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT hash FROM script WHERE path = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "hash",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "ef6795d93423f98eea82eb18e6332580dc7f7a9e5a67026f8c0b3077f371fc62"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT count(*) \n FROM worker_ping \n WHERE worker_group LIKE $1 AND ping_at > now() - INTERVAL '2 minutes'",
|
||||
"query": "SELECT count(*)\n FROM worker_ping\n WHERE worker_group LIKE $1 AND ping_at > now() - INTERVAL '2 minutes'",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -18,5 +18,5 @@
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "8dd1de2aca8c6c9ffaddd2c41c3a614a50fa5fd03c2d3b9a41bd85a7f156345e"
|
||||
"hash": "f6e8812a4479bccdd713a88ed2670ed81601acbc97bdfe4f7d4ac13b9a905b26"
|
||||
}
|
||||
@@ -41,11 +41,11 @@
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2245,6 +2245,40 @@ paths:
|
||||
job_uuid:
|
||||
type: string
|
||||
|
||||
/w/{workspace}/workspaces/run_teams_message_test_job:
|
||||
post:
|
||||
summary: run a job that sends a message to Teams
|
||||
operationId: runTeamsMessageTestJob
|
||||
tags:
|
||||
- workspace
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
requestBody:
|
||||
description: path to hub script to run and its corresponding args
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
hub_script_path:
|
||||
type: string
|
||||
channel:
|
||||
type: string
|
||||
test_msg:
|
||||
type: string
|
||||
|
||||
responses:
|
||||
"200":
|
||||
description: status
|
||||
content:
|
||||
text/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
job_uuid:
|
||||
type: string
|
||||
|
||||
/w/{workspace}/workspaces/edit_deploy_to:
|
||||
post:
|
||||
summary: edit deploy to
|
||||
@@ -3581,6 +3615,41 @@ paths:
|
||||
"200":
|
||||
description: Activity processed successfully
|
||||
|
||||
/teams/activities:
|
||||
post:
|
||||
summary: send update to Microsoft Teams activity
|
||||
description: Respond to a Microsoft Teams activity after a workspace command is run
|
||||
operationId: sendMessageToConversation
|
||||
tags:
|
||||
- teams
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required:
|
||||
- conversation_id
|
||||
- text
|
||||
properties:
|
||||
conversation_id:
|
||||
type: string
|
||||
description: The ID of the Teams conversation/activity
|
||||
success:
|
||||
type: boolean
|
||||
description: Used for styling the card conditionally
|
||||
default: true
|
||||
text:
|
||||
type: string
|
||||
description: The message text to be sent in the Teams card
|
||||
card_block:
|
||||
type: object
|
||||
description: The card block to be sent in the Teams card
|
||||
|
||||
responses:
|
||||
'200':
|
||||
description: Activity processed successfully
|
||||
|
||||
/w/{workspace}/resources/create:
|
||||
post:
|
||||
summary: create resource
|
||||
@@ -7899,6 +7968,52 @@ paths:
|
||||
"200":
|
||||
description: Interactive slack approval message sent successfully
|
||||
|
||||
/w/{workspace}/jobs/teams_approval/{id}:
|
||||
get:
|
||||
summary: generate interactive teams approval for suspended job
|
||||
operationId: getTeamsApprovalPayload
|
||||
tags:
|
||||
- job
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/JobId"
|
||||
- name: approver
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
- name: message
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
- name: team_name
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: channel_name
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: flow_step_id
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: default_args_json
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- name: dynamic_enums_json
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: Interactive slack approval message sent successfully
|
||||
|
||||
/w/{workspace}/jobs_u/resume/{id}/{resume_id}/{signature}:
|
||||
get:
|
||||
summary: resume a job for a suspended flow
|
||||
|
||||
152
backend/windmill-api/src/approvals.rs
Normal file
152
backend/windmill-api/src/approvals.rs
Normal file
@@ -0,0 +1,152 @@
|
||||
use serde::Deserialize;
|
||||
use serde_json::value::RawValue;
|
||||
use sqlx::types::Uuid;
|
||||
use windmill_common::cache;
|
||||
use windmill_common::db::DB;
|
||||
use windmill_common::error::Error;
|
||||
|
||||
use axum::extract::{Path, Query};
|
||||
|
||||
use crate::jobs::{get_resume_urls_internal, ResumeUrls, QueryApprover};
|
||||
use windmill_common::{
|
||||
error::{self},
|
||||
jobs::JobKind,
|
||||
scripts::ScriptHash,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct ResumeFormRow {
|
||||
pub resume_form: Option<serde_json::Value>,
|
||||
pub hide_cancel: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct QueryMessage {
|
||||
pub message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct QueryResourcePath {
|
||||
pub slack_resource_path: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct QueryChannelId {
|
||||
pub channel_id: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct QueryFlowStepId {
|
||||
pub flow_step_id: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct QueryDefaultArgsJson {
|
||||
pub default_args_json: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct QueryDynamicEnumJson {
|
||||
pub dynamic_enums_json: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ApprovalFormDetails {
|
||||
pub message_str: String,
|
||||
pub urls: ResumeUrls,
|
||||
pub schema: Option<ResumeFormRow>,
|
||||
}
|
||||
|
||||
pub async fn get_approval_form(
|
||||
db: DB,
|
||||
w_id: &str,
|
||||
job_id: Uuid,
|
||||
flow_step_id: Option<&str>,
|
||||
resume_id: u32,
|
||||
approver: Option<&str>,
|
||||
message: Option<&str>,
|
||||
) -> Result<ApprovalFormDetails, Error> {
|
||||
let res = get_resume_urls_internal(
|
||||
axum::Extension(db.clone()),
|
||||
Path((w_id.to_string(), job_id, resume_id)),
|
||||
Query(QueryApprover { approver: approver.map(|a| a.to_string()) }),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let urls = res.0;
|
||||
|
||||
tracing::debug!("Job ID: {:?}", job_id);
|
||||
|
||||
let (job_kind, script_hash, raw_flow, parent_job_id, created_at, created_by, script_path, args) = sqlx::query!(
|
||||
"SELECT
|
||||
v2_as_queue.job_kind AS \"job_kind!: JobKind\",
|
||||
v2_as_queue.script_hash AS \"script_hash: ScriptHash\",
|
||||
v2_as_queue.raw_flow AS \"raw_flow: sqlx::types::Json<Box<RawValue>>\",
|
||||
v2_as_completed_job.parent_job AS \"parent_job: Uuid\",
|
||||
v2_as_completed_job.created_at AS \"created_at!: chrono::NaiveDateTime\",
|
||||
v2_as_completed_job.created_by AS \"created_by!\",
|
||||
v2_as_queue.script_path,
|
||||
v2_as_queue.args AS \"args: sqlx::types::Json<Box<RawValue>>\"
|
||||
FROM v2_as_queue
|
||||
JOIN v2_as_completed_job ON v2_as_completed_job.parent_job = v2_as_queue.id
|
||||
WHERE v2_as_completed_job.id = $1 AND v2_as_completed_job.workspace_id = $2
|
||||
LIMIT 1",
|
||||
job_id,
|
||||
&w_id
|
||||
)
|
||||
.fetch_optional(&db)
|
||||
.await
|
||||
.map_err(|e| error::Error::BadRequest(e.to_string()))?
|
||||
.ok_or_else(|| error::Error::BadRequest("This workflow is no longer running and has either already timed out or been cancelled or completed.".to_string()))
|
||||
.map(|r| (r.job_kind, r.script_hash, r.raw_flow, r.parent_job, r.created_at, r.created_by, r.script_path, r.args))?;
|
||||
|
||||
let flow_data = match cache::job::fetch_flow(&db, job_kind, script_hash).await {
|
||||
Ok(data) => data,
|
||||
Err(_) => {
|
||||
if let Some(parent_job_id) = parent_job_id.as_ref() {
|
||||
cache::job::fetch_preview_flow(&db, parent_job_id, raw_flow).await?
|
||||
} else {
|
||||
return Err(error::Error::BadRequest(
|
||||
"This workflow is no longer running and has either already timed out or been cancelled or completed.".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let flow_value = &flow_data.flow;
|
||||
let flow_step_id = flow_step_id.unwrap_or("");
|
||||
let module = flow_value.modules.iter().find(|m| m.id == flow_step_id);
|
||||
|
||||
tracing::debug!("Module: {:#?}", module);
|
||||
|
||||
let schema = module.and_then(|module| {
|
||||
module.suspend.as_ref().map(|suspend| ResumeFormRow {
|
||||
resume_form: suspend.resume_form.clone(),
|
||||
hide_cancel: suspend.hide_cancel,
|
||||
})
|
||||
});
|
||||
|
||||
let args_str = args.map_or("None".to_string(), |a| a.get().to_string());
|
||||
let parent_job_id_str = parent_job_id.map_or("None".to_string(), |id| id.to_string());
|
||||
let script_path_str = script_path.as_deref().unwrap_or("None");
|
||||
|
||||
let created_at_formatted = created_at.format("%Y-%m-%d %H:%M:%S").to_string();
|
||||
|
||||
let mut message_str = format!(
|
||||
"A workflow has been suspended and is waiting for approval:\n\n\
|
||||
*Created by*: {created_by}\n\
|
||||
*Created at*: {created_at_formatted}\n\
|
||||
*Script path*: {script_path_str}\n\
|
||||
*Args*: {args_str}\n\
|
||||
*Flow ID*: {parent_job_id_str}\n\n"
|
||||
);
|
||||
|
||||
// Append custom message if provided
|
||||
if let Some(msg) = message {
|
||||
message_str.push_str(msg);
|
||||
}
|
||||
|
||||
tracing::debug!("Schema: {:#?}", schema);
|
||||
|
||||
Ok(ApprovalFormDetails { message_str, urls, schema })
|
||||
}
|
||||
@@ -61,6 +61,8 @@ use windmill_common::{utils::GIT_VERSION, BASE_URL, INSTANCE_NAME};
|
||||
use crate::scim_ee::has_scim_token;
|
||||
use windmill_common::error::AppError;
|
||||
|
||||
use crate::teams_approvals::request_teams_approval;
|
||||
|
||||
#[cfg(feature = "agent_worker_server")]
|
||||
mod agent_workers_ee;
|
||||
mod ai;
|
||||
@@ -117,7 +119,9 @@ mod scim_ee;
|
||||
mod scripts;
|
||||
mod service_logs;
|
||||
mod settings;
|
||||
mod approvals;
|
||||
mod slack_approvals;
|
||||
mod teams_approvals;
|
||||
#[cfg(feature = "smtp")]
|
||||
mod smtp_server_ee;
|
||||
#[cfg(all(feature = "enterprise", feature = "sqs_trigger"))]
|
||||
@@ -647,6 +651,10 @@ pub async fn run_server(
|
||||
"/w/:workspace_id/jobs/slack_approval/:job_id",
|
||||
get(slack_approvals::request_slack_approval),
|
||||
)
|
||||
.route(
|
||||
"/w/:workspace_id/jobs/teams_approval/:job_id",
|
||||
get(request_teams_approval),
|
||||
)
|
||||
.nest("/w/:workspace_id/github_app", {
|
||||
#[cfg(feature = "enterprise")]
|
||||
{
|
||||
|
||||
@@ -15,29 +15,3 @@ pub fn start_nats_consumers(_db: DB, mut _killpill_rx: tokio::sync::broadcast::R
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub enum NatsTriggerConfigConnection {}
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct NatsTrigger {
|
||||
pub workspace_id: String,
|
||||
pub path: String,
|
||||
pub nats_resource_path: String,
|
||||
pub subjects: Vec<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub stream_name: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub consumer_name: Option<String>,
|
||||
pub use_jetstream: bool,
|
||||
pub script_path: String,
|
||||
pub is_flow: bool,
|
||||
pub edited_by: String,
|
||||
pub email: String,
|
||||
pub edited_at: chrono::DateTime<chrono::Utc>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub server_id: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub last_server_ping: Option<chrono::DateTime<chrono::Utc>>,
|
||||
pub extra_perms: serde_json::Value,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub error: Option<String>,
|
||||
pub enabled: bool,
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
use crate::db::DB;
|
||||
use axum::Router;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use windmill_common::auth::aws::AwsAuthResourceType;
|
||||
|
||||
|
||||
pub fn workspaced_service() -> Router {
|
||||
Router::new()
|
||||
}
|
||||
|
||||
pub fn start_sqs(_db: DB, mut _killpill_rx: tokio::sync::broadcast::Receiver<()>) -> () {
|
||||
// implementation is not open source
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct SqsTrigger {
|
||||
pub queue_url: String,
|
||||
pub aws_auth_resource_type: AwsAuthResourceType,
|
||||
pub aws_resource_path: String,
|
||||
pub message_attributes: Option<Vec<String>>,
|
||||
pub path: String,
|
||||
pub script_path: String,
|
||||
pub is_flow: bool,
|
||||
pub workspace_id: String,
|
||||
pub edited_by: String,
|
||||
pub email: String,
|
||||
pub edited_at: chrono::DateTime<chrono::Utc>,
|
||||
pub extra_perms: Option<serde_json::Value>,
|
||||
pub error: Option<String>,
|
||||
pub server_id: Option<String>,
|
||||
pub last_server_ping: Option<chrono::DateTime<chrono::Utc>>,
|
||||
pub enabled: bool,
|
||||
}
|
||||
1
backend/windmill-api/src/sqs_triggers_ee.rs
Symbolic link
1
backend/windmill-api/src/sqs_triggers_ee.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/alex/windmill/windmill/../windmill-ee-private/windmill-api/src/sqs_triggers_ee.rs
|
||||
@@ -1,5 +1,7 @@
|
||||
#[cfg(feature = "stripe")]
|
||||
use axum::Router;
|
||||
|
||||
#[cfg(feature = "stripe")]
|
||||
pub fn add_stripe_routes(router: Router) -> Router {
|
||||
return router;
|
||||
}
|
||||
|
||||
74
backend/windmill-api/src/teams_approvals.rs
Normal file
74
backend/windmill-api/src/teams_approvals.rs
Normal file
@@ -0,0 +1,74 @@
|
||||
use crate::approvals::{
|
||||
get_approval_form, ApprovalFormDetails, QueryDefaultArgsJson, QueryDynamicEnumJson, QueryFlowStepId, QueryMessage, ResumeFormRow,
|
||||
};
|
||||
use crate::jobs::QueryApprover;
|
||||
use crate::db::{ApiAuthed, DB};
|
||||
use axum::{
|
||||
extract::{Path, Query},
|
||||
Extension,
|
||||
};
|
||||
use http::StatusCode;
|
||||
use serde::Deserialize;
|
||||
use uuid::Uuid;
|
||||
use windmill_common::error::Error;
|
||||
use windmill_common::teams_ee::get_global_teams_bot_token;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct RequestTeamsApprovalPayload {
|
||||
pub team_name: String,
|
||||
pub channel_name: String,
|
||||
pub message: String,
|
||||
pub approver: String,
|
||||
pub default_args_json: Option<serde_json::Value>,
|
||||
pub dynamic_enums_json: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct QueryTeamName {
|
||||
pub team_name: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct QueryChannelName {
|
||||
pub channel_name: String,
|
||||
}
|
||||
|
||||
pub async fn request_teams_approval(
|
||||
authed: ApiAuthed,
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, job_id)): Path<(String, Uuid)>,
|
||||
Query(team_name): Query<QueryTeamName>,
|
||||
Query(channel_name): Query<QueryChannelName>,
|
||||
Query(approver): Query<QueryApprover>,
|
||||
Query(message): Query<QueryMessage>,
|
||||
Query(flow_step_id): Query<QueryFlowStepId>,
|
||||
Query(default_args_json): Query<QueryDefaultArgsJson>,
|
||||
Query(dynamic_enums_json): Query<QueryDynamicEnumJson>,
|
||||
) -> Result<StatusCode, Error> {
|
||||
let teams_bot_token = get_global_teams_bot_token(&db).await?;
|
||||
|
||||
let resume_id = rand::random::<u32>();
|
||||
|
||||
let approval_details = get_approval_form(
|
||||
db,
|
||||
w_id.as_str(),
|
||||
job_id,
|
||||
Some(flow_step_id.flow_step_id.as_str()),
|
||||
resume_id,
|
||||
approver.approver.as_deref(),
|
||||
message.message.as_deref(),
|
||||
).await?;
|
||||
|
||||
let ApprovalFormDetails { mut message_str, urls, schema } = approval_details;
|
||||
|
||||
let blocks = transform_schemas(
|
||||
message_str,
|
||||
schema,
|
||||
);
|
||||
|
||||
Ok(StatusCode::OK)
|
||||
}
|
||||
|
||||
fn transform_schemas(message_str: String, schema: Option<ResumeFormRow>) -> Vec<String> {
|
||||
vec![]
|
||||
}
|
||||
@@ -14,5 +14,5 @@ cp "${script_dirpath}/s3Types.ts" "${script_dirpath}/src/"
|
||||
echo "" >> "${script_dirpath}/src/index.ts"
|
||||
echo 'export type { S3Object, DenoS3LightClientSettings } from "./s3Types";' >> "${script_dirpath}/src/index.ts"
|
||||
echo "" >> "${script_dirpath}/src/index.ts"
|
||||
echo 'export { type Base64, setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, signS3Objects, signS3Object, task, runScript, runScriptAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, Sql } from "./client";' >> "${script_dirpath}/src/index.ts"
|
||||
echo 'export { type Base64, setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, signS3Objects, signS3Object, task, runScript, runScriptAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, Sql, requestInteractiveTeamsApproval, } from "./client";' >> "${script_dirpath}/src/index.ts"
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ script_dirpath="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
rm -rf "${script_dirpath}/src"
|
||||
|
||||
npx --yes @hey-api/openapi-ts@0.43.0 --input "${script_dirpath}/../backend/windmill-api/openapi.yaml" --output "${script_dirpath}/src" --useOptions --schemas false
|
||||
npx --yes @hey-api/openapi-ts@0.43.0 --input "${script_dirpath}/../backend/windmill-api/openapi.yaml" --output "${script_dirpath}/src" --useOptions --schemas false
|
||||
cat <<EOF - src/core/OpenAPI.ts > temp_file && mv temp_file src/core/OpenAPI.ts
|
||||
const getEnv = (key: string) => {
|
||||
if (typeof window === "undefined") {
|
||||
@@ -39,4 +39,4 @@ cp "${script_dirpath}/s3Types.ts" "${script_dirpath}/src/"
|
||||
echo "" >> "${script_dirpath}/src/index.ts"
|
||||
echo 'export type { S3Object, DenoS3LightClientSettings } from "./s3Types";' >> "${script_dirpath}/src/index.ts"
|
||||
echo "" >> "${script_dirpath}/src/index.ts"
|
||||
echo 'export { type Base64, setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, setProgress, getProgress, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, signS3Objects, signS3Object, task, runScript, runScriptAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, Sql } from "./client";' >> "${script_dirpath}/src/index.ts"
|
||||
echo 'export { type Base64, setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, setProgress, getProgress, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, signS3Objects, signS3Object, task, runScript, runScriptAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, Sql, requestInteractiveTeamsApproval } from "./client";' >> "${script_dirpath}/src/index.ts"
|
||||
|
||||
@@ -456,8 +456,8 @@ export async function getProgress(jobId?: any): Promise<number | null> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a flow user state
|
||||
* @param key key of the state
|
||||
* Set a flow user state
|
||||
* @param key key of the state
|
||||
* @param value value of the state
|
||||
|
||||
*/
|
||||
@@ -920,6 +920,15 @@ interface SlackApprovalOptions {
|
||||
dynamicEnumsJson?: Record<string, any>;
|
||||
}
|
||||
|
||||
interface TeamsApprovalOptions {
|
||||
teamName: string;
|
||||
channelName: string;
|
||||
message?: string;
|
||||
approver?: string;
|
||||
defaultArgsJson?: Record<string, any>;
|
||||
dynamicEnumsJson?: Record<string, any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an interactive approval request via Slack, allowing optional customization of the message, approver, and form fields.
|
||||
*
|
||||
@@ -1012,6 +1021,98 @@ export async function requestInteractiveSlackApproval({
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an interactive approval request via Teams, allowing optional customization of the message, approver, and form fields.
|
||||
*
|
||||
* **[Enterprise Edition Only]** To include form fields in the Teams approval request, go to **Advanced -> Suspend -> Form**
|
||||
* and define a form. Learn more at [Windmill Documentation](https://www.windmill.dev/docs/flows/flow_approval#form).
|
||||
*
|
||||
* @param {Object} options - The configuration options for the Teams approval request.
|
||||
* @param {string} options.teamName - The Teams team name where the approval request will be sent.
|
||||
* @param {string} options.channelName - The Teams channel name where the approval request will be sent.
|
||||
* @param {string} [options.message] - Optional custom message to include in the Teams approval request.
|
||||
* @param {string} [options.approver] - Optional user ID or name of the approver for the request.
|
||||
* @param {DefaultArgs} [options.defaultArgsJson] - Optional object defining or overriding the default arguments to a form field.
|
||||
* @param {Enums} [options.dynamicEnumsJson] - Optional object overriding the enum default values of an enum form field.
|
||||
*
|
||||
* @returns {Promise<void>} Resolves when the Teams approval request is successfully sent.
|
||||
*
|
||||
* @throws {Error} If the function is not called within a flow or flow preview.
|
||||
* @throws {Error} If the `JobService.getTeamsApprovalPayload` call fails.
|
||||
*
|
||||
* **Usage Example:**
|
||||
* ```typescript
|
||||
* await requestInteractiveTeamsApproval({
|
||||
* teamName: "admins-teams",
|
||||
* channelName: "admins-teams-channel",
|
||||
* message: "Please approve this request",
|
||||
* approver: "approver123",
|
||||
* defaultArgsJson: { key1: "value1", key2: 42 },
|
||||
* dynamicEnumsJson: { foo: ["choice1", "choice2"], bar: ["optionA", "optionB"] },
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* **Note:** This function requires execution within a Windmill flow or flow preview.
|
||||
*/
|
||||
export async function requestInteractiveTeamsApproval({
|
||||
teamName,
|
||||
channelName,
|
||||
message,
|
||||
approver,
|
||||
defaultArgsJson,
|
||||
dynamicEnumsJson,
|
||||
}: TeamsApprovalOptions): Promise<void> {
|
||||
const workspace = getWorkspace();
|
||||
const flowJobId = getEnv("WM_FLOW_JOB_ID");
|
||||
|
||||
if (!flowJobId) {
|
||||
throw new Error(
|
||||
"You can't use this function in a standalone script or flow step preview. Please use it in a flow or a flow preview."
|
||||
);
|
||||
}
|
||||
|
||||
const flowStepId = getEnv("WM_FLOW_STEP_ID");
|
||||
if (!flowStepId) {
|
||||
throw new Error("This function can only be called as a flow step");
|
||||
}
|
||||
|
||||
// Only include non-empty parameters
|
||||
const params: {
|
||||
approver?: string;
|
||||
message?: string;
|
||||
teamName: string;
|
||||
channelName: string;
|
||||
flowStepId: string;
|
||||
defaultArgsJson?: string;
|
||||
dynamicEnumsJson?: string;
|
||||
} = {
|
||||
teamName,
|
||||
channelName,
|
||||
flowStepId,
|
||||
};
|
||||
|
||||
if (message) {
|
||||
params.message = message;
|
||||
}
|
||||
if (approver) {
|
||||
params.approver = approver;
|
||||
}
|
||||
|
||||
if (defaultArgsJson) {
|
||||
params.defaultArgsJson = JSON.stringify(defaultArgsJson);
|
||||
}
|
||||
|
||||
if (dynamicEnumsJson) {
|
||||
params.dynamicEnumsJson = JSON.stringify(dynamicEnumsJson);
|
||||
}
|
||||
|
||||
await JobService.getTeamsApprovalPayload({
|
||||
workspace,
|
||||
...params,
|
||||
id: getEnv("WM_JOB_ID") ?? "NO_JOB_ID",
|
||||
});
|
||||
}
|
||||
|
||||
async function getMockedApi(): Promise<MockedApi | undefined> {
|
||||
if (mockedApi) {
|
||||
return mockedApi;
|
||||
|
||||
Reference in New Issue
Block a user