/** * Creating a separate copy here to avoid ConcurrentModificationException as BucketList gets modified * during assignment business logic execution. * * @param bucketList * @return New object/deep copy of BucketList. */ private BucketList makeCopy(BucketList bucketList) { List<Bucket> iBucketList = new ArrayList<>(bucketList.getBuckets()); BucketList newBucketList = new BucketList(); newBucketList.setBuckets(iBucketList); return newBucketList; } }
/** * @param expId * @return BucketList for given experiment. */ @Override public BucketList getBucketList(Experiment.ID expId) { BucketList bucketList = null; Cache cache = cacheManager.getCache(EXPERIMENT_ID_TO_BUCKET_CACHE.toString()); Element val = cache.get(expId); if (isNull(val)) { bucketList = experimentRepository.getBucketList(singleEntrySet(expId)).get(expId); cache.put(new Element(expId, bucketList)); } else { bucketList = (BucketList) val.getObjectValue(); } return isNull(bucketList) ? new BucketList() : makeCopy(bucketList); }
/** * Improved way of getting BucketList for given experiments */ @Override public Map<Experiment.ID, BucketList> getBucketList(Collection<Experiment.ID> experimentIds) { LOGGER.debug("Getting buckets list by experimentIDs {}", experimentIds); Map<Experiment.ID, BucketList> bucketMap = new HashMap<>(); try { Map<Experiment.ID, ListenableFuture<Result<com.intuit.wasabi.repository.cassandra.pojo.Bucket>>> bucketFutureMap = new HashMap<>(); experimentIds.forEach(experimentId -> { bucketFutureMap.put(experimentId, bucketAccessor.asyncGetBucketByExperimentId(experimentId.getRawID())); }); for (Experiment.ID expId : bucketFutureMap.keySet()) { bucketMap.put(expId, new BucketList()); ListenableFuture<Result<com.intuit.wasabi.repository.cassandra.pojo.Bucket>> bucketFuture = bucketFutureMap.get(expId); UninterruptibleUtil.getUninterruptibly(bucketFuture).all().forEach(bucketPojo -> { bucketMap.get(expId).addBucket(BucketHelper.makeBucket(bucketPojo)); } ); } } catch (Exception e) { LOGGER.error("getBucketList for {} failed", experimentIds, e); throw new RepositoryException("Could not fetch buckets for the list of experiments", e); } LOGGER.debug("Returning bucketMap {}", bucketMap); return bucketMap; }
bucketMap.put(expId, new BucketList()); ListenableFuture<Result<com.intuit.wasabi.repository.cassandra.pojo.Bucket>> bucketFuture = bucketFutureMap.get(expId); UninterruptibleUtil.getUninterruptibly(bucketFuture).all().forEach(bucketPojo -> {
BucketList bucketList = new BucketList(); bucketList.setBuckets(buckets);
/** * {@inheritDoc} */ @Override public BucketList getBucketList(Experiment.ID experimentID) { LOGGER.debug("Getting buckets list by one experimentId {}", experimentID); BucketList bucketList = new BucketList(); try { Result<com.intuit.wasabi.repository.cassandra.pojo.Bucket> bucketPojos = bucketAccessor.getBucketByExperimentId(experimentID.getRawID()); for (com.intuit.wasabi.repository.cassandra.pojo.Bucket bucketPojo : bucketPojos .all()) { bucketList.addBucket(BucketHelper.makeBucket(bucketPojo)); } } catch (Exception e) { LOGGER.error("Getting bucket list by one experiment id {} failed", experimentID, e); throw new RepositoryException("Could not fetch buckets for experiment \"" + experimentID + "\" ", e); } LOGGER.debug("Returning buckets list by one experimentId {} bucket {}", new Object[]{experimentID, bucketList}); return bucketList; }
experimentID); BucketList returnBuckets = new BucketList();
/** * {@inheritDoc} */ @Override public BucketList combineOldAndNewBuckets(BucketList oldBuckets, BucketList newBuckets) { BucketList allBuckets = new BucketList(); for (Bucket b : oldBuckets.getBuckets()) { Boolean changed = false; for (Bucket bb : newBuckets.getBuckets()) { if (bb.getLabel().equals(b.getLabel())) { allBuckets.addBucket(bb); changed = true; break; } } if (!changed) { allBuckets.addBucket(b); } } return allBuckets; } }
BucketList changeBucketList = new BucketList(); BucketList allBuckets = new BucketList(); if (!changeBucketList.getBuckets().isEmpty()) { allBuckets = buckets.combineOldAndNewBuckets(oldBuckets, changeBucketList);
/** * {@inheritDoc} */ @Override public BucketList adjustAllocationPercentages(Experiment experiment, Bucket newBucket) { double remainingAlloc = 1. - newBucket.getAllocationPercent(); BucketList bucketList = buckets.getBuckets(experiment.getID(), false /* don't check experiment again */); BucketList newBuckets = new BucketList(); for (Bucket bucket : bucketList.getBuckets()) { if (bucket.getLabel().equals(newBucket.getLabel())) { continue; } double newAlloc = roundToTwo(remainingAlloc * bucket.getAllocationPercent()); LOGGER.debug("Add Bucket: setting allocation percentage for bucket " + bucket.getLabel() + " in experiment " + experiment.getID() + " to: " + newAlloc); Bucket.Builder builder = Bucket.from(bucket).withAllocationPercent(newAlloc); Bucket updatedBucket = builder.build(); newBuckets.addBucket(updatedBucket); if (!Experiment.State.DRAFT.equals(experiment.getState()) && Double.compare(bucket.getAllocationPercent(), updatedBucket.getAllocationPercent()) != 0) { // this is a system event, so no user needed eventLog.postEvent(new BucketChangeEvent(experiment, updatedBucket, "allocation", String.valueOf(bucket.getAllocationPercent()), String.valueOf(updatedBucket.getAllocationPercent()))); } } return newBuckets; }
List<List<Bucket.BucketAuditInfo>> allChanges = new ArrayList<>(); BucketList newBuckets = new BucketList();