我正在编写处理产品事件(创建,更新,删除)的管道。每个产品都属于具有一定持续时间的销售。我希望能够对给定销售中的所有产品进行一些汇总。出于本示例的目的,假设我只想要每笔销售的唯一商品ID列表。
因此,我的管道正在使用销售ID上的会话窗口,其间隔时间非常长(因此,当销售结束且没有更多产品更新发布时,该销售的窗口也将关闭)。我的问题是,如何为此编写单元测试?
为进行此测试,我们假设以下内容:
applyDistinctProductsTransform
基本上会执行我上面所说的内容。创建KV<String, String>
元素,其中键是销售ID;设置会话窗口的间隔时间为600秒;并最终创建一个包含每次销售所有产品ID的串联字符串。这是我到目前为止所拥有的:
我创建一个TestStream
并添加一些元素:sale1
的3个产品。接下来,我将水印提高到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();
}
但是,
sale1
,product1,product2,product3,product9
,因此product9
被附加到窗口。我希望该产品可以在单独的窗口中处理,因此最终会在输出PCollection中的不同行中出现。inWindow
函数,并且找到了一个fixed time window的示例,但我不知道如何在会话窗口中执行相同的操作。您可以查看PTransform和unit test的完整代码。
答案 0 :(得分:2)
1)我相信您有一个简单的单元问题。 Duration.standardSeconds以秒为单位指定了600的窗口间隔持续时间,而new Instant(long)使用毫秒,这意味着600秒的间隔大于700毫秒的时间间隔,从而导致会话合并。
2)会话仍在内部使用间隔窗口。您将需要根据触发策略计算所有会话合并后输出窗口的状态。默认情况下,会话窗口使用IntervalWindow(timestamp, gap duration),并合并所有overlapping windows以创建更大的窗口。例如,如果您为同一会话密钥设置了窗口(开始时间,结束时间),[10、14],[12、18],[4、14],则它们将全部合并为一个[4, 18]窗口。