Skip to content

feat(bucket-provisioner): provisionBucket returns the bucket row (#2270) - #1914

Merged
pyramation merged 3 commits into
mainfrom
feat/bucket-provision-desired-state
Oct 17, 2026
Merged

pyramation merged 3 commits into
mainfrom
feat/bucket-provision-desired-state

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Companion to constructive-io/constructive-db#4088. Implements constructive-planning #2270 (option B, approved by Dan).

What changed

<buckets>_provision(bucket_id) in constructive-db no longer enqueues a job and returns its id. It now stamps the bucket's provision_requested_at as the caller, under the buckets table's RLS, and returns the bucket row. The bucket's ledger-routed UPDATE trigger then records and enqueues the job, keyed and queued on the bucket so repeated requests collapse into one.

provisionBucket follows that contract:

  • it calls SELECT id, key, physical_name, provision_requested_at FROM <private>.<buckets>_provision($1::uuid);
  • ProvisionBucketPayload drops jobId and gains provisionRequestedAt: Datetime!, so the payload is the bucket row: bucketId, bucketKey, physicalName, provisionRequestedAt;
  • an empty result throws STORAGE_BUCKET_PROVISION_EMPTY. The SQL function raises on 0 rows itself, so this check is only a guard and is never reached silently.

The README, types.ts and the tests are updated to match.

Before / after

Tests updated first, then run against the old src/ (graphile/graphile-bucket-provisioner-plugin, npx jest):

Tests:       4 failed, 5 passed, 9 total

After:

Tests:       11 passed, 11 total

tsc --noEmit and eslint on the package are clean.

Also updated to the new contract: the simple-seed-storage fixture (auth-provision.sql is now the generator's row-returning output, schema.sql gains provision_requested_at), upload.integration.test.ts (asserts provisionRequestedAt advances on a repeat request instead of distinct job ids), and the graphql/test + server-test schema snapshots. provisionRequestedAt is selected as ISO text so the Datetime scalar keeps sub-second precision (a Date was serialized via String(), dropping milliseconds).

Written by Devin

@tenki-reviewer

tenki-reviewer Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Review complete. 🟠 1 high · 🟡 1 medium

💬 Inline comments (2)

  • 🟠 Provision SELECT assumes row-returning _provision function — plugin.ts:203
  • 🟡 Remove jobId from ProvisionBucketPayload without deprecation — plugin.ts:239

The change reworks the provisionBucket mutation to call the storage module's _provision function directly, return the bucket row with a new non-null provisionRequestedAt field, and dedupe repeated provision requests via an UPDATE-trigger job model. The payload type and its tests are updated to match, and the README documents the new contract.

Files Change
graphile/graphile-bucket-provisioner-plugin/src/plugin.ts Rewrites the resolver to select the bucket row and provisionRequestedAt from _provision
graphile/graphile-bucket-provisioner-plugin/src/types.ts Replaces jobId: UUID! with provisionRequestedAt: Datetime! on ProvisionBucketPayload
graphile/graphile-bucket-provisioner-plugin/__tests__/ Updates plugin and type tests to assert the new payload shape and idempotency
graphile/graphile-bucket-provisioner-plugin/README.md Documents the new provision-request flow and payload contract

Reviewed commit: 9c2f2ed

@tenki-reviewer tenki-reviewer Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This PR updates the graphile-bucket-provisioner-plugin to make provisionBucket idempotent and return the bucket record with a provisionRequestedAt timestamp instead of a job id, removing jobId from the payload type.

Key findings

  • 🟠 Provision SELECT assumes row-returning _provision function — plugin.ts:203
  • 🟡 Remove jobId from ProvisionBucketPayload without deprecation — plugin.ts:239

Comment on lines 239 to 247
type ProvisionBucketPayload {
"""The logical bucket row that was queued for reconciliation."""
"""The logical bucket row whose reconciliation was requested."""
bucketId: UUID!
bucketKey: String!
"""The physical bucket name already recorded, or null when reconciliation has not completed."""
physicalName: String
"""The reconciler job enqueued to provision this bucket."""
jobId: UUID!
"""When reconciliation was last requested for this bucket."""
provisionRequestedAt: Datetime!
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 api-data · medium

Remove jobId from ProvisionBucketPayload without deprecation

ProvisionBucketPayload.jobId: UUID! is deleted and replaced with provisionRequestedAt: Datetime! with no deprecation window (graphile/graphile-bucket-provisioner-plugin/src/plugin.ts:239-247). Any persisted operation selecting jobId now fails schema validation outright.

The repo itself is a victim: the integration suite still queries and asserts jobId, the schema snapshot still records jobId: UUID!, and the generated SDK still types jobId: string — all three fail against the new schema.

📋 Prompt for AI Agents

In graphile/graphile-bucket-provisioner-plugin/src/plugin.ts lines 239-247 the jobId: UUID! field of ProvisionBucketPayload was replaced by provisionRequestedAt: Datetime! with no deprecation, but several in-repo consumers still reference jobId and will fail against the new schema: graphql/server-test/tests/upload.integration.test.ts (query at line 107, assertions at lines 702, 716, 724-725), graphql/server-test/tests/snapshots/schema-snapshot.test.ts.snap (line 1618), and sdk/constructive-sdk/src/storage/orm/input-types.ts (lines 1901-1915). Update the integration test to request provisionRequestedAt and rework the distinct-job-id assertions around the returned timestamp, refresh the snapshot (or regenerate it), and regenerate the SDK payload types. If a deprecation window is preferred instead, restore jobId as a deprecated field backed by a nullable value.

Comment on lines 203 to 205
`SELECT id, key, physical_name, provision_requested_at FROM ${provisionFunction}($1::uuid)`,
[bucket.id],
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 bug · high

Provision SELECT assumes row-returning _provision function

requestReconciliation now runs SELECT id, key, physical_name, provision_requested_at FROM <private>.<buckets>_provision($1::uuid) (graphile/graphile-bucket-provisioner-plugin/src/plugin.ts:203), which only succeeds if the generated function RETURNS TABLE with those columns. The only provision-function definition in this repo still RETURNS bigint and returns a job id, so the FROM-clause select fails at the SQL level against it.

Impact: every provisionBucket mutation errors with an opaque Postgres message against the current in-repo contract, and the server-test integration suite fails at runtime.

📋 Prompt for AI Agents

In graphile/graphile-bucket-provisioner-plugin/src/plugin.ts lines 201-205, requestReconciliation selects id, key, physical_name, provision_requested_at from the generated <private>.<buckets>_provision(uuid) function, but the only in-repo definition of that function (graphql/server-test/fixtures/seed/simple-seed-storage/auth-provision.sql lines 42-61, a copy of the constructive-db generator output) still RETURNS bigint and returns a job id, so the SELECT fails at parse time against it. Confirm the storage-module generator now emits a row-returning function; if it does, regenerate the seed fixture (and the buckets-table column in that fixture's schema.sql) to the new contract in this same change; if it does not, keep the scalar call form and fetch the stamped row from the buckets table separately. Also consider mapping the mismatch to a clear STORAGE_MODULE_OUTDATED-style error so deployed modules on the old contract fail with a useful message instead of a raw Postgres error.

@blacksmith-sh

This comment has been minimized.

@pyramation
pyramation merged commit 6d2414b into main Oct 17, 2026
19 checks passed
@pyramation
pyramation deleted the feat/bucket-provision-desired-state branch October 17, 2026 15:32
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