SITES-49202: remove deprecated brand semrushWorkspaceId mirror (§5 PR B, spacecat-shared) - #1867
SITES-49202: remove deprecated brand semrushWorkspaceId mirror (§5 PR B, spacecat-shared)#1867aliciadriani wants to merge 5 commits into
Conversation
…SITES-49202) §5 PR B of the Serenity post-GA cleanup. Removes the deprecated, read-only `semrushWorkspaceId` mirror attribute from the Brand model (mysticat-data-service `brands.semrush_workspace_id`), now that project-elmo-ui PR #2730 (PR A) has migrated the last direct reader to the canonical `semrushSubWorkspaceId`. Precondition (verified): the brand mirror carries no unique data (prod DB: 0 rows where it is the only value) and has no backend caller of its finder/setter. The org-level `Organization.semrushWorkspaceId` is a distinct, correctly-named field and is deliberately KEPT. Removed (brand model only): - brand.schema.js: the `semrushWorkspaceId` readOnly attribute and its `addAllIndex(['semrushWorkspaceId'])`. - brand.model.js: the @deprecated `setSemrushWorkspaceId()` BC delegate + docblock. - brand.collection.js / index.d.ts: the mirror finder references and type declarations (get/set/findBy/allBySemrushWorkspaceId). - brand unit tests: the corresponding mirror assertions/fixtures. Note: `addAllIndex(['semrushWorkspaceId'])` defines a DynamoDB GSI in the electrodb schema — this change stops the code using it, but the physical GSI teardown is a separate infra op and needs DynamoDB review before merge+deploy. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
aliciadriani
left a comment
There was a problem hiding this comment.
Review — §5 PR B (manual)
Summary
Removes the deprecated brand semrushWorkspaceId mirror (readOnly attribute, its addAllIndex GSI, the @deprecated setSemrushWorkspaceId() delegate, and the finder/getter type decls) from the electrodb Brand model. Consistent and well-scoped; the org-level field is correctly left alone.
Must Fix
None.
Should Fix
None.
Nits
None material. The brand.collection.js pointer-repair docblock now points at findBySemrushSubWorkspaceId — verified that finder is generated from the retained addAllIndex(['semrushSubWorkspaceId']), so the doc is accurate.
What's Good
- Pre-removal grep across spacecat-shared / spacecat-api-service / llmo-data-retrieval-service / project-elmo-ui / mysticat-data-service found no brand-context reader — every hit was the org field or design-spec prose. Precondition solid.
- Reads of existing DynamoDB items are unaffected (electrodb ignores stored fields absent from the schema); the attribute was
readOnly, so nothing wrote through it. - 2774 data-access unit tests pass; lint clean.
- PR body correctly flags the DynamoDB GSI infra-review gate, the PR C ordering (must land after this releases), and the semver bump.
aliciadriani
left a comment
There was a problem hiding this comment.
DynamoDB GSI infra review — CLEARED (safe to merge; no infra change needed)
TL;DR: removing addAllIndex(['semrushWorkspaceId']) is safe with no Terraform/GSI teardown required, because the electrodb Brand entity is not populated — nothing anywhere writes or reads it.
What I checked
- Is the entity used? Grepped all 5 repos (spacecat-shared, spacecat-api-service, llmo-data-retrieval-service, project-elmo-ui, mysticat-data-service) for
dataAccess.Brandreads/writes/queries → zero. Serenity brands live in mysticat-data-service Postgres via PostgREST (brands-storage.js), never the electrodb Brand model. So there are no Brand items in DynamoDB. - Does removal renumber the GSIs? Yes.
schema.builder.jsassigns physicalgsi{N}pk/skby index insertion order. OnmainBrand has twoall-indexes (semrushWorkspaceId=gsi1,semrushSubWorkspaceId=gsi2); after removalsemrushSubWorkspaceIdshifts to gsi1 (empirically confirmed: PR branch buildsgsi1only). On a populated entity this would orphan existing items' GSI-projected data and breakfindBySemrushSubWorkspaceId— but per (1) the entity is empty, so zero runtime impact. - Physical GSI teardown? Not applicable. This is a shared single-table design — physical
gsi1..gsi5are shared across all entities (Site/Org/…) and stay provisioned. Removing Brand's logical index doesn't delete any physical GSI. There is no dedicated brand GSI to tear down.
Verdict
Infra-safe to merge. The PR body's "physical GSI teardown is a separate infra op" caveat can be downgraded — no such op exists here.
One caveat + a follow-up
- I could not inspect
spacecat-infrastructuredirectly (not checked out). Evidence strongly indicates standard sharedgsi1-5; a 30-sec confirm from the table owner that no dedicated brand GSI is provisioned would make this airtight. - Bigger picture: the electrodb
Brandentity appears entirely dead (unused everywhere). Worth a separate follow-up to consider removing the whole model — out of scope for §5.
|
This PR will trigger a patch release when merged. |
There was a problem hiding this comment.
- spacecat-shared-data-access is PostgREST/Postgres-backed, not DynamoDB.
base.collection.js:53isstatic DATASTORE_TYPE = DATASTORE_TYPE.POSTGREST; the layer requiresPOSTGREST_URL/POSTGREST_SCHEMA/POSTGREST_API_KEYand queries via@supabase/postgrest-js(postgrestService.from(tableName)). Thegsi{N}pk/addAllIndexnaming inschema.builder.jsis a legacy electrodb vestige — no DynamoDB table or GSI is involved. - spacecat-infrastructure has no spacecat data table with brand GSIs — it provisions the Mysticat Postgres data service and one unrelated
mysticat_github_serviceidempotency lock table. There is no DynamoDB GSI to review or tear down. - The real physical artifact behind
findBySemrushWorkspaceIdis a Postgres UNIQUE index —brands_semrush_workspace_id_key ON brands (semrush_workspace_id), confirmed present on prod right now. It is dropped automatically when §5 PR C drops thebrands.semrush_workspace_idcolumn (mysticat-data-service migration). Nothing to do in Terraform/DynamoDB.
Net
This PR is a code-only schema/finder removal with NO infra dependency — it just stops the data-access layer generating the semrushWorkspaceId finder. The prior "DynamoDB GSI teardown is a separate infra op" flag in the PR body is retracted — no such op exists. The only physical cleanup (the Postgres index) rides along with §5 PR C.
The renumbering note from my earlier comment is also moot (and was DynamoDB-specific); disregard it.
What & why
PR B of the phased §5 Serenity post-GA cleanup — removes the deprecated, read-only brand
semrushWorkspaceIdmirror from@adobe/spacecat-shared-data-access.This mirror shadowed the canonical
semrushSubWorkspaceId(write-of-record) and was maintained by the mysticat-data-servicebrands_sync_semrush_workspace_idDB trigger. Now that PR A (project-elmo-ui #2730, merged) migrated the last direct reader, the mirror can go.Precondition (verified before removal)
origin/mainof spacecat-shared, spacecat-api-service, llmo-data-retrieval-service, project-elmo-ui, mysticat-data-service forfindBySemrushWorkspaceId/allBySemrushWorkspaceId/setSemrushWorkspaceId/ brand-contextgetSemrushWorkspaceId(— every hit is org-context (Organization/org./organization.) or design-spec prose. No genuine brand-context reader.Datastore / index note — NO infra op (corrected)
This data-access layer is PostgREST/Postgres-backed (
base.collection.js→static DATASTORE_TYPE = DATASTORE_TYPE.POSTGREST,@supabase/postgrest-js,POSTGREST_URL). Despite the legacy electrodb-stylegsi{N}pk/addAllIndexnaming inschema.builder.js, there is no DynamoDB table or GSI here — verified directly againstspacecat-infrastructure(which provisions the Mysticat Postgres service + one unrelated github-service lock table, no spacecat data table with brand GSIs).Removing
addAllIndex(['semrushWorkspaceId'])just stops the data-access layer generating thesemrushWorkspaceIdfinder — no infra/table change, and none needed. The one physical artifact is the Postgres unique indexbrands_semrush_workspace_id_key ON brands(semrush_workspace_id)(confirmed live on prod), which drops automatically with the column in PR C (mysticat-data-service migration). So this PR is code-only with no infra dependency.org-level field deliberately KEPT
Organization.semrushWorkspaceId(correctly-named, distinct entity) is untouched — this is a brand-only removal. The symbol collision is the trap here; org getter/finder/setter all stay.Changes (brand model only)
src/models/brand/brand.schema.jssemrushWorkspaceIdreadOnly mirror attribute andaddAllIndex(['semrushWorkspaceId']); tidied surrounding comments.src/models/brand/brand.model.js@deprecated setSemrushWorkspaceId()BC delegate + docblock; updated the class docblock to describesemrushSubWorkspaceIdas the dual-mode switch.src/models/brand/brand.collection.jsfindBySemrushSubWorkspaceId.src/models/brand/index.d.tsgetSemrushWorkspaceId,setSemrushWorkspaceId,allBySemrushWorkspaceId,findBySemrushWorkspaceId.test/unit/models/brand/brand.schema.test.jstest/unit/models/brand/brand.model.test.jstest/unit/models/brand/brand.collection.test.jsNext step — PR C (do NOT land before this releases)
PR C = mysticat-data-service migration dropping the
brands.semrush_workspace_idcolumn and thesync_semrush_workspace_id_from_subtrigger (the Postgres unique indexbrands_semrush_workspace_id_keydrops with the column). It must land only AFTER this PR is released/deployed, so no deployed consumer still references the mirror attribute when the column/trigger disappear.Semver
Published package — this removes public model members, so a semver bump is expected and handled by semantic-release from the conventional-commit message. No manual version edits.
Validation
npm run lint(data-access): clean.npm test(data-access, full unit suite): 2774 passing, 0 failing.Links