killbill-aplcache
Changes
meter/pom.xml 109(+109 -0)
meter/README.md 5(+5 -0)
meter/src/main/java/com/ning/billing/meter/timeline/aggregator/TimelineAggregatorSqlDao.java 2(+1 -1)
meter/src/main/java/com/ning/billing/meter/timeline/categories/CategoryAndMetricsForSources.java 2(+1 -1)
meter/src/main/java/com/ning/billing/meter/timeline/categories/CategoryIdAndMetricBinder.java 4(+2 -2)
meter/src/main/java/com/ning/billing/meter/timeline/categories/CategoryIdAndMetricMapper.java 2(+1 -1)
meter/src/main/java/com/ning/billing/meter/timeline/persistent/StreamyBytesPersistentOutputStream.java 2(+1 -1)
meter/src/main/resources/com/ning/billing/meter/timeline/aggregator/TimelineAggregatorSqlDao.sql.stg 0(+0 -0)
meter/src/main/resources/com/ning/billing/meter/timeline/persistent/TimelineSqlDao.sql.stg 16(+8 -8)
meter/src/test/java/com/ning/billing/meter/timeline/chunks/TestTimeBytesAndSampleBytes.java 6(+3 -3)
meter/src/test/java/com/ning/billing/meter/timeline/codec/TestEncodedBytesAndSampleCount.java 6(+3 -3)
meter/src/test/java/com/ning/billing/meter/timeline/codec/TestTimelineChunkAccumulator.java 19(+9 -10)
meter/src/test/java/com/ning/billing/meter/timeline/metrics/TestSamplesForMetricAndSource.java 6(+3 -3)
pom.xml 6(+6 -0)
server/pom.xml 8(+8 -0)
usage/pom.xml 16(+0 -16)
usage/README.md 5(+5 -0)
Details
diff --git a/api/src/main/java/com/ning/billing/meter/api/MeterUserApi.java b/api/src/main/java/com/ning/billing/meter/api/MeterUserApi.java
new file mode 100644
index 0000000..5869d67
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/meter/api/MeterUserApi.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.meter.api;
+
+import java.util.Map;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.util.callcontext.CallContext;
+
+public interface MeterUserApi {
+
+ /**
+ * Shortcut API to record a usage value of "1" for a given category and metric.
+ *
+ * @param bundleId bundle id source
+ * @param categoryName category name for this usage
+ * @param metricName metric name associated with this category
+ * @param context call context
+ */
+ public void incrementUsage(UUID bundleId, String categoryName, String metricName, DateTime timestamp, CallContext context);
+
+ /**
+ * Shortcut API to record a usage value of "1" for a given category and metric.
+ * <p/>
+ * This will also store an aggregation of all usage data across all metrics for that category.
+ * This is useful if one wants to store fine grained usage information (e.g. number of minutes used per cell phone number),
+ * while keeping a fast access path to the aggregate (e.g. number of minutes used across all cell phone numbers).
+ *
+ * @param bundleId bundle id source
+ * @param categoryName category name for this usage
+ * @param metricName metric name associated with this category
+ * @param context call context
+ */
+ public void incrementUsageAndAggregate(UUID bundleId, String categoryName, String metricName, DateTime timestamp, CallContext context);
+
+ /**
+ * Fine grained usage API. This is used to record e.g. "X has used 2 credits at 2012/02/04 4:12pm".
+ *
+ * @param bundleId bundle id source
+ * @param samplesForCategoriesAndMetrics samples per metric and category
+ * @param timestamp timestamp of this usage
+ * @param context tenant context
+ */
+ public void incrementUsage(UUID bundleId, Map<String, Map<String, Object>> samplesForCategoriesAndMetrics, DateTime timestamp, CallContext context);
+}
diff --git a/api/src/main/java/com/ning/billing/usage/api/RolledUpUsage.java b/api/src/main/java/com/ning/billing/usage/api/RolledUpUsage.java
new file mode 100644
index 0000000..8774b71
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/usage/api/RolledUpUsage.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.usage.api;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+public interface RolledUpUsage {
+
+ UUID getSubscriptionId();
+
+ String getUnitType();
+
+ DateTime getStartTime();
+
+ DateTime getEndTime();
+
+ BigDecimal getAmount();
+}
diff --git a/api/src/main/java/com/ning/billing/usage/api/UsageUserApi.java b/api/src/main/java/com/ning/billing/usage/api/UsageUserApi.java
index 8735313..296b58a 100644
--- a/api/src/main/java/com/ning/billing/usage/api/UsageUserApi.java
+++ b/api/src/main/java/com/ning/billing/usage/api/UsageUserApi.java
@@ -16,46 +16,37 @@
package com.ning.billing.usage.api;
+import java.math.BigDecimal;
import java.util.UUID;
import org.joda.time.DateTime;
-import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.TenantContext;
public interface UsageUserApi {
/**
- * Shortcut API to record a usage value of "1" for a given metric.
+ * Bulk usage API when the external system (or the meter module) rolls-up usage data.
+ * <p/>
+ * This is used to record e.g. "X has used 12 minutes of his data plan between 2012/02/04 and 2012/02/06".
*
- * @param bundleId bundle id source
- * @param metricName metric name for this usage
- * @param context call context
+ * @param subscriptionId subscription id source
+ * @param unitType unit type for this usage
+ * @param startTime start date of the usage period
+ * @param endTime end date of the usage period
+ * @param amount value to record
+ * @param context tenant context
*/
- public void incrementUsage(UUID bundleId, String metricName, CallContext context) throws EntitlementUserApiException;
+ public void recordRolledUpUsage(UUID subscriptionId, String unitType, DateTime startTime, DateTime endTime,
+ BigDecimal amount, CallContext context);
/**
- * Fine grained usage API if the external system doesn't roll its usage data. This is used to record e.g. "X has used
- * 2 credits from his plan at 2012/02/04 4:12pm".
+ * Get usage information for a given subscription.
*
- * @param bundleId bundle id source
- * @param metricName metric name for this usage
- * @param timestamp timestamp of this usage
- * @param value value to record
- * @param context tenant context
+ * @param subscriptionId subscription id
+ * @param context tenant context
+ * @return usage data (rolled-up)
*/
- public void recordUsage(UUID bundleId, String metricName, DateTime timestamp, long value, CallContext context) throws EntitlementUserApiException;
-
- /**
- * Bulk usage API if the external system rolls-up usage data. This is used to record e.g. "X has used 12 minutes
- * of his data plan between 2012/02/04 and 2012/02/06".
- *
- * @param bundleId bundle id source
- * @param metricName metric name for this usage
- * @param startDate start date of the usage period
- * @param endDate end date of the usage period
- * @param value value to record
- * @param context tenant context
- */
- public void recordRolledUpUsage(UUID bundleId, String metricName, DateTime startDate, DateTime endDate, long value, CallContext context) throws EntitlementUserApiException;
+ public RolledUpUsage getUsageForSubscription(UUID subscriptionId, TenantContext context);
}
meter/pom.xml 109(+109 -0)
diff --git a/meter/pom.xml b/meter/pom.xml
new file mode 100644
index 0000000..f9d3a62
--- /dev/null
+++ b/meter/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ~ Copyright 2010-2011 Ning, Inc. ~ ~ Ning 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. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill</artifactId>
+ <version>0.1.45-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>killbill-meter</artifactId>
+ <name>killbill-meter</name>
+ <packaging>jar</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.jdbi</groupId>
+ <artifactId>jdbi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.datatype</groupId>
+ <artifactId>jackson-datatype-joda</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.dataformat</groupId>
+ <artifactId>jackson-dataformat-smile</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.util</groupId>
+ <artifactId>low-gc-membuffers</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-util</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.skife.config</groupId>
+ <artifactId>config-magic</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>stringtemplate</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-mxj</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-mxj-db-files</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
meter/README.md 5(+5 -0)
diff --git a/meter/README.md b/meter/README.md
new file mode 100644
index 0000000..c2b0c54
--- /dev/null
+++ b/meter/README.md
@@ -0,0 +1,5 @@
+Meter
+-----
+
+The meter modules takes care of aggregating usage information (e.g. rolling up individual pageviews to a website into daily or monthly aggregates).
+See the usage module for the billing aspect.
diff --git a/meter/src/main/java/com/ning/billing/meter/api/user/DefaultMeterUserApi.java b/meter/src/main/java/com/ning/billing/meter/api/user/DefaultMeterUserApi.java
new file mode 100644
index 0000000..28024af
--- /dev/null
+++ b/meter/src/main/java/com/ning/billing/meter/api/user/DefaultMeterUserApi.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.meter.api.user;
+
+import java.util.Map;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.ObjectType;
+import com.ning.billing.meter.api.MeterUserApi;
+import com.ning.billing.meter.timeline.TimelineEventHandler;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalCallContextFactory;
+
+import com.google.common.collect.ImmutableMap;
+
+public class DefaultMeterUserApi implements MeterUserApi {
+
+ private static final String AGGREGATE_METRIC_NAME = "__AGGREGATE__";
+
+ private final TimelineEventHandler timelineEventHandler;
+ private final InternalCallContextFactory internalCallContextFactory;
+
+ @Inject
+ public DefaultMeterUserApi(final TimelineEventHandler timelineEventHandler,
+ final InternalCallContextFactory internalCallContextFactory) {
+ this.timelineEventHandler = timelineEventHandler;
+ this.internalCallContextFactory = internalCallContextFactory;
+ }
+
+ @Override
+ public void incrementUsage(final UUID bundleId, final String categoryName, final String metricName,
+ final DateTime timestamp, final CallContext context) {
+ incrementUsage(bundleId,
+ ImmutableMap.<String, Map<String, Object>>of(categoryName, ImmutableMap.<String, Object>of(metricName, (short) 1)),
+ timestamp,
+ context);
+ }
+
+ @Override
+ public void incrementUsageAndAggregate(final UUID bundleId, final String categoryName, final String metricName,
+ final DateTime timestamp, final CallContext context) {
+ incrementUsage(bundleId,
+ ImmutableMap.<String, Map<String, Object>>of(categoryName, ImmutableMap.<String, Object>of(metricName, (short) 1,
+ AGGREGATE_METRIC_NAME, (short) 1)),
+ timestamp,
+ context);
+ }
+
+ @Override
+ public void incrementUsage(final UUID bundleId, final Map<String, Map<String, Object>> samplesForCategoriesAndMetrics,
+ final DateTime timestamp, final CallContext context) {
+ final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(bundleId, ObjectType.BUNDLE, context);
+
+ for (final String category : samplesForCategoriesAndMetrics.keySet()) {
+ final String sourceName = bundleId.toString();
+ timelineEventHandler.record(sourceName, category, timestamp, samplesForCategoriesAndMetrics.get(category),
+ internalCallContext);
+ }
+ }
+}
diff --git a/meter/src/main/java/com/ning/billing/meter/glue/MeterModule.java b/meter/src/main/java/com/ning/billing/meter/glue/MeterModule.java
new file mode 100644
index 0000000..5eef3b9
--- /dev/null
+++ b/meter/src/main/java/com/ning/billing/meter/glue/MeterModule.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.meter.glue;
+
+import java.io.IOException;
+
+import org.skife.config.ConfigSource;
+import org.skife.config.ConfigurationObjectFactory;
+import org.skife.config.SimplePropertyConfigSource;
+
+import com.ning.billing.meter.timeline.codec.DefaultSampleCoder;
+import com.ning.billing.meter.timeline.codec.SampleCoder;
+import com.ning.billing.meter.timeline.persistent.FileBackedBuffer;
+import com.ning.billing.meter.timeline.persistent.TimelineDao;
+import com.ning.billing.meter.timeline.times.DefaultTimelineCoder;
+import com.ning.billing.meter.timeline.times.TimelineCoder;
+import com.ning.billing.util.config.MeterConfig;
+
+import com.google.inject.AbstractModule;
+
+public class MeterModule extends AbstractModule {
+
+ private final ConfigSource configSource;
+
+ public MeterModule() {
+ this(new SimplePropertyConfigSource(System.getProperties()));
+ }
+
+ public MeterModule(final ConfigSource configSource) {
+ this.configSource = configSource;
+ }
+
+ protected MeterConfig installConfig() {
+ final MeterConfig config = new ConfigurationObjectFactory(configSource).build(MeterConfig.class);
+ bind(MeterConfig.class).toInstance(config);
+
+ return config;
+ }
+
+ protected void configureDao() {
+ bind(TimelineDao.class).toProvider(CachingDefaultTimelineDaoProvider.class).asEagerSingleton();
+ }
+
+ protected void configureTimelineObjects() {
+ bind(TimelineCoder.class).to(DefaultTimelineCoder.class).asEagerSingleton();
+ bind(SampleCoder.class).to(DefaultSampleCoder.class).asEagerSingleton();
+ }
+
+ protected void configureFileBackedBuffer(final MeterConfig config) {
+ // Persistent buffer for in-memory samples
+ try {
+ final boolean deleteFilesOnClose = config.getShutdownSaveMode().equals("save_all_timelines");
+ final FileBackedBuffer fileBackedBuffer = new FileBackedBuffer(config.getSpoolDir(), "TimelineEventHandler", deleteFilesOnClose, config.getSegmentsSize(), config.getMaxNbSegments());
+ bind(FileBackedBuffer.class).toInstance(fileBackedBuffer);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected void configure() {
+
+ final MeterConfig config = installConfig();
+
+ configureFileBackedBuffer(config);
+ configureDao();
+ configureTimelineObjects();
+
+ // TODO
+ //configureTimelineAggregator();
+ //configureBackgroundDBChunkWriter();
+ //configureReplayer();
+ }
+}
diff --git a/meter/src/main/resources/com/ning/billing/meter/timeline/ddl.sql b/meter/src/main/resources/com/ning/billing/meter/timeline/ddl.sql
new file mode 100644
index 0000000..23f046d
--- /dev/null
+++ b/meter/src/main/resources/com/ning/billing/meter/timeline/ddl.sql
@@ -0,0 +1,71 @@
+create table sources (
+ record_id int(11) unsigned not null auto_increment
+, bundle_id char(36) default null
+, subscription_id char(36) default null
+, created_date datetime default null
+, created_by varchar(50) default null
+, updated_date datetime default null
+, updated_by varchar(50) default null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+, index created_date_record_id_dx (created_date, record_id)
+) engine = innodb default charset = latin1;
+create index sources_tenant_account_record_id on sources(tenant_record_id, account_record_id);
+
+create table event_categories (
+ record_id integer not null auto_increment
+, event_category varchar(256) not null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+, unique index event_category_unq (event_category)
+) engine = innodb default charset = latin1;
+create index event_categories_tenant_record_id on event_categories(tenant_record_id);
+
+create table metrics (
+ record_id int(11) unsigned not null auto_increment
+, event_category_id integer not null
+, metric varchar(256) not null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+, unique index metric_unq (event_category_id, metric)
+) engine = innodb default charset = latin1;
+create index metrics_tenant_record_id on metrics(tenant_record_id);
+
+create table timeline_chunks (
+ record_id bigint not null auto_increment
+, source_id integer not null
+, metric_id integer not null
+, sample_count integer not null
+, start_time integer not null
+, end_time integer not null
+, not_valid tinyint default 0
+, aggregation_level tinyint default 0
+, dont_aggregate tinyint default 0
+, in_row_samples varbinary(400) default null
+, blob_samples mediumblob default null
+, primary key(record_id)
+, unique index source_id_timeline_chunk_metric_idx (source_id, metric_id, start_time, aggregation_level)
+, index valid_agg_host_start_time (not_valid, aggregation_level, source_id, metric_id, start_time)
+) engine = innodb default charset = latin1;
+
+create table last_start_times (
+ time_inserted int not null primary key
+, start_times mediumtext not null
+) engine = innodb default charset = latin1;
+
+insert ignore into timeline_chunks(record_id, source_id, metric_id, sample_count, start_time, end_time, in_row_samples, blob_samples)
+ values (0, 0, 0, 0, 0, 0, null, null);
+
+create table timeline_rolled_up_chunk (
+ record_id bigint not null auto_increment
+, source_id integer not null
+, metric_id integer not null
+, start_time date not null
+, end_time date not null
+, value bigint not null
+, account_record_id int(11) unsigned default null
+, tenant_record_id int(11) unsigned default null
+, primary key(record_id)
+) engine = innodb default charset = latin1;
+create index timeline_rolled_up_chunk_tenant_account_record_id on timeline_rolled_up_chunk(tenant_record_id, account_record_id);
diff --git a/meter/src/test/java/com/ning/billing/meter/MeterTestSuite.java b/meter/src/test/java/com/ning/billing/meter/MeterTestSuite.java
new file mode 100644
index 0000000..d6ae3a6
--- /dev/null
+++ b/meter/src/test/java/com/ning/billing/meter/MeterTestSuite.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.meter;
+
+import com.ning.billing.KillbillTestSuite;
+
+public class MeterTestSuite extends KillbillTestSuite {
+
+}
diff --git a/meter/src/test/java/com/ning/billing/meter/MeterTestSuiteWithEmbeddedDB.java b/meter/src/test/java/com/ning/billing/meter/MeterTestSuiteWithEmbeddedDB.java
new file mode 100644
index 0000000..ec039b5
--- /dev/null
+++ b/meter/src/test/java/com/ning/billing/meter/MeterTestSuiteWithEmbeddedDB.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.meter;
+
+import com.ning.billing.KillbillTestSuiteWithEmbeddedDB;
+
+public class MeterTestSuiteWithEmbeddedDB extends KillbillTestSuiteWithEmbeddedDB {
+
+}
pom.xml 6(+6 -0)
diff --git a/pom.xml b/pom.xml
index 1d86c33..30b5439 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,6 +46,7 @@
<module>entitlement</module>
<module>invoice</module>
<module>junction</module>
+ <module>meter</module>
<module>overdue</module>
<module>payment</module>
<module>usage</module>
@@ -194,6 +195,11 @@
</dependency>
<dependency>
<groupId>com.ning.billing</groupId>
+ <artifactId>killbill-meter</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
<artifactId>killbill-overdue</artifactId>
<version>${project.version}</version>
</dependency>
server/pom.xml 8(+8 -0)
diff --git a/server/pom.xml b/server/pom.xml
index 1cc4442..c184f05 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -197,6 +197,10 @@
</dependency>
<dependency>
<groupId>com.ning.billing</groupId>
+ <artifactId>killbill-meter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
<artifactId>killbill-overdue</artifactId>
</dependency>
<dependency>
@@ -204,6 +208,10 @@
<artifactId>killbill-tenant</artifactId>
</dependency>
<dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-usage</artifactId>
+ </dependency>
+ <dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>11.0.2</version>
usage/pom.xml 16(+0 -16)
diff --git a/usage/pom.xml b/usage/pom.xml
index 6b03f41..f607f7b 100644
--- a/usage/pom.xml
+++ b/usage/pom.xml
@@ -25,22 +25,6 @@
<artifactId>jdbi</artifactId>
</dependency>
<dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.datatype</groupId>
- <artifactId>jackson-datatype-joda</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.dataformat</groupId>
- <artifactId>jackson-dataformat-smile</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.util</groupId>
- <artifactId>low-gc-membuffers</artifactId>
- </dependency>
- <dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<scope>provided</scope>
usage/README.md 5(+5 -0)
diff --git a/usage/README.md b/usage/README.md
new file mode 100644
index 0000000..78fef20
--- /dev/null
+++ b/usage/README.md
@@ -0,0 +1,5 @@
+Usage
+-----
+
+The usage module handles billing of units consumed, based on rolled-up usage information (e.g. per day or per month).
+See the meter module to handle aggregation of units.
diff --git a/usage/src/main/java/com/ning/billing/usage/api/user/DefaultRolledUpUsage.java b/usage/src/main/java/com/ning/billing/usage/api/user/DefaultRolledUpUsage.java
new file mode 100644
index 0000000..83ddeff
--- /dev/null
+++ b/usage/src/main/java/com/ning/billing/usage/api/user/DefaultRolledUpUsage.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.usage.api.user;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.usage.api.RolledUpUsage;
+import com.ning.billing.usage.dao.RolledUpUsageModelDao;
+
+public class DefaultRolledUpUsage implements RolledUpUsage {
+
+ private final UUID subscriptionId;
+ private final String unitType;
+ private final DateTime startTime;
+ private final DateTime endTime;
+ private final BigDecimal amount;
+
+ public DefaultRolledUpUsage(final UUID subscriptionId, final String unitType, final DateTime startTime, final DateTime endTime,
+ final BigDecimal amount) {
+ this.subscriptionId = subscriptionId;
+ this.unitType = unitType;
+ this.startTime = startTime;
+ this.endTime = endTime;
+ this.amount = amount;
+ }
+
+ public DefaultRolledUpUsage(final RolledUpUsageModelDao usageForSubscription) {
+ this(usageForSubscription.getSubscriptionId(), usageForSubscription.getUnitType(), usageForSubscription.getStartTime(),
+ usageForSubscription.getEndTime(), usageForSubscription.getAmount());
+ }
+
+ @Override
+ public UUID getSubscriptionId() {
+ return subscriptionId;
+ }
+
+ public String getUnitType() {
+ return unitType;
+ }
+
+ @Override
+ public DateTime getStartTime() {
+ return startTime;
+ }
+
+ @Override
+ public DateTime getEndTime() {
+ return endTime;
+ }
+
+ @Override
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DefaultRolledUpUsage");
+ sb.append("{subscriptionId=").append(subscriptionId);
+ sb.append(", unitType='").append(unitType).append('\'');
+ sb.append(", startTime=").append(startTime);
+ sb.append(", endTime=").append(endTime);
+ sb.append(", amount=").append(amount);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultRolledUpUsage that = (DefaultRolledUpUsage) o;
+
+ if (amount != null ? !amount.equals(that.amount) : that.amount != null) {
+ return false;
+ }
+ if (endTime != null ? !endTime.equals(that.endTime) : that.endTime != null) {
+ return false;
+ }
+ if (unitType != null ? !unitType.equals(that.unitType) : that.unitType != null) {
+ return false;
+ }
+ if (startTime != null ? !startTime.equals(that.startTime) : that.startTime != null) {
+ return false;
+ }
+ if (subscriptionId != null ? !subscriptionId.equals(that.subscriptionId) : that.subscriptionId != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = subscriptionId != null ? subscriptionId.hashCode() : 0;
+ result = 31 * result + (unitType != null ? unitType.hashCode() : 0);
+ result = 31 * result + (startTime != null ? startTime.hashCode() : 0);
+ result = 31 * result + (endTime != null ? endTime.hashCode() : 0);
+ result = 31 * result + (amount != null ? amount.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/usage/src/main/java/com/ning/billing/usage/api/user/DefaultUsageUserApi.java b/usage/src/main/java/com/ning/billing/usage/api/user/DefaultUsageUserApi.java
index 4df52f2..aa65345 100644
--- a/usage/src/main/java/com/ning/billing/usage/api/user/DefaultUsageUserApi.java
+++ b/usage/src/main/java/com/ning/billing/usage/api/user/DefaultUsageUserApi.java
@@ -16,76 +16,45 @@
package com.ning.billing.usage.api.user;
+import java.math.BigDecimal;
import java.util.UUID;
import javax.inject.Inject;
import org.joda.time.DateTime;
-import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
-import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.ObjectType;
+import com.ning.billing.usage.api.RolledUpUsage;
import com.ning.billing.usage.api.UsageUserApi;
import com.ning.billing.usage.dao.RolledUpUsageDao;
-import com.ning.billing.usage.timeline.TimelineEventHandler;
+import com.ning.billing.usage.dao.RolledUpUsageModelDao;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.InternalCallContext;
import com.ning.billing.util.callcontext.InternalCallContextFactory;
-import com.ning.billing.util.clock.Clock;
-import com.ning.billing.util.svcapi.entitlement.EntitlementInternalApi;
-
-import com.google.common.collect.ImmutableMap;
+import com.ning.billing.util.callcontext.TenantContext;
public class DefaultUsageUserApi implements UsageUserApi {
- private static final String DEFAULT_EVENT_TYPE = "__DefaultUsageUserApi__";
-
private final RolledUpUsageDao rolledUpUsageDao;
- private final TimelineEventHandler timelineEventHandler;
- private final EntitlementInternalApi entitlementApi;
- private final Clock clock;
private final InternalCallContextFactory internalCallContextFactory;
@Inject
public DefaultUsageUserApi(final RolledUpUsageDao rolledUpUsageDao,
- final TimelineEventHandler timelineEventHandler,
- final EntitlementInternalApi entitlementApi,
- final Clock clock,
final InternalCallContextFactory internalCallContextFactory) {
this.rolledUpUsageDao = rolledUpUsageDao;
- this.timelineEventHandler = timelineEventHandler;
- this.entitlementApi = entitlementApi;
- this.clock = clock;
this.internalCallContextFactory = internalCallContextFactory;
}
@Override
- public void incrementUsage(final UUID bundleId, final String metricName, final CallContext context) throws EntitlementUserApiException {
- recordUsage(bundleId, metricName, clock.getUTCNow(), 1, context);
- }
-
- @Override
- public void recordUsage(final UUID bundleId, final String metricName, final DateTime timestamp, final long value, final CallContext context) throws EntitlementUserApiException {
- final String sourceName = getSourceNameFromBundleId(bundleId);
- timelineEventHandler.record(sourceName, DEFAULT_EVENT_TYPE, timestamp, ImmutableMap.<String, Object>of(metricName, value), createInternalCallContext(bundleId, context));
+ public void recordRolledUpUsage(final UUID subscriptionId, final String unitType, final DateTime startTime, final DateTime endTime,
+ final BigDecimal amount, final CallContext context) {
+ final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(subscriptionId, ObjectType.SUBSCRIPTION, context);
+ rolledUpUsageDao.record(subscriptionId, unitType, startTime, endTime, amount, internalCallContext);
}
@Override
- public void recordRolledUpUsage(final UUID bundleId, final String metricName, final DateTime startDate, final DateTime endDate,
- final long value, final CallContext context) throws EntitlementUserApiException {
- final String sourceName = getSourceNameFromBundleId(bundleId);
-
- rolledUpUsageDao.record(sourceName, DEFAULT_EVENT_TYPE, metricName, startDate, endDate, value, createInternalCallContext(bundleId, context));
- }
-
- private InternalCallContext createInternalCallContext(final UUID bundleId, final CallContext context) throws EntitlementUserApiException {
- // Retrieve the bundle to get the account id for the internal call context
- // API_FIX
- final SubscriptionBundle bundle = null; // entitlementApi.getBundleFromId(bundleId, context);
- return internalCallContextFactory.createInternalCallContext(bundle.getAccountId(), context);
- }
-
- private String getSourceNameFromBundleId(final UUID bundleId) {
- // TODO we should do better
- return bundleId.toString();
+ public RolledUpUsage getUsageForSubscription(final UUID subscriptionId, final TenantContext context) {
+ final RolledUpUsageModelDao usageForSubscription = rolledUpUsageDao.getUsageForSubscription(subscriptionId, internalCallContextFactory.createInternalTenantContext(context));
+ return new DefaultRolledUpUsage(usageForSubscription);
}
}
diff --git a/usage/src/main/java/com/ning/billing/usage/dao/DefaultRolledUpUsageDao.java b/usage/src/main/java/com/ning/billing/usage/dao/DefaultRolledUpUsageDao.java
index c4bd958..1bc4b78 100644
--- a/usage/src/main/java/com/ning/billing/usage/dao/DefaultRolledUpUsageDao.java
+++ b/usage/src/main/java/com/ning/billing/usage/dao/DefaultRolledUpUsageDao.java
@@ -16,14 +16,15 @@
package com.ning.billing.usage.dao;
+import java.math.BigDecimal;
+import java.util.UUID;
+
import javax.inject.Inject;
import org.joda.time.DateTime;
-import org.skife.jdbi.v2.Transaction;
-import org.skife.jdbi.v2.TransactionStatus;
-import com.ning.billing.usage.timeline.persistent.TimelineSqlDao;
import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
public class DefaultRolledUpUsageDao implements RolledUpUsageDao {
@@ -35,38 +36,16 @@ public class DefaultRolledUpUsageDao implements RolledUpUsageDao {
}
@Override
- public void record(final String source, final String eventType, final String metricName, final DateTime startDate,
- final DateTime endDate, final long value, final InternalCallContext context) {
- rolledUpUsageSqlDao.inTransaction(new Transaction<Void, RolledUpUsageSqlDao>() {
- @Override
- public Void inTransaction(final RolledUpUsageSqlDao transactional, final TransactionStatus status) throws Exception {
- final TimelineSqlDao timelineSqlDao = transactional.become(TimelineSqlDao.class);
-
- // Create the source if it doesn't exist
- Integer sourceId = timelineSqlDao.getSourceId(source, context);
- if (sourceId == null) {
- timelineSqlDao.addSource(source, context);
- sourceId = timelineSqlDao.getSourceId(source, context);
- }
-
- // Create the category if it doesn't exist
- Integer categoryId = timelineSqlDao.getEventCategoryId(eventType, context);
- if (categoryId == null) {
- timelineSqlDao.addEventCategory(eventType, context);
- categoryId = timelineSqlDao.getEventCategoryId(eventType, context);
- }
-
- // Create the metric if it doesn't exist
- Integer metricId = timelineSqlDao.getMetricId(categoryId, metricName, context);
- if (metricId == null) {
- timelineSqlDao.addMetric(categoryId, metricName, context);
- metricId = timelineSqlDao.getMetricId(categoryId, metricName, context);
- }
-
- transactional.record(sourceId, metricId, startDate.toDate(), endDate.toDate(), value, context);
+ public void record(final UUID subscriptionId, final String unitType, final DateTime startTime, final DateTime endTime,
+ final BigDecimal amount, final InternalCallContext context) {
+ final RolledUpUsageModelDao rolledUpUsageModelDao = new RolledUpUsageModelDao(subscriptionId, unitType, startTime,
+ endTime, amount
+ );
+ rolledUpUsageSqlDao.create(rolledUpUsageModelDao, context);
+ }
- return null;
- }
- });
+ @Override
+ public RolledUpUsageModelDao getUsageForSubscription(final UUID subscriptionId, final InternalTenantContext context) {
+ return rolledUpUsageSqlDao.getUsageForSubscription(subscriptionId, context);
}
}
diff --git a/usage/src/main/java/com/ning/billing/usage/dao/RolledUpUsageDao.java b/usage/src/main/java/com/ning/billing/usage/dao/RolledUpUsageDao.java
index 25419d4..3907589 100644
--- a/usage/src/main/java/com/ning/billing/usage/dao/RolledUpUsageDao.java
+++ b/usage/src/main/java/com/ning/billing/usage/dao/RolledUpUsageDao.java
@@ -16,16 +16,18 @@
package com.ning.billing.usage.dao;
+import java.math.BigDecimal;
+import java.util.UUID;
+
import org.joda.time.DateTime;
import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
-/**
- * Dao to record already rolled-up usage data (rolled-up by the user).
- * For raw tracking of the data, @see TimelineEventHandler.
- */
public interface RolledUpUsageDao {
- public void record(final String sourceName, final String eventType, final String metricName, final DateTime startDate,
- final DateTime endDate, final long value, final InternalCallContext context);
+ void record(UUID subscriptionId, String unitType, DateTime startTime,
+ DateTime endTime, BigDecimal amount, InternalCallContext context);
+
+ RolledUpUsageModelDao getUsageForSubscription(UUID subscriptionId, InternalTenantContext context);
}
diff --git a/usage/src/main/java/com/ning/billing/usage/dao/RolledUpUsageModelDao.java b/usage/src/main/java/com/ning/billing/usage/dao/RolledUpUsageModelDao.java
new file mode 100644
index 0000000..7b03aec
--- /dev/null
+++ b/usage/src/main/java/com/ning/billing/usage/dao/RolledUpUsageModelDao.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.usage.dao;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+public class RolledUpUsageModelDao {
+
+ private UUID id;
+ private UUID subscriptionId;
+ private String unitType;
+ private DateTime startTime;
+ private DateTime endTime;
+ private BigDecimal amount;
+
+ public RolledUpUsageModelDao() { /* For the DAO mapper */ }
+
+ public RolledUpUsageModelDao(final UUID subscriptionId, final String unitType, final DateTime startTime,
+ final DateTime endTime, final BigDecimal amount) {
+ this.id = UUID.randomUUID();
+ this.subscriptionId = subscriptionId;
+ this.unitType = unitType;
+ this.startTime = startTime;
+ this.endTime = endTime;
+ this.amount = amount;
+ }
+
+ public UUID getId() {
+ return id;
+ }
+
+ public UUID getSubscriptionId() {
+ return subscriptionId;
+ }
+
+ public String getUnitType() {
+ return unitType;
+ }
+
+ public DateTime getStartTime() {
+ return startTime;
+ }
+
+ public DateTime getEndTime() {
+ return endTime;
+ }
+
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("RolledUpUsageModelDao");
+ sb.append("{id=").append(id);
+ sb.append(", subscriptionId=").append(subscriptionId);
+ sb.append(", unitType='").append(unitType).append('\'');
+ sb.append(", startTime=").append(startTime);
+ sb.append(", endTime=").append(endTime);
+ sb.append(", amount=").append(amount);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final RolledUpUsageModelDao that = (RolledUpUsageModelDao) o;
+
+ if (amount != null ? !amount.equals(that.amount) : that.amount != null) {
+ return false;
+ }
+ if (endTime != null ? !endTime.equals(that.endTime) : that.endTime != null) {
+ return false;
+ }
+ if (id != null ? !id.equals(that.id) : that.id != null) {
+ return false;
+ }
+ if (unitType != null ? !unitType.equals(that.unitType) : that.unitType != null) {
+ return false;
+ }
+ if (startTime != null ? !startTime.equals(that.startTime) : that.startTime != null) {
+ return false;
+ }
+ if (subscriptionId != null ? !subscriptionId.equals(that.subscriptionId) : that.subscriptionId != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = id != null ? id.hashCode() : 0;
+ result = 31 * result + (subscriptionId != null ? subscriptionId.hashCode() : 0);
+ result = 31 * result + (unitType != null ? unitType.hashCode() : 0);
+ result = 31 * result + (startTime != null ? startTime.hashCode() : 0);
+ result = 31 * result + (endTime != null ? endTime.hashCode() : 0);
+ result = 31 * result + (amount != null ? amount.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/usage/src/main/java/com/ning/billing/usage/dao/RolledUpUsageSqlDao.java b/usage/src/main/java/com/ning/billing/usage/dao/RolledUpUsageSqlDao.java
index 52db57c..8a78f4a 100644
--- a/usage/src/main/java/com/ning/billing/usage/dao/RolledUpUsageSqlDao.java
+++ b/usage/src/main/java/com/ning/billing/usage/dao/RolledUpUsageSqlDao.java
@@ -16,25 +16,26 @@
package com.ning.billing.usage.dao;
-import java.util.Date;
+import java.util.UUID;
import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.BindBean;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
-import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
-import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
-import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.UseStringTemplate3StatementLocator;
import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
import com.ning.billing.util.callcontext.InternalTenantContextBinder;
-@ExternalizedSqlViaStringTemplate3()
-public interface RolledUpUsageSqlDao extends Transactional<RolledUpUsageSqlDao>, Transmogrifier {
+@UseStringTemplate3StatementLocator()
+public interface RolledUpUsageSqlDao {
@SqlUpdate
- public void record(@Bind("sourceId") final int sourceId,
- @Bind("metricId") final int metricId,
- @Bind("startTime") final Date startTime,
- @Bind("endTime") final Date endTime,
- @Bind("value") final long value,
+ public void create(@BindBean RolledUpUsageModelDao rolledUpUsage,
@InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlQuery
+ public RolledUpUsageModelDao getUsageForSubscription(@Bind("subscriptionId") final UUID subscriptionId,
+ @InternalTenantContextBinder final InternalTenantContext context);
}
diff --git a/usage/src/main/java/com/ning/billing/usage/glue/UsageModule.java b/usage/src/main/java/com/ning/billing/usage/glue/UsageModule.java
index 1eafd1e..45fd6a2 100644
--- a/usage/src/main/java/com/ning/billing/usage/glue/UsageModule.java
+++ b/usage/src/main/java/com/ning/billing/usage/glue/UsageModule.java
@@ -16,73 +16,11 @@
package com.ning.billing.usage.glue;
-import java.io.IOException;
-
-import org.skife.config.ConfigSource;
-import org.skife.config.ConfigurationObjectFactory;
-import org.skife.config.SimplePropertyConfigSource;
-
-import com.ning.billing.util.config.UsageConfig;
-import com.ning.billing.usage.timeline.codec.DefaultSampleCoder;
-import com.ning.billing.usage.timeline.codec.SampleCoder;
-import com.ning.billing.usage.timeline.persistent.FileBackedBuffer;
-import com.ning.billing.usage.timeline.persistent.TimelineDao;
-import com.ning.billing.usage.timeline.times.DefaultTimelineCoder;
-import com.ning.billing.usage.timeline.times.TimelineCoder;
-
import com.google.inject.AbstractModule;
public class UsageModule extends AbstractModule {
- private final ConfigSource configSource;
-
- public UsageModule() {
- this(new SimplePropertyConfigSource(System.getProperties()));
- }
-
- public UsageModule(final ConfigSource configSource) {
- this.configSource = configSource;
- }
-
- protected UsageConfig installConfig() {
- final UsageConfig config = new ConfigurationObjectFactory(configSource).build(UsageConfig.class);
- bind(UsageConfig.class).toInstance(config);
-
- return config;
- }
-
- protected void configureFileBackedBuffer(final UsageConfig config) {
- // Persistent buffer for in-memory samples
- try {
- final boolean deleteFilesOnClose = config.getShutdownSaveMode().equals("save_all_timelines");
- final FileBackedBuffer fileBackedBuffer = new FileBackedBuffer(config.getSpoolDir(), "TimelineEventHandler", deleteFilesOnClose, config.getSegmentsSize(), config.getMaxNbSegments());
- bind(FileBackedBuffer.class).toInstance(fileBackedBuffer);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- protected void configureDao() {
- bind(TimelineDao.class).toProvider(CachingDefaultTimelineDaoProvider.class).asEagerSingleton();
- }
-
- protected void configureTimelineObjects() {
- bind(TimelineCoder.class).to(DefaultTimelineCoder.class).asEagerSingleton();
- bind(SampleCoder.class).to(DefaultSampleCoder.class).asEagerSingleton();
- }
-
@Override
protected void configure() {
- final UsageConfig config = installConfig();
-
- configureFileBackedBuffer(config);
- configureDao();
- configureTimelineObjects();
-
- // TODO
- //configureTimelineAggregator();
- //configureBackgroundDBChunkWriter();
- //configureReplayer();
}
}
-
diff --git a/usage/src/main/resources/com/ning/billing/usage/dao/RolledUpUsageSqlDao.sql.stg b/usage/src/main/resources/com/ning/billing/usage/dao/RolledUpUsageSqlDao.sql.stg
new file mode 100644
index 0000000..e028757
--- /dev/null
+++ b/usage/src/main/resources/com/ning/billing/usage/dao/RolledUpUsageSqlDao.sql.stg
@@ -0,0 +1,51 @@
+group RolledUpUsageSqlDao;
+
+tableName() ::= "usage"
+
+tableFields(prefix) ::= <<
+ <prefix>id
+, <prefix>subscription_id
+, <prefix>unit_type
+, <prefix>start_time
+, <prefix>end_time
+, <prefix>amount
+, <prefix>created_by
+, <prefix>created_date
+, <prefix>account_record_id
+, <prefix>tenant_record_id
+>>
+
+tableValues() ::= <<
+ :id
+, :subscriptionId
+, :unitType
+, :startTime
+, :endTime
+, :amount
+, :userName
+, :createdDate
+, :accountRecordId
+, :tenantRecordId
+>>
+
+CHECK_TENANT(prefix) ::= "<prefix>tenant_record_id = :tenantRecordId"
+AND_CHECK_TENANT(prefix) ::= "and <CHECK_TENANT(prefix)>"
+
+create() ::= <<
+insert into <tableName()> (
+ <tableFields()>
+)
+values (
+ <tableValues()>
+)
+;
+>>
+
+getUsageForSubscription() ::= <<
+select
+ <tableFields("t.")>
+from <tableName()> t
+where subscription_id = :subscriptionId
+<AND_CHECK_TENANT()>
+;
+>>
diff --git a/usage/src/main/resources/com/ning/billing/usage/ddl.sql b/usage/src/main/resources/com/ning/billing/usage/ddl.sql
index 23f046d..c2cd87c 100644
--- a/usage/src/main/resources/com/ning/billing/usage/ddl.sql
+++ b/usage/src/main/resources/com/ning/billing/usage/ddl.sql
@@ -1,71 +1,18 @@
-create table sources (
- record_id int(11) unsigned not null auto_increment
-, bundle_id char(36) default null
-, subscription_id char(36) default null
-, created_date datetime default null
-, created_by varchar(50) default null
-, updated_date datetime default null
-, updated_by varchar(50) default null
-, account_record_id int(11) unsigned default null
-, tenant_record_id int(11) unsigned default null
-, primary key(record_id)
-, index created_date_record_id_dx (created_date, record_id)
-) engine = innodb default charset = latin1;
-create index sources_tenant_account_record_id on sources(tenant_record_id, account_record_id);
-
-create table event_categories (
- record_id integer not null auto_increment
-, event_category varchar(256) not null
-, tenant_record_id int(11) unsigned default null
-, primary key(record_id)
-, unique index event_category_unq (event_category)
-) engine = innodb default charset = latin1;
-create index event_categories_tenant_record_id on event_categories(tenant_record_id);
-
-create table metrics (
- record_id int(11) unsigned not null auto_increment
-, event_category_id integer not null
-, metric varchar(256) not null
-, tenant_record_id int(11) unsigned default null
-, primary key(record_id)
-, unique index metric_unq (event_category_id, metric)
-) engine = innodb default charset = latin1;
-create index metrics_tenant_record_id on metrics(tenant_record_id);
-
-create table timeline_chunks (
- record_id bigint not null auto_increment
-, source_id integer not null
-, metric_id integer not null
-, sample_count integer not null
-, start_time integer not null
-, end_time integer not null
-, not_valid tinyint default 0
-, aggregation_level tinyint default 0
-, dont_aggregate tinyint default 0
-, in_row_samples varbinary(400) default null
-, blob_samples mediumblob default null
-, primary key(record_id)
-, unique index source_id_timeline_chunk_metric_idx (source_id, metric_id, start_time, aggregation_level)
-, index valid_agg_host_start_time (not_valid, aggregation_level, source_id, metric_id, start_time)
-) engine = innodb default charset = latin1;
-
-create table last_start_times (
- time_inserted int not null primary key
-, start_times mediumtext not null
-) engine = innodb default charset = latin1;
-
-insert ignore into timeline_chunks(record_id, source_id, metric_id, sample_count, start_time, end_time, in_row_samples, blob_samples)
- values (0, 0, 0, 0, 0, 0, null, null);
-
-create table timeline_rolled_up_chunk (
- record_id bigint not null auto_increment
-, source_id integer not null
-, metric_id integer not null
-, start_time date not null
-, end_time date not null
-, value bigint not null
-, account_record_id int(11) unsigned default null
-, tenant_record_id int(11) unsigned default null
-, primary key(record_id)
-) engine = innodb default charset = latin1;
-create index timeline_rolled_up_chunk_tenant_account_record_id on timeline_rolled_up_chunk(tenant_record_id, account_record_id);
+DROP TABLE IF EXISTS rolled_up_usage;
+CREATE TABLE rolled_up_usage (
+ record_id int(11) unsigned NOT NULL AUTO_INCREMENT,
+ id char(36) NOT NULL,
+ subscription_id char(36),
+ unit_type varchar(50),
+ start_date date NOT NULL,
+ end_date date,
+ amount numeric(10,10) NOT NULL,
+ created_by varchar(50) NOT NULL,
+ created_date datetime NOT NULL,
+ account_record_id int(11) unsigned default null,
+ tenant_record_id int(11) unsigned default null,
+ PRIMARY KEY(record_id)
+) ENGINE=innodb;
+CREATE UNIQUE INDEX rolled_up_usage_id ON rolled_up_usage(id);
+CREATE INDEX rolled_up_usage_subscription_id ON rolled_up_usage(subscription_id ASC);
+CREATE INDEX rolled_up_usage_tenant_account_record_id ON rolled_up_usage(tenant_record_id, account_record_id);