-
Notifications
You must be signed in to change notification settings - Fork 840
feat: allow http trigger to be disabled #6976
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Deploying windmill with
|
| Latest commit: |
7f4a9d1
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://56f0657e.windmill.pages.dev |
| Branch Preview URL: | https://dieri-allow-http-trigger-to.windmill.pages.dev |
|
I'll analyze this and get back to you. |
|
Claude finished @dieriba's task —— View job PR Review: Allow HTTP Trigger to be DisabledI've completed a comprehensive review of this PR. The feature implementation is solid overall, but there are several important issues that should be addressed before merging. SummaryThis PR adds the ability to enable/disable HTTP triggers in Windmill. The implementation includes:
Critical Issues 🔴1. Migration Missing Default Value (backend/migrations/...up.sql:2)The migration adds
Fix Required: ALTER TABLE http_trigger ADD COLUMN enabled BOOLEAN NOT NULL DEFAULT true;2. Inconsistent Default Behavior (handler.rs:860 + RouteEditorInner.svelte:273)There are conflicting defaults throughout the codebase:
This creates confusing behavior where new triggers work but existing ones don't. Fix Required: Ensure consistent Major Issues 🟡3. Non-Admin Users Can't Update Enabled State (handler.rs:514)The non-admin update path (lines 535-586) doesn't include the Question: Is this intentional? If so, please document. Otherwise, add 4. Filename Typo (migration files)Migration files are named Performance Considerations 🔵5. Disabled Triggers Loaded Into Router Cache (mod.rs:248)The
Minor Issues & Suggestions6. OpenAPI Spec Typo (Already noted by ellipsis-dev)Line 9909: "enable/disalbe" → "enable/disable" 7. Missing Loading State in UI (routes/+page.svelte:362)The toggle switch doesn't show loading state while the API call is in progress. Consider adding visual feedback. 8. Good Practices Observed ✅
Security AssessmentNo security issues identified. The feature properly:
Code QualityThe code follows Windmill's established patterns well:
Testing RecommendationsBefore merging, please test:
Reproduction Instructions for TestingTo test the changes in the Windmill application interface: Navigate to the Routes page (accessible from the main navigation menu under "Triggers" or directly at RecommendationRequest Changes - The migration issue (#1) is critical and will cause breaking changes in production. Please address the critical issues before merging. The other issues are important for code quality and UX but not blockers. |
| @@ -0,0 +1,2 @@ | |||
| -- Add up migration script here | |||
| ALTER TABLE http_trigger ADD COLUMN enabled BOOLEAN; No newline at end of file | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Migration Issue: Missing default value
The enabled column is added without a NOT NULL constraint or a default value. This could lead to:
- Existing triggers having
NULLvalues - All existing HTTP triggers will haveenabled = NULLafter this migration runs - Logic issues - The code checks
trigger.enabled.unwrap_or(false)(line 860 in handler.rs), which means existing triggers will default tofalse(disabled) after migration
Recommendation:
ALTER TABLE http_trigger ADD COLUMN enabled BOOLEAN NOT NULL DEFAULT true;This ensures:
- Existing HTTP triggers remain enabled by default (backward compatible)
- New triggers are enabled by default (unless explicitly set otherwise)
- No NULL handling needed in application code
| @@ -0,0 +1,2 @@ | |||
| -- Add up migration script here | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in filename: The migration file is named allow_to_diasable_http_trigger but should be allow_to_disable_http_trigger (typo: "diasable" → "disable")
| .await | ||
| .map_err(|e| e.into_response())?; | ||
|
|
||
| if !trigger.enabled.unwrap_or(false) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential Issue: Inconsistent behavior with NULL enabled field
The check trigger.enabled.unwrap_or(false) defaults to false when enabled is NULL. However:
- In
insert_new_trigger_into_db(line 228), new triggers usetrigger.base.enabled.unwrap_or(true)- defaulting totrue - This creates inconsistent behavior where:
- New triggers are enabled by default ✓
- Existing triggers (after migration) will be disabled by default ✗
Recommendation:
Either:
- Change this to
.unwrap_or(true)to match insertion behavior, OR - Ensure the migration adds the column with
DEFAULT true(see migration comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
| script_path, | ||
| is_flow, | ||
| route_path, | ||
| enabled, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Query Performance Concern
This query in refresh_routers loads ALL HTTP triggers regardless of their enabled state. This means:
- Disabled triggers are still loaded into the router cache
- The check happens later at request time (line 860 in handler.rs)
- This adds memory overhead and potentially slower router matching
Recommendation: Consider filtering disabled triggers at load time:
SELECT ... FROM http_trigger
WHERE http_method = $1 AND (enabled IS NULL OR enabled = true)This would:
- Reduce memory footprint
- Improve router matching performance
- Prevent disabled routes from being accessible at all
Note: If you want to keep disabled routes in the router for faster enable/disable (avoiding cache refresh), the current approach is acceptable but should be documented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should filter out disabled routes
| trigger.base.script_path, | ||
| trigger.base.path, | ||
| trigger.base.is_flow, | ||
| trigger.base.enabled, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing enabled field in non-admin update path
When a non-admin user updates a trigger (lines 535-586), the enabled field is not included in the UPDATE statement. This means:
- Non-admin users cannot modify the
enabledstate even if they have write permissions - The
enabledvalue intrigger.base.enabledis silently ignored
Question: Is this intentional? If so, it should be documented. If not, consider adding enabled = $N to the non-admin UPDATE statement as well.
The admin path (lines 473-531) correctly includes enabled = $10.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
| wrap_body = cfg?.wrap_body ?? false | ||
| raw_string = cfg?.raw_string ?? false | ||
| summary = cfg?.summary ?? '' | ||
| enabled = cfg?.enabled ?? false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent default value
When loading trigger config, enabled defaults to false:
enabled = cfg?.enabled ?? falseHowever:
- In
openNew()(line 239), enabled defaults totrue - In the backend insertion (handler.rs:228), it defaults to
true - The backend check (handler.rs:860) defaults to
falsefor NULL values
Recommendation: Change this line to:
enabled = cfg?.enabled ?? trueThis ensures consistency across the codebase and better user experience (routes enabled by default).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that will make existing triggers shown as disabled
| error_handler_args: routeCfg.error_handler_path ? routeCfg.error_handler_args : undefined, | ||
| retry: routeCfg.retry | ||
| retry: routeCfg.retry, | ||
| enabled: routeCfg.enabled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New field added to save function
Good! The enabled field is correctly included in the request body for both create and update operations.
| <SharedBadge {canWrite} extraPerms={extra_perms} /> | ||
| </div> | ||
|
|
||
| <Toggle |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UI Implementation looks good
The Toggle component is:
- Correctly bound to the
enabledstate - Disabled when user lacks write permissions (
disabled={!canWrite}) - Calls
setTriggerEnabledon change
One minor suggestion: Consider adding visual feedback (loading state) while the API call is in progress, since setTriggerEnabled is async but there's no loading indicator shown to the user.
hugocasa
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- you either have to set default to true in the migration or handle enabled is null correctly everywhere
| trigger.base.script_path, | ||
| trigger.base.path, | ||
| trigger.base.is_flow, | ||
| trigger.base.enabled, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
| .await | ||
| .map_err(|e| e.into_response())?; | ||
|
|
||
| if !trigger.enabled.unwrap_or(false) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
| script_path, | ||
| is_flow, | ||
| route_path, | ||
| enabled, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should filter out disabled routes
| "enabled", | ||
| "error_handler_path", | ||
| "error_handler_args", | ||
| "retry", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it safe because this fn is only called when supports_server_state is set to true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it safe because this fn is only called when supports_server_state is set to true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup its because all listener object have supports_server_state to true thats why its safe
| wrap_body = cfg?.wrap_body ?? false | ||
| raw_string = cfg?.raw_string ?? false | ||
| summary = cfg?.summary ?? '' | ||
| enabled = cfg?.enabled ?? false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that will make existing triggers shown as disabled
| script_path, | ||
| is_flow, | ||
| route_path, | ||
| enabled, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you don't need enabled anymore as you know it will be enabled
| "enabled", | ||
| "error_handler_path", | ||
| "error_handler_args", | ||
| "retry", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it safe because this fn is only called when supports_server_state is set to true?
| Ok(()) | ||
| } | ||
|
|
||
| async fn set_enabled( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't already handled by the trait?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is but for http we need to increase_trigger_version otherwise the cache we'd have outdated http trigger

No description provided.