public DefaultOverduePosterBase(final NotificationQueueService notificationQueueService, final IDBI dbi, @Named(MAIN_RO_IDBI_NAMED) final IDBI roDbi, final Clock clock, final CacheControllerDispatcher cacheControllerDispatcher, final NonEntityDao nonEntityDao, final InternalCallContextFactory internalCallContextFactory) { this.notificationQueueService = notificationQueueService; this.transactionalSqlDao = new EntitySqlDaoTransactionalJdbiWrapper(dbi, roDbi, clock, cacheControllerDispatcher, nonEntityDao, internalCallContextFactory); }
@Override public TenantModelDao getTenantByApiKey(final String apiKey) { return transactionalSqlDao.execute(true, new EntitySqlDaoTransactionWrapper<TenantModelDao>() { @Override public TenantModelDao inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception { return entitySqlDaoWrapperFactory.become(TenantSqlDao.class).getByApiKey(apiKey); } }); }
@Override public void create(final M entity, final InternalCallContext context) throws U { final M refreshedEntity = transactionalSqlDao.execute(false, targetExceptionClass, getCreateEntitySqlDaoTransactionWrapper(entity, context)); // Populate the caches only after the transaction has been committed, in case of rollbacks transactionalSqlDao.populateCaches(refreshedEntity); }
final Long totalNbRecordsOrNull = transactionalSqlDao.execute(true, new EntitySqlDaoTransactionWrapper<Long>() { @Override public Long inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception { final EntitySqlDao<M, E> sqlDao = transactionalSqlDao.onDemandForStreamingResults(sqlDaoClazz); final Long maxNbRecords; if (context == null) {
@Override public Pagination<M> getAll(final InternalTenantContext context) { // We usually always want to wrap our queries in an EntitySqlDaoTransactionWrapper... except here. // Since we want to stream the results out, we don't want to auto-commit when this method returns. final EntitySqlDao<M, E> sqlDao = transactionalSqlDao.onDemandForStreamingResults(realSqlDao); // Note: we need to perform the count before streaming the results, as the connection // will be busy as we stream the results out. This is also why we cannot use // SQL_CALC_FOUND_ROWS / FOUND_ROWS (which may not be faster anyways). final Long count = sqlDao.getCount(context); final Iterator<M> results = sqlDao.getAll(context); return new DefaultPagination<M>(count, results); }
/** * @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); } }
final Long totalNbRecordsOrNull = transactionalSqlDao.execute(true, new EntitySqlDaoTransactionWrapper<Long>() { @Override public Long inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception { final EntitySqlDao<M, E> sqlDao = transactionalSqlDao.onDemandForStreamingResults(sqlDaoClazz); final Long maxNbRecords; if (context == null) {
@Override public DefaultAccountAuditLogs getAuditLogsForAccountRecordId(final AuditLevel auditLevel, final InternalTenantContext context) { final UUID accountId = dbRouter.onDemand(true).getIdFromObject(context.getAccountRecordId(), TableName.ACCOUNT.getTableName()); // Lazy evaluate records to minimize the memory footprint (these can yield a lot of results) // We usually always want to wrap our queries in an EntitySqlDaoTransactionWrapper... except here. // Since we want to stream the results out, we don't want to auto-commit when this method returns. final EntitySqlDao auditSqlDao = transactionalSqlDao.onDemandForStreamingResults(EntitySqlDao.class); final Iterator<AuditLogModelDao> auditLogsForAccountRecordId = auditSqlDao.getAuditLogsForAccountRecordId(context); final Iterator<AuditLog> allAuditLogs = buildAuditLogsFromModelDao(auditLogsForAccountRecordId, context); return new DefaultAccountAuditLogs(accountId, auditLevel, allAuditLogs); }
/** * @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); } }
@Override public List<AuditLogWithHistory> getEmailAuditLogsWithHistoryForId(final UUID accountEmailId, final AuditLevel auditLevel, final InternalTenantContext context) { return transactionalSqlDao.execute(true, new EntitySqlDaoTransactionWrapper<List<AuditLogWithHistory>>() { @Override public List<AuditLogWithHistory> inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) { final AccountEmailSqlDao transactional = entitySqlDaoWrapperFactory.become(AccountEmailSqlDao.class); return auditDao.getAuditLogsWithHistoryForId(transactional, TableName.ACCOUNT_EMAIL, accountEmailId, auditLevel, context); } }); } }
@Inject public DefaultCustomFieldDao(final IDBI dbi, @Named(MAIN_RO_IDBI_NAMED) final IDBI roDbi, final Clock clock, final CacheControllerDispatcher controllerDispatcher, final NonEntityDao nonEntityDao, final InternalCallContextFactory internalCallContextFactory, final PersistentBus bus, final AuditDao auditDao) { super(new EntitySqlDaoTransactionalJdbiWrapper(dbi, roDbi, clock, controllerDispatcher, nonEntityDao, internalCallContextFactory), CustomFieldSqlDao.class); this.bus = bus; this.auditDao = auditDao; }
public void create(final Iterable<M> entities, final InternalCallContext context) throws U { final List<M> refreshedEntities = transactionalSqlDao.execute(false, targetExceptionClass, getCreateEntitySqlDaoTransactionWrapper(entities, context)); // Populate the caches only after the transaction has been committed, in case of rollbacks for (M refreshedEntity : refreshedEntities) { transactionalSqlDao.populateCaches(refreshedEntity); } }
@Override public DefaultAccountAuditLogsForObjectType getAuditLogsForAccountRecordId(final TableName tableName, final AuditLevel auditLevel, final InternalTenantContext context) { final String actualTableName; if (tableName.hasHistoryTable()) { actualTableName = tableName.getHistoryTableName().name(); // upper cased } else { actualTableName = tableName.getTableName(); } // Lazy evaluate records to minimize the memory footprint (these can yield a lot of results) // We usually always want to wrap our queries in an EntitySqlDaoTransactionWrapper... except here. // Since we want to stream the results out, we don't want to auto-commit when this method returns. final EntitySqlDao auditSqlDao = transactionalSqlDao.onDemandForStreamingResults(EntitySqlDao.class); final Iterator<AuditLogModelDao> auditLogsForTableNameAndAccountRecordId = auditSqlDao.getAuditLogsForTableNameAndAccountRecordId(actualTableName, context); final Iterator<AuditLog> allAuditLogs = buildAuditLogsFromModelDao(auditLogsForTableNameAndAccountRecordId, context); return new DefaultAccountAuditLogsForObjectType(auditLevel, allAuditLogs); }
@Override public List<TenantKVModelDao> searchTenantKeyValues(final String searchKeyPrefix, final InternalTenantContext context) { return transactionalSqlDao.execute(true, new EntitySqlDaoTransactionWrapper<List<TenantKVModelDao>>() { @Override public List<TenantKVModelDao> inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception { return entitySqlDaoWrapperFactory.become(TenantKVSqlDao.class).searchTenantKeyValues(String.format("%s%%", searchKeyPrefix), context); } }); }
@Inject public DefaultTenantDao(final IDBI dbi, @Named(MAIN_RO_IDBI_NAMED) final IDBI roDbi, final Clock clock, final CacheControllerDispatcher cacheControllerDispatcher, final NonEntityDao nonEntityDao, final InternalCallContextFactory internalCallContextFactory, final SecurityConfig securityConfig) { super(new EntitySqlDaoTransactionalJdbiWrapper(dbi, roDbi, clock, cacheControllerDispatcher, nonEntityDao, internalCallContextFactory), TenantSqlDao.class); this.securityConfig = securityConfig; }
@Override public void create(final AccountModelDao entity, final InternalCallContext context) throws AccountApiException { // We don't enforce the created_date for the Account because it is extracted from context // so, if there is no referenceTime specified we have to set it from the InternalCallContext#created_date // if (entity.getReferenceTime() == null) { entity.setReferenceTime(context.getCreatedDate()); } final AccountModelDao refreshedEntity = transactionalSqlDao.execute(false, getCreateEntitySqlDaoTransactionWrapper(entity, context)); // Populate the caches only after the transaction has been committed, in case of rollbacks transactionalSqlDao.populateCaches(refreshedEntity); // Eagerly populate the account-immutable cache as well accountImmutableCacheController.putIfAbsent(refreshedEntity.getRecordId(), new DefaultImmutableAccountData(refreshedEntity)); }
@Override public Pagination<M> getAll(final InternalTenantContext context) { // We usually always want to wrap our queries in an EntitySqlDaoTransactionWrapper... except here. // Since we want to stream the results out, we don't want to auto-commit when this method returns. final EntitySqlDao<M, E> sqlDao = transactionalSqlDao.onDemandForStreamingResults(realSqlDao); // Note: we need to perform the count before streaming the results, as the connection // will be busy as we stream the results out. This is also why we cannot use // SQL_CALC_FOUND_ROWS / FOUND_ROWS (which may not be faster anyways). final Long count = sqlDao.getCount(context); final Iterator<M> results = sqlDao.getAll(context); return new DefaultPagination<M>(count, results); }
@Override public List<AuditLogWithHistory> getTagDefinitionAuditLogsWithHistoryForId(final UUID tagDefinitionId, final AuditLevel auditLevel, final InternalTenantContext context) { return transactionalSqlDao.execute(true, new EntitySqlDaoTransactionWrapper<List<AuditLogWithHistory>>() { @Override public List<AuditLogWithHistory> inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) { final TagDefinitionSqlDao transactional = entitySqlDaoWrapperFactory.become(TagDefinitionSqlDao.class); return auditDao.getAuditLogsWithHistoryForId(transactional, TableName.TAG_DEFINITIONS, tagDefinitionId, auditLevel, context); } }); }
@Inject public DefaultTagDao(final IDBI dbi, @Named(MAIN_RO_IDBI_NAMED) final IDBI roDbi, final TagEventBuilder tagEventBuilder, final PersistentBus bus, final Clock clock, final CacheControllerDispatcher controllerDispatcher, final NonEntityDao nonEntityDao, final InternalCallContextFactory internalCallContextFactory, final AuditDao auditDao) { super(new EntitySqlDaoTransactionalJdbiWrapper(dbi, roDbi, clock, controllerDispatcher, nonEntityDao, internalCallContextFactory), TagSqlDao.class); this.tagEventBuilder = tagEventBuilder; this.bus = bus; this.auditDao = auditDao; }
@Override public void create(final M entity, final InternalCallContext context) throws U { final M refreshedEntity = transactionalSqlDao.execute(false, targetExceptionClass, getCreateEntitySqlDaoTransactionWrapper(entity, context)); // Populate the caches only after the transaction has been committed, in case of rollbacks transactionalSqlDao.populateCaches(refreshedEntity); }