我有一个 ExecuteScript 处理器,该处理器针对schematron进行了XML流文件验证。我希望将schematron文件的内容缓存在某个位置,而不是一次又一次从磁盘读取每个流文件的内容。
执行此操作的最佳选择是什么?我是否还需要另一个脚本,将schematron的内容放入 context.stateManager 或 PutDistributedMapCache 或什么?
答案 0 :(得分:1)
我正要回答否,但似乎有可能。 您可以在ExecuteScript处理器中缓存变量。
通过 EcmaScript 引擎在 ExecuteScript 处理器中使用简单脚本,您实际上可以将状态存储在处理器中。
var flowFile = session.get();
if (flowFile !== null) {
var x = (x || 0) + 1;
log.error('this is round: ' + x);
session.transfer(flowFile, REL_SUCCESS);
}
在处理器内部使用此脚本将导致某些事情被记录下来:
...
ExecuteScript[id=...] this is round: 3
ExecuteScript[id=...] this is round: 2
ExecuteScript[id=...] this is round: 1
我borowed来自现有NiFi ValidateXML 处理器的基本代码。
基本思想是在以下情况下更新文件
以下代码将实现此目的,其中 SCHEMA_FILE_PATH 是架构文件的路径。在这种情况下,x为三十秒:
// type definitions
var File = Java.type("java.io.File");
var FileNotFoundException = Java.type("java.io.FileNotFoundException");
var System = Java.type("java.lang.System");
// constants
var SCHEMA_FILE_PATH = "/foo/bar"; // exchange with real path
var timeoutInMillis = 30 * 1000; // 30 seconds
// initialize
var schemaFile = schemaFile || null;
var lastUpdateMillis = lastUpdateMillis || 0;
var flowFile = session.get();
function updateSchemaFile() {
schemaFile = new File(SCHEMA_FILE_PATH);
if (!schemaFile.exists()) {
throw new FileNotFoundException("Schema file not found at specified location: " + schemaFile.getAbsolutePath());
}
lastUpdateMillis = System.currentTimeMillis();
}
if (flowFile !== null) {
var now = System.currentTimeMillis();
var schemaFileShouldBeUpdated = (schemaFile == null) || ((lastUpdateMillis || 0) + timeoutInMillis) < now;
if (schemaFileShouldBeUpdated) {
updateSchemaFile();
}
// TODO Do with the file whatever you want
log.error('was file updated this round? ' + schemaFileShouldBeUpdated + '; last update millis: ' + lastUpdateMillis);
session.transfer(flowFile, REL_SUCCESS);
}
免责声明
我无法确定是否可以清除变量,更不用说何时清除了。检查ExecuteScript处理器中使用的source code表示该脚本文件会定期重新加载。我不确定这样做的后果。
我还没有尝试使用受支持的另一种ScriptingLanguage,因为我对JavaScript最熟悉。
答案 1 :(得分:1)
在groovy
脚本中,可以用静态变量声明类,因此它们肯定会在处理器启动后保持状态。
另外,要管理这些静态变量的初始化,您可以使用ExecuteGroovyScript
处理器的功能来拦截处理器的启动和停止。
在下面的示例中,我将比较流文件内容和磁盘上的某些文件,因为我对schematron不熟悉。
import org.apache.nifi.processor.ProcessContext
class Cache {
static String validatorText = null
}
//this function called on processor start, so you can't use flow file in it
static void onStart(ProcessContext context){
//init cached(static) variable from file
Cache.validatorText = new File('/path/to/validator.txt').getText('UTF-8')
println "onStart ${context}"
}
//process flow file and compare it to `Cache.validatorText`
def ff=session.get()
if(!ff)return
def ffText = ff.read().getText("UTF-8")
assert ffText = Cache.validatorText
REL_SUCCESS << ff
注意:您可以设置
Failure strategy
=transfer to failure
。 在这种情况下,任何错误(包括断言失败)的流文件都将被重定向到REL_FAILURE,而无需其他代码。