-
Notifications
You must be signed in to change notification settings - Fork 0
feat(data-access): add scopeType and scopeId to Opportunity model #1576
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
eb7dac2
fa9dcea
f9ddca7
7d48e2a
6136d91
aba6037
7eeb083
df0394b
6b0e10a
577b6d3
57d91d8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,8 @@ | |
| * governing permissions and limitations under the License. | ||
| */ | ||
|
|
||
| import { hasText } from '@adobe/spacecat-shared-utils'; | ||
|
|
||
| import BaseCollection from '../base/base.collection.js'; | ||
|
|
||
| /** | ||
|
|
@@ -22,7 +24,24 @@ import BaseCollection from '../base/base.collection.js'; | |
| class OpportunityCollection extends BaseCollection { | ||
| static COLLECTION_NAME = 'OpportunityCollection'; | ||
|
|
||
| // add custom methods here | ||
| /** | ||
| * Returns all opportunities with a given scope type and scope ID. | ||
| * Used to fetch brand-scoped opportunities directly by brandId | ||
| * without going through site association. | ||
| * | ||
| * @param {string} scopeType - The scope type (e.g. 'brand', 'site'). | ||
| * @param {string} scopeId - The scope entity UUID (e.g. brand UUID). | ||
| * @returns {Promise<Opportunity[]>} The matching opportunities. | ||
| */ | ||
| async allByScopeId(scopeType, scopeId) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Important - method name is misleading, and two issues around validation. Rename
|
||
| if (!hasText(scopeType)) { | ||
| throw new Error('scopeType is required'); | ||
| } | ||
| if (!hasText(scopeId)) { | ||
| throw new Error('scopeId is required'); | ||
| } | ||
| return this.allByIndexKeys({ scopeType, scopeId }); | ||
| } | ||
| } | ||
|
|
||
| export default OpportunityCollection; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -64,6 +64,12 @@ const schema = new SchemaBuilder(Opportunity, OpportunityCollection) | |
| .addAttribute('lastAuditedAt', { | ||
| type: 'string', | ||
| validate: (value) => !value || isIsoDate(value), | ||
| }) | ||
| .addAttribute('scopeType', { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Important - no co-presence validation, and strict enum may reject existing NULL rows. Two issues at No co-presence enforcement. Both attributes are independently optional. A record can be saved with Strict enum may break hydration of legacy rows. |
||
| type: Object.values(Opportunity.SCOPE_TYPES), | ||
| }) | ||
| .addAttribute('scopeId', { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical - missing composite index AND no format constraint on Two issues at this attribute declaration: Missing index for No format constraint on import { isValidUUID } from '@adobe/spacecat-shared-utils';
.addAttribute('scopeId', {
type: 'string',
validate: (value) => !value || isValidUUID(value),
}) |
||
| type: 'string', | ||
| }); | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Co-presence gap: there is no cross-field validator enforcing that |
||
| export default schema.build(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hot partition: .addIndex({ composite: ['scopeId'] }, { composite: ['scopeType'] })Fix while no production data exists yet. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,7 +17,7 @@ services: | |
|
|
||
| data-service: | ||
| platform: ${MYSTICAT_DATA_SERVICE_PLATFORM:-linux/amd64} | ||
| image: ${MYSTICAT_DATA_SERVICE_REPOSITORY:-682033462621.dkr.ecr.us-east-1.amazonaws.com/mysticat-data-service}:${MYSTICAT_DATA_SERVICE_TAG:-v1.67.8} | ||
| image: ${MYSTICAT_DATA_SERVICE_REPOSITORY:-682033462621.dkr.ecr.us-east-1.amazonaws.com/mysticat-data-service}:${MYSTICAT_DATA_SERVICE_TAG:-v5.1.1} | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical - unexplained 4-major-version image bump. v1.67.8 to v5.1.1 is a four-major-version jump with no explanation in the PR description. Either:
A future bisect on this commit will need to unpack which of two simultaneous changes caused a regression. Also: the image is pinned by tag (mutable) - pin by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unexplained bump + mutable tag: the jump from v1.67.8 to v5.1.1 needs a comment or PR description entry explaining that v5.x carries the DynamoDB migration for Also, tag-pinned images are mutable - the same tag can change without notice. Pin to a digest instead: image: 682033462621.dkr.ecr.us-east-1.amazonaws.com/mysticat-data-service@sha256:<digest>
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment added in this commit explains the bump policy for developers running tests locally - that is an improvement. Two gaps remain:
|
||
| depends_on: | ||
| db: | ||
| condition: service_healthy | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Important - TypeScript return types disagree with runtime behavior.
getScopeId(): string | nullandgetScopeType(): string | nulldeclarenullfor the absent case, but the unit tests assertto.be.undefined. Callers checking=== nullget a false negative on the unset case. Auth-path code relying on this falls through silently.Either normalize the getters to return
null(preferred for JSON/DB API consistency), or change the TS declarations tostring | undefined. Pick one and align code and types.