killbill-memoizeit
Changes
analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java 40(+29 -11)
analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java 1(+1 -0)
analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionMapper.java 63(+32 -31)
analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDao.sql.stg 11(+7 -4)
analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java 32(+22 -10)
Details
diff --git a/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java b/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
index d623338..1735062 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
@@ -36,14 +36,15 @@ public class AnalyticsListener
}
@Subscribe
- public void handleSubscriptionTransitionChange(final SubscriptionTransition event) throws AccountApiException {
+ public void handleSubscriptionTransitionChange(final SubscriptionTransition event) throws AccountApiException
+ {
switch (event.getTransitionType()) {
case MIGRATE_ENTITLEMENT:
// TODO do nothing for now
- break;
+ break;
case CREATE:
bstRecorder.subscriptionCreated(event);
- break;
+ break;
case CANCEL:
bstRecorder.subscriptionCancelled(event);
break;
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransition.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransition.java
index 8da7ff0..6c3a393 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransition.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransition.java
@@ -18,6 +18,8 @@ package com.ning.billing.analytics;
import org.joda.time.DateTime;
+import java.util.UUID;
+
/**
* Describe a state change between two BusinessSubscription
* <p/>
@@ -25,6 +27,7 @@ import org.joda.time.DateTime;
*/
public class BusinessSubscriptionTransition
{
+ private final UUID id;
private final String key;
private final String accountKey;
private final DateTime requestedTimestamp;
@@ -32,8 +35,11 @@ public class BusinessSubscriptionTransition
private final BusinessSubscription previousSubscription;
private final BusinessSubscription nextSubscription;
- public BusinessSubscriptionTransition(final String key, final String accountKey, final DateTime requestedTimestamp, final BusinessSubscriptionEvent event, final BusinessSubscription previousSubscription, final BusinessSubscription nextsubscription)
+ public BusinessSubscriptionTransition(final UUID id, final String key, final String accountKey, final DateTime requestedTimestamp, final BusinessSubscriptionEvent event, final BusinessSubscription previousSubscription, final BusinessSubscription nextsubscription)
{
+ if (id == null) {
+ throw new IllegalArgumentException("An event must have an id");
+ }
if (key == null) {
throw new IllegalArgumentException("An event must have an key");
}
@@ -47,6 +53,7 @@ public class BusinessSubscriptionTransition
throw new IllegalArgumentException("No event specified");
}
+ this.id = id;
this.key = key;
this.accountKey = accountKey;
this.requestedTimestamp = requestedTimestamp;
@@ -55,6 +62,11 @@ public class BusinessSubscriptionTransition
this.nextSubscription = nextsubscription;
}
+ public UUID getId()
+ {
+ return id;
+ }
+
public BusinessSubscriptionEvent getEvent()
{
return event;
@@ -90,10 +102,11 @@ public class BusinessSubscriptionTransition
{
final StringBuilder sb = new StringBuilder();
sb.append("BusinessSubscriptionTransition");
- sb.append("{event=").append(event);
+ sb.append("{accountKey='").append(accountKey).append('\'');
+ sb.append(", id=").append(id);
sb.append(", key='").append(key).append('\'');
- sb.append(", accountKey='").append(accountKey).append('\'');
sb.append(", requestedTimestamp=").append(requestedTimestamp);
+ sb.append(", event=").append(event);
sb.append(", previousSubscription=").append(previousSubscription);
sb.append(", nextSubscription=").append(nextSubscription);
sb.append('}');
@@ -112,13 +125,16 @@ public class BusinessSubscriptionTransition
final BusinessSubscriptionTransition that = (BusinessSubscriptionTransition) o;
+ if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != null) {
+ return false;
+ }
if (event != null ? !event.equals(that.event) : that.event != null) {
return false;
}
- if (key != null ? !key.equals(that.key) : that.key != null) {
+ if (id != null ? !id.equals(that.id) : that.id != null) {
return false;
}
- if (accountKey != null ? !accountKey.equals(that.accountKey) : that.accountKey != null) {
+ if (key != null ? !key.equals(that.key) : that.key != null) {
return false;
}
if (nextSubscription != null ? !nextSubscription.equals(that.nextSubscription) : that.nextSubscription != null) {
@@ -137,7 +153,8 @@ public class BusinessSubscriptionTransition
@Override
public int hashCode()
{
- int result = key != null ? key.hashCode() : 0;
+ int result = id != null ? id.hashCode() : 0;
+ result = 31 * result + (key != null ? key.hashCode() : 0);
result = 31 * result + (accountKey != null ? accountKey.hashCode() : 0);
result = 31 * result + (requestedTimestamp != null ? requestedTimestamp.hashCode() : 0);
result = 31 * result + (event != null ? event.hashCode() : 0);
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
index 0384fab..438850f 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
@@ -30,6 +30,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
+import java.util.UUID;
public class BusinessSubscriptionTransitionRecorder
{
@@ -47,37 +48,45 @@ public class BusinessSubscriptionTransitionRecorder
this.accountApi = accountApi;
}
- public void subscriptionCreated(final SubscriptionTransition created) throws AccountApiException {
+ public void subscriptionCreated(final SubscriptionTransition created) throws AccountApiException
+ {
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionCreated(created.getNextPlan());
recordTransition(event, created);
}
- public void subscriptionCancelled(final SubscriptionTransition cancelled) throws AccountApiException {
- final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionCancelled(cancelled.getNextPlan());
+ public void subscriptionCancelled(final SubscriptionTransition cancelled) throws AccountApiException
+ {
+ // cancelled.getNextPlan() is null here - need to look at the previous one to create the correct event name
+ final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionCancelled(cancelled.getPreviousPlan());
recordTransition(event, cancelled);
}
- public void subscriptionChanged(final SubscriptionTransition changed) throws AccountApiException {
+ public void subscriptionChanged(final SubscriptionTransition changed) throws AccountApiException
+ {
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionChanged(changed.getNextPlan());
recordTransition(event, changed);
}
- public void subscriptionPaused(final SubscriptionTransition paused) throws AccountApiException {
+ public void subscriptionPaused(final SubscriptionTransition paused) throws AccountApiException
+ {
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionPaused(paused.getNextPlan());
recordTransition(event, paused);
}
- public void subscriptionResumed(final SubscriptionTransition resumed) throws AccountApiException {
+ public void subscriptionResumed(final SubscriptionTransition resumed) throws AccountApiException
+ {
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionResumed(resumed.getNextPlan());
recordTransition(event, resumed);
}
- public void subscriptionPhaseChanged(final SubscriptionTransition phaseChanged) throws AccountApiException {
+ public void subscriptionPhaseChanged(final SubscriptionTransition phaseChanged) throws AccountApiException
+ {
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionPhaseChanged(phaseChanged.getNextPlan(), phaseChanged.getNextState());
recordTransition(event, phaseChanged);
}
- public void recordTransition(final BusinessSubscriptionEvent event, final SubscriptionTransition transition) throws AccountApiException {
+ public void recordTransition(final BusinessSubscriptionEvent event, final SubscriptionTransition transition) throws AccountApiException
+ {
Currency currency = null;
String transitionKey = null;
String accountKey = null;
@@ -113,15 +122,24 @@ public class BusinessSubscriptionTransitionRecorder
else {
prevSubscription = new BusinessSubscription(transition.getPreviousPriceList(), transition.getPreviousPlan(), transition.getPreviousPhase(), currency, previousEffectiveTransitionTime, transition.getPreviousState(), transition.getSubscriptionId(), transition.getBundleId());
}
- final BusinessSubscription nextSubscription = new BusinessSubscription(transition.getNextPriceList(), transition.getNextPlan(), transition.getNextPhase(), currency, transition.getEffectiveTransitionTime(), transition.getNextState(), transition.getSubscriptionId(), transition.getBundleId());
+ final BusinessSubscription nextSubscription;
+
+ // next plan is null for CANCEL events
+ if (transition.getNextPlan() == null) {
+ nextSubscription = null;
+ }
+ else {
+ nextSubscription = new BusinessSubscription(transition.getNextPriceList(), transition.getNextPlan(), transition.getNextPhase(), currency, transition.getEffectiveTransitionTime(), transition.getNextState(), transition.getSubscriptionId(), transition.getBundleId());
+ }
- record(transitionKey, accountKey, transition.getRequestedTransitionTime(), event, prevSubscription, nextSubscription);
+ record(transition.getId(), transitionKey, accountKey, transition.getRequestedTransitionTime(), event, prevSubscription, nextSubscription);
}
// Public for internal reasons
- public void record(final String key, final String accountKey, final DateTime requestedDateTime, final BusinessSubscriptionEvent event, final BusinessSubscription prevSubscription, final BusinessSubscription nextSubscription)
+ public void record(final UUID id, final String key, final String accountKey, final DateTime requestedDateTime, final BusinessSubscriptionEvent event, final BusinessSubscription prevSubscription, final BusinessSubscription nextSubscription)
{
final BusinessSubscriptionTransition transition = new BusinessSubscriptionTransition(
+ id,
key,
accountKey,
requestedDateTime,
diff --git a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java
index 374f296..b769e5a 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java
@@ -43,6 +43,7 @@ public @interface BusinessSubscriptionTransitionBinder
{
public void bind(final SQLStatement q, final BusinessSubscriptionTransitionBinder bind, final BusinessSubscriptionTransition arg)
{
+ q.bind("event_id", arg.getId().toString());
q.bind("event_key", arg.getKey());
q.bind("account_key", arg.getAccountKey());
q.bind("requested_timestamp", arg.getRequestedTimestamp().getMillis());
diff --git a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionMapper.java b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionMapper.java
index a31d104..ed41ab5 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionMapper.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionMapper.java
@@ -38,20 +38,20 @@ public class BusinessSubscriptionTransitionMapper implements ResultSetMapper<Bus
public BusinessSubscriptionTransition map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException
{
BusinessSubscription prev = new BusinessSubscription(
- r.getString(5), // productName
- r.getString(6), // productType
- r.getString(7) == null ? null : ProductCategory.valueOf(r.getString(7)), // productCategory
- r.getString(8), // slug
- r.getString(9), // phase
- r.getString(10), // billing period
- BigDecimal.valueOf(r.getDouble(11)), // price
- r.getString(12), // priceList
- BigDecimal.valueOf(r.getDouble(13)), // mrr
- r.getString(14), // currency
- r.getLong(15) == 0 ? null : new DateTime(r.getLong(15), DateTimeZone.UTC), // startDate
- r.getString(16) == null ? null : SubscriptionState.valueOf(r.getString(16)), // state
- r.getString(17) == null ? null : UUID.fromString(r.getString(17)), // subscriptionId
- r.getString(18) == null ? null : UUID.fromString(r.getString(18)) //bundleId
+ r.getString(6), // productName
+ r.getString(7), // productType
+ r.getString(8) == null ? null : ProductCategory.valueOf(r.getString(8)), // productCategory
+ r.getString(9), // slug
+ r.getString(10), // phase
+ r.getString(11), // billing period
+ BigDecimal.valueOf(r.getDouble(12)), // price
+ r.getString(13), // priceList
+ BigDecimal.valueOf(r.getDouble(14)), // mrr
+ r.getString(15), // currency
+ r.getLong(16) == 0 ? null : new DateTime(r.getLong(16), DateTimeZone.UTC), // startDate
+ r.getString(17) == null ? null : SubscriptionState.valueOf(r.getString(17)), // state
+ r.getString(18) == null ? null : UUID.fromString(r.getString(18)), // subscriptionId
+ r.getString(19) == null ? null : UUID.fromString(r.getString(19)) //bundleId
);
// Avoid creating a dummy subscriptions with all null fields
@@ -60,20 +60,20 @@ public class BusinessSubscriptionTransitionMapper implements ResultSetMapper<Bus
}
BusinessSubscription next = new BusinessSubscription(
- r.getString(19), // productName
- r.getString(20), // productType
- r.getString(21) == null ? null : ProductCategory.valueOf(r.getString(21)), // productCategory
- r.getString(22), // slug8
- r.getString(23), // phase
- r.getString(24), // billing period
- BigDecimal.valueOf(r.getDouble(25)), // price
- r.getString(26), // priceList
- BigDecimal.valueOf(r.getDouble(27)), // mrr
- r.getString(28), // currency
- r.getLong(29) == 0 ? null : new DateTime(r.getLong(29), DateTimeZone.UTC), // startDate
- r.getString(30) == null ? null : SubscriptionState.valueOf(r.getString(30)), // state
- r.getString(31) == null ? null : UUID.fromString(r.getString(31)), // subscriptionId
- r.getString(32) == null ? null : UUID.fromString(r.getString(32)) //bundleId
+ r.getString(20), // productName
+ r.getString(21), // productType
+ r.getString(22) == null ? null : ProductCategory.valueOf(r.getString(22)), // productCategory
+ r.getString(23), // slug8
+ r.getString(24), // phase
+ r.getString(25), // billing period
+ BigDecimal.valueOf(r.getDouble(26)), // price
+ r.getString(27), // priceList
+ BigDecimal.valueOf(r.getDouble(28)), // mrr
+ r.getString(29), // currency
+ r.getLong(30) == 0 ? null : new DateTime(r.getLong(30), DateTimeZone.UTC), // startDate
+ r.getString(31) == null ? null : SubscriptionState.valueOf(r.getString(31)), // state
+ r.getString(32) == null ? null : UUID.fromString(r.getString(32)), // subscriptionId
+ r.getString(33) == null ? null : UUID.fromString(r.getString(33)) //bundleId
);
// Avoid creating a dummy subscriptions with all null fields
@@ -81,12 +81,13 @@ public class BusinessSubscriptionTransitionMapper implements ResultSetMapper<Bus
next = null;
}
- final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.valueOf(r.getString(4));
+ final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.valueOf(r.getString(5));
return new BusinessSubscriptionTransition(
- r.getString(1),
+ UUID.fromString(r.getString(1)),
r.getString(2),
- new DateTime(r.getLong(3), DateTimeZone.UTC),
+ r.getString(3),
+ new DateTime(r.getLong(4), DateTimeZone.UTC),
event,
prev,
next
diff --git a/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDao.sql.stg b/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDao.sql.stg
index 1654b5b..de6076e 100644
--- a/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDao.sql.stg
+++ b/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionDao.sql.stg
@@ -2,7 +2,8 @@ group BusinessSubscriptionTransition;
getTransitions(event_key) ::= <<
select
- event_key
+ event_id
+ , event_key
, account_key
, requested_timestamp
, event
@@ -41,8 +42,9 @@ getTransitions(event_key) ::= <<
>>
createTransition() ::= <<
- insert into bst(
- event_key
+ insert ignore into bst(
+ event_id
+ , event_key
, account_key
, requested_timestamp
, event
@@ -75,7 +77,8 @@ createTransition() ::= <<
, next_subscription_id
, next_bundle_id
) values (
- :event_key
+ :event_id
+ , :event_key
, :account_key
, :requested_timestamp
, :event
diff --git a/analytics/src/main/resources/com/ning/billing/analytics/ddl.sql b/analytics/src/main/resources/com/ning/billing/analytics/ddl.sql
index 49e48f0..6489b12 100644
--- a/analytics/src/main/resources/com/ning/billing/analytics/ddl.sql
+++ b/analytics/src/main/resources/com/ning/billing/analytics/ddl.sql
@@ -1,6 +1,7 @@
drop table if exists bst;
create table bst (
- event_key varchar(50) not null
+ event_id char(36) not null
+, event_key varchar(50) not null
, account_key varchar(50) not null
, requested_timestamp bigint not null
, event varchar(50) not null
@@ -32,6 +33,7 @@ create table bst (
, next_state varchar(32) default null
, next_subscription_id varchar(100) default null
, next_bundle_id varchar(100) default null
+, primary key(event_id)
) engine=innodb;
create index bst_key_index on bst (event_key, requested_timestamp asc);
diff --git a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
index 6054529..d869e88 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
@@ -72,6 +72,7 @@ import static org.testng.Assert.fail;
@Guice(modules = AnalyticsTestModule.class)
public class TestAnalyticsService
{
+ private static final UUID ID = UUID.randomUUID();
private static final String KEY = "12345";
private static final String ACCOUNT_KEY = "pierre-12345";
private static final DefaultTagDefinition TAG_ONE = new DefaultTagDefinition("batch20", "something", "pierre", new DateTime(DateTimeZone.UTC));
@@ -165,7 +166,7 @@ public class TestAnalyticsService
final String priceList = "something";
transition = new SubscriptionTransitionData(
- UUID.randomUUID(),
+ ID,
subscriptionId,
bundle.getId(),
EntitlementEvent.EventType.API_USER,
@@ -182,6 +183,7 @@ public class TestAnalyticsService
priceList
);
expectedTransition = new BusinessSubscriptionTransition(
+ ID,
KEY,
ACCOUNT_KEY,
requestedTransitionTime,
diff --git a/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java b/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java
index c17cdd4..a9a5422 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java
@@ -52,6 +52,7 @@ import java.util.UUID;
public class TestAnalyticsDao
{
+ private static final UUID EVENT_ID = UUID.randomUUID();
private static final String EVENT_KEY = "12345";
private static final String ACCOUNT_KEY = "pierre-143343-vcc";
@@ -84,7 +85,7 @@ public class TestAnalyticsDao
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionCancelled(plan);
final DateTime requestedTimestamp = new DateTime(DateTimeZone.UTC);
- transition = new BusinessSubscriptionTransition(EVENT_KEY, ACCOUNT_KEY, requestedTimestamp, event, prevSubscription, nextSubscription);
+ transition = new BusinessSubscriptionTransition(EVENT_ID, EVENT_KEY, ACCOUNT_KEY, requestedTimestamp, event, prevSubscription, nextSubscription);
final IDBI dbi = helper.getDBI();
businessSubscriptionTransitionDao = dbi.onDemand(BusinessSubscriptionTransitionDao.class);
@@ -130,9 +131,50 @@ public class TestAnalyticsDao
}
@Test(groups = "slow")
+ public void testHandleDuplicatedEvents()
+ {
+ final BusinessSubscriptionTransition transitionWithNullPrev = new BusinessSubscriptionTransition(
+ transition.getId(),
+ transition.getKey(),
+ transition.getAccountKey(),
+ transition.getRequestedTimestamp(),
+ transition.getEvent(),
+ null,
+ transition.getNextSubscription()
+ );
+
+ businessSubscriptionTransitionDao.createTransition(transitionWithNullPrev);
+ List<BusinessSubscriptionTransition> transitions = businessSubscriptionTransitionDao.getTransitions(EVENT_KEY);
+ Assert.assertEquals(transitions.size(), 1);
+ Assert.assertEquals(transitions.get(0), transitionWithNullPrev);
+ // Try to add the same transition, with the same UUID - we should only store one though
+ businessSubscriptionTransitionDao.createTransition(transitionWithNullPrev);
+ transitions = businessSubscriptionTransitionDao.getTransitions(EVENT_KEY);
+ Assert.assertEquals(transitions.size(), 1);
+ Assert.assertEquals(transitions.get(0), transitionWithNullPrev);
+
+ // Try now to store a look-alike transition (same fields except UUID) - we should store it this time
+ final BusinessSubscriptionTransition secondTransitionWithNullPrev = new BusinessSubscriptionTransition(
+ UUID.randomUUID(),
+ transition.getKey(),
+ transition.getAccountKey(),
+ transition.getRequestedTimestamp(),
+ transition.getEvent(),
+ null,
+ transition.getNextSubscription()
+ );
+ businessSubscriptionTransitionDao.createTransition(secondTransitionWithNullPrev);
+ transitions = businessSubscriptionTransitionDao.getTransitions(EVENT_KEY);
+ Assert.assertEquals(transitions.size(), 2);
+ Assert.assertTrue(transitions.contains(transitionWithNullPrev));
+ Assert.assertTrue(transitions.contains(secondTransitionWithNullPrev));
+ }
+
+ @Test(groups = "slow")
public void testTransitionsWithNullPrevSubscription()
{
final BusinessSubscriptionTransition transitionWithNullPrev = new BusinessSubscriptionTransition(
+ transition.getId(),
transition.getKey(),
transition.getAccountKey(),
transition.getRequestedTimestamp(),
@@ -151,6 +193,7 @@ public class TestAnalyticsDao
public void testTransitionsWithNullNextSubscription()
{
final BusinessSubscriptionTransition transitionWithNullNext = new BusinessSubscriptionTransition(
+ transition.getId(),
transition.getKey(),
transition.getAccountKey(),
transition.getRequestedTimestamp(),
@@ -170,6 +213,7 @@ public class TestAnalyticsDao
{
final BusinessSubscription subscriptionWithNullFields = new BusinessSubscription(null, plan, phase, Currency.USD, null, null, null, null);
final BusinessSubscriptionTransition transitionWithNullFields = new BusinessSubscriptionTransition(
+ transition.getId(),
transition.getKey(),
transition.getAccountKey(),
transition.getRequestedTimestamp(),
@@ -189,6 +233,7 @@ public class TestAnalyticsDao
{
final BusinessSubscription subscriptionWithNullPlanAndPhase = new BusinessSubscription(null, null, null, Currency.USD, null, null, null, null);
final BusinessSubscriptionTransition transitionWithNullPlanAndPhase = new BusinessSubscriptionTransition(
+ transition.getId(),
transition.getKey(),
transition.getAccountKey(),
transition.getRequestedTimestamp(),
@@ -213,6 +258,7 @@ public class TestAnalyticsDao
{
final BusinessSubscription subscriptionWithNullPlan = new BusinessSubscription(null, null, phase, Currency.USD, null, null, null, null);
final BusinessSubscriptionTransition transitionWithNullPlan = new BusinessSubscriptionTransition(
+ transition.getId(),
transition.getKey(),
transition.getAccountKey(),
transition.getRequestedTimestamp(),
@@ -233,6 +279,7 @@ public class TestAnalyticsDao
{
final BusinessSubscription subscriptionWithNullPhase = new BusinessSubscription(null, plan, null, Currency.USD, null, null, null, null);
final BusinessSubscriptionTransition transitionWithNullPhase = new BusinessSubscriptionTransition(
+ transition.getId(),
transition.getKey(),
transition.getAccountKey(),
transition.getRequestedTimestamp(),
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java b/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
index ec6d9ae..a9a8293 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
@@ -17,8 +17,6 @@
package com.ning.billing.analytics;
-import java.util.UUID;
-
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.Plan;
@@ -30,13 +28,14 @@ import com.ning.billing.entitlement.api.user.SubscriptionTransitionData;
import com.ning.billing.entitlement.events.EntitlementEvent;
import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.util.clock.ClockMock;
-
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import java.util.UUID;
+
public class TestAnalyticsListener
{
@@ -68,7 +67,7 @@ public class TestAnalyticsListener
final DateTime effectiveTransitionTime = new DateTime(DateTimeZone.UTC);
final DateTime requestedTransitionTime = new DateTime(DateTimeZone.UTC);
final SubscriptionTransitionData firstTransition = createFirstSubscriptionTransition(requestedTransitionTime, effectiveTransitionTime);
- final BusinessSubscriptionTransition firstBST = createExpectedFirstBST(requestedTransitionTime, effectiveTransitionTime);
+ final BusinessSubscriptionTransition firstBST = createExpectedFirstBST(firstTransition.getId(), requestedTransitionTime, effectiveTransitionTime);
listener.handleSubscriptionTransitionChange(firstTransition);
Assert.assertEquals(dao.getTransitions(KEY).size(), 1);
Assert.assertEquals(dao.getTransitions(KEY).get(0), firstBST);
@@ -77,7 +76,7 @@ public class TestAnalyticsListener
final DateTime effectivePauseTransitionTime = new DateTime(DateTimeZone.UTC);
final DateTime requestedPauseTransitionTime = new DateTime(DateTimeZone.UTC);
final SubscriptionTransitionData pausedSubscriptionTransition = createPauseSubscriptionTransition(effectivePauseTransitionTime, requestedPauseTransitionTime, firstTransition.getNextState());
- final BusinessSubscriptionTransition pausedBST = createExpectedPausedBST(requestedPauseTransitionTime, effectivePauseTransitionTime, firstBST.getNextSubscription());
+ final BusinessSubscriptionTransition pausedBST = createExpectedPausedBST(pausedSubscriptionTransition.getId(), requestedPauseTransitionTime, effectivePauseTransitionTime, firstBST.getNextSubscription());
listener.handleSubscriptionTransitionChange(pausedSubscriptionTransition);
Assert.assertEquals(dao.getTransitions(KEY).size(), 2);
Assert.assertEquals(dao.getTransitions(KEY).get(1), pausedBST);
@@ -86,7 +85,7 @@ public class TestAnalyticsListener
final DateTime effectiveResumeTransitionTime = new DateTime(DateTimeZone.UTC);
final DateTime requestedResumeTransitionTime = new DateTime(DateTimeZone.UTC);
final SubscriptionTransitionData resumedSubscriptionTransition = createResumeSubscriptionTransition(requestedResumeTransitionTime, effectiveResumeTransitionTime, pausedSubscriptionTransition.getNextState());
- final BusinessSubscriptionTransition resumedBST = createExpectedResumedBST(requestedResumeTransitionTime, effectiveResumeTransitionTime, pausedBST.getNextSubscription());
+ final BusinessSubscriptionTransition resumedBST = createExpectedResumedBST(resumedSubscriptionTransition.getId(), requestedResumeTransitionTime, effectiveResumeTransitionTime, pausedBST.getNextSubscription());
listener.handleSubscriptionTransitionChange(resumedSubscriptionTransition);
Assert.assertEquals(dao.getTransitions(KEY).size(), 3);
Assert.assertEquals(dao.getTransitions(KEY).get(2), resumedBST);
@@ -94,41 +93,42 @@ public class TestAnalyticsListener
// Cancel it
final DateTime effectiveCancelTransitionTime = new DateTime(DateTimeZone.UTC);
final DateTime requestedCancelTransitionTime = new DateTime(DateTimeZone.UTC);
- listener.handleSubscriptionTransitionChange(createCancelSubscriptionTransition(requestedCancelTransitionTime, effectiveCancelTransitionTime, resumedSubscriptionTransition.getNextState()));
- final BusinessSubscriptionTransition cancelledBST = createExpectedCancelledBST(requestedCancelTransitionTime, effectiveCancelTransitionTime, resumedBST.getNextSubscription());
+ final SubscriptionTransitionData cancelledSubscriptionTransition = createCancelSubscriptionTransition(requestedCancelTransitionTime, effectiveCancelTransitionTime, resumedSubscriptionTransition.getNextState());
+ final BusinessSubscriptionTransition cancelledBST = createExpectedCancelledBST(cancelledSubscriptionTransition.getId(), requestedCancelTransitionTime, effectiveCancelTransitionTime, resumedBST.getNextSubscription());
+ listener.handleSubscriptionTransitionChange(cancelledSubscriptionTransition);
Assert.assertEquals(dao.getTransitions(KEY).size(), 4);
Assert.assertEquals(dao.getTransitions(KEY).get(3), cancelledBST);
}
- private BusinessSubscriptionTransition createExpectedFirstBST(final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime)
+ private BusinessSubscriptionTransition createExpectedFirstBST(final UUID id, final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime)
{
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionCreated(plan);
final Subscription.SubscriptionState subscriptionState = Subscription.SubscriptionState.ACTIVE;
- return createExpectedBST(event, requestedTransitionTime, effectiveTransitionTime, null, subscriptionState);
+ return createExpectedBST(id, event, requestedTransitionTime, effectiveTransitionTime, null, subscriptionState);
}
- private BusinessSubscriptionTransition createExpectedPausedBST(final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime, final BusinessSubscription lastSubscription)
+ private BusinessSubscriptionTransition createExpectedPausedBST(final UUID id, final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime, final BusinessSubscription lastSubscription)
{
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionPaused(plan);
final Subscription.SubscriptionState subscriptionState = Subscription.SubscriptionState.PAUSED;
- return createExpectedBST(event, requestedTransitionTime, effectiveTransitionTime, lastSubscription, subscriptionState);
+ return createExpectedBST(id, event, requestedTransitionTime, effectiveTransitionTime, lastSubscription, subscriptionState);
}
- private BusinessSubscriptionTransition createExpectedResumedBST(final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime, final BusinessSubscription lastSubscription)
+ private BusinessSubscriptionTransition createExpectedResumedBST(final UUID id, final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime, final BusinessSubscription lastSubscription)
{
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionResumed(plan);
final Subscription.SubscriptionState nextState = Subscription.SubscriptionState.ACTIVE;
- return createExpectedBST(event, requestedTransitionTime, effectiveTransitionTime, lastSubscription, nextState);
+ return createExpectedBST(id, event, requestedTransitionTime, effectiveTransitionTime, lastSubscription, nextState);
}
- private BusinessSubscriptionTransition createExpectedCancelledBST(final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime, final BusinessSubscription lastSubscription)
+ private BusinessSubscriptionTransition createExpectedCancelledBST(final UUID id, final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime, final BusinessSubscription lastSubscription)
{
final BusinessSubscriptionEvent event = BusinessSubscriptionEvent.subscriptionCancelled(plan);
- final Subscription.SubscriptionState nextState = Subscription.SubscriptionState.CANCELLED;
- return createExpectedBST(event, requestedTransitionTime, effectiveTransitionTime, lastSubscription, nextState);
+ return createExpectedBST(id, event, requestedTransitionTime, effectiveTransitionTime, lastSubscription, null);
}
private BusinessSubscriptionTransition createExpectedBST(
+ final UUID eventId,
final BusinessSubscriptionEvent eventType,
final DateTime requestedTransitionTime,
final DateTime effectiveTransitionTime,
@@ -137,12 +137,13 @@ public class TestAnalyticsListener
)
{
return new BusinessSubscriptionTransition(
+ eventId,
KEY,
ACCOUNT_KEY,
requestedTransitionTime,
eventType,
previousSubscription,
- new BusinessSubscription(
+ nextState == null ? null : new BusinessSubscription(
null,
plan,
phase,
@@ -195,8 +196,24 @@ public class TestAnalyticsListener
private SubscriptionTransitionData createCancelSubscriptionTransition(final DateTime requestedTransitionTime, final DateTime effectiveTransitionTime, final Subscription.SubscriptionState previousState)
{
final ApiEventType eventType = ApiEventType.CANCEL;
- final Subscription.SubscriptionState nextState = Subscription.SubscriptionState.CANCELLED;
- return createSubscriptionTransition(eventType, requestedTransitionTime, effectiveTransitionTime, previousState, nextState);
+ // next state is null for canceled events
+ return new SubscriptionTransitionData(
+ UUID.randomUUID(),
+ subscriptionId,
+ bundleUUID,
+ EntitlementEvent.EventType.API_USER,
+ eventType,
+ requestedTransitionTime,
+ effectiveTransitionTime,
+ previousState,
+ plan,
+ phase,
+ priceList,
+ null,
+ null,
+ null,
+ null
+ );
}
private SubscriptionTransitionData createSubscriptionTransition(
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java
index a8a954c..3b33bef 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java
@@ -28,6 +28,8 @@ import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import java.util.UUID;
+
import static com.ning.billing.catalog.api.Currency.USD;
public class TestBusinessSubscriptionTransition
@@ -36,6 +38,7 @@ public class TestBusinessSubscriptionTransition
private BusinessSubscription nextSubscription;
private BusinessSubscriptionEvent event;
private DateTime requestedTimestamp;
+ private UUID id;
private String key;
private String accountKey;
private BusinessSubscriptionTransition transition;
@@ -53,9 +56,10 @@ public class TestBusinessSubscriptionTransition
nextSubscription = new BusinessSubscription(nextISubscription, USD);
event = BusinessSubscriptionEvent.subscriptionCancelled(prevISubscription.getCurrentPlan());
requestedTimestamp = new DateTime(DateTimeZone.UTC);
+ id = UUID.randomUUID();
key = "1234";
accountKey = "pierre-1234";
- transition = new BusinessSubscriptionTransition(key, accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
+ transition = new BusinessSubscriptionTransition(id, key, accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
}
@Test(groups = "fast")
@@ -76,22 +80,22 @@ public class TestBusinessSubscriptionTransition
BusinessSubscriptionTransition otherTransition;
- otherTransition = new BusinessSubscriptionTransition(key, accountKey, new DateTime(), event, prevSubscription, nextSubscription);
+ otherTransition = new BusinessSubscriptionTransition(id, key, accountKey, new DateTime(), event, prevSubscription, nextSubscription);
Assert.assertTrue(!transition.equals(otherTransition));
- otherTransition = new BusinessSubscriptionTransition("12345", accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
+ otherTransition = new BusinessSubscriptionTransition(id, "12345", accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
Assert.assertTrue(!transition.equals(otherTransition));
- otherTransition = new BusinessSubscriptionTransition(key, accountKey, requestedTimestamp, BusinessSubscriptionEvent.subscriptionPaused(null), prevSubscription, nextSubscription);
+ otherTransition = new BusinessSubscriptionTransition(id, key, accountKey, requestedTimestamp, BusinessSubscriptionEvent.subscriptionPaused(null), prevSubscription, nextSubscription);
Assert.assertTrue(!transition.equals(otherTransition));
- otherTransition = new BusinessSubscriptionTransition(key, accountKey, requestedTimestamp, event, prevSubscription, prevSubscription);
+ otherTransition = new BusinessSubscriptionTransition(id, key, accountKey, requestedTimestamp, event, prevSubscription, prevSubscription);
Assert.assertTrue(!transition.equals(otherTransition));
- otherTransition = new BusinessSubscriptionTransition(key, accountKey, requestedTimestamp, event, nextSubscription, nextSubscription);
+ otherTransition = new BusinessSubscriptionTransition(id, key, accountKey, requestedTimestamp, event, nextSubscription, nextSubscription);
Assert.assertTrue(!transition.equals(otherTransition));
- otherTransition = new BusinessSubscriptionTransition(key, accountKey, requestedTimestamp, event, nextSubscription, prevSubscription);
+ otherTransition = new BusinessSubscriptionTransition(id, key, accountKey, requestedTimestamp, event, nextSubscription, prevSubscription);
Assert.assertTrue(!transition.equals(otherTransition));
}
@@ -99,7 +103,15 @@ public class TestBusinessSubscriptionTransition
public void testRejectInvalidTransitions() throws Exception
{
try {
- new BusinessSubscriptionTransition(null, accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
+ new BusinessSubscriptionTransition(null, key, accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
+ Assert.fail();
+ }
+ catch (IllegalArgumentException e) {
+ Assert.assertTrue(true);
+ }
+
+ try {
+ new BusinessSubscriptionTransition(id, null, accountKey, requestedTimestamp, event, prevSubscription, nextSubscription);
Assert.fail();
}
catch (IllegalArgumentException e) {
@@ -107,7 +119,7 @@ public class TestBusinessSubscriptionTransition
}
try {
- new BusinessSubscriptionTransition(key, accountKey, null, event, prevSubscription, nextSubscription);
+ new BusinessSubscriptionTransition(id, key, accountKey, null, event, prevSubscription, nextSubscription);
Assert.fail();
}
catch (IllegalArgumentException e) {
@@ -115,7 +127,7 @@ public class TestBusinessSubscriptionTransition
}
try {
- new BusinessSubscriptionTransition(key, accountKey, requestedTimestamp, null, prevSubscription, nextSubscription);
+ new BusinessSubscriptionTransition(id, key, accountKey, requestedTimestamp, null, prevSubscription, nextSubscription);
Assert.fail();
}
catch (IllegalArgumentException e) {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
index 0f5375b..a2e6839 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
@@ -125,7 +125,7 @@ public class Engine implements EventListener, EntitlementService {
}
@Override
public long getDaoClaimTimeMs() {
- return config.getDaoMaxReadyEvents();
+ return config.getDaoClaimTimeMs();
}
});
} catch (NotificationQueueAlreadyExists e) {
diff --git a/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java b/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java
index 0dd5e3a..5107d71 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java
@@ -48,15 +48,15 @@ public class DefaultNextBillingDateNotifier implements NextBillingDateNotifier
private final EntitlementDao entitlementDao;
private NotificationQueue nextBillingQueue;
- private InvoiceListener listener;
+ private final InvoiceListener listener;
@Inject
- public DefaultNextBillingDateNotifier(NotificationQueueService notificationQueueService,
+ public DefaultNextBillingDateNotifier(NotificationQueueService notificationQueueService,
InvoiceConfig config, EntitlementDao entitlementDao, InvoiceListener listener){
this.notificationQueueService = notificationQueueService;
this.config = config;
this.entitlementDao = entitlementDao;
- this.listener = listener;
+ this.listener = listener;
}
@Override
@@ -97,7 +97,7 @@ public class DefaultNextBillingDateNotifier implements NextBillingDateNotifier
}
@Override
public long getDaoClaimTimeMs() {
- return config.getDaoMaxReadyEvents();
+ return config.getDaoClaimTimeMs();
}
});
} catch (NotificationQueueAlreadyExists e) {
@@ -121,5 +121,5 @@ public class DefaultNextBillingDateNotifier implements NextBillingDateNotifier
listener.handleNextBillingDateEvent(subscriptionId, eventDateTime);
}
-
+
}
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueBase.java b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueBase.java
index cc1ea28..a4f4c97 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueBase.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueBase.java
@@ -182,6 +182,11 @@ public abstract class NotificationQueueBase implements NotificationQueue {
waitForNotificationStartCompletion();
}
+ @Override
+ public String toString() {
+ return getFullQName();
+ }
+
private void completedQueueStop() {
synchronized (this) {
stoppedComplete = true;