Merge branch 'main' into alp/fix_build

This commit is contained in:
Alexander Petric
2025-02-13 16:37:47 -05:00
committed by GitHub
21 changed files with 147 additions and 273 deletions
@@ -1,12 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DROP INDEX CONCURRENTLY IF EXISTS ix_completed_job_workspace_id_created_at_new_6",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "42177e249794a4b7b945b93efd853afc1f1ad354599de11ebc6e256b58543265"
}
@@ -1,12 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DROP INDEX CONCURRENTLY IF EXISTS concurrency_limit_stats_completed_job",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "4d3bbcc029ec0926bf97de4b5ef97dfd5eeda5977a8746be77c8aa65a7ec299e"
}
@@ -1,12 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DROP INDEX CONCURRENTLY IF EXISTS ix_completed_job_workspace_id_started_at_new",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "608393951c85d9e721b506d2f6a7a47667b6f9f3dc0d51987cce159433459ab0"
}
@@ -1,12 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DROP INDEX CONCURRENTLY IF EXISTS root_job_index_by_path_2",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "6536214f31e9d600e868b01385d8c6395e2440ea27553b7ccb18d7149b106728"
}
@@ -1,12 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DROP INDEX CONCURRENTLY IF EXISTS ix_completed_job_workspace_id_created_at_new_2",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "74754b03304a69391d61560848e89569fe5666e36ca2650dabd9b494dc30f435"
}
@@ -1,12 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DROP INDEX CONCURRENTLY IF EXISTS ix_completed_job_workspace_id_created_at_new_3",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "85181656012b18cd26998128c30b1bf1f70e17486a9d315db130852d5e325200"
}
@@ -1,12 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DROP INDEX CONCURRENTLY IF EXISTS scheduled_root_job",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "93586f1ffc7b8dbe62b21a21acfa6854a34a99d2bf107feaafc499588f7330a0"
}
@@ -0,0 +1,12 @@
{
"db_name": "PostgreSQL",
"query": "ALTER TABLE v2_job ENABLE ROW LEVEL SECURITY",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "c458012c39f1327fb2bfd6b087ee6dbe1380eca532f50bab0cb89a91d42131cf"
}
@@ -1,12 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "create index concurrently if not exists ix_v2_job_root_by_path\n on v2_job (workspace_id, runnable_path, created_at DESC)\n where parent_job is null",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "cb5a8545ea140ed69c7b70d8c08cb3c037309f09e84acbb7945a0466d6e9f576"
}
@@ -1,12 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DROP INDEX CONCURRENTLY IF EXISTS ix_completed_job_workspace_id_created_at_new_9",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "d949e8b91fbdf4c50c1c2cbc608cf0b385bff14faab495e049f2029790f76d25"
}
@@ -1,12 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DROP INDEX CONCURRENTLY IF EXISTS ix_completed_job_workspace_id_created_at_new_8",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "e00144305b880cca3994b53c4a080e111a159a749728ce5363100cf883bdf02a"
}
@@ -1,12 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DROP INDEX CONCURRENTLY IF EXISTS ix_completed_job_workspace_id_created_at_new_7",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "e9038a6fcfd8bdf4855c5919ce634b976cbe0280e7215862aaf5ef445663793d"
}
@@ -1,12 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DROP INDEX CONCURRENTLY IF EXISTS ix_completed_job_created_at",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "ebfd39f168722701fb63cd37aaef3741b9782d8e2d4b6ff6c104fdcac5f58323"
}
@@ -1,12 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DROP INDEX CONCURRENTLY IF EXISTS ix_completed_job_workspace_id_created_at_new_5",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "fa94a9ee5514f6808d3813394e62c86a69b7b7378333322a57856f8e43c6cd77"
}
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT\n workspace.id AS \"id!\",\n workspace.name AS \"name!\",\n workspace.owner AS \"owner!\",\n workspace.deleted AS \"deleted!\",\n workspace.premium AS \"premium!\",\n workspace_settings.color AS \"color!\"\n FROM workspace\n LEFT JOIN workspace_settings ON workspace.id = workspace_settings.workspace_id\n LIMIT $1 OFFSET $2",
"query": "SELECT\n workspace.id AS \"id!\",\n workspace.name AS \"name!\",\n workspace.owner AS \"owner!\",\n workspace.deleted AS \"deleted!\",\n workspace.premium AS \"premium!\",\n workspace_settings.color AS \"color\"\n FROM workspace\n LEFT JOIN workspace_settings ON workspace.id = workspace_settings.workspace_id\n LIMIT $1 OFFSET $2",
"describe": {
"columns": [
{
@@ -30,7 +30,7 @@
},
{
"ordinal": 5,
"name": "color!",
"name": "color",
"type_info": "Varchar"
}
],
@@ -41,13 +41,13 @@
]
},
"nullable": [
true,
true,
true,
true,
true,
false,
false,
false,
false,
false,
true
]
},
"hash": "72f98539ff9874479f6fc0e9f45f55354ad0397356c67a6162249a3cc553f125"
"hash": "fec6d5674dc6b5a6a0ece419c40508835affcb7679a48f2a443777e829bd1e74"
}
+99 -87
View File
@@ -225,27 +225,27 @@ pub async fn migrate(db: &DB) -> Result<(), Error> {
}
});
// if !has_done_migration(db, "v2_finalize_disable_sync").await {
// let db2 = db.clone();
// let _ = tokio::task::spawn(async move {
// loop {
// if !*MIN_VERSION_IS_AT_LEAST_1_461.read().await {
// tracing::info!("Waiting for all workers to be at least version 1.461 before applying v2 finalize migration, sleeping for 5s...");
// tokio::time::sleep(Duration::from_secs(5)).await;
// continue;
// }
// if let Err(err) = v2_finalize(&db2).await {
// tracing::error!(
// "{err:#}: Could not apply v2 finalize migration, retry in 30s.."
// );
// tokio::time::sleep(Duration::from_secs(30)).await;
// continue;
// }
// tracing::info!("v2 finalization step successfully applied.");
// break;
// }
// });
// }
if !has_done_migration(db, "v2_finalize_disable_sync_III").await {
let db2 = db.clone();
let _ = tokio::task::spawn(async move {
loop {
if !*MIN_VERSION_IS_AT_LEAST_1_461.read().await {
tracing::info!("Waiting for all workers to be at least version 1.461 before applying v2 finalize migration, sleeping for 5s...");
tokio::time::sleep(Duration::from_secs(5)).await;
continue;
}
if let Err(err) = v2_finalize(&db2).await {
tracing::error!(
"{err:#}: Could not apply v2 finalize migration, retry in 30s.."
);
tokio::time::sleep(Duration::from_secs(30)).await;
continue;
}
tracing::info!("v2 finalization step successfully applied.");
break;
}
});
}
Ok(())
}
@@ -329,9 +329,12 @@ macro_rules! run_windmill_migration {
sqlx::migrate::MigrateError::Execute(e)
})?
.unwrap_or(false);
if !r {
tracing::info!("PG {migration_job_name} lock already acquired by another server or worker, retrying in 5s. (look for the advisory lock in pg_lock with granted = true)");
drop($tx);
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
$tx = db.begin().await?;
}
}
tracing::info!("acquired lock for {migration_job_name}");
@@ -367,21 +370,25 @@ macro_rules! run_windmill_migration {
}
async fn v2_finalize(db: &DB) -> Result<(), Error> {
run_windmill_migration!("v2_finalize_disable_sync", db, |tx| {
run_windmill_migration!("v2_finalize_disable_sync_III", db, |tx| {
tx.execute(
r#"
DROP FUNCTION v2_job_after_update CASCADE;
DROP FUNCTION v2_job_completed_before_insert CASCADE;
DROP FUNCTION v2_job_completed_before_update CASCADE;
DROP FUNCTION v2_job_queue_after_insert CASCADE;
DROP FUNCTION v2_job_queue_before_insert CASCADE;
DROP FUNCTION v2_job_queue_before_update CASCADE;
DROP FUNCTION v2_job_runtime_before_insert CASCADE;
DROP FUNCTION v2_job_runtime_before_update CASCADE;
DROP FUNCTION v2_job_status_before_insert CASCADE;
DROP FUNCTION v2_job_status_before_update CASCADE;
ALTER TABLE v2_job_queue DISABLE ROW LEVEL SECURITY;
ALTER TABLE v2_job_completed DISABLE ROW LEVEL SECURITY;
DROP VIEW completed_job, completed_job_view, job, queue, queue_view CASCADE;
DROP FUNCTION IF EXISTS v2_job_after_update CASCADE;
DROP FUNCTION IF EXISTS v2_job_completed_before_insert CASCADE;
DROP FUNCTION IF EXISTS v2_job_completed_before_update CASCADE;
DROP FUNCTION IF EXISTS v2_job_queue_after_insert CASCADE;
DROP FUNCTION IF EXISTS v2_job_queue_before_insert CASCADE;
DROP FUNCTION IF EXISTS v2_job_queue_before_update CASCADE;
DROP FUNCTION IF EXISTS v2_job_runtime_before_insert CASCADE;
DROP FUNCTION IF EXISTS v2_job_runtime_before_update CASCADE;
DROP FUNCTION IF EXISTS v2_job_status_before_insert CASCADE;
DROP FUNCTION IF EXISTS v2_job_status_before_update CASCADE;
DROP VIEW IF EXISTS completed_job, completed_job_view, job, queue, queue_view CASCADE;
"#,
)
.await?;
@@ -390,36 +397,36 @@ async fn v2_finalize(db: &DB) -> Result<(), Error> {
tx.execute(
r#"
ALTER TABLE v2_job_queue
DROP COLUMN __parent_job CASCADE,
DROP COLUMN __created_by CASCADE,
DROP COLUMN __script_hash CASCADE,
DROP COLUMN __script_path CASCADE,
DROP COLUMN __args CASCADE,
DROP COLUMN __logs CASCADE,
DROP COLUMN __raw_code CASCADE,
DROP COLUMN __canceled CASCADE,
DROP COLUMN __last_ping CASCADE,
DROP COLUMN __job_kind CASCADE,
DROP COLUMN __env_id CASCADE,
DROP COLUMN __schedule_path CASCADE,
DROP COLUMN __permissioned_as CASCADE,
DROP COLUMN __flow_status CASCADE,
DROP COLUMN __raw_flow CASCADE,
DROP COLUMN __is_flow_step CASCADE,
DROP COLUMN __language CASCADE,
DROP COLUMN __same_worker CASCADE,
DROP COLUMN __raw_lock CASCADE,
DROP COLUMN __pre_run_error CASCADE,
DROP COLUMN __email CASCADE,
DROP COLUMN __visible_to_owner CASCADE,
DROP COLUMN __mem_peak CASCADE,
DROP COLUMN __root_job CASCADE,
DROP COLUMN __leaf_jobs CASCADE,
DROP COLUMN __concurrent_limit CASCADE,
DROP COLUMN __concurrency_time_window_s CASCADE,
DROP COLUMN __timeout CASCADE,
DROP COLUMN __flow_step_id CASCADE,
DROP COLUMN __cache_ttl CASCADE;
DROP COLUMN IF EXISTS __parent_job CASCADE,
DROP COLUMN IF EXISTS __created_by CASCADE,
DROP COLUMN IF EXISTS __script_hash CASCADE,
DROP COLUMN IF EXISTS __script_path CASCADE,
DROP COLUMN IF EXISTS __args CASCADE,
DROP COLUMN IF EXISTS __logs CASCADE,
DROP COLUMN IF EXISTS __raw_code CASCADE,
DROP COLUMN IF EXISTS __canceled CASCADE,
DROP COLUMN IF EXISTS __last_ping CASCADE,
DROP COLUMN IF EXISTS __job_kind CASCADE,
DROP COLUMN IF EXISTS __env_id CASCADE,
DROP COLUMN IF EXISTS __schedule_path CASCADE,
DROP COLUMN IF EXISTS __permissioned_as CASCADE,
DROP COLUMN IF EXISTS __flow_status CASCADE,
DROP COLUMN IF EXISTS __raw_flow CASCADE,
DROP COLUMN IF EXISTS __is_flow_step CASCADE,
DROP COLUMN IF EXISTS __language CASCADE,
DROP COLUMN IF EXISTS __same_worker CASCADE,
DROP COLUMN IF EXISTS __raw_lock CASCADE,
DROP COLUMN IF EXISTS __pre_run_error CASCADE,
DROP COLUMN IF EXISTS __email CASCADE,
DROP COLUMN IF EXISTS __visible_to_owner CASCADE,
DROP COLUMN IF EXISTS __mem_peak CASCADE,
DROP COLUMN IF EXISTS __root_job CASCADE,
DROP COLUMN IF EXISTS __leaf_jobs CASCADE,
DROP COLUMN IF EXISTS __concurrent_limit CASCADE,
DROP COLUMN IF EXISTS __concurrency_time_window_s CASCADE,
DROP COLUMN IF EXISTS __timeout CASCADE,
DROP COLUMN IF EXISTS __flow_step_id CASCADE,
DROP COLUMN IF EXISTS __cache_ttl CASCADE;
"#,
)
.await?;
@@ -427,31 +434,30 @@ async fn v2_finalize(db: &DB) -> Result<(), Error> {
run_windmill_migration!("v2_finalize_job_completed", db, |tx| {
tx.execute(
r#"
LOCK TABLE v2_job_queue IN ACCESS EXCLUSIVE MODE;
ALTER TABLE v2_job_completed
DROP COLUMN __parent_job CASCADE,
DROP COLUMN __created_by CASCADE,
DROP COLUMN __created_at CASCADE,
DROP COLUMN __success CASCADE,
DROP COLUMN __script_hash CASCADE,
DROP COLUMN __script_path CASCADE,
DROP COLUMN __args CASCADE,
DROP COLUMN __logs CASCADE,
DROP COLUMN __raw_code CASCADE,
DROP COLUMN __canceled CASCADE,
DROP COLUMN __job_kind CASCADE,
DROP COLUMN __env_id CASCADE,
DROP COLUMN __schedule_path CASCADE,
DROP COLUMN __permissioned_as CASCADE,
DROP COLUMN __raw_flow CASCADE,
DROP COLUMN __is_flow_step CASCADE,
DROP COLUMN __language CASCADE,
DROP COLUMN __is_skipped CASCADE,
DROP COLUMN __raw_lock CASCADE,
DROP COLUMN __email CASCADE,
DROP COLUMN __visible_to_owner CASCADE,
DROP COLUMN __tag CASCADE,
DROP COLUMN __priority CASCADE;
DROP COLUMN IF EXISTS __parent_job CASCADE,
DROP COLUMN IF EXISTS __created_by CASCADE,
DROP COLUMN IF EXISTS __created_at CASCADE,
DROP COLUMN IF EXISTS __success CASCADE,
DROP COLUMN IF EXISTS __script_hash CASCADE,
DROP COLUMN IF EXISTS __script_path CASCADE,
DROP COLUMN IF EXISTS __args CASCADE,
DROP COLUMN IF EXISTS __logs CASCADE,
DROP COLUMN IF EXISTS __raw_code CASCADE,
DROP COLUMN IF EXISTS __canceled CASCADE,
DROP COLUMN IF EXISTS __job_kind CASCADE,
DROP COLUMN IF EXISTS __env_id CASCADE,
DROP COLUMN IF EXISTS __schedule_path CASCADE,
DROP COLUMN IF EXISTS __permissioned_as CASCADE,
DROP COLUMN IF EXISTS __raw_flow CASCADE,
DROP COLUMN IF EXISTS __is_flow_step CASCADE,
DROP COLUMN IF EXISTS __language CASCADE,
DROP COLUMN IF EXISTS __is_skipped CASCADE,
DROP COLUMN IF EXISTS __raw_lock CASCADE,
DROP COLUMN IF EXISTS __email CASCADE,
DROP COLUMN IF EXISTS __visible_to_owner CASCADE,
DROP COLUMN IF EXISTS __tag CASCADE,
DROP COLUMN IF EXISTS __priority CASCADE;
"#,
)
.await?;
@@ -641,6 +647,12 @@ async fn fix_job_completed_index(db: &DB) -> Result<(), Error> {
.await?;
});
// run_windmill_migration!("v2_jobs_rls", &db, |tx| {
// sqlx::query!("ALTER TABLE v2_job ENABLE ROW LEVEL SECURITY")
// .execute(db)
// .await?;
// });
Ok(())
}
+2 -1
View File
@@ -341,6 +341,7 @@ pub struct ScheduleLight {
pub script_path: String,
pub is_flow: bool,
pub summary: Option<String>,
pub extra_perms: serde_json::Value,
}
async fn list_schedule(
authed: ApiAuthed,
@@ -351,7 +352,7 @@ async fn list_schedule(
let mut tx = user_db.begin(&authed).await?;
let (per_page, offset) = paginate(Pagination { per_page: lsq.per_page, page: lsq.page });
let mut sqlb = SqlBuilder::select_from("schedule")
.field("workspace_id, path, edited_by, edited_at, schedule, timezone, enabled, script_path, is_flow, summary")
.field("workspace_id, path, edited_by, edited_at, schedule, timezone, enabled, script_path, is_flow, summary, extra_perms")
.order_by("edited_at", true)
.and_where("workspace_id = ?".bind(&w_id))
.offset(offset)
+1 -1
View File
@@ -1410,7 +1410,7 @@ async fn list_workspaces_as_super_admin(
workspace.owner AS \"owner!\",
workspace.deleted AS \"deleted!\",
workspace.premium AS \"premium!\",
workspace_settings.color AS \"color!\"
workspace_settings.color AS \"color\"
FROM workspace
LEFT JOIN workspace_settings ON workspace.id = workspace_settings.workspace_id
LIMIT $1 OFFSET $2",
@@ -422,6 +422,9 @@
[e.target['value']]: ''
}
}
if (e.target?.['value'] === 'teams_channel') {
fetchTeams()
}
}}
value={(() => {
if (!v) return 'email'
@@ -456,15 +459,17 @@
selected={!$values['critical_error_channels'][i]?.teams_channel
?.team_id}>Select team</option
>
{#each $values['teams'] as team}
<option
value={team.team_id}
selected={$values['critical_error_channels'][i]?.teams_channel
?.team_id === team.team_id}
>
{team.team_name}
</option>
{/each}
{#if $values['teams']}
{#each $values['teams'] as team}
<option
value={team.team_id}
selected={$values['critical_error_channels'][i]?.teams_channel
?.team_id === team.team_id}
>
{team.team_name}
</option>
{/each}
{/if}
</select>
{#if $values['critical_error_channels'][i]?.teams_channel?.team_id}
<select
@@ -17,17 +17,17 @@
let username = $userStore?.username ?? ''
let pgroups = $userStore?.pgroups ?? []
let pusername = `u/${username}`
let extraPermsKeys = Object.keys(extraPerms)
let extraPermsKeys = Object.keys(extraPerms ?? {})
if (pusername in extraPermsKeys) {
if (extraPerms[pusername]) {
if (extraPerms?.[pusername]) {
kind = 'write'
} else {
kind = 'read'
}
reason = 'This item was shared to you personally'
} else {
let writeGroup = pgroups.find((x) => extraPermsKeys.includes(x) && extraPerms[x])
let writeGroup = pgroups.find((x) => extraPermsKeys.includes(x) && extraPerms?.[x])
if (writeGroup) {
kind = 'write'
reason = `This item was write shared to the group ${writeGroup} which you are a member of`
+8 -8
View File
@@ -82,9 +82,9 @@ export function displayDate(
}
const dateChoices: Intl.DateTimeFormatOptions = displayDate
? {
day: 'numeric',
month: 'numeric'
}
day: 'numeric',
month: 'numeric'
}
: {}
return date.toLocaleString(undefined, {
...timeChoices,
@@ -351,7 +351,7 @@ export function removeItemAll<T>(arr: T[], value: T) {
}
export function emptyString(str: string | undefined | null): boolean {
return str === undefined || str === null || str === ''
return str === undefined || str === null || str === ''
}
export function emptyStringTrimmed(str: string | undefined | null): boolean {
@@ -705,7 +705,7 @@ export function canWrite(
if (user?.is_admin || user?.is_super_admin) {
return true
}
let keys = Object.keys(extra_perms)
let keys = Object.keys(extra_perms ?? {})
if (!user) {
return false
}
@@ -713,10 +713,10 @@ export function canWrite(
return true
}
let userOwner = `u/${user.username}`
if (keys.includes(userOwner) && extra_perms[userOwner]) {
if (keys.includes(userOwner) && extra_perms?.[userOwner]) {
return true
}
if (user.pgroups.findIndex((x) => keys.includes(x) && extra_perms[x]) != -1) {
if (user.pgroups.findIndex((x) => keys.includes(x) && extra_perms?.[x]) != -1) {
return true
}
if (user.folders.findIndex((x) => path.startsWith('f/' + x + '/') && user.folders[x]) != -1) {
@@ -846,7 +846,7 @@ export async function tryEvery({
try {
await tryCode()
break
} catch (err) {}
} catch (err) { }
i++
}
if (i >= times) {