actinarium/philtre

构建配置化处理链的简单解决方案,包括过滤器和流。

1.1 2014-05-03 00:10 UTC

This package is not auto-updated.

Last update: 2024-09-28 15:43:59 UTC


README

Philtre 是构建配置化处理链的简单解决方案,包括过滤器和流。

目前库的开发还处于早期阶段,我现在无法花更多时间在这上面。事实上,我需要这个库来为即将到期的项目使用,但决定分享它,因为其他人可能也会觉得它有用。所以现在请原谅文档的不足,请查看 phpdoc / 测试来了解它是如何工作的。

Build Status Scrutinizer Code Quality Code Coverage

许可

此库根据 BSD 3-Clause 许可协议 许可。

Philtre 的架构

Philtre 的主要概念包括

  • 过滤器 — 实现了 process() 方法的对象,负责处理输入并产生输出。过滤器应执行一个原子操作,例如填充文本模板,执行正则表达式替换,从磁盘读取数据,将输入解析成对象等。过滤器产生或操作的所有内容,都应从上下文中检索并存储。过滤器还可以接受参数,这些参数在语义上更像是配置而不是数据。
  • FilterContext — 一个对象,其中一个或多个过滤器从中获取输入并将输出存储。多个过滤器可以共享一个 FilterContext 来重用相同的资源,以及每个过滤器都可以在自己的 FilterContext 中“沙盒化”。包含三种类型的 FilterContext:SimpleFilterContextStreamedFilterContextWiringFilterContext
  • ExecutionManager — 负责创建过滤器,将它们分配给过滤器上下文并调用处理链,所有这些都是根据提供的配置动态进行的。包含一个执行管理器:BundledPipeline

库鼓励通过提供一系列接口来实现自己的过滤器、上下文和执行管理器。

待办事项:有时间后完成文档。

管道描述符

这是对 test/Actinarium/Philtre/Test/Resources/reference_config.json 管道描述符的解释,该描述符用于 BundledPipelineTest

配置以 JSON 格式存储,方便使用。它可以是你喜欢的任何格式——重要的是在最后,你为 BundledPipeline 构造函数提供了一个正确组成的对象(或关联数组,但最好是对象)。

过滤器别名

"filters" : {
    "fixture" : "\\Actinarium\\Philtre\\Test\\Resources\\FixtureFilter"
}

此配置允许将过滤器类别名为 ID。通常这是一个全局应用程序配置,它与传入的配置混合,而不是在每个管道描述符中重复。

初始数据

"streams" : {
    "INPUT1" : "BaseOne",
    "INPUT2" : "BaseTwo"
}

在这里,您可以定义在过滤器开始处理数据之前应初始化的流。键是管理器中的流 ID,值可以是您的处理链中有效的任何内容(在这种情况下,两者都是字符串)。

参数

"parameters" : {
    "paramOne" : "One",
    "paramTwo" : [2, 3]
}

在这里,您可以定义可以稍后作为参数传递给您的过滤器的参数。要使用在此处定义的参数,应将参数 ID 用百分号包裹传递。

...
"filter"     : "fixture",
"parameters" : {
    "someParam"  : "%paramOne%",
    "someParam2" : "%paramTwo%"
},
...

值可以是您的处理链中有效的任何内容(在这种情况下,两者都是字符串)。

要返回的数据

"return" : {
    "input1"   : "INPUT1",
    "input2"   : "INPUT2",
    "input2-1" : "INPUT2EDITEDONCE",
    "input2-2" : "INPUT2EDITEDTWICE",
    "output"   : "OUTPUT",
    "output-2" : "OUTPUTTWICE"
},

此块表示:返回关联数组,其中$result['input1']包含来自输入流INPUT1的数据,$result['output-2']包含来自输出流OUTPUTTWICE的数据等。 注意:处理时所有这些流都应存在,否则将抛出异常。

存在两种不同的表示方法

"return" : ["INPUT1", "INPUT2", "INPUT2EDITEDONCE", "INPUT2EDITEDTWICE", "OUTPUT", "OUTPUTTWICE"],

这意味着,返回关联数组,键是流ID(例如$result['INPUT2EDITEDONCE'])。基本上这与前一种方法相似,但没有对流ID进行别名化。

"return" : "OUTPUT"

这意味着只返回一个字符串的数据,而不将其包装在关联数组中。

过滤器链

过滤器链是可选的,然而创建一个没有过滤器的链似乎没有太多意义,对吧?

"chain" : [
    {
        "filter"     : "fixture",
        "context"    : "C1",
        "parameters" : {
            "suffix" : "First"
        },
        "inject"     : {
            "IN1" : "INPUT1",
            "IN2" : "INPUT2"
        },
        "extract"    : {
            "OUT" : "OUTPUT"
        }
    },
    {
        // filter #2 descriptor
    },
    ...
    {
        // filter #n descriptor
    }
]

链定义了一个将按列表中出现的顺序依次处理数据的过滤器列表。

注意:处理不是事务性的,这意味着如果某些过滤器更改了状态(例如,将数据写入磁盘),然后后续的过滤器失败,更改将不会被回滚。这就是为什么建议将状态更改操作放在最后执行。

过滤器链描述符

filter

"filter" : "fixture"

"filter" : "\\Actinarium\\Philtre\\Test\\Resources\\FixtureFilter"

必填。您可以使用过滤器的ID或完整类名。

context

"context" : "C1"

可选。如果您想多个过滤器共享一个上下文,您必须显式指定相同的上下文ID(可以是任何字符串)。对于不共享上下文的沙箱过滤器,您可以安全地省略上下文声明,并且管理器将只为该过滤器创建一个匿名上下文。

parameters

"parameters" : {
    "suffix"        : "Second",
    "externalParam" : "%paramSetForWholeChain%",
    ...
}

parameters包含将传递给当前过滤器构造函数的数据。参数可以是任何类型,不仅仅是字符串。您可以使用通过将它们的ID包裹在百分号中来定义全局参数。

inject

"inject" : {
    "IN1" : "INPUT1",
    "IN2" : "INPUT2"
}

此行指示在触发过滤器之前,将管理器中的INPUT1和INPUT2流分别放入当前过滤器上下文中的IN1和IN2 ID下。这些应遵守过滤器的所需和使用流。

管理器有义务将其当前过滤器所需的全部流提供到其上下文中。

注意:如果有多个过滤器共享一个上下文,则只能向它们中的第一个注入数据,除非您想在共享上下文中中途替换数据。

extract

"extract"    : {
    "IN2" : "INPUT2EDITEDTWICE",
    "OUT" : "OUTPUTTWICE"
}

此行指示在过滤器完成处理之后,将IN2和OUT流从当前过滤器上下文中提取到管理器流INPUT2EDITEDTWICE和OUTPUTTWICE中分别。这些应遵守过滤器的导出和使用流。

如果管理器在后续处理中不需要过滤器输出,或者不需要将其作为返回值,则管理器没有义务获取过滤器输出。

注意:如果有多个过滤器共享一个上下文,则只能从它们中的最后一个提取数据,除非您想提取中间数据。

参考配置流程说明

以下是BundledPipelineTest工作时的发生情况

  1. INPUT1和INPUT2被初始化为值"BaseOne"和"BaseTwo"。
  2. 在第一个过滤器触发后,管理器将当前IN2值"BaseTwo_BaseOne"从上下文存储到INPUT2EDITEDONCE流中,并将当前OUT值("BaseOne_BaseTwo_First")存储到OUTPUT流中。请注意,在此点,INPUT1和INPUT2都没有发生变化:IN2的数据在过滤器的上下文中编辑,而不是在管理器的上下文中。
  3. 对于第二个过滤器,管理器提供INPUT1和INPUT2,但从未获得任何输出。此外,管理器为过滤器创建了一个命名上下文,但它不会与其他任何过滤器共享,因此这是有点多余的。
  4. 第三个过滤器与第一个过滤器在相同的上下文中初始化。它已经有了IN1、IN2和OUT值,IN2为"BaseTwo_BaseOne"。管理器将第一个过滤器存储的OUTPUT覆盖上下文中的IN1,然后再次提取更改后的IN2("BaseTwo_BaseOne_BaseOne_BaseTwo_First")到INPUT2EDITEDTWICE,并将OUT("BaseOne_BaseTwo_First_BaseTwo_BaseOne_Third")到OUTPUTTWICE。
  5. 第四个过滤器使用匿名上下文创建;它接收INPUT1和INPUT2(仍然未更改)并生成OUTPUT("BaseOne_BaseTwo_Fourth"),这覆盖了从第一个过滤器传递给第三个过滤器的OUTPUT。

希望这能理解。