Skip to content

fix: wrap updateRecords with bigTransactionTimeout like createRecords#2668

Open
dkindlund wants to merge 1 commit intoteableio:developfrom
dkindlund:fix/update-records-transaction-timeout
Open

fix: wrap updateRecords with bigTransactionTimeout like createRecords#2668
dkindlund wants to merge 1 commit intoteableio:developfrom
dkindlund:fix/update-records-transaction-timeout

Conversation

@dkindlund
Copy link
Contributor

Bug Description

RecordOpenApiService.updateRecords calls recordModifyService.updateRecords directly without wrapping it in a prismaService.$tx() block with an explicit timeout. This means update operations fall back to the Prisma default transaction timeout (5 seconds, or the PRISMA_TRANSACTION_TIMEOUT env var), rather than using the application-configured bigTransactionTimeout (10 minutes by default via BIG_TRANSACTION_TIMEOUT).

In contrast, both multipleCreateRecords (line 58) and createRecords (line 117) already wrap their calls with { timeout: this.thresholdConfig.bigTransactionTimeout }.

This inconsistency causes update operations on records with large link fields (e.g., hundreds or thousands of many-to-many links) to time out, even though the same operation volume succeeds for create operations.

Steps to Reproduce

  1. Set PRISMA_TRANSACTION_TIMEOUT=5000 (default) or leave unset
  2. Create a record with a ManyMany link field containing hundreds of links
  3. PATCH the record to update the link field (add/remove links)
  4. If the junction table operations (DELETE + INSERT for all links) take more than 5 seconds, the operation fails with Prisma error P2028 (transaction timeout)
  5. The same number of links in a createRecords call would succeed because it uses bigTransactionTimeout (10 minutes)

Expected Behavior

Update operations should use the same bigTransactionTimeout as create operations, ensuring consistent timeout behavior across all record mutation operations.

What This Fix Does

Wraps updateRecords in this.prismaService.$tx() with { timeout: this.thresholdConfig.bigTransactionTimeout }, matching the pattern already used by multipleCreateRecords and createRecords.

updateRecord (singular) delegates to updateRecords (plural), so this fix covers both single and batch update operations.

Client Information

  • OS: Linux (Docker container on Google Cloud Run)
  • Database: PostgreSQL 17 (Google Cloud SQL)

Platform

Docker standalone (Google Cloud Run)

Additional Context

This was discovered while investigating a JSONB/junction desync issue in a production deployment. A record with 602 many-to-many links could not be updated because the junction table operations exceeded the default 5-second transaction timeout, even though the deployment had set PRISMA_TRANSACTION_TIMEOUT=60000. The bigTransactionTimeout (configured at 10 minutes) would have been more than sufficient.

The `updateRecords` method in RecordOpenApiService calls
`recordModifyService.updateRecords` directly without wrapping it in a
`$tx` block with an explicit timeout. This means it falls back to the
Prisma default transaction timeout (5 seconds or PRISMA_TRANSACTION_TIMEOUT
env var), rather than using the application's configured
`bigTransactionTimeout` (10 minutes by default).

In contrast, both `multipleCreateRecords` and `createRecords` already
wrap their calls with `{ timeout: this.thresholdConfig.bigTransactionTimeout }`.

This inconsistency causes update operations on records with large link
fields (e.g., thousands of many-to-many links) to fail with Prisma error
P2028 (transaction timeout) even though the operation would complete
within the application's intended timeout window.

This fix wraps `updateRecords` in `this.prismaService.$tx()` with the
same `bigTransactionTimeout` option used by the create methods, ensuring
consistent timeout behavior across all record mutation operations.

Note: `updateRecord` (singular) delegates to `updateRecords` (plural),
so this fix covers both single and batch update operations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant