Google cloud dataflow 如何在Beam管道中为会话窗口编写单元测试?

Google cloud dataflow 如何在Beam管道中为会话窗口编写单元测试?,google-cloud-dataflow,apache-beam,Google Cloud Dataflow,Apache Beam,我正在编写一个处理产品事件(创建、更新、删除)的管道。每种产品都属于有一定期限的销售。我希望能够对给定销售中的所有产品执行一些聚合。在本例中,假设我只需要每次销售的唯一产品ID列表 因此,我的管道在销售id上使用会话窗口,间隔时间很长(因此,当销售结束并且没有发布更多产品更新时,该销售的窗口也会关闭)。我的问题是,我如何为此编写单元测试 为了进行此测试,让我们假设以下情况: 事件只是带有销售ID和产品ID的字符串,由空格分隔 applydistinctproductstrasform将基本上执

我正在编写一个处理产品事件(创建、更新、删除)的管道。每种产品都属于有一定期限的销售。我希望能够对给定销售中的所有产品执行一些聚合。在本例中,假设我只需要每次销售的唯一产品ID列表

因此,我的管道在销售id上使用会话窗口,间隔时间很长(因此,当销售结束并且没有发布更多产品更新时,该销售的窗口也会关闭)。我的问题是,我如何为此编写单元测试

为了进行此测试,让我们假设以下情况:

  • 事件只是带有销售ID和产品ID的字符串,由空格分隔
  • applydistinctproductstrasform
    将基本上执行我上面所说的。创建
    KV
    元素,其中键是销售id;设置间隔时间为600秒的会话窗口;最后创建每个销售的所有产品ID的连接字符串
以下是我到目前为止的情况:

我创建了一个
TestStream
并添加了一些元素:3个产品用于
sale1
。接下来,我将水印提前到700,远远超出了间隔时间。添加另一个产品,最后水印被提升到无穷大

@Test
public void TestSessionWindow() {
    Coder<String> utfCoder = StringUtf8Coder.of();
    TestStream<String> onTimeProducts = 
TestStream.create(utfCoder).addElements(
            TimestampedValue.of("sale1 product1", new Instant(0)),
            TimestampedValue.of("sale1 product2", new Instant(0)),
            TimestampedValue.of("sale1 product3", new Instant(0))
    )
            .advanceWatermarkTo(new Instant(700)) // watermark passes trigger time
    .addElements(
            TimestampedValue.of("campaign1 product9", new Instant(710))
    )
    .advanceWatermarkToInfinity();

    PCollection<KV<String, String>> results = applyDistinctProductsTransform(pipeline, onTimeProducts);

    PAssert.that(results).containsInAnyOrder(
            KV.of("sale1", "product1,product2,product3"),
            KV.of("sale1", "product9")
    );
    pipeline.run().waitUntilFinish();
}
@测试
public void TestSessionWindow(){
Coder utfCoder=StringUtf8Coder.of();
TestStream onTimeProducts=
create(utfCoder).addElements(
TimestampedValue.of(“sale1 product1”,新即时(0)),
TimestampedValue.of(“sale1 product2”,新即时(0)),
TimestampedValue.of(“sale1 product3”,新即时(0))
)
.advanceWatermarkTo(新即时(700))//水印通过触发时间
.补遗(
TimestampedValue.of(“活动1产品9”,新即时(710))
)
.advancewatermarktofinity();
PCollection results=applyDistinctProductsTransform(管道、onTimeProducts);
(结果)包含任何顺序(
KV.(“销售1”、“产品1、产品2、产品3”),
千伏(“销售1”、“产品9”)
);
pipeline.run().waitUntilFinish();
}
但是,

  • 管道输出的KV为
    sale1
    product1、product2、product3、product9
    ,因此
    product9
    被附加到窗口中。我希望这个产品在一个单独的窗口中处理,因此最终在输出PCollection的另一行中结束
  • 我怎么能在过路人中只得到一个窗口的结果?我知道有
    inWindow
    函数,我已经找到了一个示例,但是我不知道如何对会话窗口执行相同的操作
  • 您可以查看和的完整代码。

    1)我相信您有一个简单的单元问题。窗口间隔持续时间600以秒为单位指定,但使用毫秒,这意味着600秒的间隔大于700毫秒的时间间隔,导致会话合并

    2) 会话仍然在内部使用间隔窗口。您需要根据触发策略计算合并所有会话后的输出窗口。默认情况下,会话窗口使用,并合并所有以创建更大的窗口。例如,如果对同一会话密钥有窗口(开始时间、结束时间),[10,14]、[12,18]、[4,14],则它们都将合并生成一个[4,18]窗口