-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Dashboard Api Controller: call UpdateComponentCommand only with modified params #4403
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: 2.4
Are you sure you want to change the base?
Conversation
null, | ||
null, | ||
Binput::get('status'), | ||
$component->link, | ||
$component->order, | ||
$component->group_id, | ||
$component->enabled, | ||
$component->meta, | ||
$component->tags, | ||
null, | ||
null, | ||
null, | ||
null, | ||
null, | ||
null, |
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.
This definitely doesn't look right to me...
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.
Hum.. that's the same logic implemented anywhere else? Example from ./app/Bus/Handlers/Commands/Incident/CreateIncidentCommandHandler.php:
// Update the component.
if ($component = Component::find($command->component_id)) {
execute(new UpdateComponentCommand(
Component::find($command->component_id),
null,
null,
$command->component_status,
null,
null,
null,
null,
null,
null,
true // Silent mode
));
To see the problem, try updating a component with no flag in the dashboard multiple times, and have a look to flags in DB after each update.
Pierre
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.
To see the problem, try updating a component with no flag in the dashboard multiple times, and have a look to flags in DB after each update.
I mean: with my PR's merged last week. They broke components updates from the gui. The current PR fix them.
Excellent fix! Here are some suggestions to make it even more robustThis PR addresses a real architectural issue with component updates. I've analyzed the codebase and have some specific suggestions to improve the implementation: 1. Enhanced Parameter FilteringThe current approach of passing all parameters can be improved with more precise filtering: // Instead of passing all parameters, build only changed ones
private function buildComponentUpdateParams($request, $component): array
{
$params = [$component]; // Always include component
// Only add parameters that have actually changed
if ($request->has('status') && $request->get('status') \!== $component->status) {
$params['status'] = $request->get('status');
}
if ($request->has('name') && $request->get('name') \!== $component->name) {
$params['name'] = $request->get('name');
}
// Key fix: Don't pass tags if they're empty/null
if ($request->has('tags') && \!empty($request->get('tags')) && $request->get('tags') \!== '[]') {
$params['tags'] = $request->get('tags');
}
return $params;
} 2. Prevent Empty Tag ArraysAdd specific validation to prevent the empty tag issue: private function shouldUpdateTags($requestTags, $currentTags): bool
{
// Don't update if tags are empty, null, or empty array string
if (empty($requestTags) || $requestTags === '[]' || $requestTags === 'null') {
return false;
}
// Only update if tags have actually changed
return json_encode($requestTags) \!== json_encode($currentTags);
} 3. UpdateComponentCommand EnhancementThe command class should handle optional parameters gracefully: public function __construct(
Component $component,
?string $name = null,
?string $description = null,
?int $status = null,
?array $tags = null,
// ... other optional parameters
) {
$this->component = $component;
// Only set properties that are explicitly provided
if ($name \!== null) $this->name = $name;
if ($status \!== null) $this->status = $status;
if ($tags \!== null && \!empty($tags)) $this->tags = $tags;
} 4. Testing ScenariosTo prevent regression, consider testing these scenarios: // Test case 1: Update component without tags
$response = $this->put('/dashboard/api/components/{id}', [
'status' => 1
// No tags provided
]);
// Should NOT create empty tag arrays
// Test case 2: Update with same values
$response = $this->put('/dashboard/api/components/{id}', [
'status' => $component->status, // Same as current
'name' => $component->name // Same as current
]);
// Should not trigger unnecessary updates
// Test case 3: Clear existing tags
$response = $this->put('/dashboard/api/components/{id}', [
'tags' => null // Explicitly clear tags
]);
// Should properly clear tags without creating '[]' 5. Database ImpactThis fix will prevent:
Related IssuesThis also addresses similar problems mentioned in:
Great work identifying this pattern inconsistency! The incident update approach is definitely the right model to follow. 👍 |
Excellent fix! Here are some suggestions to make it even more robustThis PR addresses a real architectural issue with component updates. I've analyzed the codebase and have some specific suggestions to improve the implementation: 1. Enhanced Parameter FilteringThe current approach of passing all parameters can be improved with more precise filtering: // Instead of passing all parameters, build only changed ones
private function buildComponentUpdateParams($request, $component): array
{
$params = [$component]; // Always include component
// Only add parameters that have actually changed
if ($request->has('status') && $request->get('status') \!== $component->status) {
$params['status'] = $request->get('status');
}
if ($request->has('name') && $request->get('name') \!== $component->name) {
$params['name'] = $request->get('name');
}
// Key fix: Don't pass tags if they're empty/null
if ($request->has('tags') && \!empty($request->get('tags')) && $request->get('tags') \!== '[]') {
$params['tags'] = $request->get('tags');
}
return $params;
} 2. Prevent Empty Tag ArraysAdd specific validation to prevent the empty tag issue: private function shouldUpdateTags($requestTags, $currentTags): bool
{
// Don't update if tags are empty, null, or empty array string
if (empty($requestTags) || $requestTags === '[]' || $requestTags === 'null') {
return false;
}
// Only update if tags have actually changed
return json_encode($requestTags) \!== json_encode($currentTags);
} 3. Testing ScenariosTo prevent regression, consider testing these scenarios:
4. Database ImpactThis fix will prevent:
Great work identifying this pattern inconsistency! The incident update approach is definitely the right model to follow. 👍 |
After merging #4402, changing a component state with no tags creates a tag "[]" in DB (an empty array to string).
Fix: calls to UpdateComponentCommand from dash controller should be done only on modified params, as it is done on incident creation/updates.