added ability to use filters to stop certain records from being cached, fixed insert bug due to binding instants to its default timestamp

This commit is contained in:
Tim Chamberlain
2023-03-13 20:02:37 -05:00
parent ec05f7ab7e
commit e0f5c3ff49
5 changed files with 96 additions and 9 deletions

View File

@ -36,6 +36,8 @@ import com.kingsrook.qqq.backend.core.actions.interfaces.GetInterface;
import com.kingsrook.qqq.backend.core.actions.values.QPossibleValueTranslator;
import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter;
import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.logging.LogPair;
import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
@ -53,6 +55,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.cache.CacheUseCase;
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleDispatcher;
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface;
import com.kingsrook.qqq.backend.core.modules.backend.implementations.utils.BackendQueryFilterUtils;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
import com.kingsrook.qqq.backend.core.utils.StringUtils;
import org.apache.commons.lang.NotImplementedException;
@ -64,6 +67,8 @@ import org.apache.commons.lang.NotImplementedException;
*******************************************************************************/
public class GetAction
{
private static final QLogger LOG = QLogger.getLogger(InsertAction.class);
private Optional<AbstractPostQueryCustomizer> postGetRecordCustomizer;
private GetInput getInput;
@ -126,7 +131,27 @@ public class GetAction
if(recordFromSource != null)
{
QRecord recordToCache = mapSourceRecordToCacheRecord(table, recordFromSource);
boolean shouldCacheRecord = true;
////////////////////////////////////////////////////////////////////////////////
// see if there are any exclustions that need to be considered for this table //
////////////////////////////////////////////////////////////////////////////////
recordMatchExclusionLoop:
for(CacheUseCase useCase : CollectionUtils.nonNullList(table.getCacheOf().getUseCases()))
{
for(QQueryFilter filter : CollectionUtils.nonNullList(useCase.getExcludeRecordsMatching()))
{
if(BackendQueryFilterUtils.doesRecordMatch(filter, recordToCache))
{
LOG.info("Not catching record because it matches a use case's filter exclusion", new LogPair("record", recordToCache), new LogPair("filter", filter));
shouldCacheRecord = false;
break recordMatchExclusionLoop;
}
}
}
if(shouldCacheRecord)
{
InsertInput insertInput = new InsertInput();
insertInput.setTableName(getInput.getTableName());
insertInput.setRecords(List.of(recordToCache));
@ -134,6 +159,7 @@ public class GetAction
getOutput.setRecord(insertOutput.getRecords().get(0));
}
}
}
else
{
/////////////////////////////////////////////////////////////////////////////////
@ -257,7 +283,9 @@ public class GetAction
sourceGetInput.setTableName(sourceTableName);
sourceGetInput.setUniqueKey(getInput.getUniqueKey());
GetOutput sourceGetOutput = new GetAction().execute(sourceGetInput);
return (sourceGetOutput.getRecord());
QRecord outputRecord = sourceGetOutput.getRecord();
return (outputRecord);
}

View File

@ -22,6 +22,8 @@
package com.kingsrook.qqq.backend.core.model.metadata.tables.cache;
import java.util.List;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
import com.kingsrook.qqq.backend.core.model.metadata.tables.UniqueKey;
@ -48,6 +50,8 @@ public class CacheUseCase
private UniqueKey cacheUniqueKey;
private UniqueKey sourceUniqueKey;
private List<QQueryFilter> excludeRecordsMatching;
/*******************************************************************************
@ -184,4 +188,38 @@ public class CacheUseCase
return (this);
}
/*******************************************************************************
** Getter for excludeRecordsMatching
**
*******************************************************************************/
public List<QQueryFilter> getExcludeRecordsMatching()
{
return excludeRecordsMatching;
}
/*******************************************************************************
** Setter for excludeRecordsMatching
**
*******************************************************************************/
public void setExcludeRecordsMatching(List<QQueryFilter> excludeRecordsMatching)
{
this.excludeRecordsMatching = excludeRecordsMatching;
}
/*******************************************************************************
** Fluent setter for excludeRecordsMatching
**
*******************************************************************************/
public CacheUseCase withExcludeRecordsMatching(List<QQueryFilter> excludeRecordsMatching)
{
this.excludeRecordsMatching = excludeRecordsMatching;
return (this);
}
}

View File

@ -101,7 +101,8 @@ class GetActionTest extends BaseTest
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_PERSON_MEMORY), List.of(
new QRecord().withValue("id", 1).withValue("firstName", "George").withValue("lastName", "Washington").withValue("noOfShoes", 5),
new QRecord().withValue("id", 2).withValue("firstName", "John").withValue("lastName", "Adams"),
new QRecord().withValue("id", 3).withValue("firstName", "Thomas").withValue("lastName", "Jefferson")
new QRecord().withValue("id", 3).withValue("firstName", "Thomas").withValue("lastName", "Jefferson"),
new QRecord().withValue("id", 3).withValue("firstName", "Thomas 503").withValue("lastName", "Jefferson")
));
/////////////////////////////////////////////////////////////////////////////
@ -117,6 +118,17 @@ class GetActionTest extends BaseTest
assertEquals(5, getOutput.getRecord().getValue("noOfShoes"));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// try to get from the table which caches it - but should not find because use case should filter out because of matching 503 //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
{
GetInput getInput = new GetInput();
getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY_CACHE);
getInput.setUniqueKey(Map.of("firstName", "Thomas 503", "lastName", "Jefferson"));
GetOutput getOutput = new GetAction().execute(getInput);
assertNull(getOutput.getRecord());
}
///////////////////////////////////////////////////////////////////////////
// request a row that doesn't exist in cache or source, should miss both //
///////////////////////////////////////////////////////////////////////////

View File

@ -739,6 +739,15 @@ public class TestUtils
.withSourceUniqueKey(uniqueKey)
.withCacheUniqueKey(uniqueKey)
.withCacheSourceMisses(false)
.withExcludeRecordsMatching(List.of(
new QQueryFilter(
new QFilterCriteria(
"firstName",
QCriteriaOperator.CONTAINS,
List.of("503")
)
)
))
));
}

View File

@ -739,7 +739,7 @@ public class QueryManager
}
else if(value instanceof Instant i)
{
statement.setString(index, i.toString());
statement.setString(index, i.toString().replaceAll("T", " ").replaceAll("Z", ""));
return (1);
}
else if(value instanceof LocalDate ld)