use of org.killbill.billing.util.entity.Entity in project killbill by killbill.
the class EntitySqlDaoTransactionalJdbiWrapper method execute.
/**
* @param <ReturnType> object type to return from the transaction
* @param requestedRO hint as whether to use the read-only connection
* @param entitySqlDaoTransactionWrapper transaction to execute
* @return result from the transaction fo type ReturnType
*/
public <ReturnType> ReturnType execute(final boolean requestedRO, final EntitySqlDaoTransactionWrapper<ReturnType> entitySqlDaoTransactionWrapper) {
final String debugInfo = logger.isDebugEnabled() ? getDebugInfo() : null;
final Handle handle = dbRouter.getHandle(requestedRO);
logger.debug("DBI handle created, transaction: {}", debugInfo);
try {
final EntitySqlDao<EntityModelDao<Entity>, Entity> entitySqlDao = handle.attach(InitialEntitySqlDao.class);
// The transaction isolation level is now set at the pool level: this avoids 3 roundtrips for each transaction
// Note that if the pool isn't used (tests or PostgreSQL), the transaction level will depend on the DB configuration
// return entitySqlDao.inTransaction(TransactionIsolationLevel.READ_COMMITTED, new JdbiTransaction<ReturnType, EntityModelDao<Entity>, Entity>(handle, entitySqlDaoTransactionWrapper));
logger.debug("Starting transaction {}", debugInfo);
final ReturnType returnType = entitySqlDao.inTransaction(new JdbiTransaction<ReturnType, EntityModelDao<Entity>, Entity>(handle, entitySqlDaoTransactionWrapper));
logger.debug("Exiting transaction {}, returning {}", debugInfo, returnType);
return returnType;
} finally {
handle.close();
logger.debug("DBI handle closed, transaction: {}", debugInfo);
}
}
use of org.killbill.billing.util.entity.Entity in project killbill by killbill.
the class EntitySqlDaoWrapperInvocationHandler method extractEntityIdsFromBatchArgument.
private Builder<String> extractEntityIdsFromBatchArgument(final Iterable arg) {
final Iterator iterator = arg.iterator();
final Builder<String> entityIds = new Builder<String>();
while (iterator.hasNext()) {
final Object object = iterator.next();
if (!(object instanceof Entity)) {
// No good - ignore
return null;
} else {
entityIds.add(((Entity) object).getId().toString());
}
}
return entityIds;
}
use of org.killbill.billing.util.entity.Entity in project killbill by killbill.
the class EntitySqlDaoWrapperInvocationHandler method retrieveEntityIdsFromArguments.
private List<String> retrieveEntityIdsFromArguments(final Method method, final Object[] args) {
final Annotation[][] parameterAnnotations = getAnnotations(method);
int i = -1;
for (final Object arg : args) {
i++;
// This is true for e.g. create calls
if (arg instanceof Entity) {
return ImmutableList.<String>of(((Entity) arg).getId().toString());
}
// For Batch calls, the first argument will be of type List<Entity>
if (arg instanceof Iterable) {
final Builder<String> entityIds = extractEntityIdsFromBatchArgument((Iterable) arg);
if (entityIds != null) {
return entityIds.build();
}
}
for (final Annotation annotation : parameterAnnotations[i]) {
if (arg instanceof String && Bind.class.equals(annotation.annotationType()) && ("id").equals(((Bind) annotation).value())) {
return ImmutableList.<String>of((String) arg);
} else if (arg instanceof Collection && BindIn.class.equals(annotation.annotationType()) && ("ids").equals(((BindIn) annotation).value())) {
return ImmutableList.<String>copyOf((Collection) arg);
}
}
}
return ImmutableList.<String>of();
}
use of org.killbill.billing.util.entity.Entity in project killbill by killbill.
the class TestInvoiceTrackingSqlDao method testInvalidation.
@Test(groups = "slow")
public void testInvalidation() {
LocalDate startRange = new LocalDate(2019, 1, 1);
LocalDate endRange = new LocalDate(2019, 1, 31);
final UUID invoiceId1 = UUID.randomUUID();
final UUID invoiceId2 = UUID.randomUUID();
final UUID subscriptionId = UUID.randomUUID();
// invoiceId1
final InvoiceTrackingModelDao input1 = new InvoiceTrackingModelDao(UUID.randomUUID(), clock.getUTCNow(), "trackingId1", invoiceId1, subscriptionId, "unit", new LocalDate(2019, 1, 1));
final InvoiceTrackingModelDao input2 = new InvoiceTrackingModelDao(UUID.randomUUID(), clock.getUTCNow(), "trackingId2", invoiceId1, subscriptionId, "unit", new LocalDate(2019, 1, 2));
final InvoiceTrackingModelDao input3 = new InvoiceTrackingModelDao(UUID.randomUUID(), clock.getUTCNow(), "trackingId3", invoiceId1, subscriptionId, "unit", new LocalDate(2019, 1, 3));
// invoiceId2
final InvoiceTrackingModelDao input4 = new InvoiceTrackingModelDao(UUID.randomUUID(), clock.getUTCNow(), "trackingId4", invoiceId2, subscriptionId, "unit", new LocalDate(2019, 1, 5));
final List<InvoiceTrackingModelDao> inputs = new ArrayList<>();
inputs.add(input1);
inputs.add(input2);
inputs.add(input3);
inputs.add(input4);
// Create state
transactionalSqlDao.execute(false, new EntitySqlDaoTransactionWrapper<Void>() {
@Override
public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
final InvoiceTrackingSqlDao dao = entitySqlDaoWrapperFactory.become(InvoiceTrackingSqlDao.class);
dao.create(inputs, internalCallContext);
return null;
}
});
// Verify audit logs from existing state
final List<InvoiceTrackingModelDao> initialTrackingIdsByRange = transactionalSqlDao.execute(false, new EntitySqlDaoTransactionWrapper<List<InvoiceTrackingModelDao>>() {
@Override
public List<InvoiceTrackingModelDao> inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
final InvoiceTrackingSqlDao dao = entitySqlDaoWrapperFactory.become(InvoiceTrackingSqlDao.class);
final List<InvoiceTrackingModelDao> result = dao.getTrackingsByDateRange(startRange.toDate(), endRange.toDate(), internalCallContext);
Assert.assertEquals(result.size(), 4);
final List<EntityHistoryModelDao> entityHistoryModelDaos = new ArrayList<>();
final List<AuditLogModelDao> auditLogsPostCreate = new ArrayList<>();
for (int i = 0; i < 4; i++) {
List<AuditLogModelDao> tmp1 = dao.getAuditLogsViaHistoryForTargetRecordId(TableName.INVOICE_TRACKING_ID_HISTORY.name(), TableName.INVOICE_TRACKING_ID_HISTORY.getTableName().toLowerCase(), result.get(i).getRecordId(), internalCallContext);
auditLogsPostCreate.addAll(tmp1);
final List<EntityHistoryModelDao<InvoiceTrackingModelDao, Entity>> tmp2 = dao.getHistoryForTargetRecordId(true, result.get(i).getRecordId(), internalCallContext);
entityHistoryModelDaos.addAll(tmp2);
}
Assert.assertEquals(auditLogsPostCreate.size(), 4);
Assert.assertEquals(entityHistoryModelDaos.size(), 4);
for (int i = 0; i < 4; i++) {
Assert.assertEquals(auditLogsPostCreate.get(i).getChangeType(), ChangeType.INSERT);
// From the audit log entry, lookup the matching history entry
final int curIdx = i;
final EntityHistoryModelDao history = Iterables.find(entityHistoryModelDaos, new Predicate<EntityHistoryModelDao>() {
@Override
public boolean apply(final EntityHistoryModelDao input) {
return Objects.equals(input.getHistoryRecordId(), auditLogsPostCreate.get(curIdx).getTargetRecordId());
}
});
Assert.assertEquals(auditLogsPostCreate.get(i).getTargetRecordId(), history.getHistoryRecordId());
}
return result;
}
});
clock.addDays(1);
// Create state
transactionalSqlDao.execute(false, new EntitySqlDaoTransactionWrapper<Void>() {
@Override
public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
final InvoiceTrackingSqlDao dao = entitySqlDaoWrapperFactory.become(InvoiceTrackingSqlDao.class);
final InternalCallContext updatedContext = new InternalCallContext(internalCallContext.getTenantRecordId(), internalCallContext.getAccountRecordId(), internalCallContext.getFixedOffsetTimeZone(), clock.getUTCNow(), internalCallContext.getUserToken(), "invalidation-user", internalCallContext.getCallOrigin(), internalCallContext.getContextUserType(), internalCallContext.getReasonCode(), internalCallContext.getComments(), internalCallContext.getCreatedDate(), clock.getUTCNow());
dao.deactivateByIds(ImmutableList.<String>of(input1.getId().toString(), input2.getId().toString(), input3.getId().toString()), updatedContext);
return null;
}
});
// Verify audit logs from existing state
transactionalSqlDao.execute(false, new EntitySqlDaoTransactionWrapper<Void>() {
@Override
public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
final InvoiceTrackingSqlDao dao = entitySqlDaoWrapperFactory.become(InvoiceTrackingSqlDao.class);
final List<InvoiceTrackingModelDao> result2 = dao.getTrackingsByDateRange(startRange.toDate(), endRange.toDate(), internalCallContext);
Assert.assertEquals(result2.size(), 1);
final List<AuditLogModelDao> auditLogsPostDelete = new ArrayList<>();
for (int i = 0; i < 4; i++) {
List<AuditLogModelDao> tmp = dao.getAuditLogsViaHistoryForTargetRecordId(TableName.INVOICE_TRACKING_ID_HISTORY.name(), TableName.INVOICE_TRACKING_ID_HISTORY.getTableName().toLowerCase(), initialTrackingIdsByRange.get(i).getRecordId(), internalCallContext);
auditLogsPostDelete.addAll(tmp);
}
Assert.assertEquals(auditLogsPostDelete.size(), 7);
// First 3 records will show an INSERT & DELETE
for (int i = 0; i < 3; i++) {
Assert.assertEquals(auditLogsPostDelete.get(2 * i).getChangeType(), ChangeType.INSERT);
Assert.assertEquals(auditLogsPostDelete.get(2 * i + 1).getChangeType(), ChangeType.DELETE);
}
// Last record will only show an INSERT
Assert.assertEquals(auditLogsPostDelete.get(6).getChangeType(), ChangeType.INSERT);
return null;
}
});
}
Aggregations