Skip to content

Commit

Permalink
Temp/release4.1 (#840)
Browse files Browse the repository at this point in the history
* change markdata object (#821)

* change markdata object

* condition is an object

* rename variable for clarity

* Bugfix/706: Handling old experiment json formats for importing experiments and import feature enhancement (#813)

* handling mostly all old experiment json formats for import

(cherry picked from commit fd588e6)

* scroll vertical for multiple import errors and added warnings for version mismatch

* reducing code complexity for import experiment component

* typing error corrected in import exp component

* missed import in merge

---------

Co-authored-by: jreddig <[email protected]>
Co-authored-by: Pratik Prajapati <[email protected]>
  • Loading branch information
3 people authored May 9, 2023
1 parent 8d7e68d commit 485c295
Show file tree
Hide file tree
Showing 7 changed files with 515 additions and 318 deletions.
281 changes: 158 additions & 123 deletions backend/packages/Upgrade/src/api/services/ExperimentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,31 +298,32 @@ export class ExperimentService {
deleteAuditLogData,
currentUser
);

try {
await transactionalEntityManager
.getRepository(Segment)
.delete(experiment.experimentSegmentInclusion.segment.id);
} catch (err) {
const error = err as ErrorWithType;
error.details = 'Error in deleting Include Segment fron DB';
error.type = SERVER_ERROR.QUERY_FAILED;
logger.error(error);
throw error;
if (experiment.experimentSegmentInclusion) {
try {
await transactionalEntityManager
.getRepository(Segment)
.delete(experiment.experimentSegmentInclusion.segment.id);
} catch (err) {
const error = err as ErrorWithType;
error.details = 'Error in deleting Include Segment fron DB';
error.type = SERVER_ERROR.QUERY_FAILED;
logger.error(error);
throw error;
}
}

try {
await transactionalEntityManager
.getRepository(Segment)
.delete(experiment.experimentSegmentExclusion.segment.id);
} catch (err) {
const error = err as ErrorWithType;
error.details = 'Error in deleting Exclude Segment fron DB';
error.type = SERVER_ERROR.QUERY_FAILED;
logger.error(error);
throw error;
if (experiment.experimentSegmentExclusion) {
try {
await transactionalEntityManager
.getRepository(Segment)
.delete(experiment.experimentSegmentExclusion.segment.id);
} catch (err) {
const error = err as ErrorWithType;
error.details = 'Error in deleting Exclude Segment fron DB';
error.type = SERVER_ERROR.QUERY_FAILED;
logger.error(error);
throw error;
}
}

return deletedExperiment;
}

Expand Down Expand Up @@ -1131,79 +1132,100 @@ export class ExperimentService {
logger.error(error);
throw error;
}

// creating Include Segment
let includeSegmentExists = true;
let segmentIncludeDoc: Segment;
let segmentIncludeDocToSave: Partial<ExperimentSegmentInclusion> = {};
experimentDoc.experimentSegmentInclusion = experimentSegmentInclusion;
let segmentInclude;
if (experimentDoc.experimentSegmentInclusion.segment) {
const includeSegment = experimentDoc.experimentSegmentInclusion.segment;
segmentInclude = {
...experimentSegmentInclusion,
type: includeSegment.type,
userIds: includeSegment.individualForSegment.map((x) => x.userId),
groups: includeSegment.groupForSegment.map((x) => {
return { type: x.type, groupId: x.groupId };
}),
subSegmentIds: includeSegment.subSegments.map((x) => x.id),
if (experimentDoc.experimentSegmentInclusion) {
// creating Include Segment
let segmentInclude;
if (experimentDoc.experimentSegmentInclusion.segment) {
const includeSegment = experimentDoc.experimentSegmentInclusion.segment;
segmentInclude = {
...experimentSegmentInclusion,
type: includeSegment.type,
userIds: includeSegment.individualForSegment.map((x) => x.userId),
groups: includeSegment.groupForSegment.map((x) => {
return { type: x.type, groupId: x.groupId };
}),
subSegmentIds: includeSegment.subSegments.map((x) => x.id),
};
} else {
segmentInclude = experimentDoc.experimentSegmentInclusion;
}

const segmentIncludeData: SegmentInputValidator = {
...segmentInclude,
id: uuid(),
name: experiment.id + ' Inclusion Segment',
description: experiment.id + ' Inclusion Segment',
context: experiment.context[0],
type: SEGMENT_TYPE.PRIVATE,
};
try {
segmentIncludeDoc = await this.segmentService.upsertSegment(segmentIncludeData, logger);
} catch (err) {
const error = err as ErrorWithType;
error.details = 'Error in adding segment in DB';
error.type = SERVER_ERROR.QUERY_FAILED;
logger.error(error);
throw error;
}
// creating segmentInclude doc
const includeTempDoc = new ExperimentSegmentInclusion();
includeTempDoc.segment = segmentIncludeDoc;
includeTempDoc.experiment = experimentDoc;
segmentIncludeDocToSave = this.getSegmentDoc(includeTempDoc);
} else {
segmentInclude = experimentDoc.experimentSegmentInclusion;
includeSegmentExists = false;
}

const segmentIncludeData: SegmentInputValidator = {
...segmentInclude,
id: uuid(),
name: experiment.id + ' Inclusion Segment',
description: experiment.id + ' Inclusion Segment',
context: experiment.context[0],
type: SEGMENT_TYPE.PRIVATE,
};
let segmentIncludeDoc: Segment;
try {
segmentIncludeDoc = await this.segmentService.upsertSegment(segmentIncludeData, logger);
} catch (err) {
const error = err as ErrorWithType;
error.details = 'Error in adding segment in DB';
error.type = SERVER_ERROR.QUERY_FAILED;
logger.error(error);
throw error;
}

// creating Exclude Segment
let excludeSegmentExists = true;
let segmentExcludeDoc: Segment;
let segmentExcludeDocToSave: Partial<ExperimentSegmentExclusion> = {};
experimentDoc.experimentSegmentExclusion = experimentSegmentExclusion;
let segmentExclude;
if (experimentDoc.experimentSegmentExclusion.segment) {
const excludeSegment = experimentDoc.experimentSegmentExclusion.segment;
segmentExclude = {
...experimentSegmentExclusion,
type: excludeSegment.type,
userIds: excludeSegment.individualForSegment.map((x) => x.userId),
groups: excludeSegment.groupForSegment.map((x) => {
return { type: x.type, groupId: x.groupId };
}),
subSegmentIds: excludeSegment.subSegments.map((x) => x.id),
if (experimentDoc.experimentSegmentExclusion) {
// creating Exclude Segment
let segmentExclude;
if (experimentDoc.experimentSegmentExclusion.segment) {
const excludeSegment = experimentDoc.experimentSegmentExclusion.segment;
segmentExclude = {
...experimentSegmentExclusion,
type: excludeSegment.type,
userIds: excludeSegment.individualForSegment.map((x) => x.userId),
groups: excludeSegment.groupForSegment.map((x) => {
return { type: x.type, groupId: x.groupId };
}),
subSegmentIds: excludeSegment.subSegments.map((x) => x.id),
};
} else {
segmentExclude = experimentDoc.experimentSegmentExclusion;
}

const segmentExcludeData: SegmentInputValidator = {
...segmentExclude,
id: uuid(),
name: experiment.id + ' Exclusion Segment',
description: experiment.id + ' Exclusion Segment',
context: experiment.context[0],
type: SEGMENT_TYPE.PRIVATE,
};
try {
segmentExcludeDoc = await this.segmentService.upsertSegment(segmentExcludeData, logger);
} catch (err) {
const error = err as ErrorWithType;
error.details = 'Error in adding segment in DB';
error.type = SERVER_ERROR.QUERY_FAILED;
logger.error(error);
throw error;
}
// creating segmentExclude doc
const excludeTempDoc = new ExperimentSegmentExclusion();
excludeTempDoc.segment = segmentExcludeDoc;
excludeTempDoc.experiment = experimentDoc;
segmentExcludeDocToSave = this.getSegmentDoc(excludeTempDoc);
} else {
segmentExclude = experimentDoc.experimentSegmentExclusion;
}

const segmentExcludeData: SegmentInputValidator = {
...segmentExclude,
id: uuid(),
name: experiment.id + ' Exclusion Segment',
description: experiment.id + ' Exclusion Segment',
context: experiment.context[0],
type: SEGMENT_TYPE.PRIVATE,
};
let segmentExcludeDoc: Segment;
try {
segmentExcludeDoc = await this.segmentService.upsertSegment(segmentExcludeData, logger);
} catch (err) {
const error = err as ErrorWithType;
error.details = 'Error in adding segment in DB';
error.type = SERVER_ERROR.QUERY_FAILED;
logger.error(error);
throw error;
excludeSegmentExists = false;
}

// creating condition docs
Expand All @@ -1226,6 +1248,9 @@ export class ExperimentService {
return decisionPoint;
});

if (!conditionPayloads) {
experiment = { ...experiment, conditionPayloads: [] };
}
// update conditionPayloads condition uuids:
if (conditionPayloads) {
conditionPayloads.map((conditionPayload) => {
Expand All @@ -1237,7 +1262,6 @@ export class ExperimentService {
}
});
}

const conditionPayloadDocToSave: Array<Partial<ConditionPayload>> =
(conditionPayloads &&
conditionPayloads.length > 0 &&
Expand All @@ -1253,22 +1277,12 @@ export class ExperimentService {
})) ||
[];

// creating segmentInclude doc
const includeTempDoc = new ExperimentSegmentInclusion();
includeTempDoc.segment = segmentIncludeDoc;
includeTempDoc.experiment = experimentDoc;
const segmentIncludeDocToSave = this.getSegmentDoc(includeTempDoc);

// creating segmentExclude doc
const excludeTempDoc = new ExperimentSegmentExclusion();
excludeTempDoc.segment = segmentExcludeDoc;
excludeTempDoc.experiment = experimentDoc;
const segmentExcludeDocToSave = this.getSegmentDoc(excludeTempDoc);
// creating queries docs
const promiseArray = [];
let queryDocsToSave =
(queries[0] &&
(queries &&
queries.length > 0 &&
queries[0] &&
queries.map((query: any) => {
promiseArray.push(this.metricRepository.findOne(query.metric.key));
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand Down Expand Up @@ -1307,17 +1321,26 @@ export class ExperimentService {
] = await Promise.all([
this.experimentConditionRepository.insertConditions(conditionDocsToSave, transactionalEntityManager),
this.decisionPointRepository.insertDecisionPoint(decisionPointDocsToSave, transactionalEntityManager),
this.experimentSegmentInclusionRepository.insertData(
segmentIncludeDocToSave,
logger,
transactionalEntityManager
),
this.experimentSegmentExclusionRepository.insertData(
segmentExcludeDocToSave,
logger,
transactionalEntityManager
),
this.conditionPayloadRepository.insertConditionPayload(conditionPayloadDocToSave, transactionalEntityManager),
includeSegmentExists
? this.experimentSegmentInclusionRepository.insertData(
segmentIncludeDocToSave,
logger,
transactionalEntityManager
)
: (Promise.resolve([]) as any),
excludeSegmentExists
? this.experimentSegmentExclusionRepository.insertData(
segmentExcludeDocToSave,
logger,
transactionalEntityManager
)
: (Promise.resolve([]) as any),
conditionPayloadDocToSave.length > 0
? this.conditionPayloadRepository.insertConditionPayload(
conditionPayloadDocToSave,
transactionalEntityManager
)
: (Promise.resolve([]) as any),
queryDocsToSave.length > 0
? this.queryRepository.insertQueries(queryDocsToSave, transactionalEntityManager)
: (Promise.resolve([]) as any),
Expand Down Expand Up @@ -1361,17 +1384,29 @@ export class ExperimentService {
factorDocToReturn = this.formatingFactorAndLevels(factorDoc, levelDoc);
conditionDocToReturn = this.formatingElements(conditionDocToReturn, levelCombinationElementDoc, levelDoc);
}

const newExperiment = {
...experimentDoc,
conditions: conditionDocToReturn as any,
partitions: decisionPointDocToReturn as any,
factors: factorDocToReturn as any,
experimentSegmentInclusion: { ...experimentSegmentInclusionDoc, segment: segmentIncludeDoc } as any,
experimentSegmentExclusion: { ...experimentSegmentExclusionDoc, segment: segmentExcludeDoc } as any,
conditionPayloads: conditionPayloadDocToReturn as any,
queries: (queryDocToReturn as any) || [],
};
let newExperimentObject;
if (experimentDoc.experimentSegmentInclusion && experimentDoc.experimentSegmentExclusion) {
newExperimentObject = {
...experimentDoc,
conditions: conditionDocToReturn as any,
partitions: decisionPointDocToReturn as any,
factors: factorDocToReturn as any,
experimentSegmentInclusion: { ...experimentSegmentInclusionDoc, segment: segmentIncludeDoc } as any,
experimentSegmentExclusion: { ...experimentSegmentExclusionDoc, segment: segmentExcludeDoc } as any,
conditionPayloads: conditionPayloadDocToReturn as any,
queries: (queryDocToReturn as any) || [],
};
} else {
newExperimentObject = {
...experimentDoc,
conditions: conditionDocToReturn as any,
partitions: decisionPointDocToReturn as any,
factors: factorDocToReturn as any,
conditionPayloads: conditionPayloadDocToReturn as any,
queries: (queryDocToReturn as any) || [],
};
}
const newExperiment = newExperimentObject;
return newExperiment;
});
// create schedules to start experiment and end experiment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,11 @@ export class ExperimentParticipantsComponent implements OnInit {
});

this.participantsForm.get('inclusionCriteria').setValue(INCLUSION_CRITERIA.INCLUDE_SPECIFIC);

if (this.experimentInfo) {
if (
this.experimentInfo &&
this.experimentInfo.experimentSegmentInclusion &&
this.experimentInfo.experimentSegmentExclusion
) {
if (this.experimentInfo.filterMode === FILTER_MODE.EXCLUDE_ALL) {
this.participantsForm.get('inclusionCriteria').setValue(INCLUSION_CRITERIA.INCLUDE_SPECIFIC);
this.experimentInfo.experimentSegmentInclusion.segment.individualForSegment.forEach((id) => {
Expand Down Expand Up @@ -167,6 +170,7 @@ export class ExperimentParticipantsComponent implements OnInit {
this.members2.push(this.addMembers2(MemberTypes.SEGMENT, id.name));
});
}
} else {
this.members1.removeAt(0);
this.members2.removeAt(0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
<ng-container matColumnDef="File Name">
<mat-header-cell class="ft-12-700" *matHeaderCellDef> File Name </mat-header-cell>
<mat-cell class="ft-12-600" *matCellDef="let element">
{{ element.fileName }}
{{ element.filename }}
</mat-cell>
</ng-container>

<!-- Error -->
<ng-container matColumnDef="Error">
<mat-header-cell class="ft-12-700" *matHeaderCellDef> Error </mat-header-cell>
<mat-header-cell class="ft-12-700" *matHeaderCellDef> Error/Warning </mat-header-cell>
<mat-cell class="ft-12-600" *matCellDef="let element">
{{ element.error }}
</mat-cell>
Expand All @@ -42,8 +42,11 @@
<button
mat-raised-button
class="shared-modal--modal-btn default-button"
[ngClass]="{ 'default-button--disabled': uploadedFileCount === 1 && (!experimentInfo || !isExperimentJSONValid) }"
[disabled]="uploadedFileCount === 1 && (!experimentInfo || !isExperimentJSONValid)"
[ngClass]="{
'default-button--disabled':
uploadedFileCount === 0 || (uploadedFileCount === 1 && (!experimentInfo || !isExperimentJSONValid))
}"
[disabled]="uploadedFileCount === 0 || (uploadedFileCount === 1 && (!experimentInfo || !isExperimentJSONValid))"
(click)="importExperiment()"
>
{{ 'global.import.text' | translate }}
Expand Down
Loading

0 comments on commit 485c295

Please sign in to comment.