killbill-memoizeit
Changes
entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java 19(+9 -10)
entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java 11(+5 -6)
entitlement/src/main/java/org/killbill/billing/entitlement/block/DefaultBlockingChecker.java 39(+18 -21)
entitlement/src/main/java/org/killbill/billing/entitlement/engine/core/EntitlementUtils.java 2(+1 -1)
invoice/src/main/java/org/killbill/billing/invoice/notification/DefaultNextBillingDateNotifier.java 23(+6 -17)
subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java 89(+82 -7)
subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java 28(+0 -28)
subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java 3(+0 -3)
subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java 5(+0 -5)
Details
diff --git a/api/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseInternalApi.java b/api/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseInternalApi.java
index 2a05cf6..ac1df1a 100644
--- a/api/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseInternalApi.java
+++ b/api/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseInternalApi.java
@@ -76,8 +76,6 @@ public interface SubscriptionBaseInternalApi {
public SubscriptionBaseBundle getBundleFromId(UUID id, InternalTenantContext context) throws SubscriptionBaseApiException;
- public UUID getAccountIdFromSubscriptionId(UUID subscriptionId, InternalTenantContext context) throws SubscriptionBaseApiException;
-
public void setChargedThroughDate(UUID subscriptionId, DateTime chargedThruDate, InternalCallContext context) throws SubscriptionBaseApiException;
public List<EffectiveSubscriptionInternalEvent> getAllTransitions(SubscriptionBase subscription, InternalTenantContext context);
@@ -94,4 +92,10 @@ public interface SubscriptionBaseInternalApi {
public void updateBCD(final UUID subscriptionId, final int bcd, @Nullable final LocalDate effectiveFromDate, final InternalCallContext internalCallContext) throws SubscriptionBaseApiException;
public int getDefaultBillCycleDayLocal(final Map<UUID, Integer> bcdCache, final SubscriptionBase subscription, final SubscriptionBase baseSubscription, final PlanPhaseSpecifier planPhaseSpecifier, final int accountBillCycleDayLocal, final Catalog catalog, final InternalTenantContext context) throws SubscriptionBaseApiException;
+
+ public UUID getAccountIdFromBundleId(UUID bundleId, InternalTenantContext context) throws SubscriptionBaseApiException;
+
+ public UUID getBundleIdFromSubscriptionId(UUID entitlementId, InternalTenantContext context) throws SubscriptionBaseApiException;
+
+ public UUID getAccountIdFromSubscriptionId(UUID subscriptionId, InternalTenantContext context) throws SubscriptionBaseApiException;
}
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java
index f05669d..a5e8793 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java
@@ -333,10 +333,9 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements
public List<EntitlementAOStatusDryRun> getDryRunStatusForChange(final UUID bundleId, final String targetProductName, @Nullable final LocalDate effectiveDate, final TenantContext context) throws EntitlementApiException {
final InternalTenantContext internalContext = internalCallContextFactory.createInternalTenantContext(bundleId, ObjectType.BUNDLE, context);
try {
- final SubscriptionBaseBundle bundle = subscriptionBaseInternalApi.getBundleFromId(bundleId, internalContext);
final SubscriptionBase baseSubscription = subscriptionBaseInternalApi.getBaseSubscription(bundleId, internalContext);
-
- final InternalTenantContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalTenantContext(bundle.getAccountId(), context);
+ final UUID accountId = subscriptionBaseInternalApi.getAccountIdFromBundleId(bundleId, internalContext);
+ final InternalTenantContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalTenantContext(accountId, context);
final DateTime now = clock.getUTCNow();
final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(effectiveDate, now, contextWithValidAccountRecordId);
return subscriptionBaseInternalApi.getDryRunChangePlanStatus(baseSubscription.getId(), targetProductName, requestedDate, contextWithValidAccountRecordId);
@@ -356,7 +355,7 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements
final InternalTenantContext internalContext = internalCallContextFactory.createInternalTenantContext(bundleId, ObjectType.BUNDLE, tenantContext);
final UUID accountId;
try {
- accountId = subscriptionBaseInternalApi.getBundleFromId(bundleId, internalContext).getAccountId();
+ accountId = subscriptionBaseInternalApi.getAccountIdFromBundleId(bundleId, internalContext);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
}
@@ -465,12 +464,12 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements
try {
final UUID activeSubscriptionIdForKey = entitlementUtils.getFirstActiveSubscriptionIdForKeyOrNull(externalKey, contextWithSourceAccountRecordId);
- final SubscriptionBase baseSubscription = activeSubscriptionIdForKey != null ?
- subscriptionBaseInternalApi.getSubscriptionFromId(activeSubscriptionIdForKey, contextWithSourceAccountRecordId) : null;
- final SubscriptionBaseBundle baseBundle = baseSubscription != null ?
- subscriptionBaseInternalApi.getBundleFromId(baseSubscription.getBundleId(), contextWithSourceAccountRecordId) : null;
+ final UUID bundleId = activeSubscriptionIdForKey != null ?
+ subscriptionBaseInternalApi.getBundleIdFromSubscriptionId(activeSubscriptionIdForKey, contextWithSourceAccountRecordId) : null;
+ final UUID baseBundleAccountId = bundleId != null ?
+ subscriptionBaseInternalApi.getAccountIdFromBundleId(bundleId, contextWithSourceAccountRecordId) : null;
- if (baseBundle == null || !baseBundle.getAccountId().equals(sourceAccountId)) {
+ if (baseBundleAccountId == null || !baseBundleAccountId.equals(sourceAccountId)) {
throw new EntitlementApiException(new SubscriptionBaseApiException(ErrorCode.SUB_GET_INVALID_BUNDLE_KEY, externalKey));
}
@@ -485,7 +484,7 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements
// Block all associated subscriptions - TODO Do we want to block the bundle as well (this will add an extra STOP_ENTITLEMENT event in the bundle timeline stream)?
// Note that there is no un-transfer at the moment, so we effectively add a blocking state on disk for all subscriptions
- for (final SubscriptionBase subscriptionBase : subscriptionBaseInternalApi.getSubscriptionsForBundle(baseBundle.getId(), null, contextWithSourceAccountRecordId)) {
+ for (final SubscriptionBase subscriptionBase : subscriptionBaseInternalApi.getSubscriptionsForBundle(bundleId, null, contextWithSourceAccountRecordId)) {
final BlockingState blockingState = new DefaultBlockingState(subscriptionBase.getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_CANCELLED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, false, requestedDate);
blockingStates.put(blockingState, subscriptionBase.getBundleId());
}
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java
index 7316ff1..a9691ee 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java
@@ -195,8 +195,8 @@ public class DefaultSubscriptionApi implements SubscriptionApi {
}
final InternalTenantContext internalContextWithAccountRecordId = internalCallContextFactory.createInternalTenantContext(activeSubscriptionIdForKey, ObjectType.SUBSCRIPTION, context);
- final SubscriptionBase subscriptionBase = subscriptionBaseInternalApi.getSubscriptionFromId(activeSubscriptionIdForKey, internalContextWithAccountRecordId);
- return getSubscriptionBundle(subscriptionBase.getBundleId(), context);
+ final UUID bundleId = subscriptionBaseInternalApi.getBundleIdFromSubscriptionId(activeSubscriptionIdForKey, internalContextWithAccountRecordId);
+ return getSubscriptionBundle(bundleId, context);
} catch (final SubscriptionBaseApiException e) {
throw new SubscriptionApiException(e);
}
@@ -276,11 +276,10 @@ public class DefaultSubscriptionApi implements SubscriptionApi {
final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(bundleId, ObjectType.BUNDLE, callContext);
- final SubscriptionBaseBundle bundle;
final ImmutableAccountData account;
try {
- bundle = subscriptionBaseInternalApi.getBundleFromId(bundleId, internalCallContext);
- account = accountApi.getImmutableAccountDataById(bundle.getAccountId(), internalCallContext);
+ final UUID accountId = subscriptionBaseInternalApi.getAccountIdFromBundleId(bundleId, internalCallContext);
+ account = accountApi.getImmutableAccountDataById(accountId, internalCallContext);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
} catch (AccountApiException e) {
@@ -299,7 +298,7 @@ public class DefaultSubscriptionApi implements SubscriptionApi {
final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.UPDATE_BUNDLE_EXTERNAL_KEY,
- bundle.getAccountId(),
+ account.getId(),
null,
baseEntitlementWithAddOnsSpecifierList,
null,
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/block/DefaultBlockingChecker.java b/entitlement/src/main/java/org/killbill/billing/entitlement/block/DefaultBlockingChecker.java
index d793106..20f76a8 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/block/DefaultBlockingChecker.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/block/DefaultBlockingChecker.java
@@ -136,44 +136,41 @@ public class DefaultBlockingChecker implements BlockingChecker {
}
private DefaultBlockingAggregator getBlockedStateSubscriptionId(final UUID subscriptionId, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
- final SubscriptionBase subscription;
try {
- subscription = subscriptionApi.getSubscriptionFromId(subscriptionId, context);
- return getBlockedStateSubscription(subscription, upToDate, context);
+ final UUID bundleId = subscriptionApi.getBundleIdFromSubscriptionId(subscriptionId, context);
+ return getBlockedStateSubscription(bundleId, subscriptionId, upToDate, context);
} catch (final SubscriptionBaseApiException e) {
throw new BlockingApiException(e, ErrorCode.fromCode(e.getCode()));
}
}
- private DefaultBlockingAggregator getBlockedStateSubscription(final SubscriptionBase subscription, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
+ private DefaultBlockingAggregator getBlockedStateSubscription(@Nullable final UUID bundleId, @Nullable final UUID subscriptionId, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
final DefaultBlockingAggregator result = new DefaultBlockingAggregator();
- if (subscription != null) {
- final DefaultBlockingAggregator subscriptionState = getBlockedStateForId(subscription.getId(), BlockingStateType.SUBSCRIPTION, upToDate, context);
+ if (subscriptionId != null) {
+ final DefaultBlockingAggregator subscriptionState = getBlockedStateForId(subscriptionId, BlockingStateType.SUBSCRIPTION, upToDate, context);
if (subscriptionState != null) {
result.or(subscriptionState);
}
- if (subscription.getBundleId() != null) {
+ if (bundleId != null) {
// Recursive call to also fetch account state
- result.or(getBlockedStateBundleId(subscription.getBundleId(), upToDate, context));
+ result.or(getBlockedStateBundleId(bundleId, upToDate, context));
}
}
return result;
}
private DefaultBlockingAggregator getBlockedStateBundleId(final UUID bundleId, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
-
- final SubscriptionBaseBundle bundle;
try {
- bundle = subscriptionApi.getBundleFromId(bundleId, context);
- return getBlockedStateBundle(bundle, upToDate, context);
+ final UUID accountId = subscriptionApi.getAccountIdFromBundleId(bundleId, context);
+ return getBlockedStateBundle(accountId, bundleId, upToDate, context);
} catch (final SubscriptionBaseApiException e) {
throw new BlockingApiException(e, ErrorCode.fromCode(e.getCode()));
}
}
- private DefaultBlockingAggregator getBlockedStateBundle(final SubscriptionBaseBundle bundle, final DateTime upToDate, final InternalTenantContext context) {
- final DefaultBlockingAggregator result = getBlockedStateAccountId(bundle.getAccountId(), upToDate, context);
- final DefaultBlockingAggregator bundleState = getBlockedStateForId(bundle.getId(), BlockingStateType.SUBSCRIPTION_BUNDLE, upToDate, context);
+ private DefaultBlockingAggregator getBlockedStateBundle(final UUID accountId, final UUID bundleId, final DateTime upToDate, final InternalTenantContext context) {
+ final DefaultBlockingAggregator result = getBlockedStateAccountId(accountId, upToDate, context);
+ final DefaultBlockingAggregator bundleState = getBlockedStateForId(bundleId, BlockingStateType.SUBSCRIPTION_BUNDLE, upToDate, context);
if (bundleState != null) {
result.or(bundleState);
}
@@ -220,9 +217,9 @@ public class DefaultBlockingChecker implements BlockingChecker {
@Override
public void checkBlockedChange(final Blockable blockable, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
- if (blockable instanceof SubscriptionBase && getBlockedStateSubscription((SubscriptionBase) blockable, upToDate, context).isBlockChange()) {
+ if (blockable instanceof SubscriptionBase && getBlockedStateSubscription(((SubscriptionBase) blockable).getBundleId(), blockable.getId(), upToDate, context).isBlockChange()) {
throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_CHANGE, TYPE_SUBSCRIPTION, blockable.getId().toString());
- } else if (blockable instanceof SubscriptionBaseBundle && getBlockedStateBundle((SubscriptionBaseBundle) blockable, upToDate, context).isBlockChange()) {
+ } else if (blockable instanceof SubscriptionBaseBundle && getBlockedStateBundle(((SubscriptionBaseBundle) blockable).getAccountId(), blockable.getId(), upToDate, context).isBlockChange()) {
throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_CHANGE, TYPE_BUNDLE, blockable.getId().toString());
} else if (blockable instanceof Account && getBlockedStateAccount((Account) blockable, upToDate, context).isBlockChange()) {
throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_CHANGE, TYPE_ACCOUNT, blockable.getId().toString());
@@ -231,9 +228,9 @@ public class DefaultBlockingChecker implements BlockingChecker {
@Override
public void checkBlockedEntitlement(final Blockable blockable, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
- if (blockable instanceof SubscriptionBase && getBlockedStateSubscription((SubscriptionBase) blockable, upToDate, context).isBlockEntitlement()) {
+ if (blockable instanceof SubscriptionBase && getBlockedStateSubscription(((SubscriptionBase) blockable).getBundleId(), blockable.getId(), upToDate, context).isBlockEntitlement()) {
throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_ENTITLEMENT, TYPE_SUBSCRIPTION, blockable.getId().toString());
- } else if (blockable instanceof SubscriptionBaseBundle && getBlockedStateBundle((SubscriptionBaseBundle) blockable, upToDate, context).isBlockEntitlement()) {
+ } else if (blockable instanceof SubscriptionBaseBundle && getBlockedStateBundle(((SubscriptionBaseBundle) blockable).getAccountId(), blockable.getId(), upToDate, context).isBlockEntitlement()) {
throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_ENTITLEMENT, TYPE_BUNDLE, blockable.getId().toString());
} else if (blockable instanceof Account && getBlockedStateAccount((Account) blockable, upToDate, context).isBlockEntitlement()) {
throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_ENTITLEMENT, TYPE_ACCOUNT, blockable.getId().toString());
@@ -242,9 +239,9 @@ public class DefaultBlockingChecker implements BlockingChecker {
@Override
public void checkBlockedBilling(final Blockable blockable, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
- if (blockable instanceof SubscriptionBase && getBlockedStateSubscription((SubscriptionBase) blockable, upToDate, context).isBlockBilling()) {
+ if (blockable instanceof SubscriptionBase && getBlockedStateSubscription(((SubscriptionBase) blockable).getBundleId(), blockable.getId(), upToDate, context).isBlockBilling()) {
throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_BILLING, TYPE_SUBSCRIPTION, blockable.getId().toString());
- } else if (blockable instanceof SubscriptionBaseBundle && getBlockedStateBundle((SubscriptionBaseBundle) blockable, upToDate, context).isBlockBilling()) {
+ } else if (blockable instanceof SubscriptionBaseBundle && getBlockedStateBundle(((SubscriptionBaseBundle) blockable).getAccountId(), blockable.getId(), upToDate, context).isBlockBilling()) {
throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_BILLING, TYPE_BUNDLE, blockable.getId().toString());
} else if (blockable instanceof Account && getBlockedStateAccount((Account) blockable, upToDate, context).isBlockBilling()) {
throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_BILLING, TYPE_ACCOUNT, blockable.getId().toString());
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/engine/core/EntitlementUtils.java b/entitlement/src/main/java/org/killbill/billing/entitlement/engine/core/EntitlementUtils.java
index fd44b4d..5307695 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/engine/core/EntitlementUtils.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/engine/core/EntitlementUtils.java
@@ -78,7 +78,7 @@ public class EntitlementUtils {
// We only need the bundle id in case of subscriptions (at the account level, we don't need it and at the bundle level, we already have it)
if (state.getType() == BlockingStateType.SUBSCRIPTION) {
try {
- bundleId = subscriptionBaseInternalApi.getSubscriptionFromId(state.getBlockedId(), context).getBundleId();
+ bundleId = subscriptionBaseInternalApi.getBundleIdFromSubscriptionId(state.getBlockedId(), context);
} catch (final SubscriptionBaseApiException e) {
throw new RuntimeException(e);
}
diff --git a/entitlement/src/test/java/org/killbill/billing/entitlement/block/TestBlockingChecker.java b/entitlement/src/test/java/org/killbill/billing/entitlement/block/TestBlockingChecker.java
index bb480fa..e8ac66b 100644
--- a/entitlement/src/test/java/org/killbill/billing/entitlement/block/TestBlockingChecker.java
+++ b/entitlement/src/test/java/org/killbill/billing/entitlement/block/TestBlockingChecker.java
@@ -64,6 +64,8 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
try {
Mockito.when(subscriptionInternalApi.getBundleFromId(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(bundle);
+ Mockito.when(subscriptionInternalApi.getAccountIdFromBundleId(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(accountId);
+ Mockito.when(subscriptionInternalApi.getBundleIdFromSubscriptionId(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(bundleId);
} catch (SubscriptionBaseApiException e) {
Assert.fail(e.toString());
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/notification/DefaultNextBillingDateNotifier.java b/invoice/src/main/java/org/killbill/billing/invoice/notification/DefaultNextBillingDateNotifier.java
index 98ee28a..79949d9 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/notification/DefaultNextBillingDateNotifier.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/notification/DefaultNextBillingDateNotifier.java
@@ -23,9 +23,7 @@ import java.util.UUID;
import org.joda.time.DateTime;
import org.killbill.billing.invoice.InvoiceListener;
import org.killbill.billing.invoice.api.DefaultInvoiceService;
-import org.killbill.billing.subscription.api.SubscriptionBase;
import org.killbill.billing.subscription.api.SubscriptionBaseInternalApi;
-import org.killbill.billing.subscription.api.user.SubscriptionBaseApiException;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
import org.killbill.clock.Clock;
import org.killbill.notificationq.api.NotificationEvent;
@@ -84,21 +82,12 @@ public class DefaultNextBillingDateNotifier extends RetryableService implements
// Just to ensure compatibility with json that might not have that targetDate field (old versions < 0.13.6)
final DateTime targetDate = key.getTargetDate() != null ? key.getTargetDate() : eventDate;
final UUID firstSubscriptionId = key.getUuidKeys().iterator().next();
- try {
- final SubscriptionBase subscription = subscriptionApi.getSubscriptionFromId(firstSubscriptionId, internalCallContextFactory.createInternalTenantContext(tenantRecordId, accountRecordId));
- if (subscription == null) {
- log.warn("Unable to retrieve subscriptionId='{}' for event {}", firstSubscriptionId, key);
- return;
- }
- if (key.isDryRunForInvoiceNotification() != null && // Just to ensure compatibility with json that might not have that field (old versions < 0.13.6)
- key.isDryRunForInvoiceNotification()) {
- processEventForInvoiceNotification(firstSubscriptionId, targetDate, userToken, accountRecordId, tenantRecordId);
- } else {
- final boolean isRescheduled = key.isRescheduled() == Boolean.TRUE; // Handle null value (old versions < 0.19.7)
- processEventForInvoiceGeneration(firstSubscriptionId, targetDate, isRescheduled, userToken, accountRecordId, tenantRecordId);
- }
- } catch (final SubscriptionBaseApiException e) {
- log.warn("Error retrieving subscriptionId='{}'", firstSubscriptionId, e);
+ if (key.isDryRunForInvoiceNotification() != null && // Just to ensure compatibility with json that might not have that field (old versions < 0.13.6)
+ key.isDryRunForInvoiceNotification()) {
+ processEventForInvoiceNotification(firstSubscriptionId, targetDate, userToken, accountRecordId, tenantRecordId);
+ } else {
+ final boolean isRescheduled = key.isRescheduled() == Boolean.TRUE; // Handle null value (old versions < 0.19.7)
+ processEventForInvoiceGeneration(firstSubscriptionId, targetDate, isRescheduled, userToken, accountRecordId, tenantRecordId);
}
}
};
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
index c6f4c72..727f476 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
@@ -79,6 +79,12 @@ import org.killbill.billing.subscription.events.bcd.BCDEventData;
import org.killbill.billing.subscription.exceptions.SubscriptionBaseError;
import org.killbill.billing.util.UUIDs;
import org.killbill.billing.util.bcd.BillCycleDayCalculator;
+import org.killbill.billing.util.cache.AccountIdFromBundleIdCacheLoader;
+import org.killbill.billing.util.cache.BundleIdFromSubscriptionIdCacheLoader;
+import org.killbill.billing.util.cache.Cachable.CacheType;
+import org.killbill.billing.util.cache.CacheController;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+import org.killbill.billing.util.cache.CacheLoaderArgument;
import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
import org.killbill.billing.util.callcontext.TenantContext;
@@ -107,6 +113,8 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
private final AddonUtils addonUtils;
private final InternalCallContextFactory internalCallContextFactory;
private final CatalogInternalApi catalogInternalApi;
+ private final CacheController<UUID, UUID> accountIdCacheController;
+ private final CacheController<UUID, UUID> bundleIdCacheController;
public static final Comparator<SubscriptionBase> SUBSCRIPTIONS_COMPARATOR = new Comparator<SubscriptionBase>() {
@@ -129,11 +137,14 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
final Clock clock,
final CatalogInternalApi catalogInternalApi,
final AddonUtils addonUtils,
+ final CacheControllerDispatcher cacheControllerDispatcher,
final InternalCallContextFactory internalCallContextFactory) {
super(dao, apiService, clock);
this.addonUtils = addonUtils;
this.internalCallContextFactory = internalCallContextFactory;
this.catalogInternalApi = catalogInternalApi;
+ this.accountIdCacheController = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_ID_FROM_BUNDLE_ID);
+ this.bundleIdCacheController = cacheControllerDispatcher.getCacheController(CacheType.BUNDLE_ID_FROM_SUBSCRIPTION_ID);
}
private List<SubscriptionSpecifier> verifyAndBuildSubscriptionSpecifiers(final SubscriptionBaseBundle bundle,
@@ -317,7 +328,13 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
subscriptionAndAddOns.add(subscriptionAndAddOnsSpecifier);
}
- return apiService.createPlansWithAddOns(accountId, subscriptionAndAddOns, catalog, callContext);
+ final List<SubscriptionBaseWithAddOns> subscriptionBaseWithAddOns = apiService.createPlansWithAddOns(accountId, subscriptionAndAddOns, catalog, callContext);
+ for (final SubscriptionBaseWithAddOns subscriptionBaseWithAO : subscriptionBaseWithAddOns) {
+ for (final SubscriptionBase subscriptionBase : subscriptionBaseWithAO.getSubscriptionBaseList()) {
+ bundleIdCacheController.putIfAbsent(subscriptionBase.getId(), subscriptionBaseWithAO.getBundle().getId());
+ }
+ }
+ return subscriptionBaseWithAddOns;
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
}
@@ -378,7 +395,9 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
}
try {
final Catalog catalog = catalogInternalApi.getFullCatalog(true, true, context);
- return dao.createSubscriptionBundle(bundle, catalog, renameCancelledBundleIfExist, context);
+ final SubscriptionBaseBundle subscriptionBundle = dao.createSubscriptionBundle(bundle, catalog, renameCancelledBundleIfExist, context);
+ accountIdCacheController.putIfAbsent(bundle.getId(), accountId);
+ return subscriptionBundle;
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
}
@@ -544,11 +563,6 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
}
@Override
- public UUID getAccountIdFromSubscriptionId(final UUID subscriptionId, final InternalTenantContext context) throws SubscriptionBaseApiException {
- return dao.getAccountIdFromSubscriptionId(subscriptionId, context);
- }
-
- @Override
public void setChargedThroughDate(final UUID subscriptionId, final DateTime chargedThruDate, final InternalCallContext context) throws SubscriptionBaseApiException {
try {
@@ -790,6 +804,67 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
}
}
+ @Override
+ public UUID getAccountIdFromBundleId(final UUID bundleId, final InternalTenantContext context) throws SubscriptionBaseApiException {
+ final CacheLoaderArgument arg = createAccountIdFromBundleIdCacheLoaderArgument(context);
+ return accountIdCacheController.get(bundleId, arg);
+ }
+
+ @Override
+ public UUID getBundleIdFromSubscriptionId(final UUID subscriptionId, final InternalTenantContext context) throws SubscriptionBaseApiException {
+ final CacheLoaderArgument arg = createBundleIdFromSubscriptionIdCacheLoaderArgument(context);
+ return bundleIdCacheController.get(subscriptionId, arg);
+ }
+
+ @Override
+ public UUID getAccountIdFromSubscriptionId(final UUID subscriptionId, final InternalTenantContext context) throws SubscriptionBaseApiException {
+ final UUID bundleId = getBundleIdFromSubscriptionId(subscriptionId, context);
+ if (bundleId == null) {
+ throw new SubscriptionBaseApiException(ErrorCode.SUB_GET_NO_BUNDLE_FOR_SUBSCRIPTION, subscriptionId);
+ }
+ final UUID accountId = getAccountIdFromBundleId(bundleId, context);
+ if (accountId == null) {
+ throw new SubscriptionBaseApiException(ErrorCode.SUB_GET_INVALID_BUNDLE_ID, bundleId);
+ }
+ return accountId;
+ }
+
+ private CacheLoaderArgument createAccountIdFromBundleIdCacheLoaderArgument(final InternalTenantContext internalTenantContext) {
+ final AccountIdFromBundleIdCacheLoader.LoaderCallback loaderCallback = new AccountIdFromBundleIdCacheLoader.LoaderCallback() {
+ public UUID loadAccountId(final UUID bundleId, final InternalTenantContext internalTenantContext) {
+ final SubscriptionBaseBundle bundle;
+ try {
+ bundle = getBundleFromId(bundleId, internalTenantContext);
+ } catch (final SubscriptionBaseApiException e) {
+ log.warn("Unable to retrieve bundle for id='{}'", bundleId);
+ return null;
+ }
+ return bundle.getAccountId();
+ }
+ };
+
+ final Object[] args = {loaderCallback};
+ return new CacheLoaderArgument(null, args, internalTenantContext);
+ }
+
+ private CacheLoaderArgument createBundleIdFromSubscriptionIdCacheLoaderArgument(final InternalTenantContext internalTenantContext) {
+ final BundleIdFromSubscriptionIdCacheLoader.LoaderCallback loaderCallback = new BundleIdFromSubscriptionIdCacheLoader.LoaderCallback() {
+ public UUID loadBundleId(final UUID subscriptionId, final InternalTenantContext internalTenantContext) {
+ final SubscriptionBase subscriptionBase;
+ try {
+ subscriptionBase = getSubscriptionFromId(subscriptionId, internalTenantContext);
+ } catch (final SubscriptionBaseApiException e) {
+ log.warn("Unable to retrieve subscription for id='{}'", subscriptionId);
+ return null;
+ }
+ return subscriptionBase.getBundleId();
+ }
+ };
+
+ final Object[] args = {loaderCallback};
+ return new CacheLoaderArgument(null, args, internalTenantContext);
+ }
+
@VisibleForTesting
DateTime getEffectiveDateForNewBCD(final int bcd, @Nullable final LocalDate effectiveFromDate, final InternalCallContext internalCallContext) {
if (internalCallContext.getAccountRecordId() == 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 f7c8fd0..1c11dae 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
@@ -343,34 +343,6 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
}
@Override
- public UUID getAccountIdFromSubscriptionId(final UUID subscriptionId, final InternalTenantContext context) {
-
- return transactionalSqlDao.execute(true, new EntitySqlDaoTransactionWrapper<UUID>() {
- @Override
- public UUID inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
- final SubscriptionModelDao subscriptionModel = entitySqlDaoWrapperFactory.become(SubscriptionSqlDao.class).getById(subscriptionId.toString(), context);
- if (subscriptionModel == null) {
- log.warn(String.format(ErrorCode.SUB_INVALID_SUBSCRIPTION_ID.getFormat(), subscriptionId.toString()));
- return null;
- }
-
- final UUID bundleId = subscriptionModel.getBundleId();
- if (bundleId == null) {
- log.warn(String.format(ErrorCode.SUB_GET_NO_BUNDLE_FOR_SUBSCRIPTION.getFormat(), subscriptionId.toString()));
- return null;
- }
-
- final SubscriptionBundleModelDao bundleModel = entitySqlDaoWrapperFactory.become(BundleSqlDao.class).getById(bundleId.toString(), context);
- if (bundleModel == null) {
- log.warn(String.format(ErrorCode.SUB_GET_INVALID_BUNDLE_ID.getFormat(), bundleId.toString()));
- return null;
- }
- return bundleModel.getAccountId();
- }
- });
- }
-
- @Override
public SubscriptionBase getBaseSubscription(final UUID bundleId, final Catalog catalog, final InternalTenantContext context) throws CatalogApiException {
return getBaseSubscription(bundleId, true, catalog, context);
}
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 8a86d46..3e6dd6c 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
@@ -59,9 +59,6 @@ public interface SubscriptionDao extends EntityDao<SubscriptionBundleModelDao, S
public SubscriptionBase getSubscriptionFromId(UUID subscriptionId, final Catalog catalog, InternalTenantContext context) throws CatalogApiException;
- // ACCOUNT retrieval
- public UUID getAccountIdFromSubscriptionId(UUID subscriptionId, InternalTenantContext context);
-
// SubscriptionBase retrieval
public SubscriptionBase getBaseSubscription(UUID bundleId, final Catalog catalog, InternalTenantContext context) throws CatalogApiException;
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 ed8e8c2..19dbef1 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
@@ -198,11 +198,6 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
}
@Override
- public UUID getAccountIdFromSubscriptionId(final UUID subscriptionId, final InternalTenantContext context) {
- throw new UnsupportedOperationException();
- }
-
- @Override
public List<SubscriptionBaseEvent> createSubscriptionsWithAddOns(final List<SubscriptionBaseWithAddOns> subscriptions,
final Map<UUID, List<SubscriptionBaseEvent>> initialEventsMap,
final Catalog catalog,
diff --git a/util/src/main/java/org/killbill/billing/util/cache/AccountIdFromBundleIdCacheLoader.java b/util/src/main/java/org/killbill/billing/util/cache/AccountIdFromBundleIdCacheLoader.java
new file mode 100644
index 0000000..9dd2f3a
--- /dev/null
+++ b/util/src/main/java/org/killbill/billing/util/cache/AccountIdFromBundleIdCacheLoader.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.util.cache;
+
+import java.util.UUID;
+
+import javax.inject.Singleton;
+
+import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.util.cache.Cachable.CacheType;
+
+@Singleton
+public class AccountIdFromBundleIdCacheLoader extends BaseCacheLoader<UUID, UUID> {
+
+ @Override
+ public CacheType getCacheType() {
+ return CacheType.ACCOUNT_ID_FROM_BUNDLE_ID;
+ }
+
+ @Override
+ public UUID compute(final UUID key, final CacheLoaderArgument cacheLoaderArgument) {
+ if (cacheLoaderArgument.getArgs() == null ||
+ !(cacheLoaderArgument.getArgs()[0] instanceof LoaderCallback)) {
+ throw new IllegalArgumentException("Missing LoaderCallback from the arguments ");
+ }
+
+ final LoaderCallback callback = (LoaderCallback) cacheLoaderArgument.getArgs()[0];
+ return callback.loadAccountId(key, cacheLoaderArgument.getInternalTenantContext());
+ }
+
+ public interface LoaderCallback {
+
+ UUID loadAccountId(final UUID bundleId, final InternalTenantContext context);
+ }
+}
diff --git a/util/src/main/java/org/killbill/billing/util/cache/BundleIdFromSubscriptionIdCacheLoader.java b/util/src/main/java/org/killbill/billing/util/cache/BundleIdFromSubscriptionIdCacheLoader.java
new file mode 100644
index 0000000..b88d7b7
--- /dev/null
+++ b/util/src/main/java/org/killbill/billing/util/cache/BundleIdFromSubscriptionIdCacheLoader.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.util.cache;
+
+import java.util.UUID;
+
+import javax.inject.Singleton;
+
+import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.util.cache.Cachable.CacheType;
+
+@Singleton
+public class BundleIdFromSubscriptionIdCacheLoader extends BaseCacheLoader<UUID, UUID> {
+
+ @Override
+ public CacheType getCacheType() {
+ return CacheType.BUNDLE_ID_FROM_SUBSCRIPTION_ID;
+ }
+
+ @Override
+ public UUID compute(final UUID key, final CacheLoaderArgument cacheLoaderArgument) {
+ if (cacheLoaderArgument.getArgs() == null ||
+ !(cacheLoaderArgument.getArgs()[0] instanceof LoaderCallback)) {
+ throw new IllegalArgumentException("Missing LoaderCallback from the arguments ");
+ }
+
+ final LoaderCallback callback = (LoaderCallback) cacheLoaderArgument.getArgs()[0];
+ return callback.loadBundleId(key, cacheLoaderArgument.getInternalTenantContext());
+ }
+
+ public interface LoaderCallback {
+
+ UUID loadBundleId(final UUID subscriptionId, final InternalTenantContext context);
+ }
+}
diff --git a/util/src/main/java/org/killbill/billing/util/cache/Cachable.java b/util/src/main/java/org/killbill/billing/util/cache/Cachable.java
index 97d5cb6..240ff3c 100644
--- a/util/src/main/java/org/killbill/billing/util/cache/Cachable.java
+++ b/util/src/main/java/org/killbill/billing/util/cache/Cachable.java
@@ -50,6 +50,8 @@ public @interface Cachable {
String OVERRIDDEN_PLAN_CACHE_NAME = "overridden-plan";
String ACCOUNT_IMMUTABLE_CACHE_NAME = "account-immutable";
String ACCOUNT_BCD_CACHE_NAME = "account-bcd";
+ String ACCOUNT_ID_FROM_BUNDLE_ID_CACHE_NAME = "account-id-from-bundle-id";
+ String BUNDLE_ID_FROM_SUBSCRIPTION_ID_CACHE_NAME = "bundle-id-from-subscription-id";
CacheType value();
@@ -99,7 +101,13 @@ public @interface Cachable {
ACCOUNT_IMMUTABLE(ACCOUNT_IMMUTABLE_CACHE_NAME, Long.class, ImmutableAccountData.class, false),
/* Account BCD config cache */
- ACCOUNT_BCD(ACCOUNT_BCD_CACHE_NAME, UUID.class, Integer.class, false);
+ ACCOUNT_BCD(ACCOUNT_BCD_CACHE_NAME, UUID.class, Integer.class, false),
+
+ /* Bundle id to Account id cache */
+ ACCOUNT_ID_FROM_BUNDLE_ID(ACCOUNT_ID_FROM_BUNDLE_ID_CACHE_NAME, UUID.class, UUID.class, false),
+
+ /* Entitlement id to Bundle id cache */
+ BUNDLE_ID_FROM_SUBSCRIPTION_ID(BUNDLE_ID_FROM_SUBSCRIPTION_ID_CACHE_NAME, UUID.class, UUID.class, false);
private final String cacheName;
private final Class keyType;
diff --git a/util/src/main/java/org/killbill/billing/util/glue/CacheModule.java b/util/src/main/java/org/killbill/billing/util/glue/CacheModule.java
index d4ddf25..cb7c571 100644
--- a/util/src/main/java/org/killbill/billing/util/glue/CacheModule.java
+++ b/util/src/main/java/org/killbill/billing/util/glue/CacheModule.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2015 Groupon, Inc
- * Copyright 2014-2015 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
@@ -22,10 +22,12 @@ import javax.cache.CacheManager;
import org.killbill.billing.platform.api.KillbillConfigSource;
import org.killbill.billing.util.cache.AccountBCDCacheLoader;
+import org.killbill.billing.util.cache.AccountIdFromBundleIdCacheLoader;
import org.killbill.billing.util.cache.AccountRecordIdCacheLoader;
import org.killbill.billing.util.cache.AuditLogCacheLoader;
import org.killbill.billing.util.cache.AuditLogViaHistoryCacheLoader;
import org.killbill.billing.util.cache.BaseCacheLoader;
+import org.killbill.billing.util.cache.BundleIdFromSubscriptionIdCacheLoader;
import org.killbill.billing.util.cache.CacheControllerDispatcher;
import org.killbill.billing.util.cache.CacheControllerDispatcherProvider;
import org.killbill.billing.util.cache.ImmutableAccountCacheLoader;
@@ -77,5 +79,7 @@ public class CacheModule extends KillBillModule {
resultSetMapperSetBinder.addBinding().to(TenantCacheLoader.class).asEagerSingleton();
resultSetMapperSetBinder.addBinding().to(OverriddenPlanCacheLoader.class).asEagerSingleton();
resultSetMapperSetBinder.addBinding().to(TenantStateMachineConfigCacheLoader.class).asEagerSingleton();
+ resultSetMapperSetBinder.addBinding().to(AccountIdFromBundleIdCacheLoader.class).asEagerSingleton();
+ resultSetMapperSetBinder.addBinding().to(BundleIdFromSubscriptionIdCacheLoader.class).asEagerSingleton();
}
}