Merge branch 'main' into dieri/change-workspace-id-async

This commit is contained in:
dieriba
2025-10-24 16:39:13 +02:00
8 changed files with 61 additions and 44 deletions
@@ -62,7 +62,9 @@ pub async fn increase_trigger_version(tx: &mut PgConnection) -> Result<()> {
}
pub fn generate_route_path_key(route_path: &str) -> String {
ROUTE_PATH_KEY_RE.replace_all(route_path, "/*").to_string()
ROUTE_PATH_KEY_RE
.replace_all(route_path, "${1}${2}key")
.to_string()
}
pub async fn route_path_key_exists(
@@ -322,7 +324,7 @@ async fn check_if_route_exist(
workspace_id: &str,
trigger_path: Option<&str>,
) -> Result<String> {
let route_path_key = ROUTE_PATH_KEY_RE.replace_all(&config.route_path, ":key");
let route_path_key = generate_route_path_key(&config.route_path);
let exists = route_path_key_exists(
&route_path_key,
@@ -340,7 +342,7 @@ async fn check_if_route_exist(
));
}
Ok(route_path_key.into_owned())
Ok(route_path_key)
}
pub struct HttpTrigger;
@@ -192,8 +192,9 @@ impl<'de> Deserialize<'de> for HttpConfigRequest {
// Regex patterns for route validation
lazy_static::lazy_static! {
static ref ROUTE_PATH_KEY_RE: regex::Regex = regex::Regex::new(r"/?:[-\w]+").unwrap();
static ref VALID_ROUTE_PATH_RE: regex::Regex = regex::Regex::new(r"^:?[-\w]+(/:?[-\w]+)*$").unwrap();
// Matches named params like :id or wildcards like :* or *
static ref ROUTE_PATH_KEY_RE: regex::Regex = regex::Regex::new(r"(/)?(:|\*)[-\w]+").unwrap();
static ref VALID_ROUTE_PATH_RE: regex::Regex = regex::Regex::new(r"^(\*[-\w]+$|:?[-\w]+)(/(\*[-\w]+$|:?[-\w]+))*$").unwrap();
}
#[derive(Deserialize)]
+1 -5
View File
@@ -409,10 +409,6 @@ fn format_pull_query(peek: String) -> String {
raw_flow, script_entrypoint_override, preprocessed
FROM v2_job
WHERE id = (SELECT id FROM peek)
), delete_debounce AS NOT MATERIALIZED (
DELETE FROM debounce_key
USING j
WHERE j.kind::text != 'flowdependencies' AND j.kind::text != 'appdependencies' AND j.kind::text != 'dependencies' AND debounce_key.job_id = j.id
) SELECT j.id, j.workspace_id, j.parent_job, j.created_by, started_at, scheduled_for,
j.runnable_id, j.runnable_path, j.args, canceled_by,
canceled_reason, j.kind, j.trigger, j.trigger_kind, j.permissioned_as,
@@ -430,7 +426,7 @@ fn format_pull_query(peek: String) -> String {
",
peek
);
// tracing::debug!("pull query: {}", r);
tracing::debug!("pull query: {}", r);
r
}
+10 -2
View File
@@ -3622,8 +3622,8 @@ pub async fn push<'c, 'd>(
cache_ttl,
dedicated_worker,
_low_level_priority,
custom_debounce_key,
debounce_delay_s,
mut custom_debounce_key,
mut debounce_delay_s,
) = match job_payload {
JobPayload::ScriptHash {
hash,
@@ -4391,6 +4391,14 @@ pub async fn push<'c, 'd>(
),
};
if custom_debounce_key.is_some() {
tracing::warn!("debouncing has been disabled temporarily, ignoring debounce_key");
custom_debounce_key = None;
}
if debounce_delay_s.is_some() {
tracing::warn!("debouncing has been disabled temporarily, ignoring debounce_delay_s");
debounce_delay_s = None;
}
// Enforce concurrency limit on all dependency jobs.
// TODO: We can ignore this for scripts djobs. The main reason we need all djobs to be sequential is because we have
// nodes_to_relock and we need all locks whose corresponding steps aren't in nodes_to_relock be already present.
+27 -28
View File
@@ -142,7 +142,7 @@ export async function findResourceFile(path: string) {
if (validCandidates.length > 1) {
throw new Error(
"Found two resource files for the same resource" +
validCandidates.join(", ")
validCandidates.join(", ")
);
}
if (validCandidates.length < 1) {
@@ -214,7 +214,8 @@ export async function handleFile(
if (codebase.customBundler) {
log.info(`Using custom bundler ${codebase.customBundler} for ${path}`);
bundleContent = execSync(
codebase.customBundler + " " + path
codebase.customBundler + " " + path,
{ maxBuffer: 1024 * 1024 * 50 }
).toString();
log.info("Custom bundler executed for " + path);
} else {
@@ -273,20 +274,20 @@ export async function handleFile(
let typed = opts?.skipScriptsMetadata
? undefined
: (
await parseMetadataFile(
remotePath,
opts
? {
...opts,
path,
workspaceRemote: workspace,
schemaOnly: codebase ? true : undefined,
}
: undefined,
globalDeps,
codebases
)
)?.payload;
await parseMetadataFile(
remotePath,
opts
? {
...opts,
path,
workspaceRemote: workspace,
schemaOnly: codebase ? true : undefined,
}
: undefined,
globalDeps,
codebases
)
)?.payload;
const workspaceId = workspace.workspaceId;
@@ -373,19 +374,19 @@ export async function handleFile(
deepEqual(typed.schema, remote.schema) &&
typed.tag == remote.tag &&
(typed.ws_error_handler_muted ?? false) ==
remote.ws_error_handler_muted &&
remote.ws_error_handler_muted &&
typed.dedicated_worker == remote.dedicated_worker &&
typed.cache_ttl == remote.cache_ttl &&
typed.concurrency_time_window_s ==
remote.concurrency_time_window_s &&
remote.concurrency_time_window_s &&
typed.concurrent_limit == remote.concurrent_limit &&
Boolean(typed.restart_unless_cancelled) ==
Boolean(remote.restart_unless_cancelled) &&
Boolean(remote.restart_unless_cancelled) &&
Boolean(typed.visible_to_runner_only) ==
Boolean(remote.visible_to_runner_only) &&
Boolean(remote.visible_to_runner_only) &&
Boolean(typed.no_main_func) == Boolean(remote.no_main_func) &&
Boolean(typed.has_preprocessor) ==
Boolean(remote.has_preprocessor) &&
Boolean(remote.has_preprocessor) &&
typed.priority == Boolean(remote.priority) &&
typed.timeout == remote.timeout &&
//@ts-ignore
@@ -478,8 +479,7 @@ async function createScript(
});
} catch (e: any) {
throw Error(
`Script creation for ${body.path} with parent ${
body.parent_hash
`Script creation for ${body.path} with parent ${body.parent_hash
} was not successful: ${e.body ?? e.message} `
);
}
@@ -505,8 +505,7 @@ async function createScript(
});
if (req.status != 201) {
throw Error(
`Script snapshot creation was not successful: ${req.status} - ${
req.statusText
`Script snapshot creation was not successful: ${req.status} - ${req.statusText
} - ${await req.text()} `
);
}
@@ -518,8 +517,8 @@ export async function findContentFile(filePath: string) {
const candidates = filePath.endsWith("script.json")
? exts.map((x) => filePath.replace(".script.json", x))
: filePath.endsWith("script.lock")
? exts.map((x) => filePath.replace(".script.lock", x))
: exts.map((x) => filePath.replace(".script.yaml", x));
? exts.map((x) => filePath.replace(".script.lock", x))
: exts.map((x) => filePath.replace(".script.yaml", x));
const validCandidates = (
await Promise.all(
@@ -538,7 +537,7 @@ export async function findContentFile(filePath: string) {
if (validCandidates.length > 1) {
throw new Error(
"No content path given and more than one candidate found: " +
validCandidates.join(", ")
validCandidates.join(", ")
);
}
if (validCandidates.length < 1) {
@@ -20,6 +20,7 @@
additionalExitAction?: () => void
triggerOnSearchParamsChange?: boolean
onDiscardChanges?: () => void
tabMode?: boolean
}
let {
@@ -27,7 +28,8 @@
diffDrawer = undefined,
additionalExitAction = () => {},
triggerOnSearchParamsChange = false,
onDiscardChanges = undefined
onDiscardChanges = undefined,
tabMode = false
}: Props = $props()
let savedValue: Value | undefined = $state(undefined)
let modifiedValue: Value | undefined = $state(undefined)
@@ -66,7 +68,9 @@
orderedJsonStringify(replaceFalseWithUndefined(draftOrDeployed)) ===
orderedJsonStringify(replaceFalseWithUndefined(current))
) {
bypassBeforeNavigate = true
if (!tabMode) {
bypassBeforeNavigate = true
}
additionalExitAction?.()
} else {
await openModal()
@@ -54,7 +54,11 @@
clearTimeout(validateTimeout)
}
validateTimeout = setTimeout(async () => {
if (!routePath || !method || !/^:?[-\w]+(\/:?[-\w]+)*$/.test(routePath)) {
if (
!routePath ||
!method ||
!/^(\*[-\w]+$|:?[-\w]+)(\/(\*[-\w]+$|:?[-\w]+))*$/.test(routePath)
) {
routeError = 'Endpoint not valid'
} else if (await routeExists(routePath, method, workspaced_route)) {
routeError = 'Endpoint already taken'
@@ -140,7 +144,9 @@
bind:value={route_path}
error={routeError !== ''}
/>
<div class="text-2xs text-secondary"> ':myparam' for path params </div>
<div class="text-2xs text-secondary">
Use ':myparam' for path params and '*mywildcard' for wildcards
</div>
</div>
</label>
@@ -1047,6 +1047,7 @@
getInitialAndModifiedValues={getAllUnsavedChanges}
onDiscardChanges={discardAllChanges}
triggerOnSearchParamsChange={true}
tabMode={true}
/>
<style>