@Override public List<AuditLogWithHistory> getAuditLogsWithHistoryForId(final HistorySqlDao transactional, final TableName tableName, final UUID objectId, final AuditLevel auditLevel, final InternalTenantContext context) { final TableName historyTableName = tableName.getHistoryTableName(); if (historyTableName == null) { throw new IllegalStateException("History table shouldn't be null for " + tableName);
private TableName findTableNameForHistoryTableName(final TableName historyTableName) { for (final TableName tableName : TableName.values()) { if (historyTableName.equals(tableName.getHistoryTableName())) { return tableName; } } return null; } });
@Override public M execute() throws Throwable { final M reHydratedEntity; if (changeType == ChangeType.DELETE) { reHydratedEntity = deletedEntity; } else { // See note above regarding "markAsInactive" operations reHydratedEntity = MoreObjects.firstNonNull(sqlDao.getById(entityId, context), deletedEntity); printSQLWarnings(); } Preconditions.checkNotNull(reHydratedEntity, "reHydratedEntity cannot be null"); final Long entityRecordId = reHydratedEntity.getRecordId(); final TableName tableName = reHydratedEntity.getTableName(); // Note: audit entries point to the history record id final Long historyRecordId; if (tableName.getHistoryTableName() != null) { historyRecordId = insertHistory(entityRecordId, reHydratedEntity, changeType, context); } else { historyRecordId = entityRecordId; } // Make sure to re-hydrate the object (especially needed for create calls) insertAudits(tableName, reHydratedEntity, entityRecordId, historyRecordId, changeType, context); return reHydratedEntity; } });
private List<AuditLog> doGetAuditLogsViaHistoryForId(final TableName tableName, final UUID objectId, final AuditLevel auditLevel, final InternalTenantContext context) { final TableName historyTableName = tableName.getHistoryTableName(); if (historyTableName == null) { throw new IllegalStateException("History table shouldn't be null for " + tableName); } final Long targetRecordId = dbRouter.onDemand(true).getRecordIdFromObject(objectId.toString(), tableName.getTableName()); final List<AuditLog> allAuditLogs = transactionalSqlDao.execute(true, new EntitySqlDaoTransactionWrapper<List<AuditLog>>() { @Override public List<AuditLog> inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception { final List<AuditLogModelDao> auditLogsViaHistoryForTargetRecordId = entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsViaHistoryForTargetRecordId(historyTableName.name(), historyTableName.getTableName().toLowerCase(), targetRecordId, context); return buildAuditLogsFromModelDao(auditLogsViaHistoryForTargetRecordId, tableName.getObjectType(), objectId); } }); return filterAuditLogs(auditLevel, allAuditLogs); }
private void insertAudits(final TableName tableName, final M entityModelDao, final Long entityRecordId, final Long historyRecordId, final ChangeType changeType, final InternalCallContext contextMaybeWithoutAccountRecordId) { final TableName destinationTableName = MoreObjects.firstNonNull(tableName.getHistoryTableName(), tableName); final EntityAudit audit = new EntityAudit(destinationTableName, historyRecordId, changeType, contextMaybeWithoutAccountRecordId.getCreatedDate()); final InternalCallContext context; // Populate the account record id when creating the account record if (TableName.ACCOUNT.equals(tableName) && ChangeType.INSERT.equals(changeType)) { // AccountModelDao in practice final TimeZoneAwareEntity accountModelDao = (TimeZoneAwareEntity) entityModelDao; context = internalCallContextFactory.createInternalCallContext(accountModelDao, entityRecordId, contextMaybeWithoutAccountRecordId); } else { context = contextMaybeWithoutAccountRecordId; } sqlDao.insertAuditFromTransaction(audit, context); printSQLWarnings(); // We need to invalidate the caches. There is a small window of doom here where caches will be stale. // TODO Knowledge on how the key is constructed is also in AuditSqlDao if (tableName.getHistoryTableName() != null) { final CacheController<String, List> cacheController = cacheControllerDispatcher.getCacheController(CacheType.AUDIT_LOG_VIA_HISTORY); if (cacheController != null) { final String key = buildCacheKey(ImmutableMap.<Integer, Object>of(0, tableName.getHistoryTableName(), 1, tableName.getHistoryTableName(), 2, entityRecordId)); cacheController.remove(key); } } else { final CacheController<String, List> cacheController = cacheControllerDispatcher.getCacheController(CacheType.AUDIT_LOG); if (cacheController != null) { final String key = buildCacheKey(ImmutableMap.<Integer, Object>of(0, tableName, 1, entityRecordId)); cacheController.remove(key); } } }
@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); }
private TableName findTableNameForHistoryTableName(final TableName historyTableName) { for (final TableName tableName : TableName.values()) { if (historyTableName.equals(tableName.getHistoryTableName())) { return tableName; } } return null; } });
@Override public List<AuditLogWithHistory> getAuditLogsWithHistoryForId(final HistorySqlDao transactional, final TableName tableName, final UUID objectId, final AuditLevel auditLevel, final InternalTenantContext context) { final TableName historyTableName = tableName.getHistoryTableName(); if (historyTableName == null) { throw new IllegalStateException("History table shouldn't be null for " + tableName);
@Override public M execute() throws Throwable { final M reHydratedEntity; if (changeType == ChangeType.DELETE) { reHydratedEntity = deletedEntity; } else { // See note above regarding "markAsInactive" operations reHydratedEntity = MoreObjects.firstNonNull(sqlDao.getById(entityId, context), deletedEntity); printSQLWarnings(); } Preconditions.checkNotNull(reHydratedEntity, "reHydratedEntity cannot be null"); final Long entityRecordId = reHydratedEntity.getRecordId(); final TableName tableName = reHydratedEntity.getTableName(); // Note: audit entries point to the history record id final Long historyRecordId; if (tableName.getHistoryTableName() != null) { historyRecordId = insertHistory(entityRecordId, reHydratedEntity, changeType, context); } else { historyRecordId = entityRecordId; } // Make sure to re-hydrate the object (especially needed for create calls) insertAudits(tableName, reHydratedEntity, entityRecordId, historyRecordId, changeType, context); return reHydratedEntity; } });
private List<AuditLog> doGetAuditLogsViaHistoryForId(final TableName tableName, final UUID objectId, final AuditLevel auditLevel, final InternalTenantContext context) { final TableName historyTableName = tableName.getHistoryTableName(); if (historyTableName == null) { throw new IllegalStateException("History table shouldn't be null for " + tableName); } final Long targetRecordId = dbRouter.onDemand(true).getRecordIdFromObject(objectId.toString(), tableName.getTableName()); final List<AuditLog> allAuditLogs = transactionalSqlDao.execute(true, new EntitySqlDaoTransactionWrapper<List<AuditLog>>() { @Override public List<AuditLog> inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception { final List<AuditLogModelDao> auditLogsViaHistoryForTargetRecordId = entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsViaHistoryForTargetRecordId(historyTableName.name(), historyTableName.getTableName().toLowerCase(), targetRecordId, context); return buildAuditLogsFromModelDao(auditLogsViaHistoryForTargetRecordId, tableName.getObjectType(), objectId); } }); return filterAuditLogs(auditLevel, allAuditLogs); }
private void insertAudits(final TableName tableName, final M entityModelDao, final Long entityRecordId, final Long historyRecordId, final ChangeType changeType, final InternalCallContext contextMaybeWithoutAccountRecordId) { final TableName destinationTableName = MoreObjects.firstNonNull(tableName.getHistoryTableName(), tableName); final EntityAudit audit = new EntityAudit(destinationTableName, historyRecordId, changeType, contextMaybeWithoutAccountRecordId.getCreatedDate()); final InternalCallContext context; // Populate the account record id when creating the account record if (TableName.ACCOUNT.equals(tableName) && ChangeType.INSERT.equals(changeType)) { // AccountModelDao in practice final TimeZoneAwareEntity accountModelDao = (TimeZoneAwareEntity) entityModelDao; context = internalCallContextFactory.createInternalCallContext(accountModelDao, entityRecordId, contextMaybeWithoutAccountRecordId); } else { context = contextMaybeWithoutAccountRecordId; } sqlDao.insertAuditFromTransaction(audit, context); printSQLWarnings(); // We need to invalidate the caches. There is a small window of doom here where caches will be stale. // TODO Knowledge on how the key is constructed is also in AuditSqlDao if (tableName.getHistoryTableName() != null) { final CacheController<String, List> cacheController = cacheControllerDispatcher.getCacheController(CacheType.AUDIT_LOG_VIA_HISTORY); if (cacheController != null) { final String key = buildCacheKey(ImmutableMap.<Integer, Object>of(0, tableName.getHistoryTableName(), 1, tableName.getHistoryTableName(), 2, entityRecordId)); cacheController.remove(key); } } else { final CacheController<String, List> cacheController = cacheControllerDispatcher.getCacheController(CacheType.AUDIT_LOG); if (cacheController != null) { final String key = buildCacheKey(ImmutableMap.<Integer, Object>of(0, tableName, 1, entityRecordId)); cacheController.remove(key); } } }
@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); }