Skip to content

validateObject re-introspects the datasource once per object, so validating M federated objects on one datasource performs M live remote schema reads #10962

Description

@os-elon

Found while implementing #10537 (out of scope there: that card scoped the REST route's work to the URL's datasource; this is the residual cost inside one datasource).

What is true at head

packages/services/service-datasource/src/external-datasource-service.tsvalidateObject(objectName) (:345) reads the live remote schema for the object's datasource on every call:

constschema=awaitthis.config.introspect(datasource);

There is no memoisation, so the sweep (validateAll, and since PR #10960 the scoped validateDatasource) performs one introspect(datasource) per object, all in flight at once via Promise.all. A datasource with 20 federated objects is introspected 20 times per validation, concurrently, against the same remote.

In production introspect resolves to IDataEngine.introspectDatasource(datasource) (wired in plugin.ts), i.e. a real driver round-trip, not a cached read.

The contract's own wording reads the other way

packages/spec/src/contracts/external-datasource-service.ts:157 documents validateAll as:

Validate every federated object, parallelised per datasource.

The parallelism is per object; nothing is shared per datasource. Whichever way this is resolved, the doc line and the implementation should stop disagreeing — a reader sizing the cost of a validation sweep from that sentence gets the wrong number by a factor of the object count.

Not fixed in #10537

That card's fix narrows which datasources are dialled (one, not N); this is how many times the one is dialled. Folding a memo into the sweep changes when a remote is read within a single validation — an observable-timing change with its own test surface — so it is filed rather than ridden in.

If taken, the shape to consider is a per-call (not per-instance) introspection memo threaded through the sweep, so a long-lived service never serves a stale schema to a later validation, plus the doc-line correction above.

Unassigned — filed for triage to level and route.


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions