Skip to content

SDK drift: Router.sql() bypasses the retrying transport in TypeScript, unlike Python and unlike sibling Router methods #1796

Description

@realfishsam

Drift

Router.sql() was added in commit d8ca8fb (feat(sdk): add Router.sql() and cross-venue Router.fetchOrderBook(), #1129/#1670). TypeScript's implementation issues a bare fetch() call with no retry logic, while Python's implementation routes the same request through the SDK's shared retry wrapper. This is the same class of drift already tracked for compareMarketPrices in issue #1485 ("compareMarketPrices bypasses the shared retrying transport in TypeScript, unlike Python and unlike its own TS sibling Router methods"), but sql() is a distinct, newer method not covered by that issue.

TypeScript SDK

sdks/typescript/pmxt/router.ts:671-682:

async sql(query: string): Promise<SqlResult> {
    await this.initPromise;
    try {
        const url = `${this.resolveBaseUrl()}/v0/sql`;
        const response = await fetch(url, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
            body: JSON.stringify({ query }),
            signal: AbortSignal.timeout(30_000),
        });

This calls the global fetch directly. Every other network call on Exchange (the base class Router extends) goes through private async fetchWithRetry(...) (sdks/typescript/pmxt/client.ts:559), e.g. sdks/typescript/pmxt/client.ts:765,821,845,867. sql() is the only generated/hand-written method on Router/Exchange in this file that calls fetch directly instead of this.fetchWithRetry.

Python SDK

sdks/python/pmxt/router.py:709-716:

response = self._fetch_with_retry(
    lambda: self._api_client.call_api(
        method="POST", url=url, body={"query": query}, header_params=headers,
    )
)

Routes through self._fetch_with_retry (sdks/python/pmxt/client.py:496), the same retry wrapper used by every other read method on Exchange.

Expected

sql() should use the same shared retry transport as every other call on the class in both languages — either both retry transient failures or neither does. Given Python and the rest of the TS Exchange/Router surface retry, TypeScript's sql() should call this.fetchWithRetry(...) instead of the global fetch.

Impact

A transient network blip or brief server hiccup during router.sql(...) is silently retried and recovered in Python, but immediately surfaces as a failure to the caller in TypeScript — the same query against the same backend behaves differently under identical transient-failure conditions depending on SDK language.


Found by automated SDK cross-language drift audit

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions