killbill-memoizeit

Fixes #375

8/18/2015 11:22:50 PM

Changes

beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestRepairIntegration.java 360(+0 -360)

subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultDeletedEvent.java 42(+0 -42)

subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultNewEvent.java 58(+0 -58)

subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultRepairSubscriptionEvent.java 120(+0 -120)

subscription/src/main/java/org/killbill/billing/subscription/api/timeline/RepairSubscriptionApiService.java 55(+0 -55)

subscription/src/main/java/org/killbill/billing/subscription/api/timeline/RepairSubscriptionLifecycleDao.java 30(+0 -30)

subscription/src/main/java/org/killbill/billing/subscription/api/timeline/SubscriptionDataRepair.java 228(+0 -228)

subscription/src/main/java/org/killbill/billing/subscription/engine/dao/RepairSubscriptionDao.java 350(+0 -350)

subscription/src/test/java/org/killbill/billing/subscription/api/timeline/TestRepairBP.java 702(+0 -702)

subscription/src/test/java/org/killbill/billing/subscription/api/timeline/TestRepairWithAO.java 726(+0 -726)

subscription/src/test/java/org/killbill/billing/subscription/api/timeline/TestRepairWithError.java 421(+0 -421)

Details

diff --git a/api/src/main/java/org/killbill/billing/subscription/api/timeline/SubscriptionBaseTimeline.java b/api/src/main/java/org/killbill/billing/subscription/api/timeline/SubscriptionBaseTimeline.java
index 855e0a1..a0a981f 100644
--- a/api/src/main/java/org/killbill/billing/subscription/api/timeline/SubscriptionBaseTimeline.java
+++ b/api/src/main/java/org/killbill/billing/subscription/api/timeline/SubscriptionBaseTimeline.java
@@ -30,20 +30,9 @@ import org.killbill.billing.util.entity.Entity;
 /**
  * The interface {@code} shows a view of all the events for a particular {@code SubscriptionBase}.
  * <p/>
- * It can be used to display information, or it can be used to modify the subscription stream of events
- * and 'repair' the stream by versioning the events.
  */
 public interface SubscriptionBaseTimeline extends Entity {
 
-    /**
-     * @return the list of events that should be deleted when repairing the stream.
-     */
-    public List<DeletedEvent> getDeletedEvents();
-
-    /**
-     * @return the list of events that should be added when repairing the stream
-     */
-    public List<NewEvent> getNewEvents();
 
     /**
      * @return the current list of events for that {@code SubscriptionBase}
@@ -56,17 +45,16 @@ public interface SubscriptionBaseTimeline extends Entity {
     public long getActiveVersion();
 
 
-    public interface DeletedEvent {
+
+    public interface ExistingEvent {
 
         /**
          * @return the unique if for the event to delete
          */
         public UUID getEventId();
-    }
-
-    public interface NewEvent {
 
         /**
+         *
          * @return the description for the event to be added
          */
         public PlanPhaseSpecifier getPlanPhaseSpecifier();
@@ -81,10 +69,6 @@ public interface SubscriptionBaseTimeline extends Entity {
          */
         public SubscriptionBaseTransitionType getSubscriptionTransitionType();
 
-    }
-
-    public interface ExistingEvent extends DeletedEvent, NewEvent {
-
         /**
          * @return the date at which this event was effective
          */
diff --git a/api/src/main/java/org/killbill/billing/subscription/api/timeline/SubscriptionBaseTimelineApi.java b/api/src/main/java/org/killbill/billing/subscription/api/timeline/SubscriptionBaseTimelineApi.java
index ae0a861..1d96853 100644
--- a/api/src/main/java/org/killbill/billing/subscription/api/timeline/SubscriptionBaseTimelineApi.java
+++ b/api/src/main/java/org/killbill/billing/subscription/api/timeline/SubscriptionBaseTimelineApi.java
@@ -16,23 +16,11 @@
 
 package org.killbill.billing.subscription.api.timeline;
 
-import java.util.UUID;
-
 import org.killbill.billing.subscription.api.user.SubscriptionBaseBundle;
-import org.killbill.billing.util.callcontext.CallContext;
 import org.killbill.billing.util.callcontext.TenantContext;
 
 public interface SubscriptionBaseTimelineApi {
 
     public BundleBaseTimeline getBundleTimeline(SubscriptionBaseBundle bundle, TenantContext context)
             throws SubscriptionBaseRepairException;
-
-    public BundleBaseTimeline getBundleTimeline(UUID accountId, String bundleName, TenantContext context)
-            throws SubscriptionBaseRepairException;
-
-    public BundleBaseTimeline getBundleTimeline(UUID bundleId, TenantContext context)
-            throws SubscriptionBaseRepairException;
-
-    public BundleBaseTimeline repairBundle(BundleBaseTimeline input, boolean dryRun, CallContext context)
-            throws SubscriptionBaseRepairException;
 }
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultSubscriptionBaseTimeline.java b/subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultSubscriptionBaseTimeline.java
index e81a703..5b4c7d7 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultSubscriptionBaseTimeline.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultSubscriptionBaseTimeline.java
@@ -16,7 +16,6 @@
 
 package org.killbill.billing.subscription.api.timeline;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.LinkedList;
@@ -26,7 +25,6 @@ import java.util.UUID;
 import javax.annotation.Nullable;
 
 import org.joda.time.DateTime;
-
 import org.killbill.billing.catalog.api.BillingPeriod;
 import org.killbill.billing.catalog.api.Catalog;
 import org.killbill.billing.catalog.api.CatalogApiException;
@@ -36,48 +34,22 @@ import org.killbill.billing.catalog.api.PlanPhase;
 import org.killbill.billing.catalog.api.PlanPhaseSpecifier;
 import org.killbill.billing.catalog.api.ProductCategory;
 import org.killbill.billing.subscription.api.SubscriptionBaseTransitionType;
+import org.killbill.billing.subscription.api.user.DefaultSubscriptionBase;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseTransitionData;
 import org.killbill.billing.subscription.events.SubscriptionBaseEvent;
 import org.killbill.billing.subscription.events.phase.PhaseEvent;
 import org.killbill.billing.subscription.events.user.ApiEvent;
 import org.killbill.billing.subscription.events.user.ApiEventType;
 
-
 public class DefaultSubscriptionBaseTimeline implements SubscriptionBaseTimeline {
 
     private final UUID id;
     private final List<ExistingEvent> existingEvents;
-    private final List<NewEvent> newEvents;
-    private final List<DeletedEvent> deletedEvents;
     private final long activeVersion;
 
-    public DefaultSubscriptionBaseTimeline(final UUID id, final long activeVersion) {
-        this.id = id;
-        this.activeVersion = activeVersion;
-        this.existingEvents = Collections.<SubscriptionBaseTimeline.ExistingEvent>emptyList();
-        this.deletedEvents = Collections.<SubscriptionBaseTimeline.DeletedEvent>emptyList();
-        this.newEvents = Collections.<SubscriptionBaseTimeline.NewEvent>emptyList();
-    }
-
-    public DefaultSubscriptionBaseTimeline(final SubscriptionBaseTimeline input) {
-        this.id = input.getId();
-        this.activeVersion = input.getActiveVersion();
-        this.existingEvents = (input.getExistingEvents() != null) ? new ArrayList<SubscriptionBaseTimeline.ExistingEvent>(input.getExistingEvents()) :
-                              Collections.<SubscriptionBaseTimeline.ExistingEvent>emptyList();
-        sortExistingEvent(this.existingEvents);
-        this.deletedEvents = (input.getDeletedEvents() != null) ? new ArrayList<SubscriptionBaseTimeline.DeletedEvent>(input.getDeletedEvents()) :
-                             Collections.<SubscriptionBaseTimeline.DeletedEvent>emptyList();
-        this.newEvents = (input.getNewEvents() != null) ? new ArrayList<SubscriptionBaseTimeline.NewEvent>(input.getNewEvents()) :
-                         Collections.<SubscriptionBaseTimeline.NewEvent>emptyList();
-        sortNewEvent(this.newEvents);
-    }
-
-    // CTOR for returning events only
-    public DefaultSubscriptionBaseTimeline(final SubscriptionDataRepair input, final Catalog catalog) throws CatalogApiException {
+    public DefaultSubscriptionBaseTimeline(final DefaultSubscriptionBase input, final Catalog catalog) throws CatalogApiException {
         this.id = input.getId();
         this.existingEvents = toExistingEvents(catalog, input.getActiveVersion(), input.getCategory(), input.getEvents());
-        this.deletedEvents = null;
-        this.newEvents = null;
         this.activeVersion = input.getActiveVersion();
     }
 
@@ -199,89 +171,6 @@ public class DefaultSubscriptionBaseTimeline implements SubscriptionBaseTimeline
         return result;
     }
 
-
-    /*
-
-    private List<ExistingEvent> toExistingEvents(final Catalog catalog, final long processingVersion, final ProductCategory category, final List<SubscriptionBaseEvent> events, List<ExistingEvent> result)
-        throws CatalogApiException {
-
-
-        String prevProductName = null;
-        BillingPeriod prevBillingPeriod = null;
-        String prevPriceListName = null;
-        PhaseType prevPhaseType = null;
-
-        DateTime startDate = null;
-
-        for (final SubscriptionBaseEvent cur : events) {
-
-            if (processingVersion != cur.getActiveVersion()) {
-                continue;
-            }
-
-            // First active event is used to figure out which catalog version to use.
-            startDate = (startDate == null && cur.getActiveVersion() == processingVersion) ?  cur.getEffectiveDate() : startDate;
-
-            String productName = null;
-            BillingPeriod billingPeriod = null;
-            String priceListName = null;
-            PhaseType phaseType = null;
-
-            ApiEventType apiType = null;
-            switch (cur.getType()) {
-            case PHASE:
-                PhaseEvent phaseEV = (PhaseEvent) cur;
-                phaseType = catalog.findPhase(phaseEV.getPhase(), cur.getEffectiveDate(), startDate).getPhaseType();
-                productName = prevProductName;
-                billingPeriod = prevBillingPeriod;
-                priceListName = prevPriceListName;
-                break;
-
-            case API_USER:
-                ApiEvent userEV = (ApiEvent) cur;
-                apiType = userEV.getEventType();
-                Plan plan =  (userEV.getEventPlan() != null) ? catalog.findPlan(userEV.getEventPlan(), cur.getRequestedDate(), startDate) : null;
-                phaseType = (userEV.getEventPlanPhase() != null) ? catalog.findPhase(userEV.getEventPlanPhase(), cur.getEffectiveDate(), startDate).getPhaseType() : prevPhaseType;
-                productName = (plan != null) ? plan.getProduct().getName() : prevProductName;
-                billingPeriod = (plan != null) ? plan.getBillingPeriod() : prevBillingPeriod;
-                priceListName = (userEV.getPriceList() != null) ? userEV.getPriceList() : prevPriceListName;
-                break;
-            }
-
-            final SubscriptionBaseTransitionType transitionType = SubscriptionBaseTransitionData.toSubscriptionTransitionType(cur.getType(), apiType);
-
-            final PlanPhaseSpecifier spec = new PlanPhaseSpecifier(productName, category, billingPeriod, priceListName, phaseType);
-            result.add(new ExistingEvent() {
-                @Override
-                public SubscriptionBaseTransitionType getSubscriptionTransitionType() {
-                    return transitionType;
-                }
-                @Override
-                public DateTime getRequestedDate() {
-                    return cur.getRequestedDate();
-                }
-                @Override
-                public PlanPhaseSpecifier getPlanPhaseSpecifier() {
-                    return spec;
-                }
-                @Override
-                public UUID getEventId() {
-                    return cur.getId();
-                }
-                @Override
-                public DateTime getEffectiveDate() {
-                    return cur.getEffectiveDate();
-                }
-            });
-            prevProductName = productName;
-            prevBillingPeriod = billingPeriod;
-            prevPriceListName = priceListName;
-            prevPhaseType = phaseType;
-        }
-    }
-    */
-
-
     @Override
     public UUID getId() {
         return id;
@@ -298,16 +187,6 @@ public class DefaultSubscriptionBaseTimeline implements SubscriptionBaseTimeline
     }
 
     @Override
-    public List<DeletedEvent> getDeletedEvents() {
-        return deletedEvents;
-    }
-
-    @Override
-    public List<NewEvent> getNewEvents() {
-        return newEvents;
-    }
-
-    @Override
     public List<ExistingEvent> getExistingEvents() {
         return existingEvents;
     }
@@ -317,7 +196,6 @@ public class DefaultSubscriptionBaseTimeline implements SubscriptionBaseTimeline
         return activeVersion;
     }
 
-
     private void sortExistingEvent(final List<ExistingEvent> events) {
         if (events != null) {
             Collections.sort(events, new Comparator<ExistingEvent>() {
@@ -329,14 +207,4 @@ public class DefaultSubscriptionBaseTimeline implements SubscriptionBaseTimeline
         }
     }
 
-    private void sortNewEvent(final List<NewEvent> events) {
-        if (events != null) {
-            Collections.sort(events, new Comparator<NewEvent>() {
-                @Override
-                public int compare(final NewEvent arg0, final NewEvent arg1) {
-                    return arg0.getRequestedDate().compareTo(arg1.getRequestedDate());
-                }
-            });
-        }
-    }
 }
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultSubscriptionBaseTimelineApi.java b/subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultSubscriptionBaseTimelineApi.java
index 4171cc0..0658302 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultSubscriptionBaseTimelineApi.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultSubscriptionBaseTimelineApi.java
@@ -16,111 +16,60 @@
 
 package org.killbill.billing.subscription.api.timeline;
 
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.UUID;
 
-import javax.annotation.Nullable;
-
 import org.joda.time.DateTime;
-
 import org.killbill.billing.ErrorCode;
-import org.killbill.billing.catalog.api.Catalog;
+import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.catalog.api.CatalogApiException;
 import org.killbill.billing.catalog.api.CatalogService;
-import org.killbill.billing.catalog.api.ProductCategory;
 import org.killbill.billing.subscription.api.SubscriptionApiBase;
+import org.killbill.billing.subscription.api.SubscriptionBase;
 import org.killbill.billing.subscription.api.SubscriptionBaseApiService;
-import org.killbill.billing.subscription.api.SubscriptionBaseTransitionType;
+import org.killbill.billing.subscription.api.user.DefaultSubscriptionBase;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseBundle;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseBundle;
-import org.killbill.billing.subscription.api.user.SubscriptionBaseTransition;
-import org.killbill.billing.subscription.api.user.SubscriptionBuilder;
-import org.killbill.billing.subscription.api.user.DefaultSubscriptionBase;
-import org.killbill.billing.subscription.api.user.SubscriptionBaseTransitionData;
-import org.killbill.billing.subscription.engine.addon.AddonUtils;
 import org.killbill.billing.subscription.engine.dao.SubscriptionDao;
 import org.killbill.billing.subscription.events.SubscriptionBaseEvent;
-import org.killbill.billing.subscription.glue.DefaultSubscriptionModule;
-import org.killbill.billing.subscription.api.timeline.SubscriptionBaseTimeline.NewEvent;
-import org.killbill.billing.subscription.api.SubscriptionBase;
-import org.killbill.billing.util.callcontext.CallContext;
 import org.killbill.billing.util.callcontext.InternalCallContextFactory;
-import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.util.callcontext.TenantContext;
 import org.killbill.clock.Clock;
 
-import com.google.common.base.Function;
-import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
 import com.google.inject.Inject;
-import com.google.inject.name.Named;
 
 public class DefaultSubscriptionBaseTimelineApi extends SubscriptionApiBase implements SubscriptionBaseTimelineApi {
 
-    private final RepairSubscriptionLifecycleDao repairDao;
     private final CatalogService catalogService;
     private final InternalCallContextFactory internalCallContextFactory;
-    private final AddonUtils addonUtils;
-
-    private final SubscriptionBaseApiService repairApiService;
-
-    private enum RepairType {
-        BASE_REPAIR,
-        ADD_ON_REPAIR,
-        STANDALONE_REPAIR
-    }
 
     @Inject
     public DefaultSubscriptionBaseTimelineApi(final CatalogService catalogService,
                                               final SubscriptionBaseApiService apiService,
-                                              @Named(DefaultSubscriptionModule.REPAIR_NAMED) final RepairSubscriptionLifecycleDao repairDao, final SubscriptionDao dao,
-                                              @Named(DefaultSubscriptionModule.REPAIR_NAMED) final SubscriptionBaseApiService repairApiService,
-                                              final InternalCallContextFactory internalCallContextFactory, final Clock clock, final AddonUtils addonUtils) {
+                                              final SubscriptionDao dao,
+                                              final InternalCallContextFactory internalCallContextFactory,
+                                              final Clock clock) {
         super(dao, apiService, clock, catalogService);
         this.catalogService = catalogService;
-        this.repairDao = repairDao;
         this.internalCallContextFactory = internalCallContextFactory;
-        this.repairApiService = repairApiService;
-        this.addonUtils = addonUtils;
     }
 
     @Override
     public BundleBaseTimeline getBundleTimeline(final SubscriptionBaseBundle bundle, final TenantContext context)
             throws SubscriptionBaseRepairException {
-        return getBundleTimelineInternal(bundle, bundle.getExternalKey(), context);
-    }
-
-    @Override
-    public BundleBaseTimeline getBundleTimeline(final UUID accountId, final String bundleName, final TenantContext context)
-            throws SubscriptionBaseRepairException {
-        final List<SubscriptionBaseBundle> bundles = dao.getSubscriptionBundlesForAccountAndKey(accountId, bundleName, internalCallContextFactory.createInternalTenantContext(context));
-        final SubscriptionBaseBundle bundle = bundles.size() > 0 ? bundles.get(bundles.size() - 1) : null;
-        return getBundleTimelineInternal(bundle, bundleName + " [accountId= " + accountId.toString() + "]", context);
-    }
-
-    @Override
-    public BundleBaseTimeline getBundleTimeline(final UUID bundleId, final TenantContext context) throws SubscriptionBaseRepairException {
-
-        final SubscriptionBaseBundle bundle = dao.getSubscriptionBundleFromId(bundleId, internalCallContextFactory.createInternalTenantContext(context));
-        return getBundleTimelineInternal(bundle, bundleId.toString(), context);
-    }
-
-    private BundleBaseTimeline getBundleTimelineInternal(final SubscriptionBaseBundle bundle, final String descBundle, final TenantContext context) throws SubscriptionBaseRepairException {
         try {
             if (bundle == null) {
-                throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_UNKNOWN_BUNDLE, descBundle);
+                throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_UNKNOWN_BUNDLE, bundle.getExternalKey());
             }
             final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(bundle.getAccountId(), context);
-            final List<SubscriptionDataRepair> subscriptions = convertToSubscriptionsDataRepair(dao.getSubscriptions(bundle.getId(),
-                                                                                                                     ImmutableList.<SubscriptionBaseEvent>of(),
-                                                                                                                     internalTenantContext));
+            final List<SubscriptionBase> subscriptions = dao.getSubscriptions(bundle.getId(),
+                                                                              ImmutableList.<SubscriptionBaseEvent>of(),
+                                                                              internalTenantContext);
             if (subscriptions.size() == 0) {
                 throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_NO_ACTIVE_SUBSCRIPTIONS, bundle.getId());
             }
@@ -132,273 +81,7 @@ public class DefaultSubscriptionBaseTimelineApi extends SubscriptionApiBase impl
         }
     }
 
-    private List<SubscriptionDataRepair> convertToSubscriptionsDataRepair(List<SubscriptionBase> input) {
-        return new ArrayList<SubscriptionDataRepair>(Collections2.transform(input, new Function<SubscriptionBase, SubscriptionDataRepair>() {
-            @Override
-            public SubscriptionDataRepair apply(@Nullable final SubscriptionBase subscription) {
-                return convertToSubscriptionDataRepair((DefaultSubscriptionBase) subscription);
-            }
-        }));
-    }
-    private SubscriptionDataRepair convertToSubscriptionDataRepair(DefaultSubscriptionBase input) {
-        return new SubscriptionDataRepair(input, repairApiService, (SubscriptionDao) repairDao, clock, addonUtils, catalogService, internalCallContextFactory);
-    }
-
-    @Override
-    public BundleBaseTimeline repairBundle(final BundleBaseTimeline input, final boolean dryRun, final CallContext context) throws SubscriptionBaseRepairException {
-        final InternalTenantContext tenantContext = internalCallContextFactory.createInternalTenantContext(context);
-        try {
-            final SubscriptionBaseBundle bundle = dao.getSubscriptionBundleFromId(input.getId(), tenantContext);
-            if (bundle == null) {
-                throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_UNKNOWN_BUNDLE, input.getId());
-            }
-
-            // Subscriptions are ordered with BASE subscription first-- if exists
-            final List<SubscriptionDataRepair> subscriptions = convertToSubscriptionsDataRepair(dao.getSubscriptions(input.getId(), ImmutableList.<SubscriptionBaseEvent>of(), tenantContext));
-            if (subscriptions.size() == 0) {
-                throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_NO_ACTIVE_SUBSCRIPTIONS, input.getId());
-            }
-
-            final String viewId = getViewId(((DefaultSubscriptionBaseBundle) bundle).getLastSysUpdateDate(), subscriptions);
-            if (!viewId.equals(input.getViewId())) {
-                throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_VIEW_CHANGED, input.getId(), input.getViewId(), viewId);
-            }
-
-            DateTime firstDeletedBPEventTime = null;
-            DateTime lastRemainingBPEventTime = null;
-
-            boolean isBasePlanRecreate = false;
-            DateTime newBundleStartDate = null;
-
-            SubscriptionDataRepair baseSubscriptionRepair = null;
-            final List<SubscriptionDataRepair> addOnSubscriptionInRepair = new LinkedList<SubscriptionDataRepair>();
-            final List<SubscriptionDataRepair> inRepair = new LinkedList<SubscriptionDataRepair>();
-            for (final SubscriptionBase cur : subscriptions) {
-                final SubscriptionBaseTimeline curRepair = findAndCreateSubscriptionRepair(cur.getId(), input.getSubscriptions());
-                if (curRepair != null) {
-                    final SubscriptionDataRepair curInputRepair = ((SubscriptionDataRepair) cur);
-                    final List<SubscriptionBaseEvent> remaining = getRemainingEventsAndValidateDeletedEvents(curInputRepair, firstDeletedBPEventTime, curRepair.getDeletedEvents());
-
-                    final boolean isPlanRecreate = (curRepair.getNewEvents().size() > 0
-                                                    && (curRepair.getNewEvents().get(0).getSubscriptionTransitionType() == SubscriptionBaseTransitionType.CREATE
-                                                        || curRepair.getNewEvents().get(0).getSubscriptionTransitionType() == SubscriptionBaseTransitionType.RE_CREATE));
-
-                    final DateTime newSubscriptionStartDate = isPlanRecreate ? curRepair.getNewEvents().get(0).getRequestedDate() : null;
-
-                    if (isPlanRecreate && remaining.size() != 0) {
-                        throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_SUB_RECREATE_NOT_EMPTY, cur.getId(), cur.getBundleId());
-                    }
-
-                    if (!isPlanRecreate && remaining.size() == 0) {
-                        throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_SUB_EMPTY, cur.getId(), cur.getBundleId());
-                    }
-
-                    if (cur.getCategory() == ProductCategory.BASE) {
-
-                        final int bpTransitionSize = ((DefaultSubscriptionBase) cur).getAllTransitions().size();
-                        lastRemainingBPEventTime = (remaining.size() > 0) ? curInputRepair.getAllTransitions().get(remaining.size() - 1).getEffectiveTransitionTime() : null;
-                        firstDeletedBPEventTime = (remaining.size() < bpTransitionSize) ? curInputRepair.getAllTransitions().get(remaining.size()).getEffectiveTransitionTime() : null;
-
-                        isBasePlanRecreate = isPlanRecreate;
-                        newBundleStartDate = newSubscriptionStartDate;
-                    }
-
-                    if (curRepair.getNewEvents().size() > 0) {
-                        final DateTime lastRemainingEventTime = (remaining.size() == 0) ? null : curInputRepair.getAllTransitions().get(remaining.size() - 1).getEffectiveTransitionTime();
-                        validateFirstNewEvent(curInputRepair, curRepair.getNewEvents().get(0), lastRemainingBPEventTime, lastRemainingEventTime);
-                    }
-
-                    final SubscriptionDataRepair curOutputRepair = createSubscriptionDataRepair(curInputRepair, newBundleStartDate, newSubscriptionStartDate, remaining, tenantContext);
-                    repairDao.initializeRepair(curInputRepair.getId(), remaining, tenantContext);
-                    inRepair.add(curOutputRepair);
-                    if (curOutputRepair.getCategory() == ProductCategory.ADD_ON) {
-                        // Check if ADD_ON RE_CREATE is before BP start
-                        if (isPlanRecreate && (subscriptions.get(0)).getStartDate().isAfter(curRepair.getNewEvents().get(0).getRequestedDate())) {
-                            throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_AO_CREATE_BEFORE_BP_START, cur.getId(), cur.getBundleId());
-                        }
-                        addOnSubscriptionInRepair.add(curOutputRepair);
-                    } else if (curOutputRepair.getCategory() == ProductCategory.BASE) {
-                        baseSubscriptionRepair = curOutputRepair;
-                    }
-                }
-            }
-
-            final RepairType repairType = getRepairType(subscriptions.get(0), (baseSubscriptionRepair != null));
-            switch (repairType) {
-                case BASE_REPAIR:
-                    // We need to add any existing addon that are not in the input repair list
-                    for (final SubscriptionBase cur : subscriptions) {
-                        if (cur.getCategory() == ProductCategory.ADD_ON && !inRepair.contains(cur)) {
-                            final SubscriptionDataRepair curOutputRepair = createSubscriptionDataRepair((SubscriptionDataRepair) cur, newBundleStartDate, null,
-                                                                                                        ((SubscriptionDataRepair) cur).getEvents(), tenantContext);
-                            repairDao.initializeRepair(curOutputRepair.getId(), ((SubscriptionDataRepair) cur).getEvents(), tenantContext);
-                            inRepair.add(curOutputRepair);
-                            addOnSubscriptionInRepair.add(curOutputRepair);
-                        }
-                    }
-                    break;
-                case ADD_ON_REPAIR:
-                    // We need to set the baseSubscription as it is useful to calculate addon validity
-                    final SubscriptionDataRepair baseSubscription = (SubscriptionDataRepair) subscriptions.get(0);
-                    baseSubscriptionRepair = createSubscriptionDataRepair(baseSubscription, baseSubscription.getBundleStartDate(), baseSubscription.getAlignStartDate(),
-                                                                          baseSubscription.getEvents(), tenantContext);
-                    break;
-                case STANDALONE_REPAIR:
-                default:
-                    break;
-            }
-
-            validateBasePlanRecreate(isBasePlanRecreate, subscriptions, input.getSubscriptions());
-            validateInputSubscriptionsKnown(subscriptions, input.getSubscriptions());
-
-            final Collection<NewEvent> newEvents = createOrderedNewEventInput(input.getSubscriptions());
-            for (final NewEvent newEvent : newEvents) {
-                final DefaultNewEvent cur = (DefaultNewEvent) newEvent;
-                final SubscriptionDataRepair curDataRepair = findSubscriptionDataRepair(cur.getSubscriptionId(), inRepair);
-                if (curDataRepair == null) {
-                    throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_UNKNOWN_SUBSCRIPTION, cur.getSubscriptionId());
-                }
-                curDataRepair.addNewRepairEvent(cur, baseSubscriptionRepair, addOnSubscriptionInRepair, context);
-            }
-
-            if (dryRun) {
-                baseSubscriptionRepair.addFutureAddonCancellation(addOnSubscriptionInRepair, context);
-
-                final List<SubscriptionBaseTimeline> repairs = createGetSubscriptionRepairList(subscriptions, convertDataRepair(inRepair, tenantContext), tenantContext);
-                return createGetBundleRepair(input.getId(), bundle.getExternalKey(), input.getViewId(), repairs);
-            } else {
-                dao.repair(bundle.getAccountId(), input.getId(), inRepair, internalCallContextFactory.createInternalCallContext(bundle.getAccountId(), context));
-                return getBundleTimeline(input.getId(), context);
-            }
-        } catch (CatalogApiException e) {
-            throw new SubscriptionBaseRepairException(e);
-        } finally {
-            repairDao.cleanup(tenantContext);
-        }
-    }
-
-    private RepairType getRepairType(final SubscriptionBase firstSubscription, final boolean gotBaseSubscription) {
-        if (firstSubscription.getCategory() == ProductCategory.BASE) {
-            return gotBaseSubscription ? RepairType.BASE_REPAIR : RepairType.ADD_ON_REPAIR;
-        } else {
-            return RepairType.STANDALONE_REPAIR;
-        }
-    }
-
-    private void validateBasePlanRecreate(final boolean isBasePlanRecreate, final List<SubscriptionDataRepair> subscriptions, final List<SubscriptionBaseTimeline> input)
-            throws SubscriptionBaseRepairException {
-        if (!isBasePlanRecreate) {
-            return;
-        }
-        if (subscriptions.size() != input.size()) {
-            throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_BP_RECREATE_MISSING_AO, subscriptions.get(0).getBundleId());
-        }
-        for (final SubscriptionBaseTimeline cur : input) {
-            if (cur.getNewEvents().size() != 0
-                && (cur.getNewEvents().get(0).getSubscriptionTransitionType() != SubscriptionBaseTransitionType.CREATE
-                    && cur.getNewEvents().get(0).getSubscriptionTransitionType() != SubscriptionBaseTransitionType.RE_CREATE)) {
-                throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_BP_RECREATE_MISSING_AO_CREATE, subscriptions.get(0).getBundleId());
-            }
-        }
-    }
-
-    private void validateInputSubscriptionsKnown(final List<SubscriptionDataRepair> subscriptions, final List<SubscriptionBaseTimeline> input)
-            throws SubscriptionBaseRepairException {
-        for (final SubscriptionBaseTimeline cur : input) {
-            boolean found = false;
-            for (final SubscriptionBase s : subscriptions) {
-                if (s.getId().equals(cur.getId())) {
-                    found = true;
-                    break;
-                }
-            }
-            if (!found) {
-                throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_UNKNOWN_SUBSCRIPTION, cur.getId());
-            }
-        }
-    }
-
-    private void validateFirstNewEvent(final DefaultSubscriptionBase data, final NewEvent firstNewEvent, final DateTime lastBPRemainingTime, final DateTime lastRemainingTime)
-            throws SubscriptionBaseRepairException {
-        if (lastBPRemainingTime != null &&
-            firstNewEvent.getRequestedDate().isBefore(lastBPRemainingTime)) {
-            throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_NEW_EVENT_BEFORE_LAST_BP_REMAINING, firstNewEvent.getSubscriptionTransitionType(), data.getId());
-        }
-        if (lastRemainingTime != null &&
-            firstNewEvent.getRequestedDate().isBefore(lastRemainingTime)) {
-            throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_NEW_EVENT_BEFORE_LAST_AO_REMAINING, firstNewEvent.getSubscriptionTransitionType(), data.getId());
-        }
-
-    }
-
-    private Collection<NewEvent> createOrderedNewEventInput(final List<SubscriptionBaseTimeline> subscriptionsReapir) {
-        final TreeSet<NewEvent> newEventSet = new TreeSet<SubscriptionBaseTimeline.NewEvent>(new Comparator<NewEvent>() {
-            @Override
-            public int compare(final NewEvent o1, final NewEvent o2) {
-                return o1.getRequestedDate().compareTo(o2.getRequestedDate());
-            }
-        });
-        for (final SubscriptionBaseTimeline cur : subscriptionsReapir) {
-            for (final NewEvent e : cur.getNewEvents()) {
-                newEventSet.add(new DefaultNewEvent(cur.getId(), e.getPlanPhaseSpecifier(), e.getRequestedDate(), e.getSubscriptionTransitionType()));
-            }
-        }
-
-        return newEventSet;
-    }
-
-    private List<SubscriptionBaseEvent> getRemainingEventsAndValidateDeletedEvents(final SubscriptionDataRepair data, final DateTime firstBPDeletedTime,
-                                                                              final List<SubscriptionBaseTimeline.DeletedEvent> deletedEvents)
-            throws SubscriptionBaseRepairException {
-        if (deletedEvents == null || deletedEvents.size() == 0) {
-            return data.getEvents();
-        }
-
-        int nbDeleted = 0;
-        final LinkedList<SubscriptionBaseEvent> result = new LinkedList<SubscriptionBaseEvent>();
-        for (final SubscriptionBaseEvent cur : data.getEvents()) {
-
-            boolean foundDeletedEvent = false;
-            for (final SubscriptionBaseTimeline.DeletedEvent d : deletedEvents) {
-                if (cur.getId().equals(d.getEventId())) {
-                    foundDeletedEvent = true;
-                    nbDeleted++;
-                    break;
-                }
-            }
-            if (!foundDeletedEvent && nbDeleted > 0) {
-                throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_INVALID_DELETE_SET, cur.getId(), data.getId());
-            }
-            if (firstBPDeletedTime != null &&
-                !cur.getEffectiveDate().isBefore(firstBPDeletedTime) &&
-                !foundDeletedEvent) {
-                throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_MISSING_AO_DELETE_EVENT, cur.getId(), data.getId());
-            }
-
-            if (nbDeleted == 0) {
-                result.add(cur);
-            }
-        }
-
-        if (nbDeleted != deletedEvents.size()) {
-            for (final SubscriptionBaseTimeline.DeletedEvent d : deletedEvents) {
-                boolean found = false;
-                for (final SubscriptionBaseTransition cur : data.getAllTransitions()) {
-                    if (((SubscriptionBaseTransitionData) cur).getId().equals(d.getEventId())) {
-                        found = true;
-                    }
-                }
-                if (!found) {
-                    throw new SubscriptionBaseRepairException(ErrorCode.SUB_REPAIR_NON_EXISTENT_DELETE_EVENT, d.getEventId(), data.getId());
-                }
-            }
-
-        }
-
-        return result;
-    }
-
-    private String getViewId(final DateTime lastUpdateBundleDate, final List<SubscriptionDataRepair> subscriptions) {
+    private String getViewId(final DateTime lastUpdateBundleDate, final List<SubscriptionBase> subscriptions) {
         final StringBuilder tmp = new StringBuilder();
         long lastOrderedId = -1;
         for (final SubscriptionBase cur : subscriptions) {
@@ -445,7 +128,7 @@ public class DefaultSubscriptionBaseTimelineApi extends SubscriptionApiBase impl
         };
     }
 
-    private List<SubscriptionBaseTimeline> createGetSubscriptionRepairList(final List<SubscriptionDataRepair> subscriptions, final List<SubscriptionBaseTimeline> inRepair, final InternalTenantContext tenantContext) throws CatalogApiException {
+    private List<SubscriptionBaseTimeline> createGetSubscriptionRepairList(final List<SubscriptionBase> subscriptions, final List<SubscriptionBaseTimeline> inRepair, final InternalTenantContext tenantContext) throws CatalogApiException {
 
         final List<SubscriptionBaseTimeline> result = new LinkedList<SubscriptionBaseTimeline>();
         final Set<UUID> repairIds = new TreeSet<UUID>();
@@ -456,62 +139,11 @@ public class DefaultSubscriptionBaseTimelineApi extends SubscriptionApiBase impl
 
         for (final SubscriptionBase cur : subscriptions) {
             if (!repairIds.contains(cur.getId())) {
-                result.add(new DefaultSubscriptionBaseTimeline((SubscriptionDataRepair) cur, catalogService.getFullCatalog(tenantContext)));
+                result.add(new DefaultSubscriptionBaseTimeline((DefaultSubscriptionBase) cur, catalogService.getFullCatalog(tenantContext)));
             }
         }
-
-        return result;
-    }
-
-    private List<SubscriptionBaseTimeline> convertDataRepair(final List<SubscriptionDataRepair> input, final InternalTenantContext tenantContext) throws CatalogApiException {
-        final List<SubscriptionBaseTimeline> result = new LinkedList<SubscriptionBaseTimeline>();
-        for (final SubscriptionDataRepair cur : input) {
-            result.add(new DefaultSubscriptionBaseTimeline(cur, catalogService.getFullCatalog(tenantContext)));
-        }
-
         return result;
     }
 
-    private SubscriptionDataRepair findSubscriptionDataRepair(final UUID targetId, final List<SubscriptionDataRepair> input) {
-        for (final SubscriptionDataRepair cur : input) {
-            if (cur.getId().equals(targetId)) {
-                return cur;
-            }
-        }
-
-        return null;
-    }
-
-    private SubscriptionDataRepair createSubscriptionDataRepair(final DefaultSubscriptionBase curData, final DateTime newBundleStartDate, final DateTime newSubscriptionStartDate,
-                                                                final List<SubscriptionBaseEvent> initialEvents, final InternalTenantContext tenantContext) throws CatalogApiException {
-        final SubscriptionBuilder builder = new SubscriptionBuilder(curData);
-        builder.setActiveVersion(curData.getActiveVersion() + 1);
-        if (newBundleStartDate != null) {
-            builder.setBundleStartDate(newBundleStartDate);
-        }
-        if (newSubscriptionStartDate != null) {
-            builder.setAlignStartDate(newSubscriptionStartDate);
-        }
-        if (initialEvents.size() > 0) {
-            for (final SubscriptionBaseEvent cur : initialEvents) {
-                cur.setActiveVersion(builder.getActiveVersion());
-            }
-        }
-
-        final SubscriptionDataRepair subscriptiondataRepair = new SubscriptionDataRepair(builder, curData.getEvents(), repairApiService, (SubscriptionDao) repairDao, clock, addonUtils, catalogService, internalCallContextFactory);
-        final Catalog fullCatalog = catalogService.getFullCatalog(tenantContext);
-        subscriptiondataRepair.rebuildTransitions(curData.getEvents(), fullCatalog);
-        return subscriptiondataRepair;
-    }
-
-    private SubscriptionBaseTimeline findAndCreateSubscriptionRepair(final UUID target, final List<SubscriptionBaseTimeline> input) {
-        for (final SubscriptionBaseTimeline cur : input) {
-            if (target.equals(cur.getId())) {
-                return new DefaultSubscriptionBaseTimeline(cur);
-            }
-        }
-
-        return null;
-    }
 }
 
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java
index 03e813e..7c91589 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java
@@ -46,14 +46,11 @@ import org.killbill.billing.catalog.api.ProductCategory;
 import org.killbill.billing.entitlement.api.SubscriptionApiException;
 import org.killbill.billing.entity.EntityPersistenceException;
 import org.killbill.billing.events.EffectiveSubscriptionInternalEvent;
-import org.killbill.billing.events.RepairSubscriptionInternalEvent;
 import org.killbill.billing.subscription.api.SubscriptionBase;
 import org.killbill.billing.subscription.api.SubscriptionBaseTransitionType;
 import org.killbill.billing.subscription.api.migration.AccountMigrationData;
 import org.killbill.billing.subscription.api.migration.AccountMigrationData.BundleMigrationData;
 import org.killbill.billing.subscription.api.migration.AccountMigrationData.SubscriptionMigrationData;
-import org.killbill.billing.subscription.api.timeline.DefaultRepairSubscriptionEvent;
-import org.killbill.billing.subscription.api.timeline.SubscriptionDataRepair;
 import org.killbill.billing.subscription.api.transfer.TransferCancelData;
 import org.killbill.billing.subscription.api.user.DefaultEffectiveSubscriptionEvent;
 import org.killbill.billing.subscription.api.user.DefaultRequestedSubscriptionEvent;
@@ -971,44 +968,6 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
     }
 
     @Override
-    public void repair(final UUID accountId, final UUID bundleId, final List<SubscriptionDataRepair> inRepair, final InternalCallContext context) {
-        transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
-            @Override
-            public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
-                final SubscriptionSqlDao transactional = entitySqlDaoWrapperFactory.become(SubscriptionSqlDao.class);
-
-                final SubscriptionEventSqlDao transEventDao = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class);
-                for (final SubscriptionDataRepair cur : inRepair) {
-                    transactional.updateForRepair(cur.getId().toString(), cur.getActiveVersion(), cur.getAlignStartDate().toDate(), cur.getBundleStartDate().toDate(), context);
-                    for (final SubscriptionBaseEvent event : cur.getInitialEvents()) {
-                        transEventDao.updateVersion(event.getId().toString(), event.getActiveVersion(), context);
-                    }
-                    for (final SubscriptionBaseEvent event : cur.getNewEvents()) {
-                        transEventDao.create(new SubscriptionEventModelDao(event), context);
-                        if (event.getEffectiveDate().isAfter(clock.getUTCNow())) {
-                            recordFutureNotificationFromTransaction(entitySqlDaoWrapperFactory,
-                                                                    event.getEffectiveDate(),
-                                                                    new SubscriptionNotificationKey(event.getId()),
-                                                                    context);
-                        }
-                    }
-                }
-
-                try {
-                    // Note: we don't send a requested change event here, but a repair event
-                    final RepairSubscriptionInternalEvent busEvent = new DefaultRepairSubscriptionEvent(accountId, bundleId, clock.getUTCNow(),
-                                                                                                        context.getAccountRecordId(), context.getTenantRecordId(), context.getUserToken());
-                    eventBus.postFromTransaction(busEvent, entitySqlDaoWrapperFactory.getHandle().getConnection());
-                } catch (EventBusException e) {
-                    log.warn("Failed to post repair subscription event for bundle " + bundleId, e);
-                }
-
-                return null;
-            }
-        });
-    }
-
-    @Override
     public void transfer(final UUID srcAccountId, final UUID destAccountId, final BundleMigrationData bundleTransferData,
                          final List<TransferCancelData> transferCancelData, final InternalCallContext fromContext, final InternalCallContext toContext) {
 
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java
index 5503b99..13cfa2b 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java
@@ -27,7 +27,6 @@ import org.killbill.billing.entitlement.api.SubscriptionApiException;
 import org.killbill.billing.subscription.api.SubscriptionBase;
 import org.killbill.billing.subscription.api.migration.AccountMigrationData;
 import org.killbill.billing.subscription.api.migration.AccountMigrationData.BundleMigrationData;
-import org.killbill.billing.subscription.api.timeline.SubscriptionDataRepair;
 import org.killbill.billing.subscription.api.transfer.TransferCancelData;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBase;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseBundle;
@@ -99,8 +98,5 @@ public interface SubscriptionDao extends EntityDao<SubscriptionBundleModelDao, S
 
     public void updateBundleExternalKey(UUID bundleId, String externalKey, InternalCallContext context);
 
-    // Repair
-    public void repair(UUID accountId, UUID bundleId, List<SubscriptionDataRepair> inRepair, InternalCallContext context);
-
 }
 
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/glue/DefaultSubscriptionModule.java b/subscription/src/main/java/org/killbill/billing/subscription/glue/DefaultSubscriptionModule.java
index 01531ea..e0ba5ab 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/glue/DefaultSubscriptionModule.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/glue/DefaultSubscriptionModule.java
@@ -29,8 +29,6 @@ import org.killbill.billing.subscription.api.migration.DefaultSubscriptionBaseMi
 import org.killbill.billing.subscription.api.migration.SubscriptionBaseMigrationApi;
 import org.killbill.billing.subscription.api.svcs.DefaultSubscriptionInternalApi;
 import org.killbill.billing.subscription.api.timeline.DefaultSubscriptionBaseTimelineApi;
-import org.killbill.billing.subscription.api.timeline.RepairSubscriptionApiService;
-import org.killbill.billing.subscription.api.timeline.RepairSubscriptionLifecycleDao;
 import org.killbill.billing.subscription.api.timeline.SubscriptionBaseTimelineApi;
 import org.killbill.billing.subscription.api.transfer.DefaultSubscriptionBaseTransferApi;
 import org.killbill.billing.subscription.api.transfer.SubscriptionBaseTransferApi;
@@ -38,18 +36,13 @@ import org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseApiServ
 import org.killbill.billing.subscription.engine.addon.AddonUtils;
 import org.killbill.billing.subscription.engine.core.DefaultSubscriptionBaseService;
 import org.killbill.billing.subscription.engine.dao.DefaultSubscriptionDao;
-import org.killbill.billing.subscription.engine.dao.RepairSubscriptionDao;
 import org.killbill.billing.subscription.engine.dao.SubscriptionDao;
 import org.killbill.billing.util.config.SubscriptionConfig;
 import org.killbill.billing.util.glue.KillBillModule;
 import org.skife.config.ConfigurationObjectFactory;
 
-import com.google.inject.name.Names;
-
 public class DefaultSubscriptionModule extends KillBillModule implements SubscriptionModule {
 
-    public static final String REPAIR_NAMED = "repair";
-
     public DefaultSubscriptionModule(final KillbillConfigSource configSource) {
         super(configSource);
     }
@@ -61,15 +54,10 @@ public class DefaultSubscriptionModule extends KillBillModule implements Subscri
 
     protected void installSubscriptionDao() {
         bind(SubscriptionDao.class).to(DefaultSubscriptionDao.class).asEagerSingleton();
-        bind(SubscriptionDao.class).annotatedWith(Names.named(REPAIR_NAMED)).to(RepairSubscriptionDao.class);
-        bind(RepairSubscriptionLifecycleDao.class).annotatedWith(Names.named(REPAIR_NAMED)).to(RepairSubscriptionDao.class);
-        bind(RepairSubscriptionDao.class).asEagerSingleton();
     }
 
     protected void installSubscriptionCore() {
-        bind(SubscriptionBaseApiService.class).annotatedWith(Names.named(REPAIR_NAMED)).to(RepairSubscriptionApiService.class).asEagerSingleton();
         bind(SubscriptionBaseApiService.class).to(DefaultSubscriptionBaseApiService.class).asEagerSingleton();
-
         bind(DefaultSubscriptionBaseService.class).asEagerSingleton();
         bind(PlanAligner.class).asEagerSingleton();
         bind(AddonUtils.class).asEagerSingleton();
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/api/TestEventJson.java b/subscription/src/test/java/org/killbill/billing/subscription/api/TestEventJson.java
index 2121dc0..1141782 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/api/TestEventJson.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/api/TestEventJson.java
@@ -24,10 +24,8 @@ import org.testng.annotations.Test;
 
 import org.killbill.billing.GuicyKillbillTestSuiteNoDB;
 import org.killbill.billing.entitlement.api.Entitlement.EntitlementState;
-import org.killbill.billing.subscription.api.timeline.DefaultRepairSubscriptionEvent;
 import org.killbill.billing.subscription.api.user.DefaultEffectiveSubscriptionEvent;
 import org.killbill.billing.events.EffectiveSubscriptionInternalEvent;
-import org.killbill.billing.events.RepairSubscriptionInternalEvent;
 import org.killbill.billing.util.jackson.ObjectMapper;
 
 public class TestEventJson extends GuicyKillbillTestSuiteNoDB {
@@ -47,15 +45,4 @@ public class TestEventJson extends GuicyKillbillTestSuiteNoDB {
         final Object obj = mapper.readValue(json, claz);
         Assert.assertTrue(obj.equals(e));
     }
-
-    @Test(groups = "fast")
-    public void testRepairSubscriptionEvent() throws Exception {
-        final RepairSubscriptionInternalEvent e = new DefaultRepairSubscriptionEvent(UUID.randomUUID(), UUID.randomUUID(), new DateTime(), 1L, 2L, null);
-
-        final String json = mapper.writeValueAsString(e);
-
-        final Class<?> claz = Class.forName(DefaultRepairSubscriptionEvent.class.getName());
-        final Object obj = mapper.readValue(json, claz);
-        Assert.assertTrue(obj.equals(e));
-    }
 }
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/api/user/TestSubscriptionHelper.java b/subscription/src/test/java/org/killbill/billing/subscription/api/user/TestSubscriptionHelper.java
index 0cea1b8..3034a36 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/api/user/TestSubscriptionHelper.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/api/user/TestSubscriptionHelper.java
@@ -19,8 +19,6 @@
 package org.killbill.billing.subscription.api.user;
 
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.UUID;
@@ -30,7 +28,6 @@ import javax.inject.Inject;
 
 import org.joda.time.DateTime;
 import org.joda.time.Period;
-import org.killbill.billing.ErrorCode;
 import org.killbill.billing.account.api.Account;
 import org.killbill.billing.account.api.AccountApiException;
 import org.killbill.billing.account.api.AccountUserApi;
@@ -47,17 +44,10 @@ import org.killbill.billing.catalog.api.TimeUnit;
 import org.killbill.billing.events.EffectiveSubscriptionInternalEvent;
 import org.killbill.billing.mock.MockAccountBuilder;
 import org.killbill.billing.subscription.api.SubscriptionBaseInternalApi;
-import org.killbill.billing.subscription.api.SubscriptionBaseTransitionType;
 import org.killbill.billing.subscription.api.migration.SubscriptionBaseMigrationApi.AccountMigration;
 import org.killbill.billing.subscription.api.migration.SubscriptionBaseMigrationApi.BundleMigration;
 import org.killbill.billing.subscription.api.migration.SubscriptionBaseMigrationApi.SubscriptionMigration;
 import org.killbill.billing.subscription.api.migration.SubscriptionBaseMigrationApi.SubscriptionMigrationCase;
-import org.killbill.billing.subscription.api.timeline.BundleBaseTimeline;
-import org.killbill.billing.subscription.api.timeline.SubscriptionBaseRepairException;
-import org.killbill.billing.subscription.api.timeline.SubscriptionBaseTimeline;
-import org.killbill.billing.subscription.api.timeline.SubscriptionBaseTimeline.DeletedEvent;
-import org.killbill.billing.subscription.api.timeline.SubscriptionBaseTimeline.ExistingEvent;
-import org.killbill.billing.subscription.api.timeline.SubscriptionBaseTimeline.NewEvent;
 import org.killbill.billing.subscription.engine.dao.SubscriptionDao;
 import org.killbill.billing.subscription.events.SubscriptionBaseEvent;
 import org.killbill.billing.subscription.events.phase.PhaseEvent;
@@ -67,7 +57,6 @@ import org.killbill.billing.util.callcontext.CallContext;
 import org.killbill.clock.Clock;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.testng.Assert;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
@@ -151,31 +140,6 @@ public class TestSubscriptionHelper {
         assertTrue(in.isEqual(upper) || in.isBefore(upper));
     }
 
-    public Duration getDurationDay(final int days) {
-        final Duration result = new Duration() {
-            @Override
-            public TimeUnit getUnit() {
-                return TimeUnit.DAYS;
-            }
-
-            @Override
-            public int getNumber() {
-                return days;
-            }
-
-            @Override
-            public DateTime addToDateTime(final DateTime dateTime) {
-                return null;
-            }
-
-            @Override
-            public Period toJodaPeriod() {
-                throw new UnsupportedOperationException();
-            }
-        };
-        return result;
-    }
-
     public Duration getDurationMonth(final int months) {
         final Duration result = new Duration() {
             @Override
@@ -201,31 +165,6 @@ public class TestSubscriptionHelper {
         return result;
     }
 
-    public Duration getDurationYear(final int years) {
-        final Duration result = new Duration() {
-            @Override
-            public TimeUnit getUnit() {
-                return TimeUnit.YEARS;
-            }
-
-            @Override
-            public int getNumber() {
-                return years;
-            }
-
-            @Override
-            public DateTime addToDateTime(final DateTime dateTime) {
-                return dateTime.plusYears(years);
-            }
-
-            @Override
-            public Period toJodaPeriod() {
-                throw new UnsupportedOperationException();
-            }
-        };
-        return result;
-    }
-
     public PlanPhaseSpecifier getProductSpecifier(final String productName, final String priceList,
                                                   final BillingPeriod term,
                                                   @Nullable final PhaseType phaseType) {
@@ -401,206 +340,6 @@ public class TestSubscriptionHelper {
         return createAccountForMigrationTest(input);
     }
 
-    public SubscriptionBaseTimeline createSubscriptionRepair(final UUID id, final List<DeletedEvent> deletedEvents, final List<NewEvent> newEvents) {
-        return new SubscriptionBaseTimeline() {
-            @Override
-            public UUID getId() {
-                return id;
-            }
-
-            @Override
-            public DateTime getCreatedDate() {
-                return null;
-            }
-
-            @Override
-            public DateTime getUpdatedDate() {
-                return null;
-            }
-
-            @Override
-            public List<NewEvent> getNewEvents() {
-                return newEvents;
-            }
-
-            @Override
-            public List<ExistingEvent> getExistingEvents() {
-                return null;
-            }
-
-            @Override
-            public List<DeletedEvent> getDeletedEvents() {
-                return deletedEvents;
-            }
-
-            @Override
-            public long getActiveVersion() {
-                return 1;
-            }
-        };
-    }
-
-    public BundleBaseTimeline createBundleRepair(final UUID bundleId, final String viewId, final List<SubscriptionBaseTimeline> subscriptionRepair) {
-        return new BundleBaseTimeline() {
-            @Override
-            public String getViewId() {
-                return viewId;
-            }
-
-            @Override
-            public List<SubscriptionBaseTimeline> getSubscriptions() {
-                return subscriptionRepair;
-            }
-
-            @Override
-            public UUID getId() {
-                return bundleId;
-            }
-
-            @Override
-            public DateTime getCreatedDate() {
-                return null;
-            }
-
-            @Override
-            public DateTime getUpdatedDate() {
-                return null;
-            }
-
-            @Override
-            public String getExternalKey() {
-                return null;
-            }
-        };
-    }
-
-    public ExistingEvent createExistingEventForAssertion(final SubscriptionBaseTransitionType type,
-                                                         final String productName, final PhaseType phaseType, final ProductCategory category, final String priceListName, final BillingPeriod billingPeriod,
-                                                         final DateTime effectiveDateTime) {
-        final PlanPhaseSpecifier spec = new PlanPhaseSpecifier(productName, category, billingPeriod, priceListName, phaseType);
-        return new ExistingEvent() {
-            @Override
-            public SubscriptionBaseTransitionType getSubscriptionTransitionType() {
-                return type;
-            }
-
-            @Override
-            public DateTime getRequestedDate() {
-                return null;
-            }
-
-            @Override
-            public PlanPhaseSpecifier getPlanPhaseSpecifier() {
-                return spec;
-            }
-
-            @Override
-            public UUID getEventId() {
-                return null;
-            }
-
-            @Override
-            public DateTime getEffectiveDate() {
-                return effectiveDateTime;
-            }
-
-            @Override
-            public String getPlanName() {
-                return null;
-            }
-
-            @Override
-            public String getPlanPhaseName() {
-                return null;
-            }
-        };
-    }
-
-    public SubscriptionBaseTimeline getSubscriptionRepair(final UUID id, final BundleBaseTimeline bundleRepair) {
-        for (final SubscriptionBaseTimeline cur : bundleRepair.getSubscriptions()) {
-            if (cur.getId().equals(id)) {
-                return cur;
-            }
-        }
-        Assert.fail("Failed to find SubscriptionRepair " + id);
-        return null;
-    }
-
-    public void validateExistingEventForAssertion(final ExistingEvent expected, final ExistingEvent input) {
-        log.debug(String.format("Got %s -> Expected %s", input.getPlanPhaseSpecifier().getProductName(), expected.getPlanPhaseSpecifier().getProductName()));
-        assertEquals(input.getPlanPhaseSpecifier().getProductName(), expected.getPlanPhaseSpecifier().getProductName());
-        log.debug(String.format("Got %s -> Expected %s", input.getPlanPhaseSpecifier().getPhaseType(), expected.getPlanPhaseSpecifier().getPhaseType()));
-        assertEquals(input.getPlanPhaseSpecifier().getPhaseType(), expected.getPlanPhaseSpecifier().getPhaseType());
-        log.debug(String.format("Got %s -> Expected %s", input.getPlanPhaseSpecifier().getProductCategory(), expected.getPlanPhaseSpecifier().getProductCategory()));
-        assertEquals(input.getPlanPhaseSpecifier().getProductCategory(), expected.getPlanPhaseSpecifier().getProductCategory());
-        log.debug(String.format("Got %s -> Expected %s", input.getPlanPhaseSpecifier().getPriceListName(), expected.getPlanPhaseSpecifier().getPriceListName()));
-        assertEquals(input.getPlanPhaseSpecifier().getPriceListName(), expected.getPlanPhaseSpecifier().getPriceListName());
-        log.debug(String.format("Got %s -> Expected %s", input.getPlanPhaseSpecifier().getBillingPeriod(), expected.getPlanPhaseSpecifier().getBillingPeriod()));
-        assertEquals(input.getPlanPhaseSpecifier().getBillingPeriod(), expected.getPlanPhaseSpecifier().getBillingPeriod());
-        log.debug(String.format("Got %s -> Expected %s", input.getEffectiveDate(), expected.getEffectiveDate()));
-        assertEquals(input.getEffectiveDate(), expected.getEffectiveDate());
-    }
-
-    public DeletedEvent createDeletedEvent(final UUID eventId) {
-        return new DeletedEvent() {
-            @Override
-            public UUID getEventId() {
-                return eventId;
-            }
-        };
-    }
-
-    public NewEvent createNewEvent(final SubscriptionBaseTransitionType type, final DateTime requestedDate, final PlanPhaseSpecifier spec) {
-        return new NewEvent() {
-            @Override
-            public SubscriptionBaseTransitionType getSubscriptionTransitionType() {
-                return type;
-            }
-
-            @Override
-            public DateTime getRequestedDate() {
-                return requestedDate;
-            }
-
-            @Override
-            public PlanPhaseSpecifier getPlanPhaseSpecifier() {
-                return spec;
-            }
-        };
-    }
-
-    public void sortEventsOnBundle(final BundleBaseTimeline bundle) {
-        if (bundle.getSubscriptions() == null) {
-            return;
-        }
-        for (final SubscriptionBaseTimeline cur : bundle.getSubscriptions()) {
-            if (cur.getExistingEvents() != null) {
-                sortExistingEvent(cur.getExistingEvents());
-            }
-            if (cur.getNewEvents() != null) {
-                sortNewEvent(cur.getNewEvents());
-            }
-        }
-    }
-
-    public void sortExistingEvent(final List<ExistingEvent> events) {
-        Collections.sort(events, new Comparator<ExistingEvent>() {
-            @Override
-            public int compare(final ExistingEvent arg0, final ExistingEvent arg1) {
-                return arg0.getEffectiveDate().compareTo(arg1.getEffectiveDate());
-            }
-        });
-    }
-
-    public void sortNewEvent(final List<NewEvent> events) {
-        Collections.sort(events, new Comparator<NewEvent>() {
-            @Override
-            public int compare(final NewEvent arg0, final NewEvent arg1) {
-                return arg0.getRequestedDate().compareTo(arg1.getRequestedDate());
-            }
-        });
-    }
-
     public static DateTime addOrRemoveDuration(final DateTime input, final List<Duration> durations, final boolean add) {
         DateTime result = input;
         for (final Duration cur : durations) {
@@ -628,22 +367,12 @@ public class TestSubscriptionHelper {
         return addOrRemoveDuration(input, durations, true);
     }
 
-    public static DateTime removeDuration(final DateTime input, final List<Duration> durations) {
-        return addOrRemoveDuration(input, durations, false);
-    }
-
     public static DateTime addDuration(final DateTime input, final Duration duration) {
         final List<Duration> list = new ArrayList<Duration>();
         list.add(duration);
         return addOrRemoveDuration(input, list, true);
     }
 
-    public static DateTime removeDuration(final DateTime input, final Duration duration) {
-        final List<Duration> list = new ArrayList<Duration>();
-        list.add(duration);
-        return addOrRemoveDuration(input, list, false);
-    }
-
     public static class SubscriptionMigrationCaseWithCTD implements SubscriptionMigrationCase {
 
         private final PlanPhaseSpecifier pps;
@@ -678,20 +407,4 @@ public class TestSubscriptionHelper {
         }
     }
 
-    public interface TestWithExceptionCallback {
-
-        public void doTest() throws SubscriptionBaseRepairException, SubscriptionBaseApiException;
-    }
-
-    public static class TestWithException {
-
-        public void withException(final TestWithExceptionCallback callback, final ErrorCode code) throws Exception {
-            try {
-                callback.doTest();
-                Assert.fail("Failed to catch exception " + code);
-            } catch (SubscriptionBaseRepairException e) {
-                assertEquals(e.getCode(), code.getCode());
-            }
-        }
-    }
 }
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java b/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
index 1891725..9b608c0 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
@@ -41,7 +41,6 @@ import org.killbill.billing.subscription.api.SubscriptionBase;
 import org.killbill.billing.subscription.api.migration.AccountMigrationData;
 import org.killbill.billing.subscription.api.migration.AccountMigrationData.BundleMigrationData;
 import org.killbill.billing.subscription.api.migration.AccountMigrationData.SubscriptionMigrationData;
-import org.killbill.billing.subscription.api.timeline.SubscriptionDataRepair;
 import org.killbill.billing.subscription.api.transfer.TransferCancelData;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBase;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBaseBundle;
@@ -486,11 +485,6 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
     }
 
     @Override
-    public void repair(final UUID accountId, final UUID bundleId, final List<SubscriptionDataRepair> inRepair,
-                       final InternalCallContext context) {
-    }
-
-    @Override
     public void transfer(final UUID srcAccountId, final UUID destAccountId, final BundleMigrationData data,
                          final List<TransferCancelData> transferCancelData, final InternalCallContext fromContext,
                          final InternalCallContext toContext) {
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/glue/TestDefaultSubscriptionModuleNoDB.java b/subscription/src/test/java/org/killbill/billing/subscription/glue/TestDefaultSubscriptionModuleNoDB.java
index ae1d4b7..1bb0955 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/glue/TestDefaultSubscriptionModuleNoDB.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/glue/TestDefaultSubscriptionModuleNoDB.java
@@ -22,14 +22,10 @@ import org.killbill.billing.GuicyKillbillTestNoDBModule;
 import org.killbill.billing.account.api.AccountUserApi;
 import org.killbill.billing.mock.glue.MockNonEntityDaoModule;
 import org.killbill.billing.platform.api.KillbillConfigSource;
-import org.killbill.billing.subscription.api.timeline.RepairSubscriptionLifecycleDao;
 import org.killbill.billing.subscription.engine.dao.MockSubscriptionDaoMemory;
-import org.killbill.billing.subscription.engine.dao.RepairSubscriptionDao;
 import org.killbill.billing.subscription.engine.dao.SubscriptionDao;
 import org.mockito.Mockito;
 
-import com.google.inject.name.Names;
-
 public class TestDefaultSubscriptionModuleNoDB extends TestDefaultSubscriptionModule {
 
     public TestDefaultSubscriptionModuleNoDB(final KillbillConfigSource configSource) {
@@ -39,9 +35,6 @@ public class TestDefaultSubscriptionModuleNoDB extends TestDefaultSubscriptionMo
     @Override
     protected void installSubscriptionDao() {
         bind(SubscriptionDao.class).to(MockSubscriptionDaoMemory.class).asEagerSingleton();
-        bind(SubscriptionDao.class).annotatedWith(Names.named(REPAIR_NAMED)).to(RepairSubscriptionDao.class);
-        bind(RepairSubscriptionLifecycleDao.class).annotatedWith(Names.named(REPAIR_NAMED)).to(RepairSubscriptionDao.class);
-        bind(RepairSubscriptionDao.class).asEagerSingleton();
     }
 
     @Override
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/glue/TestDefaultSubscriptionModuleWithEmbeddedDB.java b/subscription/src/test/java/org/killbill/billing/subscription/glue/TestDefaultSubscriptionModuleWithEmbeddedDB.java
index 6d8cfa2..7918876 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/glue/TestDefaultSubscriptionModuleWithEmbeddedDB.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/glue/TestDefaultSubscriptionModuleWithEmbeddedDB.java
@@ -21,15 +21,11 @@ package org.killbill.billing.subscription.glue;
 import org.killbill.billing.GuicyKillbillTestWithEmbeddedDBModule;
 import org.killbill.billing.account.glue.DefaultAccountModule;
 import org.killbill.billing.platform.api.KillbillConfigSource;
-import org.killbill.billing.subscription.api.timeline.RepairSubscriptionLifecycleDao;
 import org.killbill.billing.subscription.engine.dao.MockSubscriptionDaoSql;
-import org.killbill.billing.subscription.engine.dao.RepairSubscriptionDao;
 import org.killbill.billing.subscription.engine.dao.SubscriptionDao;
 import org.killbill.billing.util.glue.CustomFieldModule;
 import org.killbill.billing.util.glue.NonEntityDaoModule;
 
-import com.google.inject.name.Names;
-
 public class TestDefaultSubscriptionModuleWithEmbeddedDB extends TestDefaultSubscriptionModule {
 
     public TestDefaultSubscriptionModuleWithEmbeddedDB(final KillbillConfigSource configSource) {
@@ -39,9 +35,6 @@ public class TestDefaultSubscriptionModuleWithEmbeddedDB extends TestDefaultSubs
     @Override
     protected void installSubscriptionDao() {
         bind(SubscriptionDao.class).to(MockSubscriptionDaoSql.class).asEagerSingleton();
-        bind(SubscriptionDao.class).annotatedWith(Names.named(REPAIR_NAMED)).to(RepairSubscriptionDao.class);
-        bind(RepairSubscriptionLifecycleDao.class).annotatedWith(Names.named(REPAIR_NAMED)).to(RepairSubscriptionDao.class);
-        bind(RepairSubscriptionDao.class).asEagerSingleton();
     }
 
     @Override