Repository navigation
The Long-Running Query opt-out knob gets its Darling store home: V135 adds the two lists to config_alert_settings with the production read's seeds as their DEFAULT, wired through the service, the Viewer, the probe and both SKUs' get_alert_settings / update_alert_settings twins (#3653 A5, Q5) - #3736
Merged
Merged
Conversation
… adds two text[] columns to config_alert_settings whose DEFAULT is the production read's seeds, wired through the service seed/read, the Viewer's Settings window and select/upsert, the viewer probe's top arm, and both SKUs' get_alert_settings / update_alert_settings twins (#3653 A5, Q5) #3734 gave both SKUs the knob - program_name PREFIXES and exact logins whose sessions the Long-Running Query alert does not evaluate, seeded from the 7-day production read (SQLAgent - TSQL JobStep; NT AUTHORITY\ SYSTEM and NT AUTHORITY\NETWORK SERVICE) - editable on Lite, and on Darling the seeds and nothing else, because a Darling alert knob has no rung-free home: the store row is authoritative (ApplyToConfig replaces config.Alerts wholesale), so a darling.json-only member is dead, and McpAlertSettingsKeyTests pins both SKUs' get_alert_settings to one shape, so neither could publish it until Darling could store it. This is that store home, one rung after #3730's V134. V135: long_running_query_excluded_program_name_prefixes and long_running_query_excluded_logins, text[] NOT NULL, DEFAULT the two seeded arrays - the one knob rung on this row that ships a non-empty default, so a pre-rung row reads as exactly what DarlingAlertSettings returned before the rung and what Lite ships, and the two SKUs and the two sides of the rung evaluate one population. An operator's cleared list is stored as an explicit '{}' and honoured: present-and-empty is a decision, and nothing re-seeds it. AlertsConfig and the Viewer's AlertSettingsRow initialise to the same seeds (pinned equal to the rung's DEFAULT and to LongRunningQueryExclusions.Default*). No reload beacon (V17's trigger), no GRANT (table-level), IF NOT EXISTS. Plumbing, all at the appended ordinals: StoreConfigProvider seeds them as $69/$70 and reads them at 67-68 (a column selected but not read resets the knob on every worker start); the Viewer's select/upsert bind them as $68/$69 and read 67-68, its Settings window gets two boxes (AlertLrqExcluded*Box, so the #1840 wiring census sees them: gated on the master switch, Restore Defaults puts the SEEDS back); the viewer probe gains the V135 sentinel as the top arm (V134's top-rung claims move here, as V134 moved V133's); DarlingAlertReader reads 67-68 for get_alert_settings; update_alert_settings accepts long_running_query.excluded_program_name_prefixes / .excluded_logins through the shared normaliser (empty array = cleared arm); Lite's get_alert_settings publishes the same two keys. Every description states the two rules, the four classes, the seeds' grounding and why the admin login is not a default. TimeHonestyRungLivePostgresTests' simulated climb drops V135's columns and stamp too and expects two rungs: the applier skips anything at or below MAX(version), so a "one rung short" store must be short of the TOP, which this rung now is. Executed on this Mac: the real Darling.Tests.dll (WindowsDesktop stripped) against PostgreSQL 18 in Docker - 402/402 across the rung, probe, seed/ read, viewer bind, MCP and engine classes (the seed -> read scratch round-trip carries a cleared login list back empty and a padded prefix list back normalised; the store's column DEFAULTs read back from the catalogue as the seeds); full suite 11,451 with 191 platform reds (PresentationFramework / SqlClient ConfigurationManager / Windows paths), the same baseline as before this change. Partial #3653 - item 6 (Q5). Does not close it.
Closed
39 tasks done
This was referenced Sep 19, 2026
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.
Mechanism
#3734 gave both SKUs the Long-Running Query opt-out knob —
program_namePREFIXES and exactlogin_names whose sessions the alert does not evaluate, seeded from the 7-day production read (SQLAgent - TSQL JobStep;NT AUTHORITY\SYSTEM,NT AUTHORITY\NETWORK SERVICE) — editable on Lite, and on Darling the seeds and nothing else. A Darling alert knob has no rung-free home: the store row is authoritative (StoreConfigProvider.ApplyToConfigreplacesconfig.Alertswholesale on every load, so adarling.json-only member reads as configured and is dead), andMcpAlertSettingsKeyTestspins both SKUs'get_alert_settingsto one shape, so neither SKU could publish the knob over MCP until Darling could store it. This PR is that store home, one rung after #3730's V134.V135 (
lrq-exclusion-knob):long_running_query_excluded_program_name_prefixesandlong_running_query_excluded_loginsonconfig.config_alert_settings,text[] NOT NULL, DEFAULT the two seeded arrays — the one knob rung on this row that ships a non-empty default, and deliberately: a pre-rung row must read as exactly whatDarlingAlertSettingsreturned before the rung (the seeds, since #3734) and what Lite ships, so the two SKUs and the two sides of the rung evaluate one population. An operator's cleared list is stored as an explicit'{}'and honoured — present-and-empty is a decision, and nothing re-seeds it.AlertsConfig(darling.json) and the Viewer'sAlertSettingsRowinitialise to the same seeds;LongRunningQueryExclusionKnobRungTestspins the rung's DEFAULT literal, both C# initialisers andLongRunningQueryExclusions.DefaultProgramNamePrefixes/DefaultLoginsequal.IF NOT EXISTS, schema-qualified, no reload beacon of its own (V17's statement-level trigger already bumpsconfig_version), no GRANT (table-level grants, no column carve).Plumbing, all at the appended ordinals (the four-parallel-sequences trap every knob rung on this row walks):
StoreConfigProviderseeds them as$69/$70through the shared normaliser and reads them at 67–68 (a column selected but not read resets the knob on every worker start);DarlingAlertSettingsforwards them by reference likeExcludedDatabases, so the store's hot-reload reaches the engine on its next sweep; the Viewer'sViewerDataService.AlertSettingsselect/upsert bind them as$68/$69and read 67–68, and its Settings window gets two boxes (AlertLrqExcludedProgramNamePrefixesBox/AlertLrqExcludedLoginsBox— named so the #1840 wiring census sees them: gated on the master switch, and Restore Defaults puts the seeds back, not empty boxes); the viewer probe gains the V135 column sentinel as the top arm (V134's "I am the top rung" claims move to this rung's tests, as V134 moved V133's);DarlingAlertReader.AlertSettingsSelectSqlreads 67–68 forget_alert_settings;update_alert_settingsacceptslong_running_query.excluded_program_name_prefixes/.excluded_loginsthrough the normaliser (pass the full list; an empty array clears that arm); Lite'sget_alert_settingspublishes the same two keys, so the parity pin holds.Docs. Every description — both
get_alert_settings,update_alert_settings, the Viewer's Settings hint,darling.sample.json,DarlingConfig, the V135 doc comment, the Darling README's settings table and ladder table — states the two rules (prefix / exact, case-insensitive, no wildcard grammar), the four classes the read found (job steps → prefix default; the twoNT AUTHORITYlogins → login default; the application's admin login → deliberately not a default, because it carries the job wave and real ad-hoc long-runners; named humans → never), the seeds' grounding ("7-day read of one large production store"), and that the seeds are defaults an operator can clear.Evidence
NT AUTHORITY\SYSTEM/NETWORK SERVICE~70 sessions across 42 servers, medians 4.8–8.6 days, 300K+ snapshots, CDC-capture shaped; the admin login carries the job wave and ad-hoc long-runners; named humans 3 sessions/week.MigrateAsyncapplies V135; the store'sinformation_schema.columns.column_defaultfor the two columns reads back asARRAY['SQLAgent - TSQL JobStep'::text]andARRAY['NT AUTHORITY\SYSTEM'::text, 'NT AUTHORITY\NETWORK SERVICE'::text]; the scratch seed → read round-trip carries a cleared login list back empty (not re-seeded) and a padded, case-duplicated prefix list back normalised.Why this shape
SelfDiskWarnGbFloorRungTests' V126 bind pin moves from[^1]to[^3], as it did when V127 landed on it).What it does NOT do
DarlingWorker.EvaluatePgLongRunningQueryAsync) — stated in the Darling README.Tests
LongRunningQueryExclusionKnobRungTests(new): the rung is registered at the top of a dense ladder; adds both columns schema-qualified with the seeds as DEFAULT (pinned equal to the engine constants,AlertsConfigandAlertSettingsRow.Defaults()), doc comment names the four classes; the probe's three sites carry the sentinel and a fully-migrated store maps to exactlyStorageVersion.SchemaVersion; every settings-row surface names both columns (service read at 67–68 + normalised seed, MCP select + report + accept, Viewer select/upsert/reader); the Settings boxes prefill/save/gate and restore the seeds; the Viewer bind round-trips normalised at the appended ordinals; the MCP reader's positional record agrees with its SELECT; the seam forwards by reference, defaults to the seeds, honours a cleared list throughApplyToConfig; both MCP payloads spell the knob identically and both descriptions state the rules, the four classes, the grounding and the admin-login reason.TimeHonestyRungTests: top-rung claims handed off (ladder pinRungVersion < SchemaVersion, probe ordinal< arity - 1, arm returns134); its live climb now drops V135's columns and stamp too and expects two rungs (the applier skips anything at or belowMAX(version)).DarlingAlertTuningKnobsTests: seam defaults are the seeds; the live scratch seed → read round-trip carries the two lists (cleared login list stays empty; prefix list normalised) and reads the column DEFAULTs back from the catalogue.SelfDiskWarnGbFloorRungTests[^3];DarlingMcpAlertToolsTestsround-trip sample carries non-default lists;LongRunningQueryExclusionsTestsDarling half flips to the by-reference shape.Darling.Tests.dll(WindowsDesktop stripped) on this Mac against PostgreSQL 18 in Docker — 402/402 across the rung, probe, seed/read, viewer bind, MCP, wiring and engine classes; the full suite 11,451 with 191 platform reds (PresentationFramework / SqlClientConfigurationManager/ Windows paths / DPAPI), the same baseline as before the change. Red-first: with the V134 live climb unadapted,MigrateAsyncapplied 0 rungs andDarlingAnalysisStoreTestscounted 133 stamps for 134 scripts — the exact skip-forever hazard the density pin describes.Depends on #3734 (merged to dev at 12:52Z; this branch is on top of it).
Partial #3653 — item 6 (Q5 — the Darling store home + MCP twins, V135)