deepline 0.1.285 → 0.1.286

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -155,7 +155,7 @@ export const SDK_RELEASE = {
155
155
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
156
156
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
157
157
  // Operators use the checkout-local deepline-admin binary instead.
158
- version: '0.1.285',
158
+ version: '0.1.286',
159
159
  contracts: {
160
160
  api: {
161
161
  name: 'sdk-http-api',
@@ -1737,7 +1737,10 @@ async function resetRuntimePostgresPool(postgresUrl: string): Promise<void> {
1737
1737
 
1738
1738
  async function withRuntimePostgres<T>(
1739
1739
  session: RuntimePostgresSession,
1740
- fn: (client: RuntimePoolClient) => Promise<T>,
1740
+ fn: (
1741
+ client: RuntimePoolClient,
1742
+ transaction: { active: boolean },
1743
+ ) => Promise<T>,
1741
1744
  options: {
1742
1745
  cachePool?: boolean;
1743
1746
  maxConnectAttempts?: number;
@@ -1746,6 +1749,7 @@ async function withRuntimePostgres<T>(
1746
1749
  ): Promise<T> {
1747
1750
  let client: RuntimePoolClient | null = null;
1748
1751
  let requestLocalPool: RuntimePool | null = null;
1752
+ let roleTransactionStarted = false;
1749
1753
  const cachePool =
1750
1754
  (options.cachePool ?? true) && canReuseRuntimePostgresPoolsAcrossRequests();
1751
1755
  const maxConnectAttempts =
@@ -1768,13 +1772,19 @@ async function withRuntimePostgres<T>(
1768
1772
  options.signal,
1769
1773
  );
1770
1774
  if (session.executionRole) {
1775
+ await client.query('BEGIN');
1776
+ roleTransactionStarted = true;
1771
1777
  await client.query(
1772
- `SET ROLE ${quoteIdentifier(session.executionRole)}`,
1778
+ `SET LOCAL ROLE ${quoteIdentifier(session.executionRole)}`,
1773
1779
  );
1774
1780
  }
1775
1781
  break;
1776
1782
  } catch (error) {
1777
1783
  if (client) {
1784
+ if (roleTransactionStarted) {
1785
+ await client.query('ROLLBACK').catch(() => {});
1786
+ roleTransactionStarted = false;
1787
+ }
1778
1788
  client.release();
1779
1789
  client = null;
1780
1790
  }
@@ -1813,15 +1823,20 @@ async function withRuntimePostgres<T>(
1813
1823
  throw new Error('Runtime Postgres connection was not acquired.');
1814
1824
  }
1815
1825
  try {
1816
- return await fn(client);
1817
- } finally {
1818
- try {
1819
- if (session.executionRole) {
1820
- await client.query('RESET ROLE');
1821
- }
1822
- } finally {
1823
- client.release();
1826
+ const result = await fn(client, { active: roleTransactionStarted });
1827
+ if (roleTransactionStarted) {
1828
+ await client.query('COMMIT');
1829
+ roleTransactionStarted = false;
1824
1830
  }
1831
+ return result;
1832
+ } catch (error) {
1833
+ if (roleTransactionStarted) {
1834
+ await client.query('ROLLBACK').catch(() => {});
1835
+ roleTransactionStarted = false;
1836
+ }
1837
+ throw error;
1838
+ } finally {
1839
+ client.release();
1825
1840
  if (requestLocalPool) {
1826
1841
  await Promise.resolve(requestLocalPool.end()).catch(() => {});
1827
1842
  }
@@ -2010,14 +2025,15 @@ async function withRuntimeSheetQueryClient<T>(
2010
2025
 
2011
2026
  return await withRuntimePostgres(
2012
2027
  session,
2013
- async (client) => {
2014
- if (input.transactional) await client.query('BEGIN');
2028
+ async (client, transaction) => {
2029
+ const managesTransaction = input.transactional && !transaction.active;
2030
+ if (managesTransaction) await client.query('BEGIN');
2015
2031
  try {
2016
2032
  const result = await operation(client);
2017
- if (input.transactional) await client.query('COMMIT');
2033
+ if (managesTransaction) await client.query('COMMIT');
2018
2034
  return result;
2019
2035
  } catch (error) {
2020
- if (input.transactional) {
2036
+ if (managesTransaction) {
2021
2037
  await client.query('ROLLBACK').catch(() => {});
2022
2038
  }
2023
2039
  throw error;
@@ -2378,19 +2394,37 @@ async function withRuntimeWorkReceiptClient<T>(
2378
2394
  // can let provider work continue after durable receipt persistence is gone.
2379
2395
  // Only the schema-migration branch below may repair ownership before its
2380
2396
  // retry. A genuinely missing schema or second failure also rethrows loudly.
2381
- const runWithSelfHeal = async (client: RuntimeQueryClient): Promise<T> => {
2397
+ const withClient = async <R>(
2398
+ run: (client: RuntimeQueryClient) => Promise<R>,
2399
+ ): Promise<R> =>
2400
+ isRuntimeOneShotQueryFactoryRegistered()
2401
+ ? await withRuntimeOneShotPostgres(session, run)
2402
+ : await withRuntimePostgres(session, run, {
2403
+ cachePool: !context.disablePostgresPoolCache,
2404
+ signal: context.abortSignal,
2405
+ });
2406
+ let selfHealAttempted = false;
2407
+
2408
+ for (
2409
+ let attempt = 1;
2410
+ attempt <= RUNTIME_WORK_RECEIPT_QUERY_MAX_ATTEMPTS;
2411
+ attempt += 1
2412
+ ) {
2382
2413
  try {
2383
- return await operation(client);
2414
+ return await withClient(operation);
2384
2415
  } catch (error) {
2385
- if (
2416
+ const missingStorage =
2386
2417
  isMissingRelationError(error) ||
2387
- isMissingRuntimeWorkReceiptSelfHealColumnError(error)
2388
- ) {
2418
+ isMissingRuntimeWorkReceiptSelfHealColumnError(error);
2419
+ if (missingStorage && !selfHealAttempted) {
2420
+ selfHealAttempted = true;
2389
2421
  runtimeWorkReceiptEnsureCache.delete(
2390
2422
  runtimeWorkReceiptEnsureCacheKey(session),
2391
2423
  );
2392
2424
  try {
2393
- await ensureRuntimeWorkReceiptTable(session, client);
2425
+ await withClient((client) =>
2426
+ ensureRuntimeWorkReceiptTable(session, client),
2427
+ );
2394
2428
  } catch (ensureError) {
2395
2429
  if (!isPostgresPermissionDeniedError(ensureError)) {
2396
2430
  throw ensureError;
@@ -2401,31 +2435,12 @@ async function withRuntimeWorkReceiptClient<T>(
2401
2435
  await repairRuntimeStorageGrants(context, {
2402
2436
  playName: context.playName?.trim() || session.playName,
2403
2437
  });
2438
+ await withClient((client) =>
2439
+ ensureRuntimeWorkReceiptTable(session, client),
2440
+ );
2404
2441
  }
2405
- } else {
2406
- throw error;
2442
+ continue;
2407
2443
  }
2408
- return await operation(client);
2409
- }
2410
- };
2411
-
2412
- for (
2413
- let attempt = 1;
2414
- attempt <= RUNTIME_WORK_RECEIPT_QUERY_MAX_ATTEMPTS;
2415
- attempt += 1
2416
- ) {
2417
- try {
2418
- return isRuntimeOneShotQueryFactoryRegistered()
2419
- ? await withRuntimeOneShotPostgres(session, runWithSelfHeal)
2420
- : await withRuntimePostgres(
2421
- session,
2422
- (client) => runWithSelfHeal(client),
2423
- {
2424
- cachePool: !context.disablePostgresPoolCache,
2425
- signal: context.abortSignal,
2426
- },
2427
- );
2428
- } catch (error) {
2429
2444
  if (
2430
2445
  attempt >= RUNTIME_WORK_RECEIPT_QUERY_MAX_ATTEMPTS ||
2431
2446
  !isTransientRuntimePostgresOperationError(error)
@@ -2928,8 +2943,9 @@ async function writeRuntimeRows(
2928
2943
  const chunks = chunkValues(rowEntries, DIRECT_POSTGRES_BATCH_SIZE);
2929
2944
  const needsTransaction = input.mode === 'replace' || chunks.length > 1;
2930
2945
 
2931
- return await withRuntimePostgres(session, async (client) => {
2932
- if (needsTransaction) await client.query('BEGIN');
2946
+ return await withRuntimePostgres(session, async (client, transaction) => {
2947
+ const managesTransaction = needsTransaction && !transaction.active;
2948
+ if (managesTransaction) await client.query('BEGIN');
2933
2949
  try {
2934
2950
  if (input.mode === 'replace') {
2935
2951
  // Collapse 4 cleanup statements into one CTE-shaped query. Postgres
@@ -3048,10 +3064,10 @@ async function writeRuntimeRows(
3048
3064
  writtenRows += Number(rows[0]?.inserted_count ?? 0);
3049
3065
  }
3050
3066
 
3051
- if (needsTransaction) await client.query('COMMIT');
3067
+ if (managesTransaction) await client.query('COMMIT');
3052
3068
  return { disposition: 'completed', writtenRows };
3053
3069
  } catch (error) {
3054
- if (needsTransaction) {
3070
+ if (managesTransaction) {
3055
3071
  await client.query('ROLLBACK').catch(() => {});
3056
3072
  }
3057
3073
  throw error;
package/dist/cli/index.js CHANGED
@@ -718,7 +718,7 @@ var SDK_RELEASE = {
718
718
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
719
719
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
720
720
  // Operators use the checkout-local deepline-admin binary instead.
721
- version: "0.1.285",
721
+ version: "0.1.286",
722
722
  contracts: {
723
723
  api: {
724
724
  name: "sdk-http-api",
@@ -703,7 +703,7 @@ var SDK_RELEASE = {
703
703
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
704
704
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
705
705
  // Operators use the checkout-local deepline-admin binary instead.
706
- version: "0.1.285",
706
+ version: "0.1.286",
707
707
  contracts: {
708
708
  api: {
709
709
  name: "sdk-http-api",
package/dist/index.js CHANGED
@@ -438,7 +438,7 @@ var SDK_RELEASE = {
438
438
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
439
439
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
440
440
  // Operators use the checkout-local deepline-admin binary instead.
441
- version: "0.1.285",
441
+ version: "0.1.286",
442
442
  contracts: {
443
443
  api: {
444
444
  name: "sdk-http-api",
package/dist/index.mjs CHANGED
@@ -367,7 +367,7 @@ var SDK_RELEASE = {
367
367
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
368
368
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
369
369
  // Operators use the checkout-local deepline-admin binary instead.
370
- version: "0.1.285",
370
+ version: "0.1.286",
371
371
  contracts: {
372
372
  api: {
373
373
  name: "sdk-http-api",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.285",
3
+ "version": "0.1.286",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {