Skip to content

Conversation

@royphilip
Copy link

Fix OgImage unique-URL constraint breaking resource registration (Issue #287)

Registering a second resource whose origin shares an OG image URL with an existing origin currently fails with:

Unique constraint failed on the fields: (url)

Root cause: OgImage.url is globally unique, but multiple origins can legitimately share the same OG image URL (e.g. shared CDN, redirects). The original upsertOrigin also keyed OgImages only by url, which conflicts with that global uniqueness.

This PR makes OgImages unique per origin, not globally, and refactors origin upsert logic to be safe and idempotent.


Changes

  • DB schema

    • OgImage.url is no longer globally unique:
      • In schema.prisma, changed:
        • url: String @unique -> url: String
      • Kept @@unique([originId, url]), so each origin can still only have one OgImage per URL.
    • (Via generated Prisma migration) drops the OgImage_url_key unique index in the database.
  • Origin upsert logic

    • Refactored upsertOrigin to use an explicit transaction and composite key:

      • Upserts ResourceOrigin by origin and returns a stable originId.
      • Deletes any OgImage rows for that origin whose URL is no longer present in the current scrape:
        await tx.ogImage.deleteMany({
          where: {
            originId,
            url: { notIn: newImageUrls },
          },
        });
      • Upserts each incoming OG image by the composite key originId_url:
        tx.ogImage.upsert({
          where: { originId_url: { originId, url } },
          create: { originId, url, height, width, title, description },
          update: { height, width, title, description },
        });
      • Returns the final ResourceOrigin including its ogImages.
    • This allows the same OG image URL to be associated with multiple origins, while keeping OgImages idempotent and clean per origin.


Behavior

  • Multiple ResourceOrigin rows can now safely reference the same OG image URL.
  • Resource registration no longer fails when different domains share a common OG image.
  • For each origin:
    • Images no longer present in the latest scrape are removed.
    • Existing images are updated in place.
    • New images are created.

No external API changes; the upsertOrigin signature and return type remain the same.


Tests / Verification

  • Applied Prisma migration locally and confirmed that the OgImage_url_key unique index is dropped while the composite originId_url constraint remains.
  • Manual repro of the reported issue:
    1. Register resource with origin https://subdomain.example.com that scrapes OG image https://cdn.example.com/shared.png.
    2. Register resource with origin https://example.com that scrapes the same OG image URL.
    3. Registration now succeeds; both origins have OgImages with url = https://cdn.example.com/shared.png.
  • Re-ran registration for an existing origin with a changed OG image set to confirm stale images are removed and new ones are upserted correctly.

Ready for review.

- Remove global unique constraint on OgImage.url
- Refactor upsertOrigin to use transactional logic with composite keys
@vercel
Copy link
Contributor

vercel bot commented Dec 3, 2025

@royphilip is attempting to deploy a commit to the Merit Systems Team on Vercel.

A member of the Team first needs to authorize it.

@shafu0x shafu0x requested review from jasonhedman and rsproule and removed request for jasonhedman January 14, 2026 16:46
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