.append(id, other.getID()) .append(creationTime, other.getCreationTime()) .append(modificationTime, other.getModificationTime()) .append(description, other.getDescription()) .append(hypothesisIsCorrect, other.getHypothesisIsCorrect()) .append(results, other.getResults()) .append(rule, other.getRule()) .append(samplingPercent, other.getSamplingPercent()) .append(startTime, other.getStartTime()) .append(endTime, other.getEndTime()) .append(state, other.getState()) .append(label, other.getLabel()) .append(applicationName, other.getApplicationName()) .append(isPersonalizationEnabled, other.getIsPersonalizationEnabled()) .append(modelName, other.getModelName()) .append(modelVersion, other.getModelVersion()) .append(isRapidExperiment, other.getIsRapidExperiment()) .append(userCap, other.getUserCap()) .append(creatorID, other.getCreatorID()) .append(tags, other.getTags()) .append(buckets, other.getBuckets()) .append(sourceURL,other.getSourceURL()) .append(experimentType,other.getExperimentType()) .isEquals();
/** * Checks that an experiment has a state "draft" and throws an exception * if it doesn't * * @param experiment Experiment object containing experiment metadata */ public void ensureStateIsDraft(Experiment experiment) { Experiment.State state = experiment.getState(); if (!state.equals(Experiment.State.DRAFT)) { throw new InvalidExperimentStateException(experiment.getID(), Experiment.State.DRAFT, experiment.getState()); } }
public void validateExperiment(Experiment experiment) { Experiment.State state = experiment.getState(); if (state.equals(Experiment.State.DELETED) || state.equals(Experiment.State.TERMINATED)) { return; } validateLabel(experiment.getLabel()); validateExperimentStartEnd(experiment.getStartTime(), experiment.getEndTime()); validateSamplingPercent(experiment.getSamplingPercent()); validateExperimentRule(experiment.getRule()); validateModelNameNotNullForPersonalizedExperiments(experiment.getIsPersonalizationEnabled() , experiment.getModelName()); }
private Builder(Experiment other, Integer priority) { this(other.getID()); instance.creationTime = copyDate(other.getCreationTime()); instance.modificationTime = copyDate(other.getModificationTime()); instance.setDescription(other.getDescription()); instance.setSamplingPercent(other.getSamplingPercent()); instance.setRule(other.getRule()); instance.setStartTime(copyDate(other.getStartTime())); instance.setEndTime(copyDate(other.getEndTime())); instance.setState(other.getState()); instance.setLabel(other.getLabel()); instance.setApplicationName(other.getApplicationName()); instance.setPriority(priority); instance.setIsPersonalizationEnabled(other.getIsPersonalizationEnabled()); instance.setModelName(other.getModelName()); instance.setModelVersion(other.getModelVersion()); instance.isRapidExperiment = other.getIsRapidExperiment(); instance.userCap = other.getUserCap(); instance.creatorID = other.getCreatorID(); instance.tags = other.getTags(); }
/** * Creates the ExperimentDetail with a given Experiment and the total number of users. * * @param exp the experiment that provides the basic information */ public ExperimentDetail(Experiment exp) { this(exp.getID(), exp.getState(), exp.getLabel(), exp.getApplicationName(), exp.getModificationTime(), exp.getStartTime(), exp.getEndTime(), exp.getDescription(), exp.getTags()); }
@Override public Experiment updateExperiment(Experiment experiment) throws RepositoryException { validator.validateExperiment(experiment); final String SQL = "update experiment " + "set description=?, sampling_percent=?, state=?, " + "label=?, start_time=?, end_time=?, app_name=? " + "where id=?"; int rowCount = newTransaction().update( SQL, experiment.getDescription() != null ? experiment.getDescription() : "", experiment.getSamplingPercent(), experiment.getState().toString(), experiment.getLabel().toString(), experiment.getStartTime(), experiment.getEndTime(), experiment.getApplicationName().toString(), experiment.getID()); if (rowCount > 1) { throw new RepositoryException("Concurrent updates; please retry"); } if (rowCount < 1) { throw new RepositoryException("No rows were updated"); } return experiment; }
/** * {@inheritDoc} */ @Override public Experiment updateExperimentState(Experiment experiment, State state) { LOGGER.debug("Updating experiment {} state {} ", new Object[]{experiment, state}); validator.validateExperiment(experiment); try { // Note that this timestamp gets serialized as mulliseconds from // the epoch, so timezone is irrelevant final Date NOW = new Date(); experimentAccessor.updateExperiment(state.name(), NOW, experiment.getID().getRawID()); experiment = Experiment.from(experiment).withState(state).build(); // Point the experiment index to this experiment updateExperimentLabelIndex(experiment.getID(), experiment.getApplicationName(), experiment.getLabel(), experiment.getStartTime(), experiment.getEndTime(), experiment.getState()); updateStateIndex(experiment); } catch (Exception e) { LOGGER.error("Error while updating experiment {} state {} ", new Object[]{experiment, state}, e); throw new RepositoryException("Could not update experiment with ID \"" + experiment.getID() + "\"" + " to state " + state.toString(), e); } return experiment; }
if (experiment.getState().equals(TERMINATED)) { if (updates.getApplicationName() != null && !updates.getApplicationName().equals(experiment.getApplicationName())) { throw new IllegalArgumentException("Invalid application name \"" + updates.getApplicationName() + "\" " + "Cannot change application name when the experiment is in TERMINATED state"); if (updates.getLabel() != null && !updates.getLabel().equals(experiment.getLabel())) { throw new IllegalArgumentException("Invalid label \"" + updates.getLabel() + "\" " + "Cannot change label when the experiment is in TERMINATED state"); if (updates.getStartTime() != null && !updates.getStartTime().equals(experiment.getStartTime())) { throw new IllegalArgumentException("Invalid startTime \"" + updates.getStartTime() + "\" " + "Cannot change start time when the experiment is in TERMINATED state"); if (updates.getEndTime() != null && !updates.getEndTime().equals(experiment.getEndTime())) { throw new IllegalArgumentException("Invalid endTime \"" + updates.getEndTime() + "\" " + "Cannot change end time when the experiment is in TERMINATED state"); if (updates.getSamplingPercent() != null && !updates.getSamplingPercent().equals(experiment.getSamplingPercent())) { throw new IllegalArgumentException("Invalid sampling percentage \"" + updates.getSamplingPercent() + "\" " + "Cannot change sampling percentage when the experiment is in TERMINATED state"); if (updates.getRule() != null && !updates.getRule().equals(experiment.getRule())) { throw new IllegalArgumentException("Invalid rule \"" + updates.getRule() + "\" " + "Cannot change sampling rule when the experiment is in TERMINATED state");
/** * {@inheritDoc} */ @Override public void checkForIllegalPausedRunningUpdate(Experiment experiment, Experiment updates) { /* Throw an exception if the experiment is in RUNNING/PAUSED state and if applicationName or Label is being updated. Also, if startTime/endTime is being updated with a value that has already passed or when the established startTime/endTime has already passed. */ if (experiment.getState().equals(RUNNING) || experiment.getState().equals(PAUSED)) { if (updates.getApplicationName() != null && !updates.getApplicationName().equals(experiment.getApplicationName())) throw new IllegalArgumentException("Cannot change AppName when the experiment is not in DRAFT state"); if (updates.getLabel() != null && !updates.getLabel().equals(experiment.getLabel())) throw new IllegalArgumentException("Cannot change Label when the experiment is not in DRAFT state"); if (updates.getStartTime() != null && !updates.getStartTime().equals(experiment.getStartTime())) checkForIllegalExperimentStartTime(experiment, updates); if (updates.getEndTime() != null && !updates.getEndTime().equals(experiment.getEndTime())) checkForIllegalExperimentEndTime(experiment, updates); } }
/** * {@inheritDoc} */ @Override public void updateExperimentState(final Experiment experiment, final Experiment.State state) { try { cassandraRepository.updateExperimentState(experiment, state); // To maintain consistency, revert the changes made in cassandra in case the mysql update fails try { databaseRepository.updateExperimentState(experiment, state); } catch (Exception exception) { cassandraRepository.updateExperimentState(experiment, experiment.getState()); throw exception; } eventLog.postEvent(new ExperimentChangeEvent(experiment, "state", experiment.getState().toString(), state.toString())); } catch (Exception exception) { LOGGER.error("Updating experiment state for experiment:{} failed with error:", experiment, exception); throw exception; } LOGGER.info("event=EXPERIMENT_METADATA_CHANGE, message=EXPERIMENT_STATE_UPDATED, applicationName={}, configuration=[experimentName={}, oldState={}, newState={}]", experiment.getApplicationName(), experiment.getLabel(), experiment.getState(), state); } }
void checkForIllegalExperimentEndTime(Experiment current, Experiment update) { if (update.getEndTime().before(currentDate)) { throw new IllegalArgumentException("Invalid endTime \"" + update.getEndTime() + "\". " + "Cannot set the experiment end time to a value in the past"); } else if (current.getEndTime().before(currentDate)) { throw new IllegalArgumentException("Invalid endTime \"" + update.getEndTime() + "\". " + "Cannot update the experiment endTime that has already passed"); } else { if (update.getStartTime() != null) { if (update.getEndTime().before(update.getStartTime())) { throw new IllegalArgumentException("Invalid startTime \"" + update.getEndTime() + "\". " + "Cannot update the experiment endTime to a value preceding the experiment startTime"); } } else { if (update.getEndTime().before(current.getStartTime())) { throw new IllegalArgumentException("Invalid startTime \"" + update.getEndTime() + "\". " + "Cannot update the experiment endTime to a value preceding the experiment startTime"); } } } }
Experiment.ID experimentID = experiment.getID(); if (experiment.getState() == Experiment.State.TERMINATED) { throw new InvalidExperimentStateException(new StringBuilder("Should not be able to access terminated experiment \"") .append(experimentID).append("\" via label \"") if (experiment.getState() == Experiment.State.DRAFT) { return nullAssignment(userID, applicationName, experimentID, Assignment.Status.EXPERIMENT_IN_DRAFT_STATE); if (currentTime < experiment.getStartTime().getTime()) { return nullAssignment(userID, applicationName, experimentID, Assignment.Status.EXPERIMENT_NOT_STARTED); if (currentTime > experiment.getEndTime().getTime()) { return nullAssignment(userID, applicationName, experimentID, Assignment.Status.EXPERIMENT_EXPIRED);
private Builder(Experiment other) { this(other.getID()); instance.creationTime = copyDate(other.creationTime); instance.modificationTime = copyDate(other.modificationTime); instance.description = other.description; instance.hypothesisIsCorrect = other.hypothesisIsCorrect; instance.results = other.results; instance.rule = other.rule; instance.ruleJson = other.ruleJson; instance.samplingPercent = other.samplingPercent; instance.startTime = copyDate(other.startTime); instance.endTime = copyDate(other.endTime); instance.state = other.state; instance.label = other.label; instance.applicationName = other.applicationName; instance.isPersonalizationEnabled = other.isPersonalizationEnabled; instance.modelName = other.modelName; instance.modelVersion = other.modelVersion; instance.isRapidExperiment = other.isRapidExperiment; instance.userCap = other.userCap; instance.creatorID = other.creatorID; instance.tags = other.tags; instance.buckets = other.buckets; instance.sourceURL=other.sourceURL; instance.experimentType=other.experimentType; }
/** * {@inheritDoc} */ @Override public void deleteExclusion(Experiment.ID expID_1, Experiment.ID expID_2, UserInfo user) { Experiment exp_1 = experiments.getExperiment(expID_1); Experiment exp_2 = experiments.getExperiment(expID_2); // Check that expID_1 is a valid experiment if (exp_1 == null) { throw new ExperimentNotFoundException(expID_1); } // Check that expID_2 is a valid experiment if (exp_2 == null) { throw new ExperimentNotFoundException(expID_2); } mutexRepository.deleteExclusion(expID_1, expID_2); eventLog.postEvent(new ExperimentChangeEvent(user, exp_1, "mutex", exp_2.getLabel().toString(), null)); LOGGER.info("event=EXPERIMENT_METADATA_CHANGE, message=MUTUAL_EXCLUSION_DELETED, applicationName={}, configuration=[experiment1={}, experiment2={}]", exp_1.getApplicationName(), exp_1.getLabel(), exp_2.getLabel()); }
/** * {@inheritDoc} */ @Override public void appendToPriorityList(Experiment.ID experimentID) { Application.Name applicationName = experiments.getExperiment(experimentID).getApplicationName(); List<Experiment.ID> priorityList = prioritiesRepository.getPriorityList(applicationName); if (priorityList == null) { priorityList = new ArrayList<>(1); } // TODO: This current logic does not modify the priority list if the given experimentID already exists in the // priority list. Check if it would be better to move the given experiment to the end of the list if it // already exists if (!priorityList.contains(experimentID)) { priorityList.add(experimentID); prioritiesRepository.createPriorities(applicationName, priorityList); } }
if (experiment.getIsRapidExperiment() != null && experiment.getIsRapidExperiment()) { int userCap = experiment.getUserCap(); AssignmentCounts assignmentCounts = null; if (null != prefetchedAssignmentCounts) { assignmentCounts = prefetchedAssignmentCounts.get(experiment.getID()); if (experiment.getState().equals(Experiment.State.RUNNING) && assignmentCounts.getTotalUsers().getBucketAssignments() >= userCap) { Experiment experimentInfoFromDB = experimentUtil.getExperiment(experiment.getID()); if (experimentInfoFromDB.getState().equals(Experiment.State.RUNNING)) { experimentUtil.updateExperimentState(experiment, Experiment.State.PAUSED);
private Application.Name getApplicationNameForModifyingPages(Experiment.ID experimentID) { Experiment experiment = experiments.getExperiment(experimentID); // Throw an exception if the experiment is not found if (experiment == null) { throw new ExperimentNotFoundException(experimentID); } Application.Name applicationName = experiment.getApplicationName(); // Throw an exception if the experiment is in a TERMINATED state if (experiment.getState() == TERMINATED) { throw new InvalidExperimentStateException("Experiment must be in DRAFT, RUNNING or PAUSED states\"" + experimentID); } // Throw an exception if the experiment's end time has passed if (experiment.getEndTime().before(NOW)) { throw new IllegalArgumentException("Cannot modify pages of the experiment \"" + experimentID + "\" that has passed its end time"); } return applicationName; }
public List<Experiment.ID> cleanPriorityList(Application.Name applicationName, List<Experiment.ID> experimentIDs) { // Removing duplicates from the priority list Set<Experiment.ID> experimentSet = new LinkedHashSet<>(experimentIDs); // Removing the experiment ID's from the priority list that are invalid for (Experiment.ID experimentID : experimentIDs) { Experiment experiment = experiments.getExperiment(experimentID); // Remove DELETED experiments from the priorityList // Remove experiments not belonging to the pertinent application // Remove TERMINATED experiments from the priorityList if (experiment == null || !experiment.getApplicationName().equals(applicationName) || experiment.getState().equals(TERMINATED)) { experimentSet.remove(experimentID); } } // Adding valid (DRAFT, RUNNING, PAUSED) experiments from the experiment column family to the priorityList that // are missing List<Experiment> experimentList = experiments.getExperiments(applicationName); if (experimentList.size() != experimentSet.size()) { for (Experiment experiment : experimentList) { if (!experimentSet.contains(experiment.getID())) { experimentSet.add(experiment.getID()); } } } return new ArrayList<>(experimentSet); }
/** * {@inheritDoc} */ @Override public Table<Experiment.ID, Experiment.Label, Experiment> getExperimentList(Application.Name appName) { try { List<com.intuit.wasabi.repository.cassandra.pojo.Experiment> experimentPojos = experimentAccessor.getExperimentByAppName(appName.toString()).all(); Table<Experiment.ID, Experiment.Label, Experiment> result = HashBasedTable.create(); for (com.intuit.wasabi.repository.cassandra.pojo.Experiment experimentPojo : experimentPojos) { Experiment experiment = ExperimentHelper.makeExperiment(experimentPojo); if (experiment.getState() != State.TERMINATED && experiment.getState() != State.DELETED) { result.put(experiment.getID(), experiment.getLabel(), experiment); } } return result; } catch (Exception e) { throw new RepositoryException("Could not retrieve experiment list " + appName.toString() + "because: " + e, e); } }
Application.Name applicationName = experiment.getApplicationName(); parallelStream().filter(experiment -> favoriteList.contains(experiment.getID())) .forEach(experiment -> experiment.setFavorite(true)); experimentsList.parallelStream() .forEach(experiment -> { Experiment.ID experimentID = experiment.getID(); BucketList bucketList = buckets.getBuckets(experimentID, false); ExperimentList exclusionExperimentList = mutex.getExclusions(experimentID); List<Experiment.ID> exclusionIdList = new ArrayList<>(); for (Experiment exclusionExperiment : exclusionList) { exclusionIdList.add(exclusionExperiment.getID()); experiment.setBuckets(bucketList.getBuckets()); experiment.setExclusionIdList(exclusionIdList); priorities.getPriorities(experiment.getApplicationName(), true); for (PrioritizedExperiment prioritizedExperiment : prioritizedExperiments.getPrioritizedExperiments()) { if (prioritizedExperiment.getID().equals(experiment.getID())) { experiment.setPriority(prioritizedExperiment.getPriority()); ExperimentPageList experimentPageList = pages.getExperimentPages(experiment.getID()); experiment.setExperimentPageList(experimentPageList.getPages()); });