public static List<UUID> makeUUIDs( Collection<Experiment.ID> experimentIDCollection) { List<UUID> experimentIds = new ArrayList<>(); for (ID id : experimentIDCollection) { experimentIds.add(id.getRawID()); } return experimentIds; }
@Override public Map<Experiment.ID, AssignmentCounts> getBucketAssignmentCountsInParallel(List<Experiment.ID> experimentIds) { Map<Experiment.ID, ListenableFuture<Result<com.intuit.wasabi.repository.cassandra.pojo.count.BucketAssignmentCount>>> experimentToBucketAssignmentFutures = new HashMap<>(); Map<Experiment.ID, AssignmentCounts> experimentToAssignmentCounts = new HashMap<>(); experimentIds.forEach(experimentId -> experimentToBucketAssignmentFutures.put(experimentId, bucketAssignmentCountAccessor.selectByAsync(experimentId.getRawID()))); experimentIds.forEach(experimentId -> experimentToAssignmentCounts.put(experimentId, getBucketAssignmentCountFromCassandraResult(experimentId, UninterruptibleUtil.getUninterruptibly(experimentToBucketAssignmentFutures.get(experimentId))))); return experimentToAssignmentCounts; }
/** * {@inheritDoc} */ @Override public List<Experiment.ID> getExclusionList(Experiment.ID experimentID) { LOGGER.debug("Getting exclusions for {}", experimentID); List<Experiment.ID> exclusionIds = new ArrayList<>(); try { Result<Exclusion> exclusions = mutexAccessor.getExclusions(experimentID.getRawID()); for (Exclusion exclusion : exclusions.all()) { exclusionIds.add(Experiment.ID.valueOf(exclusion.getPair())); } } catch (Exception e) { LOGGER.error("Error while getting exclusions for {}", experimentID, e); throw new RepositoryException("Could not fetch exclusions for experiment \"" + experimentID + "\" ", e); } LOGGER.debug("Getting exclusions list of size {}", exclusionIds); return exclusionIds; }
@Override public void deletePage(Application.Name applicationName, Experiment.ID experimentID, Page.Name pageName) { // For experiment audit log saving the current state of the experiment's page list ExperimentPageList oldPageList = getExperimentPages(experimentID); BatchStatement batch = new BatchStatement(); batch.add(pageExperimentIndexAccessor.deleteBy( applicationName.toString(), pageName.toString(), experimentID.getRawID() )); batch.add(experimentPageAccessor.deleteBy(pageName.toString(), experimentID.getRawID())); //TODO: original code does not have this // batch.add(appPageIndexAccessor.deleteBy(pageName.toString(), applicationName.toString())); executeBatchStatement(experimentID, batch); // For experiment audit log saving the current state of the experiment's page list that has been updated ExperimentPageList newPageList = getExperimentPages(experimentID); saveExperimentPageState(experimentID, oldPageList, newPageList); }
/** * {@inheritDoc} */ protected Experiment internalGetExperiment(Experiment.ID experimentID) { LOGGER.debug("Getting experiment {}", experimentID); Preconditions.checkNotNull(experimentID, "Parameter \"experimentID\" cannot be null"); try { com.intuit.wasabi.repository.cassandra.pojo.Experiment experimentPojo = experimentAccessor .getExperimentById(experimentID.getRawID()).one(); LOGGER.debug("Experiment retrieved {}", experimentPojo); if (experimentPojo == null) return null; if (State.DELETED.name().equals(experimentPojo.getState())) return null; return ExperimentHelper.makeExperiment(experimentPojo); } catch (Exception e) { LOGGER.error("Exception while getting experiment {}", experimentID); throw new RepositoryException("Could not retrieve experiment with ID \"" + experimentID + "\"", e); } }
/** * {@inheritDoc} */ @Override public Bucket updateBucketState(Bucket bucket, Bucket.State desiredState) { LOGGER.debug("Updating bucket {} state {}", new Object[]{bucket, desiredState}); try { bucketAccessor.updateState(desiredState.name(), bucket .getExperimentID().getRawID(), bucket.getLabel().toString()); Result<com.intuit.wasabi.repository.cassandra.pojo.Bucket> bucketPojo = bucketAccessor.getBucketByExperimentIdAndBucket(bucket.getExperimentID() .getRawID(), bucket.getLabel().toString()); return BucketHelper.makeBucket(bucketPojo.one()); } catch (Exception e) { LOGGER.error("Error while updating bucket {} state {}", new Object[]{bucket, desiredState}, e); throw new RepositoryException("Exception while updating bucket state " + bucket + " state " + desiredState, e); } }
@Override public ExperimentPageList getExperimentPages(Experiment.ID experimentID) { ExperimentPageList experimentPageList = new ExperimentPageList(); try { Result<PageExperimentByAppNamePage> result = experimentPageAccessor.selectBy(experimentID.getRawID()); Stream<PageExperimentByAppNamePage> resultList = StreamSupport.stream( Spliterators.spliteratorUnknownSize(result.iterator(), Spliterator.ORDERED), false); List<ExperimentPage> experimentPages = resultList .map(t -> ExperimentPage.withAttributes( Page.Name.valueOf(t.getPage()), t.isAssign() ).build() ).collect(Collectors.toList()); experimentPageList.setPages(experimentPages); } catch (ReadTimeoutException | UnavailableException | NoHostAvailableException e) { throw new RepositoryException("Could not retrieve the pages for experiment: \"" + experimentID + "\"", e); } return experimentPageList; }
/** * {@inheritDoc} */ @Override public void createExclusion(Experiment.ID baseID, Experiment.ID pairID) throws RepositoryException { LOGGER.debug("Create exclusions for {}", new Object[]{baseID, pairID}); try { BatchStatement batchStatement = new BatchStatement(); batchStatement.add(mutexAccessor.createExclusion(baseID.getRawID(), pairID.getRawID())); batchStatement.add(mutexAccessor.createExclusion(pairID.getRawID(), baseID.getRawID())); session.execute(batchStatement); } catch (Exception e) { LOGGER.error("Error while create exclusions for {}", new Object[]{baseID, pairID}, e); throw new RepositoryException("Could not insert the exclusion \"" + baseID + "\"", e); } }
/** * {@inheritDoc} */ @Override public void logBucketChanges(Experiment.ID experimentID, Bucket.Label bucketLabel, List<BucketAuditInfo> changeList) { final Date NOW = new Date(); try { for (BucketAuditInfo changeData : changeList) { bucketAuditLogAccessor.insertBy(experimentID.getRawID(), bucketLabel.toString(), NOW, changeData.getAttributeName(), (changeData.getOldValue() != null) ? changeData.getOldValue() : "", (changeData.getNewValue() != null) ? changeData.getNewValue() : ""); } } catch (Exception e) { throw new RepositoryException("Could not log bucket changes \"" + experimentID + " : " + bucketLabel + " " + "\"", e); } }
/** * {@inheritDoc} */ @Override public Bucket updateBucketAllocationPercentage(Bucket bucket, Double desiredAllocationPercentage) { try { bucketAccessor.updateAllocation(desiredAllocationPercentage, bucket.getExperimentID().getRawID(), bucket.getLabel().toString()); } catch (Exception e) { throw new RepositoryException("Could not update bucket allocation percentage \"" + bucket.getExperimentID() + "\".\"" + bucket.getLabel() + "\"", e); } // return the bucket with the updated values bucket = getBucket(bucket.getExperimentID(), bucket.getLabel()); return bucket; }
@Override @Timed public Assignment getAssignment(User.ID userID, Application.Name appName, Experiment.ID experimentID, Context context) { ListenableFuture<Result<ExperimentUserByUserIdContextAppNameExperimentId>> resultFuture = experimentUserIndexAccessor.asyncSelectBy(userID.toString(), appName.toString(), experimentID.getRawID(), context.toString()); Result<ExperimentUserByUserIdContextAppNameExperimentId> assignmentResult = UninterruptibleUtil.getUninterruptibly(resultFuture); Stream<ExperimentUserByUserIdContextAppNameExperimentId> assignmentResultStream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(assignmentResult.iterator(), Spliterator.ORDERED), false); final Stream<Assignment.Builder> assignmentBuilderStream = assignmentResultStream.map(t -> { Assignment.Builder builder = Assignment.newInstance(Experiment.ID.valueOf(t.getExperimentId())) .withUserID(User.ID.valueOf(t.getUserId())) .withContext(Context.valueOf(t.getContext())); if (nonNull(t.getBucket()) && !t.getBucket().trim().isEmpty()) { builder.withBucketLabel(Bucket.Label.valueOf(t.getBucket())); } return builder; }); Optional<Assignment> assignmentOptional = getAssignmentFromStream(experimentID, userID, context, assignmentBuilderStream); return assignmentOptional.isPresent() ? assignmentOptional.get() : null; }
@Override public void updateBucketAssignmentCount(Experiment experiment, Assignment assignment, boolean countUp) { Optional<Bucket.Label> labelOptional = Optional.ofNullable(assignment.getBucketLabel()); try { if (countUp) { bucketAssignmentCountAccessor.incrementCountBy(experiment.getID().getRawID(), labelOptional.orElseGet(() -> NULL_LABEL).toString() ); } else { bucketAssignmentCountAccessor.decrementCountBy(experiment.getID().getRawID(), labelOptional.orElseGet(() -> NULL_LABEL).toString() ); } } catch (WriteTimeoutException | UnavailableException | NoHostAvailableException e) { throw new RepositoryException("Could not update the bucket count for experiment " + experiment.getID() + " bucket " + labelOptional.orElseGet(() -> NULL_LABEL).toString(), e); } }
/** * {@inheritDoc} */ @Override public void logExperimentChanges(Experiment.ID experimentID, List<ExperimentAuditInfo> changeList) { final Date NOW = new Date(); try { for (ExperimentAuditInfo changeData : changeList) { experimentAuditLogAccessor.insertBy(experimentID.getRawID(), NOW, changeData.getAttributeName(), (changeData.getOldValue() != null) ? changeData.getOldValue() : "", (changeData.getNewValue() != null) ? changeData.getNewValue() : ""); } } catch (Exception e) { throw new RepositoryException("Could not log experiment changes for experimentID \"" + experimentID + "\"", e); } }
/** * Updates the tags for a given Experiment. This also means that tags are deleted from * the lookup table in Cassandra if they are removed from the experiment. * * @param applicationName the Application for which the tags should be added * @param expId the Id of the experiment that has changed tags * @param tags list of tags for the experiment */ public Statement updateExperimentTags(Application.Name applicationName, Experiment.ID expId, Set<String> tags) { if (tags == null) { tags = Collections.EMPTY_SET; // need this to update this to delete tags } // update the tag table, just rewrite the complete entry return experimentTagAccessor.insert(applicationName.toString(), expId.getRawID(), tags); }
/** * {@inheritDoc} */ @Override public void deleteBucket(Experiment.ID experimentID, Bucket.Label bucketLabel) { Preconditions.checkNotNull(experimentID, "Parameter \"experimentID\" cannot be null"); Preconditions.checkNotNull(bucketLabel, "Parameter \"bucketLabel\" cannot be null"); try { bucketAccessor.deleteByExperimentIdAndLabel(experimentID.getRawID(), bucketLabel.toString()); } catch (Exception e) { throw new RepositoryException("Could not delete bucket \"" + bucketLabel + "\" from experiment with ID \"" + experimentID + "\"", e); } }
/** * {@inheritDoc} */ @Override public void deleteExperiment(NewExperiment newExperiment) { LOGGER.debug("Deleting experiment {}", newExperiment); try { experimentAccessor.deleteExperiment(newExperiment.getID().getRawID()); } catch (Exception e) { LOGGER.debug("Error while deleting experiment {}", newExperiment, e); throw new RepositoryException("Could not delete experiment " + "with id \"" + newExperiment.getId() + "\"", e); } }
@Override public Argument build(Class<?> expectedType, Experiment.ID value, StatementContext context) { return new UUIDArgument(value.getRawID()); } }
void removeIndexExperimentsToUser(User.ID userID, Experiment.ID experimentID, Context context, Application.Name appName) { try { experimentUserIndexAccessor.deleteBy(userID.toString(), experimentID.getRawID(), context.getContext(), appName.toString()); } catch (WriteTimeoutException | UnavailableException | NoHostAvailableException e) { throw new RepositoryException( "Could not delete index from experiment_user_index for user: " + userID + "to experiment: " + experimentID, e); } }
void saveExperimentPageState(Experiment.ID experimentID, ExperimentPageList oldPageList, ExperimentPageList newPageList) { try { this.experimentAuditLogAccessor.insertBy( experimentID.getRawID(), new Date(), "pages", oldPageList.toString(), newPageList.toString() ); } catch (WriteTimeoutException | UnavailableException | NoHostAvailableException e) { throw new RepositoryException("Could not write pages change to audit log: \"" + experimentID + "\"", e); } }
@Override public AssignmentCounts getBucketAssignmentCount(Experiment experiment) { Result<com.intuit.wasabi.repository.cassandra.pojo.count.BucketAssignmentCount> result; try { result = bucketAssignmentCountAccessor.selectBy(experiment.getID().getRawID()); } catch (ReadTimeoutException | UnavailableException | NoHostAvailableException e) { throw new RepositoryException("Could not fetch the bucket assignment counts for experiment " + experiment.getID(), e); } return getBucketAssignmentCountFromCassandraResult(experiment.getID(), result); }