Skip to content

SchemaView: DataGridView audit + deferredDepChange protocol#10005

Draft
asheshv wants to merge 3 commits into
pgadmin-org:masterfrom
asheshv:fix/deferreddepchange-protocol
Draft

SchemaView: DataGridView audit + deferredDepChange protocol#10005
asheshv wants to merge 3 commits into
pgadmin-org:masterfrom
asheshv:fix/deferreddepchange-protocol

Conversation

@asheshv
Copy link
Copy Markdown
Contributor

@asheshv asheshv commented Jun 5, 2026

Summary

Three commits addressing silent-failure bugs in DataGridView and introducing a queue-based deferredDepChange protocol for SchemaView, with five schemas adopting the new contract.

1. fix(datagridview): correct silent-failure bugs in DataGridView

Four bugs that silently no-op'd:

  • Feature priority comparator typof1.priorty is undefined, so < was always false and features never sorted.
  • Row classNameclassList.join[' '] bracket-accesses Array.prototype.join (returns undefined). Every grid row rendered with no CSS classes.
  • Reorder hover classclassList?.append(...) — Arrays have no .append; the optional chain silently no-op'd, so the hover-row highlight never applied during drag-reorder.
  • Inherited-column lockinSchemaWithColumnCheck short-circuited on isNew(state) before reading inheritedfrom. Inherited columns in CREATE mode (no attnum) bypassed the lock, making Name and datatype editable on columns that should mirror the parent.

2. feat(schemaview): introduce deferredDepChange protocol

New queue-based protocol so schemas can run async work (confirm dialogs, server fetches) atomically across a state change:

  • SchemaState/reducer.js — appends resolved callbacks to data.__deferred__ with the canonical actionObj shape.
  • hooks/useSchemaState.jsdrainDeferredQueue processes promises in order; rejections surface via pgAdmin.Browser.notifier.error (falls back to console.error when the notifier is unavailable). Drain useEffect keyed on the __deferred__ ref identity, not .length, so replaced entries reliably re-trigger.
  • DepListener.js — prefix-match guard using delimiter-terminated joins (so shared doesn't match shared_username), cached source/dest keys, defensive deep-copy of source path on registration.
  • utils/listenDepChanges.js — full JSDoc contract: return shape, opt-out via return undefined, side-effect-before-resolve rule, actionObj fields, drain error-surfacing.

3. fix(schemas): align deferredDepChange callbacks with new protocol

Five schemas adopt the contract — real bugs fixed along the way:

  • exclusion_constraint.ui.js (amname) — opt out when amname unchanged or columns empty; pre-fix code warned about clearing an empty collection on the very first selection.
  • index.ui.js (amname) — explicit return undefined opt-out in place of Promise.resolve(()=>{}) round-trip.
  • table.ui.js (typname + coll_inherits) — typeTable?.oftype_columns ?? [] guard against stale ofTypeTables; changeColumnOptions hoisted out of the resolved callback (per protocol); same-length inherits swap handling; stale-OID guard preventing col.inheritedid != undefined from dropping local user-added columns.
  • foreign_table.ui.js (inherits) — same swap + stale-OID guard.
  • azure_schema.ui.js (is_authenticating) — orphan-Promise fix (was never resolving in the non-match branch, leaving a permanent __deferred__ entry); source-path comparison against source[source.length - 1] (arrays, not strings); auth failure surfaced via notifier with stale auth_code cleared.

Test plan

  • cd web && yarn run jest151 suites / 884 tests passing
  • cd web && yarn linterclean
  • Manual UI: exclusion-constraint create dialog with empty columns (amname pick should no longer warn)
  • Manual UI: child-table inherits — add/remove/swap parent tables (columns refresh correctly)
  • Manual UI: Azure interactive auth — success path, failure path (error surfaces, dialog unblocks)
  • Manual UI: column inherited from parent — Name field is read-only in CREATE mode

Notes

  • 3 commits, clean linear history off master.
  • New tests added per concern: feature_register.spec.js, no_bracket_on_prototype_method.spec.js, dep_listener.spec.js, reducer_deferred.spec.js, deferred_drain.spec.js, drain_useeffect_race.spec.jsx, plus *.deferred.spec.js for each of the five affected schemas.
  • The deferredDepChange JSDoc contract in utils/listenDepChanges.js is the authoritative reference for schema authors.

asheshv added 3 commits June 5, 2026 18:52
Four upstream bugs that silently no-op'd, exposed by aggressive review
of the SchemaView/DataGridView code:

- Feature priority comparator typo: `f1.priorty` is undefined,
  so the < comparison was always false and features never sorted.
- Row className: `classList.join[' ']` bracket-accesses
  `Array.prototype.join` (returns undefined), so every grid row
  rendered with no CSS classes.
- Reorder hover class: `classList?.append(...)` — Arrays have no
  `.append` method; the optional-chain silently no-op'd, so the
  hover row highlight was never applied during drag-reorder.
- Inherited-column lock: `inSchemaWithColumnCheck` short-circuited
  on `isNew(state)` before reading `inheritedfrom`. In a child
  table CREATE flow, inherited columns arrive with `attnum`
  undefined (so `isNew` returns true) — the function returned
  false (not disabled), making Name and datatype editable on
  columns that should mirror the parent table.

New regression tests pin each fix.
Add the queue-based deferredDepChange protocol so schemas can run
async work (confirm dialogs, server fetches) atomically across a
state change, with first-class error surfacing.

Core infrastructure:

- `SchemaState/reducer.js`: compose actionObj (type/path/value/
  depChange + _.cloneDeep(oldState)) and append resolved callbacks
  to data.__deferred__.
- `hooks/useSchemaState.js`: `drainDeferredQueue` processes
  queued promises in order; rejections surface via
  pgAdmin.Browser.notifier.error (falls back to console.error
  when the notifier is unavailable). Drain useEffect depends on
  the __deferred__ ref identity rather than .length so replaced
  entries reliably re-trigger.
- `DepListener.js`: prefix-match guard uses delimiter-terminated
  joins so 'shared' doesn't match 'shared_username'. Caches
  joined source/dest keys for the hot match path. addDepListener
  deep-copies the source path so a caller mutating its own array
  later doesn't poison the listener.
- `utils/listenDepChanges.js`: full JSDoc contract for depChange
  and deferredDepChange callbacks — return shape, when to opt out
  (return undefined), side-effect rule, actionObj fields, drain
  error-surfacing contract.

Tests:
- dep_listener.spec.js: prefix-match isolation, defensive snapshot,
  listener lifecycle.
- reducer_deferred.spec.js: queue mechanism, actionObj composition.
- deferred_drain.spec.js: serial processing, callback delta
  application, notifier.error on rejection, console.error fallback.
- drain_useeffect_race.spec.jsx: deterministic race regression test
  for the ref-vs-length useEffect dependency fix.
Five schemas adopt the queue-based deferredDepChange contract,
fixing real bugs along the way:

- exclusion_constraint.ui.js (amname): opt out when amname is
  unchanged or columns is empty — pre-fix code queued a
  'clear columns' confirm dialog unconditionally, warning about
  clearing an empty collection on the very first selection.
- index.ui.js (amname): explicit `return undefined` opt-out in
  place of the no-op Promise.resolve(()=>{}) round-trip.
- table.ui.js (typname + coll_inherits): typname opt-out when
  unchanged with stale-ofTypeTables guard
  (`typeTable?.oftype_columns ?? []`); changeColumnOptions
  hoisted out of the resolved callback per protocol JSDoc;
  coll_inherits handles same-length swap (previous add/remove
  branches missed it); stale-OID guard in REMOVE branch prevents
  the `col.inheritedid != undefined` filter from dropping
  local user-added columns.
- foreign_table.ui.js (inherits): same swap + stale-OID guard.
- azure_schema.ui.js (is_authenticating): orphan-Promise fix —
  the previous version returned a Promise that never resolved
  in the non-match branch, leaving a permanent __deferred__
  entry. Source path compared against
  `source[source.length - 1]` (arrays, not strings). Auth
  failure surfaces to the user via notifier and resets
  is_authenticating + clears stale auth_code on failure.

New `*.deferred.spec.js` for each schema, plus contract updates
to the existing exclusion_constraint.ui.spec.js and
table.ui.spec.js.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 5, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cf2d12c3-2525-4342-988a-c51eedec5d83

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes multiple silent UI failures in SchemaView’s DataGridView, and introduces a queue-based deferredDepChange protocol so schema dependency updates can safely perform async work (confirm dialogs, fetches) without leaking or losing pending work across batched React updates.

Changes:

  • Fix DataGridView silent no-ops (feature priority sort, row className join, reorder hover class, inherited-column edit lock).
  • Add a deferred dependency-change queue, reducer accumulation, and a drain mechanism with error surfacing; strengthen DepListener path-matching behavior.
  • Update multiple schemas/tests to follow the new deferredDepChange opt-out + “resolve to callback” contract.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
web/pgadmin/static/js/SchemaView/DataGridView/features/feature.js Fixes feature priority comparator typo so feature ordering works.
web/pgadmin/static/js/SchemaView/DataGridView/row.jsx Fixes row className construction so CSS classes actually apply.
web/pgadmin/static/js/SchemaView/DataGridView/features/reorder.jsx Fixes reorder-hover class application (Array .push vs .append).
web/pgadmin/static/js/SchemaView/SchemaState/reducer.js Accumulates deferred queue entries instead of overwriting them.
web/pgadmin/static/js/SchemaView/hooks/useSchemaState.js Adds deferred queue drain helper + ref-based effect dependency.
web/pgadmin/static/js/SchemaView/DepListener.js Improves prefix matching, caches keys, adds defCallback short-circuit.
web/pgadmin/static/js/SchemaView/utils/listenDepChanges.js Documents the authoritative deferredDepChange protocol contract.
web/pgadmin/misc/cloud/static/js/azure_schema.ui.js Adopts new deferred contract; fixes non-resolving Promise + better error surfacing.
web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.ui.js Adopts deferred contract; fixes inherits/oftype edge cases and mutation issues.
web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.ui.js Adopts deferred contract; avoids input-state mutation; clean opt-out.
web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/static/js/exclusion_constraint.ui.js Adopts deferred contract; adds opt-out and avoids unnecessary confirms.
web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.ui.js Fixes inherited-column lock ordering so CREATE-mode inherited cols are read-only.
web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/static/js/foreign_table.ui.js Adopts deferred contract; fixes swap/remove edge cases and mutation.
web/regression/javascript/SchemaView/reducer_deferred.spec.js Tests reducer queue accumulation behavior.
web/regression/javascript/SchemaView/deferred_drain.spec.js Tests drain protocol error surfacing + non-function guard behavior.
web/regression/javascript/SchemaView/drain_useeffect_race.spec.jsx Tests the React-batching dependency-array race fix.
web/regression/javascript/SchemaView/dep_listener.spec.js Tests DepListener prefix matching + deferred behavior + removal semantics.
web/regression/javascript/SchemaView/no_bracket_on_prototype_method.spec.js Guards against bracket-on-prototype-method typo across SchemaView tree.
web/regression/javascript/SchemaView/feature_register.spec.js Tests feature registration ordering by priority.
web/regression/javascript/schema_ui_files/table.ui.spec.js Updates existing table tests for opt-out behavior.
web/regression/javascript/schema_ui_files/table.ui.deferred.spec.js Adds table deferredDepChange contract/edge-case tests.
web/regression/javascript/schema_ui_files/index.ui.deferred.spec.js Adds index deferredDepChange contract/behavior tests.
web/regression/javascript/schema_ui_files/exclusion_constraint.ui.spec.js Updates existing exclusion-constraint tests for new actionObj signature/inputs.
web/regression/javascript/schema_ui_files/exclusion_constraint.deferred.spec.js Adds exclusion-constraint deferredDepChange contract/behavior tests.
web/regression/javascript/schema_ui_files/foreign_table.deferred.spec.js Adds foreign-table inherits deferredDepChange contract/edge-case tests.
web/regression/javascript/schema_ui_files/column.ui.spec.js Adds regression test for inherited-column lock in CREATE mode.
web/regression/javascript/schema_ui_files/azure_schema.deferred.spec.js Adds azure deferredDepChange contract/behavior tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +42 to +45
export const drainDeferredQueue = (items, dispatch) => {
items.forEach((item) => {
Promise.resolve(item.promise).then(
(resFunc) => {
Comment on lines 51 to +53
removeDepListener(dest) {
this._depListeners = _.filter(this._depListeners, (l)=>!_.join(l.dest, '|').startsWith(_.join(dest, '|')));
this._hasDefCallback = this._depListeners.some((l) => l.defCallback);
Comment on lines +35 to +38
register(HighPriorityFeature);
register(LowPriorityFeature);

const fs = new FeatureSet();
@asheshv
Copy link
Copy Markdown
Contributor Author

asheshv commented Jun 5, 2026

Manual Test Plan

Prerequisites

  • pgAdmin 4 running from fix/deferreddepchange-protocol branch (e.g. cd web && yarn webpacker:watch + python pgAdmin4.py)
  • Local Postgres 17 (port 5432) registered as a pgAdmin server
  • A test database created on that server, e.g. pgadmin_pr10005_test
  • A schema inside the test DB, e.g. pr_test (or use public)
  • Browser DevTools open to Console + Network tabs throughout — many checks require watching console output

Section A — DataGridView mechanical fixes

A1. Feature priority ordering (priorty typo fix)

Setup:

  • Open any node that uses DataGridView with multiple features (e.g. Table → Columns sub-grid).

Steps:

  1. Navigate: Browser tree → server → DB → Schemas → pr_test → Tables → right-click → Create → Table.
  2. Click the Columns tab.
  3. Click + to add 3 rows.

Expected:

  • Each row shows controls in stable column order: select checkbox (if any) → drag handle → cell controls → delete button on the right.
  • No console warnings like feature applied twice or React key collision warnings.
  • Resizing one column doesn't reorder features.

Validates: featurePriorityCompare now sorts (was always returning false due to the priorty typo).


A2. Row CSS class rendering (classList.join(' ') fix)

Setup: Same Create Table dialog with at least 3 columns added.

Steps:

  1. Inspect the DOM of a row in the Columns sub-grid (right-click row → Inspect).
  2. Locate the row's outer <div data-test=\"data-table-row\">.
  3. Check the class attribute.

Expected:

  • class is populated (e.g. DataGridView-tableRow some-other-feature-class).
  • Not class=\"\" or class=\"undefined\".
  • Hovering / selecting a row visibly changes its style (alternate background, hover highlight).

Validates: className={classList.join(' ')} now applies (was className={classList.join[' ']}, which evaluated to undefined).


A3. Drag-reorder hover highlight (.push not .append)

Setup: Create Table dialog with 4+ columns added.

Steps:

  1. Grab a column's drag handle (left side of the row).
  2. Hover the drag preview over a different row without releasing the mouse.
  3. Visually inspect the row currently being hovered over.

Expected:

  • The hovered target row shows a highlight (background tint, border color, etc. — exact style is theme-dependent).
  • Move to another row → highlight follows.
  • Drop → highlight clears.

Validates: classList?.push('DataGridView-tableRowHovered') (was .append(...), which silently no-op'd because Arrays have no .append).


A4. Inherited-column lock in CREATE mode

Setup:

CREATE TABLE pr_test.parent_a (a int PRIMARY KEY, b text);

Refresh the browser tree so parent_a is visible.

Steps:

  1. Right-click Tables in pr_testCreate → Table.
  2. General tab: name = child_a.
  3. Columns tab: confirm grid is empty initially.
  4. Advanced tab → Inherits from table(s): select pr_test.parent_a.
  5. Return to Columns tab.

Expected:

  • Two rows appear (a, b) with inheritedfrom set to pr_test.parent_a.
  • The Name field on each inherited row is disabled / read-only.
  • The datatype column is also disabled.
  • You cannot rename or retype a or b.

Negative case:

  • Add a local column extra (not inherited). Its Name and datatype are editable.
  • An OF-TYPE table (Advanced → "Of type"): the lock should NOT engage for inheritedfromtype — those columns are editable per their dedicated editable callback.

Validates: inSchemaWithColumnCheck now reads inheritedfrom before the isNew(state) shortcut.


Section B — deferredDepChange protocol infrastructure

B1. Drain error surfacing via notifier.error

Setup: Use the Azure cloud provisioning flow with no network (simplest reproducible failure).

Steps:

  1. Begin the Azure auth flow: trigger auth_btn click, set auth_type to interactive_browser_credential.
  2. Block outbound HTTPS / disconnect network.
  3. Wait for getAuthCode to fail.

Expected:

  • A toast / notifier error appears at top of the pgAdmin window (red/orange) reading something like "Azure authentication failed: …".
  • The Azure config dialog unblocksis_authenticating returns to false, fields become re-editable.
  • DevTools console does not show an unhandled rejection or silent console.error as the only signal.

Validates: drainDeferredQueue routes rejections through pgAdmin.Browser.notifier.error.

Negative-case sub-test: Temporarily delete pgAdmin.Browser.notifier in DevTools (delete pgAdmin.Browser.notifier), then retry. The console should fall back to console.error rather than crashing the drain.


B2. DepListener prefix-match isolation

Setup: Any schema with fields whose IDs share a prefix (e.g. shared vs shared_username).

Steps:

  1. From DevTools, type:
    schemaState.getDepChange(['shared'], schemaState.data, {type:'TEST'})
  2. Verify that listeners registered for ['shared_username'] are not invoked.

Expected: Only listeners with exact prefix ['shared'] fire.

Validates: Prefix-match guard uses delimiter-terminated joins. (Mostly covered by dep_listener.spec.js.)


B3. Drain useEffect — replaced-entry race

Setup: Exclusion Constraint amname is a good repro candidate.

Steps:

  1. Open the Exclusion Constraint create dialog.
  2. Add one column.
  3. Switch amname from btreegisthashbtree rapidly (within ~500ms).

Expected:

  • Each amname change should be reflected eventually — no transient state where the dialog gets stuck mid-transition.
  • The columns collection should be cleared appropriately after the final confirmation.
  • No console warnings about lost dispatches.

Validates: Drain useEffect keying on __deferred__ ref identity (not .length).


Section C — Per-schema deferredDepChange adoption

C1. Exclusion constraint amname opt-out (empty columns)

Steps:

  1. Open Create Table → Constraints tab → Exclusion Constraint sub-tab → +Edit the new row.
  2. With columns empty, change amname from default btreegist.

Expected: No confirmation dialog opens. State transitions silently.

  1. Add one column to the exclusion constraint.
  2. Change amname again gisthash.

Expected: A confirm dialog does open: "Change access method? Changing access method will clear columns collection."

  1. Click Cancel.

Expected: amname reverts to gist. The column is still present.

  1. Change amname again, click OK.

Expected: The column is removed.

  1. With one column added, change amname to its current value (no actual change).

Expected: No dialog (opt-out fires because amname === oldState.amname).

Validates: Opt-out when amname unchanged or columns empty; cancel reverts; OK clears columns.


C2. Index amname (sanity)

Steps:

  1. Right-click an existing table → Create → Index.
  2. Switch amname from btree to anything else with no columns added.

Expected: No confirm dialog.

  1. Add an index column.
  2. Switch amname again.

Expected: Confirm dialog appears.

  1. Click Cancel.

Expected: amname reverts, column still present.


C3. Table OF TYPE — stale ofTypeTables guard

Setup:

CREATE TYPE pr_test.row_t AS (x int, y text);

Steps:

  1. Right-click TablesCreate → Table.
  2. Advanced tab → Of type: select pr_test.row_t.
  3. Go to Columns tab.

Expected: Two columns x and y appear, derived from row_t, locked.

  1. Advanced tab → change Of type to empty.

Expected: Confirm dialog: "Remove column definitions?" → click OK → columns cleared.

Stale-options edge case (optional):
5. In DevTools, before changing Of type, set obj.ofTypeTables = [] to simulate stale options.
6. Trigger the typname change.

Expected: No TypeError; falls back to empty columns list cleanly.

Validates: typeTable?.oftype_columns ?? [] guard.


C4. Table inherits — add/remove/swap

Setup:

CREATE TABLE pr_test.parent_b (b1 int PRIMARY KEY, b2 text);
CREATE TABLE pr_test.parent_c (c1 int PRIMARY KEY, c2 text);

Steps:

  1. Open Create Table dialog, name = child_bc.
  2. Advanced tab → Inherits from table(s): add parent_b.

Expected: Columns tab now shows b1, b2 (inherited).

  1. Add a local column local_extra int.

Expected: All 3 columns shown.

  1. Advanced tab → add parent_c to inherits.

Expected: Columns tab shows b1, b2, c1, c2, local_extra.

  1. Advanced tab → remove parent_b from inherits.

Expected: Columns tab shows c1, c2, local_extra. The local local_extra must still be present (stale-OID guard verification).

  1. Swap test: From state above (only parent_c inherits + local_extra), in one operation replace parent_c with parent_b (deselect c, select b — same length, different content).

Expected: c1, c2 removed, b1, b2 added. local_extra still present.

Validates: Same-length swap handling; stale-OID guard preserves local columns.


C5. Foreign table inherits — same as C4

Setup:

CREATE EXTENSION IF NOT EXISTS postgres_fdw;
CREATE SERVER pr_fdw FOREIGN DATA WRAPPER postgres_fdw
  OPTIONS (host '127.0.0.1', dbname 'pgadmin_pr10005_test');

Steps: Repeat C4's add/remove/swap workflow under Foreign TablesCreate Foreign Table.

Expected: Same behavior as C4. Local columns survive parent removal/swap.


C6. Azure interactive auth — success + failure

Steps (success path):

  1. Tools → Deploy Cloud Instance → Azure (or your build's Azure entry).
  2. Choose interactive_browser_credential for auth_type.
  3. Click the Authenticate button.

Expected:

  • is_authenticating flips to true, button text changes / disables.
  • A device-code is displayed.
  • Browser tab opens for Microsoft login → complete it → auth_code field populates.
  • is_authenticating returns to false.

Steps (failure path):
4. Reload the dialog. Disconnect network / block Azure endpoints.
5. Click Authenticate.

Expected:

  • Notifier error toast: "Azure authentication failed: ".
  • is_authenticating returns to false (dialog unblocks).
  • auth_code is cleared (no stale code from a previous successful attempt).
  • No orphan __deferred__ entry (check DevTools: schemaState.data.__deferred__.length === 0 after settle).

Validates: Orphan-Promise fix; source-path comparison via source[length-1]; auth failure surfaced via notifier; stale auth_code cleared.


Final regression sweep

After all sections pass:

  • Open at least 3 existing tables in Edit mode → tabs render normally, no console errors.
  • Save a table with inherited columns → server-side SQL preview matches expectation.
  • Save an exclusion constraint after the amname dance → produced SQL is correct.
  • Close all open dialogs → no lingering deferred state in DevTools.
  • Browser tree refresh / re-expand → all created objects are visible.

Cleanup

DROP TABLE IF EXISTS pr_test.child_a, pr_test.child_bc CASCADE;
DROP TABLE IF EXISTS pr_test.parent_a, pr_test.parent_b, pr_test.parent_c CASCADE;
DROP TYPE  IF EXISTS pr_test.row_t;
DROP SERVER IF EXISTS pr_fdw CASCADE;
DROP SCHEMA IF EXISTS pr_test CASCADE;
DROP DATABASE IF EXISTS pgadmin_pr10005_test;

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 3 comments.

Comment on lines +42 to +86
export const drainDeferredQueue = (items, dispatch) => {
items.forEach((item) => {
Promise.resolve(item.promise).then(
(resFunc) => {
if (typeof resFunc !== 'function') {
// Protocol violation: the schema author resolved with
// something other than a (tmpstate) => deltaObj callback.
// Loud console.error so it trips dev/QA test suites; not a
// notifier toast because this is a code bug, not a runtime
// failure the end user can act on.
console.error(
'deferredDepChange promise must resolve to a callback function; '
+ 'got %o. The dispatch is skipped — see useSchemaState '
+ 'drainDeferredQueue for the protocol.',
resFunc,
);
return;
}
dispatch({
type: SCHEMA_STATE_ACTIONS.DEFERRED_DEPCHANGE,
path: item.action.path,
depChange: item.action.depChange,
listener: {
...item.listener,
callback: resFunc,
},
});
},
(err) => {
const msg = err?.message || String(err) || 'unknown error';
const userMsg = gettext('Dependent update failed: ') + msg;
const notifier = pgAdmin?.Browser?.notifier;
if (typeof notifier?.error === 'function') {
notifier.error(userMsg);
} else {
// Notifier unavailable (very early init, isolated test
// harness, etc.). Surface to console.error rather than
// silently dropping the rejection — the latter is the bug
// this drainer exists to prevent.
console.error('deferredDepChange:', userMsg, err);
}
},
);
});
};
Comment on lines +30 to +33
* 1. The resolved value MUST be a function (the callback that returns
* the data delta). If it's anything else, we warn and skip — this
* catches the common protocol mistake of resolving with a data
* object directly.
Comment on lines 51 to 54
removeDepListener(dest) {
this._depListeners = _.filter(this._depListeners, (l)=>!_.join(l.dest, '|').startsWith(_.join(dest, '|')));
this._hasDefCallback = this._depListeners.some((l) => l.defCallback);
}
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Comment on lines 51 to +53
removeDepListener(dest) {
this._depListeners = _.filter(this._depListeners, (l)=>!_.join(l.dest, '|').startsWith(_.join(dest, '|')));
this._hasDefCallback = this._depListeners.some((l) => l.defCallback);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants