Genace

generation operation unique key: deduplicate local intent without inventing API idempotency

A double-click, retried browser request, or duplicate queue delivery can represent the same business intent. A unique operation key in your database lets those attempts converge on one application record. It does not establish that repeated Genace POST requests create the same remote job. Keep local intent deduplication and remote creation semantics separate.

Choose the business identity

Scope an operation key to the application user or tenant and the action being requested. For example, a storyboard frame revision can identify one approved render. Reusing the key for a changed prompt should produce a conflict rather than silently returning an unrelated earlier result.

Store a fingerprint of a canonical specification containing model, prompt revision, aspect ratio, duration, resolution, and other supported parameters. Define canonicalization explicitly; arbitrary JSON property order should not change the fingerprint, while a meaningful parameter change should.

CREATE TABLE app_generation_intents (
  operation_id text PRIMARY KEY,
  tenant_id text NOT NULL,
  operation_key text NOT NULL,
  specification_hash text NOT NULL,
  phase text NOT NULL,
  remote_job_id text,
  UNIQUE (tenant_id, operation_key)
);

This is a new application table, not a migration for Genace’s internal job storage. Use parameterized statements and transactions in the surrounding application code. Do not make a client-provided tenant field authoritative; derive ownership from the authenticated session.

Resolve a conflict by reading the existing operation

When insertion encounters the unique constraint, load the existing row. If its fingerprint matches, return the same operation reference and current local status. If it differs, reject the reuse and ask the caller to create a new intentional operation. Do not overwrite the original request to make the conflict disappear.

Only one claimant should dispatch a prepared operation. Use a conditional transition to submitting so two processes that both found the same row cannot independently decide to POST. Keep the database transaction short and persist the accepted job_id as soon as the response arrives.

Preserve the remote uncertainty interval

If a connection ends after dispatch but before a reliable response is saved, the row should remain uncertain. A unique constraint prevents another local row but cannot prove whether the first remote request was accepted. Do not reset the row to prepared just because a lease or browser request timed out.

A known HTTP 502 submission failure may carry error.job_id; save that reference for inspection and accounting. A normal accepted response carries top-level job_id. The GET snapshot calls the identifier id, so normalize those fields in your persistence layer without changing their actual API meaning.

Test concurrency and changed inputs

Submit the same local intent from two test clients simultaneously and assert one operation row and one authorized dispatch. Retry after acceptance and verify the saved ID is returned without another POST. Reuse the key with a changed fingerprint and verify a conflict. Simulate a lost response and confirm the record stays uncertain.

Review retention rules before deleting deduplication records; removing them too early can allow old retried messages to appear new. Keep only the data necessary for your business and recovery policy.

See duplicate request handling, transactional outbox design, and worker leases.

Continue with production operations

Where these facts come from