Fix bulk modify timeout on AttributeLinkedSetIndirect#923
Open
larhip wants to merge 1 commit into
Open
Conversation
…rect on display_style Since N°3190 (commit fb1ceeb), AttributeLinkedSetIndirect::IsBulkModifyCompatible() returned true unconditionally. For the default (tab) display style this caused DisplayBulkModifyForm() to eagerly materialise and render the full link set of every selected object, leading to timeouts when bulk modifying records with thousands of links each. Bulk modify of an indirect link set is only meaningful for the property-style (tagset-like) widget introduced by N°3190 — the tab-style widget cannot be rendered inside the bulk modify form at all. IsBulkModifyCompatible() is changed from static to a regular instance method across the AttributeDefinition hierarchy so it can depend on the per-instance display_style XML property. All four call sites in cmdbabstract.class.inc.php already use instance dispatch, so no caller changes are required. Breaking change for extensions: overrides of IsBulkModifyCompatible() must drop the \`static\` modifier to avoid a PHP fatal error. Adds a regression test covering the four relevant paths (scalar, AttributeLinkedSet, AttributeLinkedSetIndirect with default tab style, AttributeLinkedSetIndirect with display_style=property).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Base information
Symptom (bug)
Bulk-modifying records that contain large
AttributeLinkedSetIndirectfields times out before the bulk modify form is rendered.Field report: bulk-modifying 4
ProviderContractrecords with ~5400 linked CIs each (≈21,600 link materialisations + HTML renders per request) reliably exceeds the PHP request timeout. Profiling shows the time is spent insideDisplayBulkModifyForm()materialising the indirect link sets of every selected object.The defect was introduced by N°3190 commit fb1ceeba, which added
AttributeLinkedSetIndirect::IsBulkModifyCompatible()returningtrueunconditionally to support the newdisplay_style=property(tagset-like) widget. The same return value, however, also enables bulk processing for the default tab display style, which is what triggers the timeout.Reproduction procedure (bug)
UserRequest::contacts_list, orProviderContract::functionalcis_listfrom a populated dataset. For a reliable reproduction, populate at least 4 objects with ≈5000 links each.Workaround that confirms the cause: temporarily change
AttributeLinkedSetIndirect::IsBulkModifyCompatible()toreturn false;— the bulk modify form renders immediately.Cause (bug)
IsBulkModifyCompatible()is checked inapplication/cmdbabstract.class.inc.php::DisplayBulkModifyForm()for every attribute of every selected object (lines 4544, 4550, 4613):For tab-style indirect link sets this work is entirely wasted:
cmdbabstract.class.inc.php:2134and:4065already gate the bulk-context rendering path onLINKSET_DISPLAY_STYLE_PROPERTY, so a tab-style indirect link set is not editable in the bulk form at all.IsBulkModifyCompatible()is declaredstatic, which is why the N°3190 override could not read the per-instancedisplay_styleXML property. As a consequence the override returns a class-level constant —truefor all indirect link sets, regardless of the actual rendering mode.A repository-wide check confirms that all four call sites (
cmdbabstract.class.inc.php:1854, 4544, 4550, 4613) already use instance dispatch (\$oAttDef->IsBulkModifyCompatible()); there is no static caller. Thestaticmodifier is therefore historical, not load-bearing.Proposed solution
Make
IsBulkModifyCompatible()a regular instance method across theAttributeDefinitionhierarchy.AttributeLinkedSetIndirectthen gates on the per-instancedisplay_style:sources/Core/AttributeDefinition/AttributeDefinition.php— dropstaticfrom the base declaration; document the migration in the docblock.sources/Core/AttributeDefinition/AttributeLinkedSet.php— dropstaticfrom the override (return value unchanged:false).sources/Core/AttributeDefinition/AttributeLinkedSetIndirect.php— dropstatic, return$this->GetDisplayStyle() === LINKSET_DISPLAY_STYLE_PROPERTY.The property-style path (the original N°3190 feature) is preserved; the tab-style path is excluded from the bulk form with the "IncompatibleAttribute" notice, matching pre-fb1ceeba behaviour.
Breaking change for extensions: overrides of
IsBulkModifyCompatible()must drop thestaticmodifier from the override declaration, otherwise PHP raises a fatal error (Cannot make non-static method ... static in class ...). The method is not marked@apiand is not part of any documented extension API; expected blast radius is small. A note has been added to the base class docblock to document the migration.Regression coverage
tests/php-unit-tests/unitary-tests/core/AttributeDefinitionTest.php::testIsBulkModifyCompatible(data-provider, 4 cases):UserRequest::title) →trueAttributeLinkedSet(UserRequest::workorders_list) →falseAttributeLinkedSetIndirect, default tab style (UserRequest::contacts_list) →false(regression case)AttributeLinkedSetIndirect,display_style=property(FunctionalCI::groups_list) →true(preserves N°3190)Checklist before requesting a review