diff --git a/incubator/command-dump/src/main/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/zilla.lua b/incubator/command-dump/src/main/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/zilla.lua index 5f09a458ee..b4e03817e0 100644 --- a/incubator/command-dump/src/main/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/zilla.lua +++ b/incubator/command-dump/src/main/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/zilla.lua @@ -433,7 +433,8 @@ local fields = { mqtt_ext_topic_length = ProtoField.int16("zilla.mqtt_ext.topic_length", "Length", base.DEC), mqtt_ext_topic = ProtoField.string("zilla.mqtt_ext.topic", "Topic", base.NONE), mqtt_ext_expiry = ProtoField.int32("zilla.mqtt_ext.expiry", "Expiry", base.DEC), - mqtt_ext_qos_max = ProtoField.uint16("zilla.mqtt_ext.qos_max", "QoS Maximum", base.DEC), + mqtt_ext_subscribe_qos_max = ProtoField.uint16("zilla.mqtt_ext.subscribe_qos_max", "Subscribe QoS Maximum", base.DEC), + mqtt_ext_publish_qos_max = ProtoField.uint16("zilla.mqtt_ext.publish_qos_max", "Publish QoS Maximum", base.DEC), mqtt_ext_packet_size_max = ProtoField.uint32("zilla.mqtt_ext.packet_size_max", "Packet Size Maximum", base.DEC), -- capabilities mqtt_ext_capabilities = ProtoField.uint8("zilla.mqtt_ext.capabilities", "Capabilities", base.HEX), @@ -1613,8 +1614,12 @@ function handle_mqtt_extension(buffer, offset, ext_subtree, frame_type_id) elseif kind == "SESSION" then handle_mqtt_data_session_extension(buffer, offset + kind_length, ext_subtree) end - elseif frame_type_id == FLUSH_ID and kind == "SUBSCRIBE" then - handle_mqtt_flush_subscribe_extension(buffer, offset + kind_length, ext_subtree) + elseif frame_type_id == FLUSH_ID then + if kind == "SUBSCRIBE" then + handle_mqtt_flush_subscribe_extension(buffer, offset + kind_length, ext_subtree) + elseif kind == "SESSION" then + handle_mqtt_flush_session_extension(buffer, offset + kind_length, ext_subtree) + end end elseif frame_type_id == RESET_ID then handle_mqtt_reset_extension(buffer, offset, ext_subtree) @@ -1720,13 +1725,18 @@ function handle_mqtt_begin_session_extension(buffer, offset, ext_subtree) local expiry_length = 4 local slice_expiry = buffer(expiry_offset, expiry_length) ext_subtree:add_le(fields.mqtt_ext_expiry, slice_expiry) - -- qos_max - local qos_max_offset = expiry_offset + expiry_length - local qos_max_length = 2 - local slice_qos_max = buffer(qos_max_offset, qos_max_length) - ext_subtree:add_le(fields.mqtt_ext_qos_max, slice_qos_max) + -- subscribe_qos_max + local subscribe_qos_max_offset = expiry_offset + expiry_length + local subscribe_qos_max_length = 2 + local slice_subscribe_qos_max = buffer(subscribe_qos_max_offset, subscribe_qos_max_length) + ext_subtree:add_le(fields.mqtt_ext_subscribe_qos_max, slice_subscribe_qos_max) + -- publish_qos_max + local publish_qos_max_offset = subscribe_qos_max_offset + subscribe_qos_max_length + local publish_qos_max_length = 2 + local slice_publish_qos_max = buffer(publish_qos_max_offset, publish_qos_max_length) + ext_subtree:add_le(fields.mqtt_ext_publish_qos_max, slice_publish_qos_max) -- packet_size_max - local packet_size_max_offset = qos_max_offset + qos_max_length + local packet_size_max_offset = publish_qos_max_offset + publish_qos_max_length local packet_size_max_length = 4 local slice_packet_size_max = buffer(packet_size_max_offset, packet_size_max_length) ext_subtree:add_le(fields.mqtt_ext_packet_size_max, slice_packet_size_max) @@ -1765,8 +1775,13 @@ function handle_mqtt_data_publish_extension(buffer, offset, ext_subtree) local flags_label = string.format("Flags: 0x%02x", slice_flags:le_uint()) local flags_subtree = ext_subtree:add(zilla_protocol, slice_flags, flags_label) flags_subtree:add_le(fields.mqtt_ext_publish_flags_retain, slice_flags) + -- packet_id + local packet_id_offset = flags_offset + flags_length + local packet_id_length = 2 + local slice_packet_id = buffer(packet_id_offset, packet_id_length) + ext_subtree:add_le(fields.mqtt_ext_packet_id, slice_packet_id) -- expiry_interval - local expiry_interval_offset = flags_offset + flags_length + local expiry_interval_offset = packet_id_offset + packet_id_length local expiry_interval_length = 4 local slice_expiry_interval = buffer(expiry_interval_offset, expiry_interval_length) ext_subtree:add_le(fields.mqtt_ext_expiry_interval, slice_expiry_interval) @@ -1945,6 +1960,14 @@ function handle_mqtt_flush_subscribe_extension(buffer, offset, ext_subtree) dissect_and_add_mqtt_topic_filters(buffer, topic_filters_offset, ext_subtree) end +function handle_mqtt_flush_session_extension(buffer, offset, ext_subtree) + -- packet_id + local packet_id_offset = offset + local packet_id_length = 2 + local slice_packet_id = buffer(packet_id_offset, packet_id_length) + ext_subtree:add_le(fields.mqtt_ext_packet_id, slice_packet_id) +end + function handle_mqtt_reset_extension(buffer, offset, ext_subtree) -- server_ref local server_ref_offset = offset diff --git a/incubator/command-dump/src/test/java/io/aklivity/zilla/runtime/command/dump/internal/airline/ZillaDumpCommandTest.java b/incubator/command-dump/src/test/java/io/aklivity/zilla/runtime/command/dump/internal/airline/ZillaDumpCommandTest.java index 1e5f4364e1..3451e1b604 100644 --- a/incubator/command-dump/src/test/java/io/aklivity/zilla/runtime/command/dump/internal/airline/ZillaDumpCommandTest.java +++ b/incubator/command-dump/src/test/java/io/aklivity/zilla/runtime/command/dump/internal/airline/ZillaDumpCommandTest.java @@ -1272,6 +1272,7 @@ public void generateStreamsBuffer() throws Exception .publish() .qos("EXACTLY_ONCE") .flags("RETAIN") + .packetId(0x42) .expiryInterval(77) .contentType("Content Type") .format("BINARY") @@ -1493,7 +1494,8 @@ public void generateStreamsBuffer() throws Exception .session() .flags("CLEAN_START") .expiry(42) - .qosMax(2) + .subscribeQosMax(2) + .publishQosMax(1) .packetSizeMax(42_000) .capabilities("RETAIN") .clientId("client-id") @@ -1518,7 +1520,8 @@ public void generateStreamsBuffer() throws Exception .session() .flags("CLEAN_START", "WILL") .expiry(42) - .qosMax(2) + .subscribeQosMax(1) + .publishQosMax(2) .packetSizeMax(42_000) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client-id") @@ -1585,6 +1588,27 @@ public void generateStreamsBuffer() throws Exception .build(); streams[0].write(DataFW.TYPE_ID, data23.buffer(), 0, data23.sizeof()); + DirectBuffer mqttSessionFlushEx1 = new UnsafeBuffer(MqttFunctions.flushEx() + .typeId(MQTT_TYPE_ID) + .session() + .packetId(0x2142) + .build() + .build()); + FlushFW flush5 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) + .originId(0x0000000900000022L) // north_mqtt_server + .routedId(0x0000000900000023L) // north_mqtt_kafka_mapping + .streamId(0x0000000000000025L) // INI + .sequence(401) + .acknowledge(402) + .maximum(7777) + .timestamp(0x0000000000000143L) + .traceId(0x0000000000000025L) + .budgetId(0x0000000000000000L) + .reserved(0x00000000) + .extension(mqttSessionFlushEx1, 0, mqttSessionFlushEx1.capacity()) + .build(); + streams[0].write(FlushFW.TYPE_ID, flush5.buffer(), 0, flush5.sizeof()); + // kafka extension // - CONSUMER DirectBuffer kafkaConsumerBeginEx1 = new UnsafeBuffer(KafkaFunctions.beginEx() @@ -1680,7 +1704,7 @@ public void generateStreamsBuffer() throws Exception .correlationId(77) .build() .build()); - FlushFW flush5 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) + FlushFW flush6 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) .originId(0x000000090000000fL) // north_kafka_cache_client .routedId(0x0000000900000010L) // south_kafka_cache_server .streamId(0x0000000000000027L) // INI @@ -1693,7 +1717,7 @@ public void generateStreamsBuffer() throws Exception .reserved(0x00000000) .extension(kafkaConsumerFlushEx1, 0, kafkaConsumerFlushEx1.capacity()) .build(); - streams[0].write(FlushFW.TYPE_ID, flush5.buffer(), 0, flush5.sizeof()); + streams[0].write(FlushFW.TYPE_ID, flush6.buffer(), 0, flush6.sizeof()); DirectBuffer kafkaResetEx1 = new UnsafeBuffer(KafkaFunctions.resetEx() .typeId(KAFKA_TYPE_ID) @@ -1773,7 +1797,7 @@ public void generateStreamsBuffer() throws Exception .memberId("member-id") .build() .build()); - FlushFW flush6 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) + FlushFW flush7 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) .originId(0x000000090000000fL) // north_kafka_cache_client .routedId(0x0000000900000010L) // south_kafka_cache_server .streamId(0x0000000000000029L) // INI @@ -1786,7 +1810,7 @@ public void generateStreamsBuffer() throws Exception .reserved(0x00000000) .extension(kafkaGroupFlushEx1, 0, kafkaGroupFlushEx1.capacity()) .build(); - streams[0].write(FlushFW.TYPE_ID, flush6.buffer(), 0, flush6.sizeof()); + streams[0].write(FlushFW.TYPE_ID, flush7.buffer(), 0, flush7.sizeof()); DirectBuffer kafkaGroupFlushEx2 = new UnsafeBuffer(KafkaFunctions.flushEx() .typeId(KAFKA_TYPE_ID) @@ -1799,7 +1823,7 @@ public void generateStreamsBuffer() throws Exception .members("member-3") .build() .build()); - FlushFW flush7 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) + FlushFW flush8 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) .originId(0x000000090000000fL) // north_kafka_cache_client .routedId(0x0000000900000010L) // south_kafka_cache_server .streamId(0x0000000000000028L) // REP @@ -1812,7 +1836,7 @@ public void generateStreamsBuffer() throws Exception .reserved(0x00000000) .extension(kafkaGroupFlushEx2, 0, kafkaGroupFlushEx2.capacity()) .build(); - streams[0].write(FlushFW.TYPE_ID, flush7.buffer(), 0, flush7.sizeof()); + streams[0].write(FlushFW.TYPE_ID, flush8.buffer(), 0, flush8.sizeof()); // - BOOTSTRAP DirectBuffer kafkaBootstrapBeginEx1 = new UnsafeBuffer(KafkaFunctions.beginEx() @@ -2062,7 +2086,7 @@ public void generateStreamsBuffer() throws Exception .correlationId(77) .build() .build()); - FlushFW flush8 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) + FlushFW flush9 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) .originId(0x000000090000000fL) // north_kafka_cache_client .routedId(0x0000000900000010L) // south_kafka_cache_server .streamId(0x0000000000000033L) // INI @@ -2075,7 +2099,7 @@ public void generateStreamsBuffer() throws Exception .reserved(0x00000000) .extension(kafkaMergedConsumerFlushEx, 0, kafkaMergedConsumerFlushEx.capacity()) .build(); - streams[0].write(FlushFW.TYPE_ID, flush8.buffer(), 0, flush8.sizeof()); + streams[0].write(FlushFW.TYPE_ID, flush9.buffer(), 0, flush9.sizeof()); DirectBuffer kafkaMergedFetchFlushEx = new UnsafeBuffer(KafkaFunctions.flushEx() .typeId(KAFKA_TYPE_ID) @@ -2092,7 +2116,7 @@ public void generateStreamsBuffer() throws Exception .key("key") .build() .build()); - FlushFW flush9 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) + FlushFW flush10 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) .originId(0x000000090000000fL) // north_kafka_cache_client .routedId(0x0000000900000010L) // south_kafka_cache_server .streamId(0x0000000000000033L) // INI @@ -2105,7 +2129,7 @@ public void generateStreamsBuffer() throws Exception .reserved(0x00000000) .extension(kafkaMergedFetchFlushEx, 0, kafkaMergedFetchFlushEx.capacity()) .build(); - streams[0].write(FlushFW.TYPE_ID, flush9.buffer(), 0, flush9.sizeof()); + streams[0].write(FlushFW.TYPE_ID, flush10.buffer(), 0, flush10.sizeof()); // - INIT_PRODUCER_ID DirectBuffer kafkaInitProducerIdBeginEx1 = new UnsafeBuffer(KafkaFunctions.beginEx() @@ -2537,7 +2561,7 @@ public void generateStreamsBuffer() throws Exception .build() .build() .build()); - FlushFW flush10 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) + FlushFW flush11 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) .originId(0x000000090000000fL) // north_kafka_cache_client .routedId(0x0000000900000010L) // south_kafka_cache_server .streamId(0x000000000000003dL) // INI @@ -2550,7 +2574,7 @@ public void generateStreamsBuffer() throws Exception .reserved(0x00000000) .extension(kafkaFetchFlushEx, 0, kafkaFetchFlushEx.capacity()) .build(); - streams[0].write(FlushFW.TYPE_ID, flush10.buffer(), 0, flush10.sizeof()); + streams[0].write(FlushFW.TYPE_ID, flush11.buffer(), 0, flush11.sizeof()); // - PRODUCE DirectBuffer kafkaProduceBeginEx1 = new UnsafeBuffer(KafkaFunctions.beginEx() @@ -2635,7 +2659,7 @@ public void generateStreamsBuffer() throws Exception .key("key") .build() .build()); - FlushFW flush11 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) + FlushFW flush12 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) .originId(0x000000090000000fL) // north_kafka_cache_client .routedId(0x0000000900000010L) // south_kafka_cache_server .streamId(0x000000000000003fL) // INI @@ -2648,7 +2672,7 @@ public void generateStreamsBuffer() throws Exception .reserved(0x00000000) .extension(kafkaProduceFlushEx, 0, kafkaProduceFlushEx.capacity()) .build(); - streams[0].write(FlushFW.TYPE_ID, flush11.buffer(), 0, flush11.sizeof()); + streams[0].write(FlushFW.TYPE_ID, flush12.buffer(), 0, flush12.sizeof()); // amqp extension DirectBuffer amqpBeginEx1 = new UnsafeBuffer(AmqpFunctions.beginEx() @@ -2814,7 +2838,7 @@ public void generateStreamsBuffer() throws Exception AMQP_TYPE_ID, 0, 0, 0, // int32 typeId 3 // uint8 AmqpCapabilities }); - FlushFW flush12 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) + FlushFW flush13 = flushRW.wrap(frameBuffer, 0, frameBuffer.capacity()) .originId(0x0000000900000025L) // north_amqp_server .routedId(0x0000000900000026L) // north_fan_server .streamId(0x0000000000000041L) // INI @@ -2827,7 +2851,7 @@ public void generateStreamsBuffer() throws Exception .reserved(0x00000000) .extension(amqpFlushEx, 0, amqpFlushEx.capacity()) .build(); - streams[0].write(FlushFW.TYPE_ID, flush12.buffer(), 0, flush12.sizeof()); + streams[0].write(FlushFW.TYPE_ID, flush13.buffer(), 0, flush13.sizeof()); DirectBuffer amqpAbortEx = new UnsafeBuffer(AmqpFunctions.abortEx() .typeId(AMQP_TYPE_ID) diff --git a/incubator/command-dump/src/test/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/engine/data0 b/incubator/command-dump/src/test/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/engine/data0 index 92621d7893..84a611e714 100644 Binary files a/incubator/command-dump/src/test/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/engine/data0 and b/incubator/command-dump/src/test/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/engine/data0 differ diff --git a/incubator/command-dump/src/test/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/expected_dump.pcap b/incubator/command-dump/src/test/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/expected_dump.pcap index c2f912a241..6eb2501ee6 100644 Binary files a/incubator/command-dump/src/test/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/expected_dump.pcap and b/incubator/command-dump/src/test/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/expected_dump.pcap differ diff --git a/incubator/command-dump/src/test/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/expected_dump.txt b/incubator/command-dump/src/test/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/expected_dump.txt index ed55d04cd6..151efc7cb7 100644 --- a/incubator/command-dump/src/test/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/expected_dump.txt +++ b/incubator/command-dump/src/test/resources/io/aklivity/zilla/runtime/command/dump/internal/airline/expected_dump.txt @@ -2665,10 +2665,10 @@ Zilla Frame .... ...1 = RETAIN: Set (1) QoS: EXACTLY_ONCE (2) -Frame 61: 381 bytes on wire (3048 bits), 381 bytes captured (3048 bits) +Frame 61: 383 bytes on wire (3064 bits), 383 bytes captured (3064 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::20, Dst: fe80::21 -Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 192, Ack: 193, Len: 307 +Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 192, Ack: 193, Len: 309 Zilla Frame Frame Type ID: 0x00000002 Frame Type: DATA @@ -2712,6 +2712,7 @@ Zilla Frame QoS: AT_LEAST_ONCE (1) Flags: 0x00 .... ...0 = RETAIN: Not set (0) + Packet ID: 0x0000 Expiry Interval: 42 Content Type: Content Type Length: 12 @@ -2748,17 +2749,17 @@ Zilla Frame Length: 7 Value: value77 -Frame 62: 349 bytes on wire (2792 bits), 349 bytes captured (2792 bits) +Frame 62: 351 bytes on wire (2808 bits), 351 bytes captured (2808 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::21, Dst: fe80::20 -Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 193, Ack: 499, Len: 275 +Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 193, Ack: 501, Len: 277 Zilla Frame Frame Type ID: 0x00000002 Frame Type: DATA Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00001c80 + Offset: 0x00001c88 Origin ID: 0x0000000900000022 Origin Namespace: example Origin Binding: north_mqtt_server @@ -2795,6 +2796,7 @@ Zilla Frame QoS: EXACTLY_ONCE (2) Flags: 0x01 .... ...1 = RETAIN: Set (1) + Packet ID: 0x0042 Expiry Interval: 77 Content Type: Content Type Length: 12 @@ -2827,7 +2829,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00001d40 + Offset: 0x00001d50 Origin ID: 0x0000000900000022 Origin Namespace: example Origin Binding: north_mqtt_server @@ -2915,7 +2917,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00001df8 + Offset: 0x00001e08 Origin ID: 0x0000000900000022 Origin Namespace: example Origin Binding: north_mqtt_server @@ -3003,7 +3005,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00001eb0 + Offset: 0x00001ec0 Origin ID: 0x0000000900000022 Origin Namespace: example Origin Binding: north_mqtt_server @@ -3101,7 +3103,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00001fa0 + Offset: 0x00001fb0 Origin ID: 0x0000000900000022 Origin Namespace: example Origin Binding: north_mqtt_server @@ -3187,7 +3189,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002088 + Offset: 0x00002098 Origin ID: 0x0000000900000022 Origin Namespace: example Origin Binding: north_mqtt_server @@ -3239,7 +3241,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002108 + Offset: 0x00002118 Origin ID: 0x0000000900000022 Origin Namespace: example Origin Binding: north_mqtt_server @@ -3291,7 +3293,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002188 + Offset: 0x00002198 Origin ID: 0x0000000900000022 Origin Namespace: example Origin Binding: north_mqtt_server @@ -3319,17 +3321,17 @@ Zilla Frame Length: 6 Value: Reason -Frame 70: 269 bytes on wire (2152 bits), 269 bytes captured (2152 bits) +Frame 70: 272 bytes on wire (2176 bits), 272 bytes captured (2176 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::24, Dst: fe80::25 -Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 0, Ack: 1, Len: 195 +Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 0, Ack: 1, Len: 198 Zilla Frame Frame Type ID: 0x00000001 Frame Type: BEGIN Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x000021f8 + Offset: 0x00002208 Origin ID: 0x0000000900000022 Origin Namespace: example Origin Binding: north_mqtt_server @@ -3355,7 +3357,8 @@ Zilla Frame .... ..1. = CLEAN_START: Set (1) .... .0.. = WILL: Not set (0) Expiry: 42 - QoS Maximum: 2 + Subscribe QoS Maximum: 2 + Publish QoS Maximum: 1 Packet Size Maximum: 42000 Capabilities: 0x01 .... ...1 = RETAIN: Set (1) @@ -3366,17 +3369,17 @@ Zilla Frame Length: 9 Client ID: client-id -Frame 71: 269 bytes on wire (2152 bits), 269 bytes captured (2152 bits) +Frame 71: 272 bytes on wire (2176 bits), 272 bytes captured (2176 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::25, Dst: fe80::24 -Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 1, Ack: 195, Len: 195 +Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 1, Ack: 198, Len: 198 Zilla Frame Frame Type ID: 0x00000001 Frame Type: BEGIN Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002268 + Offset: 0x00002280 Origin ID: 0x0000000900000022 Origin Namespace: example Origin Binding: north_mqtt_server @@ -3402,7 +3405,8 @@ Zilla Frame .... ..1. = CLEAN_START: Set (1) .... .1.. = WILL: Set (1) Expiry: 42 - QoS Maximum: 2 + Subscribe QoS Maximum: 1 + Publish QoS Maximum: 2 Packet Size Maximum: 42000 Capabilities: 0x0f .... ...1 = RETAIN: Set (1) @@ -3416,14 +3420,14 @@ Zilla Frame Frame 72: 280 bytes on wire (2240 bits), 280 bytes captured (2240 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::24, Dst: fe80::25 -Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 195, Ack: 196, Len: 206 +Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 198, Ack: 199, Len: 206 Zilla Frame Frame Type ID: 0x00000002 Frame Type: DATA Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x000022d8 + Offset: 0x000022f8 Origin ID: 0x0000000900000022 Origin Namespace: example Origin Binding: north_mqtt_server @@ -3462,14 +3466,14 @@ Zilla Frame Frame 73: 280 bytes on wire (2240 bits), 280 bytes captured (2240 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::25, Dst: fe80::24 -Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 196, Ack: 401, Len: 206 +Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 199, Ack: 404, Len: 206 Zilla Frame Frame Type ID: 0x00000002 Frame Type: DATA Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002358 + Offset: 0x00002378 Origin ID: 0x0000000900000022 Origin Namespace: example Origin Binding: north_mqtt_server @@ -3505,7 +3509,42 @@ Zilla Frame Deferred: 88 Data Kind: WILL (0x01) -Frame 74: 317 bytes on wire (2536 bits), 317 bytes captured (2536 bits) +Frame 74: 252 bytes on wire (2016 bits), 252 bytes captured (2016 bits) +Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) +Internet Protocol Version 6, Src: fe80::24, Dst: fe80::25 +Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 404, Ack: 405, Len: 178 +Zilla Frame + Frame Type ID: 0x00000005 + Frame Type: FLUSH + Protocol Type ID: 0x00000000 + Protocol Type: + Worker: 0 + Offset: 0x000023f8 + Origin ID: 0x0000000900000022 + Origin Namespace: example + Origin Binding: north_mqtt_server + Routed ID: 0x0000000900000023 + Routed Namespace: example + Routed Binding: north_mqtt_kafka_mapping + Stream ID: 0x0000000000000025 + Initial ID: 0x0000000000000025 + Reply ID: 0x0000000000000024 + Direction: INI + Sequence: 401 + Acknowledge: 402 + Maximum: 7777 + Timestamp: 0x0000000000000143 + Trace ID: 0x0000000000000025 + Authorization: 0x0000000000000000 + Budget ID: 0x0000000000000000 + Reserved: 0 + Extension: mqtt + Stream Type ID: 0x761ad4d0 + Stream Type: mqtt + Kind: SESSION (2) + Packet ID: 0x2142 + +Frame 75: 317 bytes on wire (2536 bits), 317 bytes captured (2536 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::26, Dst: fe80::27 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 0, Ack: 1, Len: 243 @@ -3515,7 +3554,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x000023d8 + Offset: 0x00002458 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -3559,7 +3598,7 @@ Zilla Frame Partition ID: 77 Partition ID: 88 -Frame 75: 301 bytes on wire (2408 bits), 301 bytes captured (2408 bits) +Frame 76: 301 bytes on wire (2408 bits), 301 bytes captured (2408 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::27, Dst: fe80::26 Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 1, Ack: 243, Len: 227 @@ -3569,7 +3608,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002478 + Offset: 0x000024f8 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -3609,7 +3648,7 @@ Zilla Frame Length: 4 Size: 0 -Frame 76: 379 bytes on wire (3032 bits), 379 bytes captured (3032 bits) +Frame 77: 379 bytes on wire (3032 bits), 379 bytes captured (3032 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::26, Dst: fe80::27 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 243, Ack: 228, Len: 305 @@ -3619,7 +3658,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002508 + Offset: 0x00002588 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -3680,7 +3719,7 @@ Zilla Frame Partition ID: 201 Partition ID: 202 -Frame 77: 307 bytes on wire (2456 bits), 307 bytes captured (2456 bits) +Frame 78: 307 bytes on wire (2456 bits), 307 bytes captured (2456 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::26, Dst: fe80::27 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 548, Ack: 228, Len: 233 @@ -3690,7 +3729,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x000025e0 + Offset: 0x00002660 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -3724,7 +3763,7 @@ Zilla Frame Leader Epoch: 42 Correlation ID: 77 -Frame 78: 261 bytes on wire (2088 bits), 261 bytes captured (2088 bits) +Frame 79: 261 bytes on wire (2088 bits), 261 bytes captured (2088 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::26, Dst: fe80::27 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 781, Ack: 228, Len: 187 @@ -3734,7 +3773,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002670 + Offset: 0x000026f0 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -3759,7 +3798,7 @@ Zilla Frame Length: 11 Consumer ID: consumer-id -Frame 79: 306 bytes on wire (2448 bits), 306 bytes captured (2448 bits) +Frame 80: 306 bytes on wire (2448 bits), 306 bytes captured (2448 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::28, Dst: fe80::29 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 0, Ack: 1, Len: 232 @@ -3769,7 +3808,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x000026d8 + Offset: 0x00002758 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -3810,7 +3849,7 @@ Zilla Frame Length: 5 Metadata: 1122334455 -Frame 80: 301 bytes on wire (2408 bits), 301 bytes captured (2408 bits) +Frame 81: 301 bytes on wire (2408 bits), 301 bytes captured (2408 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::29, Dst: fe80::28 Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 1, Ack: 232, Len: 227 @@ -3820,7 +3859,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002768 + Offset: 0x000027e8 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -3860,7 +3899,7 @@ Zilla Frame Length (varint32): 01 Length: 0 -Frame 81: 291 bytes on wire (2328 bits), 291 bytes captured (2328 bits) +Frame 82: 291 bytes on wire (2328 bits), 291 bytes captured (2328 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::28, Dst: fe80::29 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 232, Ack: 228, Len: 217 @@ -3870,7 +3909,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x000027f8 + Offset: 0x00002878 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -3904,7 +3943,7 @@ Zilla Frame Length: 4 Size: 0 -Frame 82: 343 bytes on wire (2744 bits), 343 bytes captured (2744 bits) +Frame 83: 343 bytes on wire (2744 bits), 343 bytes captured (2744 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::29, Dst: fe80::28 Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 228, Ack: 449, Len: 269 @@ -3914,7 +3953,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002878 + Offset: 0x000028f8 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -3970,7 +4009,7 @@ Zilla Frame Length (varint32): 01 Length: 0 -Frame 83: 287 bytes on wire (2296 bits), 287 bytes captured (2296 bits) +Frame 84: 287 bytes on wire (2296 bits), 287 bytes captured (2296 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::30, Dst: fe80::31 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 0, Ack: 1, Len: 213 @@ -3980,7 +4019,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002930 + Offset: 0x000029b0 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -4013,7 +4052,7 @@ Zilla Frame Consumer ID: consumer-id Timeout: 0 -Frame 84: 287 bytes on wire (2296 bits), 287 bytes captured (2296 bits) +Frame 85: 287 bytes on wire (2296 bits), 287 bytes captured (2296 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::31, Dst: fe80::30 Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 1, Ack: 213, Len: 213 @@ -4023,7 +4062,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x000029b0 + Offset: 0x00002a30 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -4056,7 +4095,7 @@ Zilla Frame Consumer ID: consumer-id Timeout: 999999 -Frame 85: 658 bytes on wire (5264 bits), 658 bytes captured (5264 bits) +Frame 86: 658 bytes on wire (5264 bits), 658 bytes captured (5264 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::32, Dst: fe80::33 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 0, Ack: 1, Len: 584 @@ -4066,7 +4105,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002a30 + Offset: 0x00002ab0 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -4309,7 +4348,7 @@ Zilla Frame Ack Mode ID: 0 Ack Mode: NONE -Frame 86: 407 bytes on wire (3256 bits), 407 bytes captured (3256 bits) +Frame 87: 407 bytes on wire (3256 bits), 407 bytes captured (3256 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::33, Dst: fe80::32 Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 1, Ack: 584, Len: 333 @@ -4319,7 +4358,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002c20 + Offset: 0x00002ca0 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -4388,7 +4427,7 @@ Zilla Frame Ack Mode ID: 1 Ack Mode: LEADER_ONLY -Frame 87: 339 bytes on wire (2712 bits), 339 bytes captured (2712 bits) +Frame 88: 339 bytes on wire (2712 bits), 339 bytes captured (2712 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::33, Dst: fe80::32 Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 334, Ack: 584, Len: 265 @@ -4398,7 +4437,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002d18 + Offset: 0x00002d98 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -4451,7 +4490,7 @@ Zilla Frame Ack Mode ID: -1 Ack Mode: IN_SYNC_REPLICAS -Frame 88: 459 bytes on wire (3672 bits), 459 bytes captured (3672 bits) +Frame 89: 459 bytes on wire (3672 bits), 459 bytes captured (3672 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::32, Dst: fe80::33 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 584, Ack: 599, Len: 385 @@ -4461,7 +4500,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002dc8 + Offset: 0x00002e48 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -4555,7 +4594,7 @@ Zilla Frame Length: 6 Value: value2 -Frame 89: 395 bytes on wire (3160 bits), 395 bytes captured (3160 bits) +Frame 90: 395 bytes on wire (3160 bits), 395 bytes captured (3160 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::32, Dst: fe80::33 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 969, Ack: 599, Len: 321 @@ -4565,7 +4604,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002ef0 + Offset: 0x00002f70 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -4643,7 +4682,7 @@ Zilla Frame Length: 6 Value: value2 -Frame 90: 304 bytes on wire (2432 bits), 304 bytes captured (2432 bits) +Frame 91: 304 bytes on wire (2432 bits), 304 bytes captured (2432 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::32, Dst: fe80::33 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 1290, Ack: 599, Len: 230 @@ -4653,7 +4692,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00002fd8 + Offset: 0x00003058 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -4687,7 +4726,7 @@ Zilla Frame Metadata: metadata Correlation ID: 77 -Frame 91: 420 bytes on wire (3360 bits), 420 bytes captured (3360 bits) +Frame 92: 420 bytes on wire (3360 bits), 420 bytes captured (3360 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::32, Dst: fe80::33 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 1520, Ack: 599, Len: 346 @@ -4697,7 +4736,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003068 + Offset: 0x000030e8 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -4776,7 +4815,7 @@ Zilla Frame Length: 3 Key: key -Frame 92: 263 bytes on wire (2104 bits), 263 bytes captured (2104 bits) +Frame 93: 263 bytes on wire (2104 bits), 263 bytes captured (2104 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::132, Dst: fe80::133 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 0, Ack: 1, Len: 189 @@ -4786,7 +4825,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003168 + Offset: 0x000031e8 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -4811,7 +4850,7 @@ Zilla Frame Producer ID: 0x0000000000000077 Producer Epoch: 0x0042 -Frame 93: 263 bytes on wire (2104 bits), 263 bytes captured (2104 bits) +Frame 94: 263 bytes on wire (2104 bits), 263 bytes captured (2104 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::133, Dst: fe80::132 Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 1, Ack: 189, Len: 189 @@ -4821,7 +4860,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x000031d0 + Offset: 0x00003250 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -4846,7 +4885,7 @@ Zilla Frame Producer ID: 0x0000000000000088 Producer Epoch: 0x0021 -Frame 94: 260 bytes on wire (2080 bits), 260 bytes captured (2080 bits) +Frame 95: 260 bytes on wire (2080 bits), 260 bytes captured (2080 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::34, Dst: fe80::35 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 0, Ack: 1, Len: 186 @@ -4856,7 +4895,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003238 + Offset: 0x000032b8 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -4882,7 +4921,7 @@ Zilla Frame Length: 5 Topic: topic -Frame 95: 260 bytes on wire (2080 bits), 260 bytes captured (2080 bits) +Frame 96: 260 bytes on wire (2080 bits), 260 bytes captured (2080 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::35, Dst: fe80::34 Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 1, Ack: 186, Len: 186 @@ -4892,7 +4931,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003298 + Offset: 0x00003318 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -4918,7 +4957,7 @@ Zilla Frame Length: 5 Topic: topic -Frame 96: 317 bytes on wire (2536 bits), 317 bytes captured (2536 bits) +Frame 97: 317 bytes on wire (2536 bits), 317 bytes captured (2536 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::34, Dst: fe80::35 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 186, Ack: 187, Len: 243 @@ -4928,7 +4967,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x000032f8 + Offset: 0x00003378 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -4974,7 +5013,7 @@ Zilla Frame Partition ID: 100 Leader ID: 4200 -Frame 97: 278 bytes on wire (2224 bits), 278 bytes captured (2224 bits) +Frame 98: 278 bytes on wire (2224 bits), 278 bytes captured (2224 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::36, Dst: fe80::37 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 0, Ack: 1, Len: 204 @@ -4984,7 +5023,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003398 + Offset: 0x00003418 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5016,7 +5055,7 @@ Zilla Frame Length: 8 Instance ID: instance -Frame 98: 278 bytes on wire (2224 bits), 278 bytes captured (2224 bits) +Frame 99: 278 bytes on wire (2224 bits), 278 bytes captured (2224 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::37, Dst: fe80::36 Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 1, Ack: 204, Len: 204 @@ -5026,7 +5065,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003410 + Offset: 0x00003490 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5058,7 +5097,7 @@ Zilla Frame Length: 8 Instance ID: instance -Frame 99: 346 bytes on wire (2768 bits), 346 bytes captured (2768 bits) +Frame 100: 346 bytes on wire (2768 bits), 346 bytes captured (2768 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::36, Dst: fe80::37 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 204, Ack: 205, Len: 272 @@ -5068,7 +5107,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003488 + Offset: 0x00003508 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5115,7 +5154,7 @@ Zilla Frame Generation ID: 42 Leader Epoch: 77 -Frame 100: 301 bytes on wire (2408 bits), 301 bytes captured (2408 bits) +Frame 101: 301 bytes on wire (2408 bits), 301 bytes captured (2408 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::38, Dst: fe80::39 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 0, Ack: 1, Len: 227 @@ -5125,7 +5164,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003540 + Offset: 0x000035c0 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5165,7 +5204,7 @@ Zilla Frame Partition ID: 77 Partition ID: 88 -Frame 101: 289 bytes on wire (2312 bits), 289 bytes captured (2312 bits) +Frame 102: 289 bytes on wire (2312 bits), 289 bytes captured (2312 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::39, Dst: fe80::38 Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 1, Ack: 227, Len: 215 @@ -5175,7 +5214,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x000035d0 + Offset: 0x00003650 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5212,7 +5251,7 @@ Zilla Frame Size: 1 Partition ID: 42 -Frame 102: 382 bytes on wire (3056 bits), 382 bytes captured (3056 bits) +Frame 103: 382 bytes on wire (3056 bits), 382 bytes captured (3056 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::38, Dst: fe80::39 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 227, Ack: 216, Len: 308 @@ -5222,7 +5261,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003650 + Offset: 0x000036d0 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5280,7 +5319,7 @@ Zilla Frame Length: 9 Metadata: metadata3 -Frame 103: 295 bytes on wire (2360 bits), 295 bytes captured (2360 bits) +Frame 104: 295 bytes on wire (2360 bits), 295 bytes captured (2360 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::3a, Dst: fe80::3b Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 0, Ack: 1, Len: 221 @@ -5290,7 +5329,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003730 + Offset: 0x000037b0 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5328,7 +5367,7 @@ Zilla Frame Length: 7 Config: config3 -Frame 104: 268 bytes on wire (2144 bits), 268 bytes captured (2144 bits) +Frame 105: 268 bytes on wire (2144 bits), 268 bytes captured (2144 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::3b, Dst: fe80::3a Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 1, Ack: 221, Len: 194 @@ -5338,7 +5377,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x000037b8 + Offset: 0x00003838 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5367,7 +5406,7 @@ Zilla Frame Length: 4 Size: 0 -Frame 105: 337 bytes on wire (2696 bits), 337 bytes captured (2696 bits) +Frame 106: 337 bytes on wire (2696 bits), 337 bytes captured (2696 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::3a, Dst: fe80::3b Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 221, Ack: 195, Len: 263 @@ -5377,7 +5416,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003820 + Offset: 0x000038a0 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5435,7 +5474,7 @@ Zilla Frame Length: 6 Value: value3 -Frame 106: 363 bytes on wire (2904 bits), 363 bytes captured (2904 bits) +Frame 107: 363 bytes on wire (2904 bits), 363 bytes captured (2904 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::3c, Dst: fe80::3d Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 0, Ack: 1, Len: 289 @@ -5445,7 +5484,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x000038d0 + Offset: 0x00003950 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5531,7 +5570,7 @@ Zilla Frame Isolation: READ_UNCOMMITTED (0) Delta Type: NONE (0) -Frame 107: 315 bytes on wire (2520 bits), 315 bytes captured (2520 bits) +Frame 108: 315 bytes on wire (2520 bits), 315 bytes captured (2520 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::3d, Dst: fe80::3c Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 1, Ack: 289, Len: 241 @@ -5541,7 +5580,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003998 + Offset: 0x00003a18 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5591,7 +5630,7 @@ Zilla Frame Isolation: READ_COMMITTED (1) Delta Type: JSON_PATCH (1) -Frame 108: 390 bytes on wire (3120 bits), 390 bytes captured (3120 bits) +Frame 109: 390 bytes on wire (3120 bits), 390 bytes captured (3120 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::3c, Dst: fe80::3d Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 289, Ack: 242, Len: 316 @@ -5601,7 +5640,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003a30 + Offset: 0x00003ab0 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5677,7 +5716,7 @@ Zilla Frame Length: 6 Value: value2 -Frame 109: 336 bytes on wire (2688 bits), 336 bytes captured (2688 bits) +Frame 110: 336 bytes on wire (2688 bits), 336 bytes captured (2688 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::3c, Dst: fe80::3d Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 605, Ack: 242, Len: 262 @@ -5687,7 +5726,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003b18 + Offset: 0x00003b98 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5742,7 +5781,7 @@ Zilla Frame Key: key1 Evaluation: LAZY (0) -Frame 110: 302 bytes on wire (2416 bits), 302 bytes captured (2416 bits) +Frame 111: 302 bytes on wire (2416 bits), 302 bytes captured (2416 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::3e, Dst: fe80::3f Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 0, Ack: 1, Len: 228 @@ -5752,7 +5791,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003bc8 + Offset: 0x00003c48 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5789,7 +5828,7 @@ Zilla Frame Length: -1 Metadata: -Frame 111: 302 bytes on wire (2416 bits), 302 bytes captured (2416 bits) +Frame 112: 302 bytes on wire (2416 bits), 302 bytes captured (2416 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::3f, Dst: fe80::3e Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 1, Ack: 228, Len: 228 @@ -5799,7 +5838,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003c58 + Offset: 0x00003cd8 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5836,7 +5875,7 @@ Zilla Frame Length: -1 Metadata: -Frame 112: 353 bytes on wire (2824 bits), 353 bytes captured (2824 bits) +Frame 113: 353 bytes on wire (2824 bits), 353 bytes captured (2824 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::3e, Dst: fe80::3f Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 228, Ack: 229, Len: 279 @@ -5846,7 +5885,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003ce8 + Offset: 0x00003d68 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5914,7 +5953,7 @@ Zilla Frame Length: 6 Value: value2 -Frame 113: 295 bytes on wire (2360 bits), 295 bytes captured (2360 bits) +Frame 114: 295 bytes on wire (2360 bits), 295 bytes captured (2360 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::3e, Dst: fe80::3f Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 507, Ack: 229, Len: 221 @@ -5924,7 +5963,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003da8 + Offset: 0x00003e28 Origin ID: 0x000000090000000f Origin Namespace: example Origin Binding: north_kafka_cache_client @@ -5962,7 +6001,7 @@ Zilla Frame Key: key Error: 0 -Frame 114: 248 bytes on wire (1984 bits), 248 bytes captured (1984 bits) +Frame 115: 248 bytes on wire (1984 bits), 248 bytes captured (1984 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::40, Dst: fe80::41 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 0, Ack: 1, Len: 174 @@ -5972,7 +6011,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003e30 + Offset: 0x00003eb0 Origin ID: 0x0000000900000025 Origin Namespace: example Origin Binding: north_amqp_server @@ -6000,7 +6039,7 @@ Zilla Frame Sender Settle Mode: SETTLED (1) Receiver Settle Mode: FIRST (0) -Frame 115: 248 bytes on wire (1984 bits), 248 bytes captured (1984 bits) +Frame 116: 248 bytes on wire (1984 bits), 248 bytes captured (1984 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::41, Dst: fe80::40 Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 1, Ack: 174, Len: 174 @@ -6010,7 +6049,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003e98 + Offset: 0x00003f18 Origin ID: 0x0000000900000025 Origin Namespace: example Origin Binding: north_amqp_server @@ -6038,7 +6077,7 @@ Zilla Frame Sender Settle Mode: MIXED (2) Receiver Settle Mode: SECOND (1) -Frame 116: 433 bytes on wire (3464 bits), 433 bytes captured (3464 bits) +Frame 117: 433 bytes on wire (3464 bits), 433 bytes captured (3464 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::40, Dst: fe80::41 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 174, Ack: 175, Len: 359 @@ -6048,7 +6087,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00003f00 + Offset: 0x00003f80 Origin ID: 0x0000000900000025 Origin Namespace: example Origin Binding: north_amqp_server @@ -6143,7 +6182,7 @@ Zilla Frame Body Kind: VALUE (9) Deferred: 9999 -Frame 117: 526 bytes on wire (4208 bits), 526 bytes captured (4208 bits) +Frame 118: 526 bytes on wire (4208 bits), 526 bytes captured (4208 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::41, Dst: fe80::40 Transmission Control Protocol, Src Port: 7114, Dst Port: 0, Seq: 175, Ack: 533, Len: 452 @@ -6153,7 +6192,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00004020 + Offset: 0x000040a0 Origin ID: 0x0000000900000025 Origin Namespace: example Origin Binding: north_amqp_server @@ -6268,7 +6307,7 @@ Zilla Frame Body Kind: VALUE_STRING32 (2) Deferred: 3333 -Frame 118: 498 bytes on wire (3984 bits), 498 bytes captured (3984 bits) +Frame 119: 498 bytes on wire (3984 bits), 498 bytes captured (3984 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::40, Dst: fe80::41 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 533, Ack: 627, Len: 424 @@ -6278,7 +6317,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x000041a0 + Offset: 0x00004220 Origin ID: 0x0000000900000025 Origin Namespace: example Origin Binding: north_amqp_server @@ -6385,7 +6424,7 @@ Zilla Frame Body Kind: VALUE_STRING32 (2) Deferred: 4444 -Frame 119: 242 bytes on wire (1936 bits), 242 bytes captured (1936 bits) +Frame 120: 242 bytes on wire (1936 bits), 242 bytes captured (1936 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::40, Dst: fe80::41 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 957, Ack: 627, Len: 168 @@ -6395,7 +6434,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00004300 + Offset: 0x00004380 Origin ID: 0x0000000900000025 Origin Namespace: example Origin Binding: north_amqp_server @@ -6419,7 +6458,7 @@ Zilla Frame Stream Type: amqp Capabilities: SEND_AND_RECEIVE (3) -Frame 120: 239 bytes on wire (1912 bits), 239 bytes captured (1912 bits) +Frame 121: 239 bytes on wire (1912 bits), 239 bytes captured (1912 bits) Ethernet II, Src: Send_00 (20:53:45:4e:44:00), Dst: Receive_00 (20:52:45:43:56:00) Internet Protocol Version 6, Src: fe80::40, Dst: fe80::41 Transmission Control Protocol, Src Port: 0, Dst Port: 7114, Seq: 1125, Ack: 627, Len: 165 @@ -6429,7 +6468,7 @@ Zilla Frame Protocol Type ID: 0x00000000 Protocol Type: Worker: 0 - Offset: 0x00004360 + Offset: 0x000043e0 Origin ID: 0x0000000900000025 Origin Namespace: example Origin Binding: north_amqp_server diff --git a/incubator/command-log/src/main/java/io/aklivity/zilla/runtime/command/log/internal/LoggableStream.java b/incubator/command-log/src/main/java/io/aklivity/zilla/runtime/command/log/internal/LoggableStream.java index 0aeb4ef3eb..72f04d6576 100644 --- a/incubator/command-log/src/main/java/io/aklivity/zilla/runtime/command/log/internal/LoggableStream.java +++ b/incubator/command-log/src/main/java/io/aklivity/zilla/runtime/command/log/internal/LoggableStream.java @@ -110,8 +110,10 @@ import io.aklivity.zilla.runtime.command.log.internal.types.stream.MqttPublishBeginExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.MqttPublishDataExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.MqttSessionBeginExFW; +import io.aklivity.zilla.runtime.command.log.internal.types.stream.MqttSessionFlushExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.MqttSubscribeBeginExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.MqttSubscribeDataExFW; +import io.aklivity.zilla.runtime.command.log.internal.types.stream.MqttSubscribeFlushExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.ProxyBeginExFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.ResetFW; import io.aklivity.zilla.runtime.command.log.internal.types.stream.SignalFW; @@ -1513,7 +1515,33 @@ private void onMqttFlushEx( final OctetsFW extension = flush.extension(); final MqttFlushExFW mqttFlushEx = mqttFlushExRO.wrap(extension.buffer(), extension.offset(), extension.limit()); - final Array32FW filters = mqttFlushEx.subscribe().filters(); + + + switch (mqttFlushEx.kind()) + { + case MqttFlushExFW.KIND_SESSION: + onMqttSessionFlushEx(offset, timestamp, mqttFlushEx.session()); + break; + case MqttFlushExFW.KIND_SUBSCRIBE: + onMqttSubscribeFlushEx(offset, timestamp, mqttFlushEx.subscribe()); + break; + } + } + + private void onMqttSessionFlushEx( + int offset, + long timestamp, + MqttSessionFlushExFW session) + { + out.printf(verboseFormat, index, offset, timestamp, format("%d", session.packetId())); + } + + private void onMqttSubscribeFlushEx( + int offset, + long timestamp, + MqttSubscribeFlushExFW subscribe) + { + final Array32FW filters = subscribe.filters(); filters.forEach(f -> out.printf(verboseFormat, index, offset, timestamp, format("%s %d %d", f.pattern(), f.subscriptionId(), f.flags()))); diff --git a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/StartingIT.java b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/StartingIT.java index 83411f0191..a445a43a84 100644 --- a/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/StartingIT.java +++ b/runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/client/StartingIT.java @@ -20,6 +20,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static org.junit.rules.RuleChain.outerRule; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.DisableOnDebug; @@ -52,6 +53,7 @@ public class StartingIT @Rule public final TestRule chain = outerRule(engine).around(k3po).around(timeout); + @Ignore("Github Actions") @Test @Configuration("client.yaml") @Specification({ diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/cache/KafkaCachePartition.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/cache/KafkaCachePartition.java index 89bbee92c1..c686dd4c45 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/cache/KafkaCachePartition.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/cache/KafkaCachePartition.java @@ -30,6 +30,8 @@ import static io.aklivity.zilla.runtime.binding.kafka.internal.types.cache.KafkaCacheEntryFW.FIELD_OFFSET_KEY; import static io.aklivity.zilla.runtime.binding.kafka.internal.types.cache.KafkaCacheEntryFW.FIELD_OFFSET_OFFSET; import static io.aklivity.zilla.runtime.binding.kafka.internal.types.cache.KafkaCacheEntryFW.FIELD_OFFSET_OWNER_ID; +import static io.aklivity.zilla.runtime.binding.kafka.internal.types.cache.KafkaCacheEntryFW.FIELD_OFFSET_PRODUCER_EPOCH; +import static io.aklivity.zilla.runtime.binding.kafka.internal.types.cache.KafkaCacheEntryFW.FIELD_OFFSET_PRODUCER_ID; import static io.aklivity.zilla.runtime.binding.kafka.internal.types.cache.KafkaCacheEntryFW.FIELD_OFFSET_SEQUENCE; import static io.aklivity.zilla.runtime.binding.kafka.internal.types.cache.KafkaCacheEntryFW.FIELD_OFFSET_TIMESTAMP; import static java.nio.ByteBuffer.allocateDirect; @@ -650,6 +652,8 @@ public int writeProduceEntryStart( entryInfo.putLong(FIELD_OFFSET_TIMESTAMP, timestamp); entryInfo.putLong(FIELD_OFFSET_OWNER_ID, ownerId); entryInfo.putLong(FIELD_OFFSET_ACKNOWLEDGE, NO_ACKNOWLEDGE); + entryInfo.putLong(FIELD_OFFSET_PRODUCER_ID, producerId); + entryInfo.putShort(FIELD_OFFSET_PRODUCER_EPOCH, producerEpoch); entryInfo.putInt(FIELD_OFFSET_SEQUENCE, sequence); entryInfo.putLong(FIELD_OFFSET_ANCESTOR, NO_ANCESTOR_OFFSET); entryInfo.putLong(FIELD_OFFSET_DESCENDANT, NO_DESCENDANT_OFFSET); diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheClientProduceFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheClientProduceFactory.java index 2fb02ad7c2..51edb9867b 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheClientProduceFactory.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaCacheClientProduceFactory.java @@ -696,12 +696,6 @@ private void onClientInitialData( final int valueLength = valueFragment != null ? valueFragment.sizeof() + deferred : -1; final int maxValueLength = valueLength + headersSizeMax; - if ((flags & FLAGS_FIN) == 0x00 && deferred == 0) - { - error = ERROR_CORRUPT_MESSAGE; - break init; - } - if (maxValueLength > partition.segmentBytes()) { error = ERROR_RECORD_LIST_TOO_LARGE; diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientInitProducerIdFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientInitProducerIdFactory.java index 74bca973ef..3467b90094 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientInitProducerIdFactory.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientInitProducerIdFactory.java @@ -68,7 +68,7 @@ public final class KafkaClientInitProducerIdFactory extends KafkaClientSaslHands private static final Consumer EMPTY_EXTENSION = ex -> {}; private static final short INIT_PRODUCE_ID_API_KEY = 22; - private static final short INIT_PRODUCE_ID_API_VERSION = 4; + private static final short INIT_PRODUCE_ID_API_VERSION = 1; private final BeginFW beginRO = new BeginFW(); private final DataFW dataRO = new DataFW(); diff --git a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientProduceFactory.java b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientProduceFactory.java index 13ef521647..8966d0a059 100644 --- a/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientProduceFactory.java +++ b/runtime/binding-kafka/src/main/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/KafkaClientProduceFactory.java @@ -549,7 +549,7 @@ private int flushRecordInit( (maxEncodeableBytes > encodePool.slotCapacity() || client.producerId != producerId || client.producerEpoch != producerEpoch || - sequence <= client.sequence)) + sequence <= client.sequence && sequence != RECORD_BATCH_BASE_SEQUENCE_NONE)) { client.doEncodeRequestIfNecessary(traceId, budgetId); } diff --git a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientProduceIT.java b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientProduceIT.java index 980b7c084f..4de16afec5 100644 --- a/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientProduceIT.java +++ b/runtime/binding-kafka/src/test/java/io/aklivity/zilla/runtime/binding/kafka/internal/stream/ClientProduceIT.java @@ -183,6 +183,16 @@ public void shouldReplyMessageValuesWithProducerId() throws Exception k3po.finish(); } + @Test + @Configuration("client.when.topic.yaml") + @Specification({ + "${app}/message.values.producer.id.changes/client", + "${net}/message.values.producer.id.changes/server"}) + public void shouldReplyMessageValuesWithProducerIdThatChanges() throws Exception + { + k3po.finish(); + } + @Test @Configuration("client.when.topic.yaml") @Specification({ diff --git a/runtime/binding-mqtt-kafka/pom.xml b/runtime/binding-mqtt-kafka/pom.xml index 4c9910f84c..78e8e17d68 100644 --- a/runtime/binding-mqtt-kafka/pom.xml +++ b/runtime/binding-mqtt-kafka/pom.xml @@ -26,7 +26,7 @@ 11 11 - 0.90 + 0.89 0 @@ -108,7 +108,7 @@ flyweight-maven-plugin ${project.version} - core mqtt kafka internal + core mqtt mqtt_kafka kafka internal io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types diff --git a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaBindingConfig.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaBindingConfig.java index 12a5f5dbe8..afcd7c7d6e 100644 --- a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaBindingConfig.java +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/config/MqttKafkaBindingConfig.java @@ -23,6 +23,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; + import io.aklivity.zilla.runtime.binding.mqtt.kafka.config.MqttKafkaConditionKind; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaSessionFactory; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Array32FW; diff --git a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaProxyFactory.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaProxyFactory.java index 7648a531bb..0a0e4a3ee4 100644 --- a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaProxyFactory.java +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaProxyFactory.java @@ -48,15 +48,16 @@ public MqttKafkaProxyFactory( { final Long2ObjectHashMap bindings = new Long2ObjectHashMap<>(); final Int2ObjectHashMap factories = new Int2ObjectHashMap<>(); + final Long2ObjectHashMap clientMetadata = new Long2ObjectHashMap<>(); - final MqttKafkaPublishFactory publishFactory = new MqttKafkaPublishFactory( - config, context, bindings::get); + final MqttKafkaPublishFactory publishFactory = new MqttKafkaPublishFactory(config, context, bindings::get, + clientMetadata::get); final MqttKafkaSubscribeFactory subscribeFactory = new MqttKafkaSubscribeFactory( config, context, bindings::get); final MqttKafkaSessionFactory sessionFactory = new MqttKafkaSessionFactory( - config, context, instanceId, bindings::get); + config, context, instanceId, bindings::get, clientMetadata); factories.put(MqttBeginExFW.KIND_PUBLISH, publishFactory); factories.put(MqttBeginExFW.KIND_SUBSCRIBE, subscribeFactory); diff --git a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishFactory.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishFactory.java index 727462d7ec..9c9c0992e6 100644 --- a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishFactory.java +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishFactory.java @@ -19,7 +19,10 @@ import static java.time.Instant.now; import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; +import java.util.Queue; import java.util.function.Function; import java.util.function.LongFunction; import java.util.function.LongUnaryOperator; @@ -29,12 +32,17 @@ import org.agrona.MutableDirectBuffer; import org.agrona.collections.Int2IntHashMap; import org.agrona.collections.Int2ObjectHashMap; +import org.agrona.collections.Long2LongHashMap; +import org.agrona.collections.Long2ObjectHashMap; import org.agrona.concurrent.UnsafeBuffer; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfiguration; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaBindingConfig; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaHeaderHelper; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaRouteConfig; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaPublishMetadata.KafkaGroup; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaPublishMetadata.KafkaOffsetMetadata; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaPublishMetadata.KafkaTopicPartition; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Flyweight; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaAckMode; @@ -44,6 +52,8 @@ import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPayloadFormat; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPayloadFormatFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPublishFlags; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPublishOffsetMetadataFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttQoS; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.OctetsFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.String16FW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.AbortFW; @@ -55,6 +65,8 @@ import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaBeginExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaDataExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaFlushExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaMergedFlushExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaMergedProduceFlushExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaResetExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttBeginExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttDataExFW; @@ -70,7 +82,6 @@ public class MqttKafkaPublishFactory implements MqttKafkaStreamFactory { private static final OctetsFW EMPTY_OCTETS = new OctetsFW().wrap(new UnsafeBuffer(new byte[0]), 0, 0); - private static final KafkaAckMode KAFKA_DEFAULT_ACK_MODE = KafkaAckMode.LEADER_ONLY; private static final String KAFKA_TYPE_NAME = "kafka"; private static final String MQTT_TYPE_NAME = "mqtt"; private static final byte SLASH_BYTE = (byte) '/'; @@ -83,6 +94,7 @@ public class MqttKafkaPublishFactory implements MqttKafkaStreamFactory private static final int KAFKA_ERROR_RECORD_LIST_TOO_LARGE = 18; private static final int KAFKA_ERROR_MESSAGE_TOO_LARGE = 10; private static final Int2IntHashMap MQTT_REASON_CODES; + private static final int OFFSET_METADATA_VERSION = 1; static { @@ -117,17 +129,20 @@ public class MqttKafkaPublishFactory implements MqttKafkaStreamFactory private final MqttBeginExFW mqttBeginExRO = new MqttBeginExFW(); private final MqttDataExFW mqttDataExRO = new MqttDataExFW(); private final KafkaResetExFW kafkaResetExRO = new KafkaResetExFW(); + private final KafkaFlushExFW kafkaFlushExRO = new KafkaFlushExFW(); private final KafkaBeginExFW.Builder kafkaBeginExRW = new KafkaBeginExFW.Builder(); private final KafkaFlushExFW.Builder kafkaFlushExRW = new KafkaFlushExFW.Builder(); private final KafkaDataExFW.Builder kafkaDataExRW = new KafkaDataExFW.Builder(); private final MqttResetExFW.Builder mqttResetExRW = new MqttResetExFW.Builder(); + private final MqttPublishOffsetMetadataFW.Builder mqttOffsetMetadataRW = new MqttPublishOffsetMetadataFW.Builder(); private final Array32FW.Builder kafkaHeadersRW = new Array32FW.Builder<>(new KafkaHeaderFW.Builder(), new KafkaHeaderFW()); private final MutableDirectBuffer writeBuffer; private final MutableDirectBuffer extBuffer; private final MutableDirectBuffer kafkaHeadersBuffer; + private final MutableDirectBuffer offsetBuffer; private final BindingHandler streamFactory; private final LongUnaryOperator supplyInitialId; private final LongUnaryOperator supplyReplyId; @@ -138,17 +153,20 @@ public class MqttKafkaPublishFactory implements MqttKafkaStreamFactory private final String16FW binaryFormat; private final String16FW textFormat; private final Int2ObjectHashMap qosLevels; + private final LongFunction supplyClientMetadata; public MqttKafkaPublishFactory( MqttKafkaConfiguration config, EngineContext context, - LongFunction supplyBinding) + LongFunction supplyBinding, + LongFunction supplyClientMetadata) { this.kafkaTypeId = context.supplyTypeId(KAFKA_TYPE_NAME); this.mqttTypeId = context.supplyTypeId(MQTT_TYPE_NAME); this.writeBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); this.extBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); this.kafkaHeadersBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); + this.offsetBuffer = new UnsafeBuffer(new byte[context.writeBuffer().capacity()]); this.helper = new MqttKafkaHeaderHelper(); this.streamFactory = context.streamFactory(); this.supplyInitialId = context::supplyInitialId; @@ -160,6 +178,7 @@ public MqttKafkaPublishFactory( this.qosLevels.put(0, new String16FW("0")); this.qosLevels.put(1, new String16FW("1")); this.qosLevels.put(2, new String16FW("2")); + this.supplyClientMetadata = supplyClientMetadata; } @Override @@ -175,6 +194,7 @@ public MessageConsumer newStream( final long routedId = begin.routedId(); final long initialId = begin.streamId(); final long authorization = begin.authorization(); + final long affinity = begin.affinity(); final OctetsFW extension = begin.extension(); final MqttBeginExFW mqttBeginEx = extension.get(mqttBeginExRO::tryWrap); @@ -191,14 +211,16 @@ public MessageConsumer newStream( { final long resolvedId = resolved.id; final String16FW messagesTopic = resolved.messages; - newStream = new MqttPublishProxy(mqtt, originId, routedId, initialId, resolvedId, - messagesTopic, binding.retainedTopic(), binding.clients)::onMqttMessage; + final int qos = mqttPublishBeginEx.qos(); + final MqttPublishProxy proxy = new MqttPublishProxy(mqtt, originId, routedId, initialId, resolvedId, affinity, + binding, messagesTopic, binding.retainedTopic(), qos, binding.clients); + newStream = proxy::onMqttMessage; } return newStream; } - private final class MqttPublishProxy + public final class MqttPublishProxy { private final MessageConsumer mqtt; private final long originId; @@ -214,6 +236,7 @@ private final class MqttPublishProxy private long initialSeq; private long initialAck; private int initialMax; + private long affinity; private long replySeq; private long replyAck; @@ -227,6 +250,13 @@ private final class MqttPublishProxy private OctetsFW clientIdOctets; private boolean retainAvailable; private int publishFlags; + private int packetId; + private int qos; + private KafkaOffsetCommitStream offsetCommit; + private Long2ObjectHashMap offsets; + private Int2ObjectHashMap> partitions; + private Long2LongHashMap leaderEpochs; + private KafkaGroup group; private MqttPublishProxy( MessageConsumer mqtt, @@ -234,8 +264,11 @@ private MqttPublishProxy( long routedId, long initialId, long resolvedId, + long affinity, + MqttKafkaBindingConfig binding, String16FW kafkaMessagesTopic, String16FW kafkaRetainedTopic, + int qos, List> clients) { this.mqtt = mqtt; @@ -243,8 +276,14 @@ private MqttPublishProxy( this.routedId = routedId; this.initialId = initialId; this.replyId = supplyReplyId.applyAsLong(initialId); - this.messages = new KafkaMessagesProxy(originId, resolvedId, this, kafkaMessagesTopic); - this.retained = new KafkaRetainedProxy(originId, resolvedId, this, kafkaRetainedTopic); + this.affinity = affinity; + this.qos = qos; + if (qos == MqttQoS.EXACTLY_ONCE.value()) + { + this.offsetCommit = new KafkaOffsetCommitStream(originId, resolvedId, this); + } + this.messages = new KafkaMessagesProxy(originId, resolvedId, affinity, this, kafkaMessagesTopic); + this.retained = new KafkaRetainedProxy(originId, resolvedId, affinity, this, kafkaRetainedTopic); this.clients = clients; } @@ -310,7 +349,7 @@ private void onMqttBegin( String topicName = mqttPublishBeginEx.topic().asString(); assert topicName != null; - final int qos = mqttPublishBeginEx.qos(); + this.qos = mqttPublishBeginEx.qos(); final String16FW clientId = mqttPublishBeginEx.clientId(); final MutableDirectBuffer clientIdBuffer = new UnsafeBuffer(new byte[clientId.sizeof() + 2]); @@ -355,28 +394,25 @@ private void onMqttBegin( .value(clientHashKeyBuffer, 0, clientHashKeyBuffer.capacity()) .build(); } - - messages.doKafkaBegin(traceId, authorization, affinity, qos); this.retainAvailable = (mqttPublishBeginEx.flags() & 1 << MqttPublishFlags.RETAIN.value()) != 0; - if (retainAvailable) + + if (qos == MqttQoS.EXACTLY_ONCE.value()) { - retained.doKafkaBegin(traceId, authorization, affinity, qos); + final MqttKafkaPublishMetadata clientMetadata = supplyClientMetadata.apply(affinity); + this.offsets = clientMetadata.offsets; + this.partitions = clientMetadata.partitions; + this.leaderEpochs = clientMetadata.leaderEpochs; + this.group = clientMetadata.group; + offsetCommit.doKafkaBegin(traceId, authorization, affinity, retainAvailable); } - } - - private String clientHashKey( - String topicName) - { - String clientHashKey = null; - if (clients != null) + else { - for (Function client : clients) + messages.doKafkaBegin(traceId, authorization, affinity, qos); + if (retainAvailable) { - clientHashKey = client.apply(topicName); - break; + retained.doKafkaBegin(traceId, authorization, affinity, qos); } } - return clientHashKey; } private void onMqttData( @@ -388,9 +424,10 @@ private void onMqttData( final long authorization = data.authorization(); final long budgetId = data.budgetId(); final int reserved = data.reserved(); - final int flags = data.flags(); final OctetsFW payload = data.payload(); final OctetsFW extension = data.extension(); + int flags = data.flags(); + int kafkaFlags = data.flags(); assert acknowledge <= sequence; assert sequence >= initialSeq; @@ -406,6 +443,8 @@ private void onMqttData( mqttDataEx = extension.get(mqttDataExRO::tryWrap); } + int deferred; + if ((flags & DATA_FLAG_INIT) != 0x00) { assert mqttDataEx.kind() == MqttDataExFW.KIND_PUBLISH; @@ -454,35 +493,106 @@ private void onMqttData( addHeader(helper.kafkaCorrelationHeaderName, mqttPublishDataEx.correlation().bytes()); } - mqttPublishDataEx.properties().forEach(property -> addHeader(property.key(), property.value())); addHeader(helper.kafkaQosHeaderName, qosLevels.get(mqttPublishDataEx.qos())); - final int deferred = mqttPublishDataEx.deferred(); + deferred = mqttPublishDataEx.deferred(); + + long producerId; + short producerEpoch; + long producerSequence; + + if (qos == MqttQoS.EXACTLY_ONCE.value()) + { + kafkaFlags = flags & ~DATA_FLAG_FIN; + final long offsetKey = offsetKey(messages.topicString, messages.qos2PartitionId); + final KafkaOffsetMetadata metadata = offsets.get(offsetKey); + producerId = metadata.producerId; + producerEpoch = metadata.producerEpoch; + producerSequence = metadata.sequence; + } + else + { + producerId = -1; + producerEpoch = -1; + producerSequence = -1; + } + kafkaDataEx = kafkaDataExRW .wrap(extBuffer, 0, extBuffer.capacity()) .typeId(kafkaTypeId) .merged(m -> m.produce(mp -> mp .deferred(deferred) .timestamp(now().toEpochMilli()) - .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .producerId(producerId) + .producerEpoch(producerEpoch) + .partition(p -> p.partitionId(-1).partitionOffset(producerSequence)) .key(b -> b.set(key)) .hashKey(this::setHashKey) .headers(kafkaHeadersRW.build()))) .build(); publishFlags = mqttPublishDataEx.flags(); + packetId = mqttPublishDataEx.packetId(); + } + else + { + deferred = 0; + if (qos == MqttQoS.EXACTLY_ONCE.value()) + { + kafkaFlags = flags & ~DATA_FLAG_FIN; + } } - messages.doKafkaData(traceId, authorization, budgetId, reserved, flags, payload, kafkaDataEx); + messages.doKafkaData(traceId, authorization, budgetId, reserved, kafkaFlags, payload, kafkaDataEx); + + if ((flags & DATA_FLAG_FIN) != 0x00 && qos == MqttQoS.EXACTLY_ONCE.value()) + { + doCommitOffsetIncomplete(traceId, authorization, messages.topicString, + messages.qos2PartitionId, packetId, messages); + } if (retainAvailable) { if (hasPublishFlagRetained(publishFlags)) { - retained.doKafkaData(traceId, authorization, budgetId, reserved, flags, payload, kafkaDataEx); + long producerId; + short producerEpoch; + long producerSequence; + + if (qos == MqttQoS.EXACTLY_ONCE.value()) + { + kafkaFlags = flags & ~DATA_FLAG_FIN; + final long offsetKey = offsetKey(messages.topicString, messages.qos2PartitionId); + final KafkaOffsetMetadata metadata = offsets.get(offsetKey); + producerId = metadata.producerId; + producerEpoch = metadata.producerEpoch; + producerSequence = metadata.sequence; + + kafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.produce(mp -> mp + .deferred(deferred) + .timestamp(now().toEpochMilli()) + .producerId(producerId) + .producerEpoch(producerEpoch) + .partition(p -> p.partitionId(-1).partitionOffset(producerSequence)) + .key(b -> b.set(key)) + .hashKey(this::setHashKey) + .headers(kafkaHeadersRW.build()))) + .build(); + } + + retained.doKafkaData(traceId, authorization, budgetId, reserved, kafkaFlags, payload, kafkaDataEx); + + if ((flags & DATA_FLAG_FIN) != 0x00 && qos == MqttQoS.EXACTLY_ONCE.value()) + { + doCommitOffsetIncomplete(traceId, authorization, retained.topicString, + retained.qos2PartitionId, packetId, retained); + } } else { @@ -498,41 +608,12 @@ private void onMqttData( } } - if ((flags & DATA_FLAG_FIN) != 0x00) + if ((flags & DATA_FLAG_FIN) != 0x00 && qos != MqttQoS.EXACTLY_ONCE.value()) { publishFlags = 0; } } - private void setHashKey( - KafkaKeyFW.Builder builder) - { - if (hashKey != null) - { - builder.set(hashKey); - } - } - - private void addFiltersHeader( - String16FW responseTopic) - { - final DirectBuffer responseBuffer = responseTopic.value(); - final int capacity = responseBuffer.capacity(); - - int offset = 0; - int matchAt = 0; - while (offset >= 0 && offset < capacity && matchAt != -1) - { - matchAt = indexOfByte(responseBuffer, offset, capacity, SLASH_BYTE); - if (matchAt != -1) - { - addHeader(helper.kafkaReplyFilterHeaderName, responseBuffer, offset, matchAt - offset); - offset = matchAt + 1; - } - } - addHeader(helper.kafkaReplyFilterHeaderName, responseBuffer, offset, capacity - offset); - } - private void onMqttEnd( EndFW end) { @@ -554,6 +635,10 @@ private void onMqttEnd( { retained.doKafkaEnd(traceId, initialSeq, authorization); } + if (offsetCommit != null) + { + offsetCommit.doKafkaEnd(traceId, authorization); + } } private void onMqttAbort( @@ -577,6 +662,10 @@ private void onMqttAbort( { retained.doKafkaAbort(traceId, authorization); } + if (offsetCommit != null) + { + offsetCommit.doKafkaAbort(traceId, authorization); + } } private void onMqttReset( @@ -603,6 +692,10 @@ private void onMqttReset( { retained.doKafkaReset(traceId); } + if (offsetCommit != null) + { + offsetCommit.doKafkaReset(traceId); + } } private void onMqttWindow( @@ -650,18 +743,6 @@ private void doMqttBegin( traceId, authorization, affinity); } - private void doMqttFlush( - long traceId, - long authorization, - long budgetId, - int reserved) - { - replySeq = messages.replySeq; - - doFlush(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, authorization, budgetId, reserved, - EMPTY_OCTETS); - } - private void doMqttAbort( long traceId, long authorization) @@ -688,9 +769,21 @@ private void doMqttEnd( } } + private void doMqttReset( + long traceId, + Flyweight extension) + { + if (!MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); + + doReset(mqtt, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, extension); + } + } + private void doMqttWindow( - long authorization, long traceId, + long authorization, long budgetId, int padding, int capabilities) @@ -703,24 +796,89 @@ private void doMqttWindow( { initialAck = newInitialAck; initialMax = newInitialMax; + int minimum = 0; + if (qos == MqttQoS.EXACTLY_ONCE.value()) + { + minimum = initialMax; + } assert initialAck <= initialSeq; - doWindow(mqtt, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, padding, 0, capabilities); + traceId, authorization, budgetId, padding, minimum, capabilities); } } - private void doMqttReset( + private String clientHashKey( + String topicName) + { + String clientHashKey = null; + if (clients != null) + { + for (Function client : clients) + { + clientHashKey = client.apply(topicName); + break; + } + } + return clientHashKey; + } + + private void doCommitOffsetIncomplete( long traceId, - Flyweight extension) + long authorization, + String topic, + int partitionId, + int packetId, + KafkaProxy kafka) { - if (!MqttKafkaState.initialClosed(state)) + final long offsetKey = offsetKey(topic, partitionId); + final KafkaOffsetMetadata metadata = offsets.get(offsetKey); + metadata.packetIds.add(packetId); + Flyweight offsetCommitEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .offsetCommit(o -> o + .topic(topic) + .progress(p -> p + .partitionId(partitionId) + .partitionOffset(metadata.sequence) + .metadata(offsetMetadataToString(metadata))) + .generationId(group.generationId) + .leaderEpoch((int) leaderEpochs.get(offsetKey))) + .build(); + + offsetCommit.unfinishedKafkas.add(kafka); + partitions.computeIfAbsent(packetId, ArrayList::new).add(new KafkaTopicPartition(topic, partitionId)); + offsetCommit.doKafkaData(traceId, authorization, 0, DATA_FLAG_COMPLETE, offsetCommitEx); + } + + private void setHashKey( + KafkaKeyFW.Builder builder) + { + if (hashKey != null) { - state = MqttKafkaState.closeInitial(state); + builder.set(hashKey); + } + } - doReset(mqtt, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, extension); + private void addFiltersHeader( + String16FW responseTopic) + { + final DirectBuffer responseBuffer = responseTopic.value(); + final int capacity = responseBuffer.capacity(); + + int offset = 0; + int matchAt = 0; + while (offset >= 0 && offset < capacity && matchAt != -1) + { + matchAt = indexOfByte(responseBuffer, offset, capacity, SLASH_BYTE); + if (matchAt != -1) + { + addHeader(helper.kafkaReplyFilterHeaderName, responseBuffer, offset, matchAt - offset); + offset = matchAt + 1; + } } + addHeader(helper.kafkaReplyFilterHeaderName, responseBuffer, offset, capacity - offset); } } @@ -814,106 +972,78 @@ private static boolean hasPublishFlagRetained( } - final class KafkaMessagesProxy + public abstract class KafkaProxy { - private MessageConsumer kafka; - private final long originId; - private final long routedId; - private final long initialId; - private final long replyId; - private final MqttPublishProxy delegate; - private final String16FW topic; - - private int state; - - private long initialSeq; - private long initialAck; - private int initialMax; - - private long replySeq; - private long replyAck; - private int replyMax; - private int replyPad; - - private KafkaMessagesProxy( + protected MessageConsumer kafka; + protected long mqttAffinity; + protected final long originId; + protected final long routedId; + protected final long initialId; + protected final long replyId; + protected final String16FW topic; + protected final String topicString; + + protected MqttPublishProxy delegate; + protected int state; + + protected long initialSeq; + protected long initialAck; + protected int initialMax; + protected int initialPad; + + protected long replySeq; + protected long replyAck; + protected int replyMax; + protected int replyPad; + protected int qos2PartitionId = -1; + + public KafkaProxy( long originId, long routedId, + long mqttAffinity, MqttPublishProxy delegate, String16FW topic) { this.originId = originId; this.routedId = routedId; + this.mqttAffinity = mqttAffinity; this.delegate = delegate; this.initialId = supplyInitialId.applyAsLong(routedId); this.replyId = supplyReplyId.applyAsLong(initialId); this.topic = topic; - - } - - private void doKafkaBegin( - long traceId, - long authorization, - long affinity, - int qos) - { - initialSeq = delegate.initialSeq; - initialAck = delegate.initialAck; - initialMax = delegate.initialMax; - state = MqttKafkaState.openingInitial(state); - - kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, affinity, topic, qos); + this.topicString = topic.asString(); } - private void doKafkaData( + abstract void doKafkaData( long traceId, long authorization, long budgetId, int reserved, int flags, OctetsFW payload, - Flyweight extension) - { - doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, flags, reserved, payload, extension); - - initialSeq += reserved; - - assert initialSeq <= initialAck + initialMax; - } + Flyweight extension); - private void doKafkaEnd( + public void sendKafkaFinData( long traceId, - long sequence, long authorization) { - if (!MqttKafkaState.initialClosed(state)) - { - initialSeq = delegate.initialSeq; - initialAck = delegate.initialAck; - initialMax = delegate.initialMax; - state = MqttKafkaState.closeInitial(state); - - doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); - } + doKafkaData(traceId, authorization, 0, 0, DATA_FLAG_FIN, EMPTY_OCTETS, EMPTY_OCTETS); } + } - private void doKafkaAbort( - long traceId, - long authorization) + public final class KafkaMessagesProxy extends KafkaProxy + { + public KafkaMessagesProxy( + long originId, + long routedId, + long mqttAffinity, + MqttPublishProxy delegate, + String16FW topic) { - if (!MqttKafkaState.initialClosed(state)) - { - initialSeq = delegate.initialSeq; - initialAck = delegate.initialAck; - initialMax = delegate.initialMax; - state = MqttKafkaState.closeInitial(state); - - doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); - } + super(originId, routedId, mqttAffinity, delegate, topic); } - private void onKafkaMessage( + public void onKafkaMessage( int msgTypeId, DirectBuffer buffer, int index, @@ -974,6 +1104,7 @@ private void onKafkaBegin( assert replyAck <= replySeq; delegate.doMqttBegin(traceId, authorization, affinity); + doKafkaWindow(traceId, authorization, 0, 0, 0); } private void onKafkaData( @@ -996,6 +1127,42 @@ private void onKafkaData( delegate.doMqttAbort(traceId, authorization); } + private void onKafkaFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + final long reserved = flush.reserved(); + final OctetsFW extension = flush.extension(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + + final ExtensionFW flushEx = extension.get(extensionRO::tryWrap); + final KafkaFlushExFW kafkaFlushEx = + flushEx != null && flushEx.typeId() == kafkaTypeId ? extension.get(kafkaFlushExRO::tryWrap) : null; + final KafkaMergedFlushExFW kafkaMergedFlushEx = + kafkaFlushEx != null && kafkaFlushEx.kind() == KafkaFlushExFW.KIND_MERGED ? kafkaFlushEx.merged() : null; + final KafkaMergedProduceFlushExFW kafkaMergedProduceFlushEx = kafkaMergedFlushEx != null && + kafkaMergedFlushEx.kind() == KafkaMergedFlushExFW.KIND_PRODUCE ? kafkaMergedFlushEx.produce() : null; + + if (kafkaMergedProduceFlushEx != null) + { + this.qos2PartitionId = kafkaMergedProduceFlushEx.partitionId(); + + if (!delegate.retainAvailable || delegate.retained.qos2PartitionId != -1) + { + delegate.doMqttWindow(traceId, authorization, 0, 0, 0); + } + } + } + private void onKafkaEnd( EndFW end) { @@ -1015,24 +1182,351 @@ private void onKafkaEnd( delegate.doMqttEnd(traceId, authorization); } - private void onKafkaFlush( - FlushFW flush) + private void onKafkaAbort( + AbortFW abort) { - final long sequence = flush.sequence(); - final long acknowledge = flush.acknowledge(); - final long traceId = flush.traceId(); - final long authorization = flush.authorization(); - final long budgetId = flush.budgetId(); - final int reserved = flush.reserved(); + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttAbort(traceId, authorization); + } + + private void onKafkaReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert acknowledge >= initialAck; + + initialAck = acknowledge; + + assert initialAck <= initialSeq; + + final OctetsFW extension = reset.extension(); + final ExtensionFW resetEx = extension.get(extensionRO::tryWrap); + final KafkaResetExFW kafkaResetEx = + resetEx != null && resetEx.typeId() == kafkaTypeId ? extension.get(kafkaResetExRO::tryWrap) : null; + + Flyweight mqttResetEx = EMPTY_OCTETS; + if (kafkaResetEx != null) + { + mqttResetEx = mqttResetExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(mqttTypeId) + .reasonCode(MQTT_REASON_CODES.get(kafkaResetEx.error())) + .build(); + } + + delegate.doMqttReset(traceId, mqttResetEx); + } + + private void onKafkaWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long authorization = window.authorization(); + final long traceId = window.traceId(); + final long budgetId = window.budgetId(); + final int padding = window.padding(); + final int capabilities = window.capabilities(); + final boolean wasOpen = MqttKafkaState.initialOpened(state); + + assert acknowledge <= sequence; + assert acknowledge >= initialAck; + assert maximum >= initialMax; + + initialAck = acknowledge; + initialMax = maximum; + initialPad = padding; + state = MqttKafkaState.openInitial(state); + + assert initialAck <= initialSeq; + + if (wasOpen || delegate.qos < MqttQoS.EXACTLY_ONCE.value()) + { + delegate.doMqttWindow(traceId, authorization, budgetId, padding, capabilities); + } + else + { + final KafkaKeyFW hashKey = delegate.hashKey != null ? delegate.hashKey : delegate.key; + final KafkaFlushExFW kafkaFlushEx = + kafkaFlushExRW.wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.produce(p -> p.hashKey(hashKey))) + .build(); + doKafkaFlush(traceId, authorization, 0, kafkaFlushEx); + } + } + + private void doKafkaBegin( + long traceId, + long authorization, + long affinity, + int qos) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + + if (!MqttKafkaState.initialOpening(state)) + { + state = MqttKafkaState.openingInitial(state); + + kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, topic, qos); + } + } + + void doKafkaData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + OctetsFW payload, + Flyweight extension) + { + doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, payload, extension); + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; + } + + private void doKafkaFlush( + long traceId, + long authorization, + long budgetId, + KafkaFlushExFW extension) + { + doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, initialPad, extension); + } + + private void doKafkaEnd( + long traceId, + long sequence, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaReset( + long traceId) + { + if (!MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + replyAck = delegate.replyAck; + replyMax = delegate.replyMax; + replyPad = delegate.replyPad; + + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, replyPad, capabilities); + } + } + + final class KafkaRetainedProxy extends KafkaProxy + { + KafkaRetainedProxy( + long originId, + long routedId, + long mqttAffinity, + MqttPublishProxy delegate, + String16FW topic) + { + super(originId, routedId, mqttAffinity, delegate, topic); + } + + private void onKafkaMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onKafkaData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onKafkaEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onKafkaAbort(abort); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onKafkaFlush(flush); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onKafkaWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onKafkaReset(reset); + break; + } + } + + private void onKafkaBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); assert acknowledge <= sequence; assert sequence >= replySeq; + assert acknowledge >= replyAck; replySeq = sequence; + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.openingReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttBegin(traceId, authorization, affinity); + doKafkaWindow(traceId, authorization, 0, 0, 0); + } + + private void onKafkaData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + doKafkaReset(traceId); + + delegate.doMqttAbort(traceId, authorization); + } + + private void onKafkaEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttEnd(traceId, authorization); + } + + private void onKafkaFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + final long reserved = flush.reserved(); + final OctetsFW extension = flush.extension(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; assert replyAck <= replySeq; - delegate.doMqttFlush(traceId, authorization, budgetId, reserved); + final ExtensionFW flushEx = extension.get(extensionRO::tryWrap); + final KafkaFlushExFW kafkaFlushEx = + flushEx != null && flushEx.typeId() == kafkaTypeId ? extension.get(kafkaFlushExRO::tryWrap) : null; + final KafkaMergedFlushExFW kafkaMergedFlushEx = + kafkaFlushEx != null && kafkaFlushEx.kind() == KafkaFlushExFW.KIND_MERGED ? kafkaFlushEx.merged() : null; + final KafkaMergedProduceFlushExFW kafkaMergedProduceFlushEx = kafkaMergedFlushEx != null && + kafkaMergedFlushEx.kind() == KafkaMergedFlushExFW.KIND_PRODUCE ? kafkaMergedFlushEx.produce() : null; + + if (kafkaMergedProduceFlushEx != null) + { + this.qos2PartitionId = kafkaMergedProduceFlushEx.partitionId(); + + if (delegate.messages.qos2PartitionId != -1) + { + delegate.doMqttWindow(traceId, authorization, 0, 0, 0); + } + } } private void onKafkaAbort( @@ -1054,6 +1548,38 @@ private void onKafkaAbort( delegate.doMqttAbort(traceId, authorization); } + private void onKafkaReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert acknowledge >= initialAck; + + initialAck = acknowledge; + + assert initialAck <= initialSeq; + + final OctetsFW extension = reset.extension(); + final ExtensionFW resetEx = extension.get(extensionRO::tryWrap); + final KafkaResetExFW kafkaResetEx = + resetEx != null && resetEx.typeId() == kafkaTypeId ? extension.get(kafkaResetExRO::tryWrap) : null; + + Flyweight mqttResetEx = EMPTY_OCTETS; + if (kafkaResetEx != null) + { + mqttResetEx = mqttResetExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(mqttTypeId) + .reasonCode(MQTT_REASON_CODES.get(kafkaResetEx.error())) + .build(); + } + + delegate.doMqttReset(traceId, mqttResetEx); + } + private void onKafkaWindow( WindowFW window) { @@ -1065,50 +1591,114 @@ private void onKafkaWindow( final long budgetId = window.budgetId(); final int padding = window.padding(); final int capabilities = window.capabilities(); + final boolean wasOpen = MqttKafkaState.initialOpened(state); assert acknowledge <= sequence; - assert acknowledge >= delegate.initialAck; - assert maximum >= delegate.initialMax; + assert acknowledge >= initialAck; + assert maximum >= initialMax; initialAck = acknowledge; + initialPad = padding; initialMax = maximum; state = MqttKafkaState.openInitial(state); assert initialAck <= initialSeq; - delegate.doMqttWindow(authorization, traceId, budgetId, padding, capabilities); + + if (wasOpen) + { + delegate.doMqttWindow(traceId, authorization, budgetId, padding, capabilities); + } + else if (delegate.qos < MqttQoS.EXACTLY_ONCE.value()) + { + delegate.doMqttWindow(traceId, authorization, budgetId, padding, capabilities); + } + else + { + final KafkaKeyFW hashKey = delegate.hashKey != null ? delegate.hashKey : delegate.key; + final KafkaFlushExFW kafkaFlushEx = + kafkaFlushExRW.wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.produce(p -> p.hashKey(hashKey))) + .build(); + doKafkaFlush(traceId, authorization, 0, kafkaFlushEx); + } } - private void onKafkaReset( - ResetFW reset) + private void doKafkaBegin( + long traceId, + long authorization, + long affinity, + int qos) { - final long sequence = reset.sequence(); - final long acknowledge = reset.acknowledge(); - final long traceId = reset.traceId(); + initialSeq = 0; + initialAck = 0; + initialMax = delegate.initialMax; + + if (!MqttKafkaState.initialOpening(state)) + { + + state = MqttKafkaState.openingInitial(state); + + kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, topic, qos); + } + } + + void doKafkaData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + OctetsFW payload, + Flyweight extension) + { + doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, payload, extension); + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; + } + + private void doKafkaFlush( + long traceId, + long authorization, + long budgetId, + KafkaFlushExFW extension) + { + doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, initialPad, extension); - assert acknowledge <= sequence; - assert acknowledge >= delegate.initialAck; + initialSeq += initialPad; - delegate.initialAck = acknowledge; + assert initialSeq <= initialAck + initialMax; + } - assert delegate.initialAck <= delegate.initialSeq; + private void doKafkaEnd( + long traceId, + long sequence, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); - final OctetsFW extension = reset.extension(); - final ExtensionFW resetEx = extension.get(extensionRO::tryWrap); - final KafkaResetExFW kafkaResetEx = - resetEx != null && resetEx.typeId() == kafkaTypeId ? extension.get(kafkaResetExRO::tryWrap) : null; + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } - Flyweight mqttResetEx = EMPTY_OCTETS; - if (kafkaResetEx != null) + private void doKafkaAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) { - mqttResetEx = mqttResetExRW - .wrap(extBuffer, 0, extBuffer.capacity()) - .typeId(mqttTypeId) - .reasonCode(MQTT_REASON_CODES.get(kafkaResetEx.error())) - .build(); - } + state = MqttKafkaState.closeInitial(state); - delegate.doMqttReset(traceId, mqttResetEx); + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } } private void doKafkaReset( @@ -1138,7 +1728,7 @@ private void doKafkaWindow( } } - final class KafkaRetainedProxy + private final class KafkaOffsetCommitStream { private MessageConsumer kafka; private final long originId; @@ -1146,87 +1736,59 @@ final class KafkaRetainedProxy private final long initialId; private final long replyId; private final MqttPublishProxy delegate; - private final String16FW topic; + private final Queue unfinishedKafkas; private int state; private long initialSeq; private long initialAck; - private int initialPad; private int initialMax; private long replySeq; private long replyAck; private int replyMax; private int replyPad; + private boolean retainAvailable; - private KafkaRetainedProxy( + + private KafkaOffsetCommitStream( long originId, long routedId, - MqttPublishProxy delegate, - String16FW topic) + MqttPublishProxy delegate) { this.originId = originId; this.routedId = routedId; this.delegate = delegate; this.initialId = supplyInitialId.applyAsLong(routedId); this.replyId = supplyReplyId.applyAsLong(initialId); - this.topic = topic; + this.unfinishedKafkas = new LinkedList<>(); } private void doKafkaBegin( long traceId, long authorization, long affinity, - int qos) + boolean retainAvailable) { - initialSeq = 0; - initialAck = 0; + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; initialMax = delegate.initialMax; state = MqttKafkaState.openingInitial(state); + this.retainAvailable = retainAvailable; - kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, affinity, topic, qos); - } - - private void doKafkaData( - long traceId, - long authorization, - long budgetId, - int reserved, - int flags, - OctetsFW payload, - Flyweight extension) - { - doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, flags, reserved, payload, extension); - - initialSeq += reserved; - - assert initialSeq <= initialAck + initialMax; - } - - private void doKafkaFlush( - long traceId, - long authorization, - long budgetId, - KafkaFlushExFW extension) - { - doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, initialPad, extension); - - initialSeq += initialPad; - - assert initialSeq <= initialAck + initialMax; + kafka = newOffsetCommitStream(this::onOffsetCommitMessage, originId, routedId, initialId, initialSeq, initialAck, + initialMax, traceId, authorization, affinity, delegate.group); } private void doKafkaEnd( long traceId, - long sequence, long authorization) { if (!MqttKafkaState.initialClosed(state)) { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; state = MqttKafkaState.closeInitial(state); doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); @@ -1239,13 +1801,16 @@ private void doKafkaAbort( { if (!MqttKafkaState.initialClosed(state)) { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; state = MqttKafkaState.closeInitial(state); doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); } } - private void onKafkaMessage( + private void onOffsetCommitMessage( int msgTypeId, DirectBuffer buffer, int index, @@ -1257,9 +1822,9 @@ private void onKafkaMessage( final BeginFW begin = beginRO.wrap(buffer, index, index + length); onKafkaBegin(begin); break; - case DataFW.TYPE_ID: - final DataFW data = dataRO.wrap(buffer, index, index + length); - onKafkaData(data); + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onKafkaWindow(window); break; case EndFW.TYPE_ID: final EndFW end = endRO.wrap(buffer, index, index + length); @@ -1269,14 +1834,6 @@ private void onKafkaMessage( final AbortFW abort = abortRO.wrap(buffer, index, index + length); onKafkaAbort(abort); break; - case FlushFW.TYPE_ID: - final FlushFW flush = flushRO.wrap(buffer, index, index + length); - onKafkaFlush(flush); - break; - case WindowFW.TYPE_ID: - final WindowFW window = windowRO.wrap(buffer, index, index + length); - onKafkaWindow(window); - break; case ResetFW.TYPE_ID: final ResetFW reset = resetRO.wrap(buffer, index, index + length); onKafkaReset(reset); @@ -1305,27 +1862,43 @@ private void onKafkaBegin( assert replyAck <= replySeq; - delegate.doMqttBegin(traceId, authorization, affinity); + doKafkaWindow(traceId, authorization, 0, 0, 0); } - private void onKafkaData( - DataFW data) + private void onKafkaWindow( + WindowFW window) { - final long sequence = data.sequence(); - final long acknowledge = data.acknowledge(); - final long traceId = data.traceId(); - final long authorization = data.authorization(); - final long budgetId = data.budgetId(); - final int reserved = data.reserved(); + final long traceId = window.traceId(); + final long authorization = window.authorization(); + final long budgetId = window.budgetId(); + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final boolean wasOpen = MqttKafkaState.initialOpened(state); assert acknowledge <= sequence; - assert sequence >= replySeq; + assert acknowledge >= initialAck; + assert maximum >= initialMax; - replySeq = sequence + reserved; + initialAck = acknowledge; + initialMax = maximum; + state = MqttKafkaState.openInitial(state); - assert replyAck <= replySeq; - doKafkaReset(traceId); - delegate.doMqttAbort(traceId, authorization); + assert initialAck <= initialSeq; + + if (!wasOpen) + { + delegate.messages.doKafkaBegin(traceId, authorization, 0, MqttQoS.EXACTLY_ONCE.value()); + if (retainAvailable) + { + delegate.retained.doKafkaBegin(traceId, authorization, 0, MqttQoS.EXACTLY_ONCE.value()); + } + } + else + { + final MqttKafkaPublishFactory.KafkaProxy kafka = unfinishedKafkas.remove(); + kafka.sendKafkaFinData(traceId, authorization); + } } private void onKafkaEnd( @@ -1333,8 +1906,6 @@ private void onKafkaEnd( { final long sequence = end.sequence(); final long acknowledge = end.acknowledge(); - final long traceId = end.traceId(); - final long authorization = end.authorization(); assert acknowledge <= sequence; assert sequence >= replySeq; @@ -1343,28 +1914,6 @@ private void onKafkaEnd( state = MqttKafkaState.closeReply(state); assert replyAck <= replySeq; - - delegate.doMqttEnd(traceId, authorization); - } - - private void onKafkaFlush( - FlushFW flush) - { - final long sequence = flush.sequence(); - final long acknowledge = flush.acknowledge(); - final long traceId = flush.traceId(); - final long authorization = flush.authorization(); - final long budgetId = flush.budgetId(); - final int reserved = flush.reserved(); - - assert acknowledge <= sequence; - assert sequence >= replySeq; - - replySeq = sequence; - - assert replyAck <= replySeq; - - delegate.doMqttFlush(traceId, authorization, budgetId, reserved); } private void onKafkaAbort( @@ -1386,32 +1935,6 @@ private void onKafkaAbort( delegate.doMqttAbort(traceId, authorization); } - private void onKafkaWindow( - WindowFW window) - { - final long sequence = window.sequence(); - final long acknowledge = window.acknowledge(); - final int maximum = window.maximum(); - final long authorization = window.authorization(); - final long traceId = window.traceId(); - final long budgetId = window.budgetId(); - final int padding = window.padding(); - final int capabilities = window.capabilities(); - - assert acknowledge <= sequence; - assert acknowledge >= initialAck; - assert maximum >= initialMax; - - initialAck = acknowledge; - initialPad = padding; - initialMax = maximum; - state = MqttKafkaState.openInitial(state); - - assert initialAck <= initialSeq; - - delegate.doMqttWindow(authorization, traceId, budgetId, padding, capabilities); - } - private void onKafkaReset( ResetFW reset) { @@ -1420,28 +1943,21 @@ private void onKafkaReset( final long traceId = reset.traceId(); assert acknowledge <= sequence; - assert acknowledge >= initialAck; - - initialAck = acknowledge; - - assert initialAck <= initialSeq; - final OctetsFW extension = reset.extension(); - final ExtensionFW resetEx = extension.get(extensionRO::tryWrap); - final KafkaResetExFW kafkaResetEx = - resetEx != null && resetEx.typeId() == kafkaTypeId ? extension.get(kafkaResetExRO::tryWrap) : null; + delegate.doMqttReset(traceId, EMPTY_OCTETS); + } - Flyweight mqttResetEx = EMPTY_OCTETS; - if (kafkaResetEx != null) - { - mqttResetEx = mqttResetExRW - .wrap(extBuffer, 0, extBuffer.capacity()) - .typeId(mqttTypeId) - .reasonCode(MQTT_REASON_CODES.get(kafkaResetEx.error())) - .build(); - } + private void doKafkaData( + long traceId, + long authorization, + long budgetId, + int flags, + Flyweight extension) + { + doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, 0, EMPTY_OCTETS, extension); - delegate.doMqttReset(traceId, mqttResetEx); + assert initialSeq <= initialAck + initialMax; } private void doKafkaReset( @@ -1471,6 +1987,30 @@ private void doKafkaWindow( } } + private String16FW offsetMetadataToString( + KafkaOffsetMetadata metadata) + { + mqttOffsetMetadataRW.wrap(offsetBuffer, 0, offsetBuffer.capacity()); + mqttOffsetMetadataRW.version(OFFSET_METADATA_VERSION); + mqttOffsetMetadataRW.producerId(metadata.producerId); + mqttOffsetMetadataRW.producerEpoch(metadata.producerEpoch); + + if (metadata.packetIds != null) + { + metadata.packetIds.forEach(p -> mqttOffsetMetadataRW.appendPacketIds(p.shortValue())); + } + final MqttPublishOffsetMetadataFW offsetMetadata = mqttOffsetMetadataRW.build(); + return new String16FW(BitUtil.toHex(offsetMetadata.buffer().byteArray(), + offsetMetadata.offset(), offsetMetadata.limit())); + } + + private static long offsetKey( + String topic, + int partitionId) + { + final int topicHashCode = System.identityHashCode(topic.intern()); + return ((long) topicHashCode << 32) | (partitionId & 0xFFFFFFFFL); + } private void doBegin( MessageConsumer receiver, @@ -1661,6 +2201,49 @@ private MessageConsumer newKafkaStream( return receiver; } + private MessageConsumer newOffsetCommitStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + KafkaGroup group) + { + final KafkaBeginExFW kafkaBeginEx = + kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .offsetCommit(o -> o + .groupId(group.groupId) + .memberId(group.memberId) + .instanceId(group.instanceId)) + .build(); + + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(kafkaBeginEx.buffer(), kafkaBeginEx.offset(), kafkaBeginEx.sizeof()) + .build(); + + MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + private void doWindow( MessageConsumer sender, long originId, diff --git a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishMetadata.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishMetadata.java new file mode 100644 index 0000000000..0ba42e3758 --- /dev/null +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishMetadata.java @@ -0,0 +1,154 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream; + +import java.util.List; +import java.util.function.IntConsumer; + +import org.agrona.BitUtil; +import org.agrona.MutableDirectBuffer; +import org.agrona.collections.Int2ObjectHashMap; +import org.agrona.collections.IntArrayList; +import org.agrona.collections.Long2LongHashMap; +import org.agrona.collections.Long2ObjectHashMap; +import org.agrona.concurrent.UnsafeBuffer; + +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPublishOffsetMetadataFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.String16FW; + +public class MqttKafkaPublishMetadata +{ + final Long2ObjectHashMap offsets; + final Int2ObjectHashMap> partitions; + final Long2LongHashMap leaderEpochs; + + KafkaGroup group; + + public MqttKafkaPublishMetadata( + Long2ObjectHashMap offsets, + Int2ObjectHashMap> partitions, + Long2LongHashMap leaderEpochs) + { + this.offsets = offsets; + this.partitions = partitions; + this.leaderEpochs = leaderEpochs; + } + + public static final class KafkaGroup + { + public final String instanceId; + public final String groupId; + public final String memberId; + public final int generationId; + + KafkaGroup( + String instanceId, + String groupId, + String memberId, + int generationId) + { + this.instanceId = instanceId; + this.groupId = groupId; + this.memberId = memberId; + this.generationId = generationId; + } + } + + public static final class KafkaTopicPartition + { + public final String topic; + public final int partitionId; + + KafkaTopicPartition( + String topic, + int partitionId) + { + this.topic = topic; + this.partitionId = partitionId; + } + } + + public static final class KafkaOffsetMetadata + { + public final long producerId; + public final short producerEpoch; + public final IntArrayList packetIds; + + public long sequence; + + KafkaOffsetMetadata( + long producerId, + short producerEpoch) + { + this(producerId, producerEpoch, new IntArrayList()); + } + + KafkaOffsetMetadata( + long producerId, + short producerEpoch, + IntArrayList packetIds) + { + this.sequence = 1; + this.producerId = producerId; + this.producerEpoch = producerEpoch; + this.packetIds = packetIds; + } + } + + public static final class KafkaOffsetMetadataHelper + { + private static final int OFFSET_METADATA_VERSION = 1; + + private final MqttPublishOffsetMetadataFW mqttOffsetMetadataRO = new MqttPublishOffsetMetadataFW(); + private final MqttPublishOffsetMetadataFW.Builder mqttOffsetMetadataRW = new MqttPublishOffsetMetadataFW.Builder(); + private final MutableDirectBuffer offsetBuffer; + + KafkaOffsetMetadataHelper( + MutableDirectBuffer offsetBuffer) + { + this.offsetBuffer = offsetBuffer; + } + + public KafkaOffsetMetadata stringToOffsetMetadata( + String16FW metadata) + { + final IntArrayList packetIds = new IntArrayList(); + UnsafeBuffer buffer = new UnsafeBuffer(BitUtil.fromHex(metadata.asString())); + final MqttPublishOffsetMetadataFW offsetMetadata = mqttOffsetMetadataRO.wrap(buffer, 0, buffer.capacity()); + if (offsetMetadata.packetIds() != null) + { + offsetMetadata.packetIds().forEachRemaining((IntConsumer) packetIds::add); + } + return new KafkaOffsetMetadata(offsetMetadata.producerId(), offsetMetadata.producerEpoch(), packetIds); + } + + public String16FW offsetMetadataToString( + KafkaOffsetMetadata metadata) + { + mqttOffsetMetadataRW.wrap(offsetBuffer, 0, offsetBuffer.capacity()); + mqttOffsetMetadataRW.version(OFFSET_METADATA_VERSION); + mqttOffsetMetadataRW.producerId(metadata.producerId); + mqttOffsetMetadataRW.producerEpoch(metadata.producerEpoch); + + if (metadata.packetIds != null) + { + metadata.packetIds.forEach(p -> mqttOffsetMetadataRW.appendPacketIds(p.shortValue())); + } + final MqttPublishOffsetMetadataFW offsetMetadata = mqttOffsetMetadataRW.build(); + return new String16FW(BitUtil.toHex(offsetMetadata.buffer().byteArray(), + offsetMetadata.offset(), offsetMetadata.limit())); + } + } +} diff --git a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSessionFactory.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSessionFactory.java index 0883705755..ec811dc013 100644 --- a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSessionFactory.java +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSessionFactory.java @@ -19,24 +19,30 @@ import static io.aklivity.zilla.runtime.engine.buffer.BufferPool.NO_SLOT; import static io.aklivity.zilla.runtime.engine.concurrent.Signaler.NO_CANCEL_ID; import static java.lang.System.currentTimeMillis; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.concurrent.TimeUnit.SECONDS; import static org.agrona.BitUtil.SIZE_OF_INT; import static org.agrona.BitUtil.SIZE_OF_LONG; import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.LongFunction; import java.util.function.LongSupplier; import java.util.function.LongUnaryOperator; import java.util.function.Supplier; +import java.util.stream.Collectors; import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; import org.agrona.collections.Int2IntHashMap; import org.agrona.collections.Int2ObjectHashMap; +import org.agrona.collections.IntArrayQueue; import org.agrona.collections.IntHashSet; +import org.agrona.collections.Long2LongHashMap; import org.agrona.collections.Long2ObjectHashMap; import org.agrona.collections.LongArrayList; import org.agrona.collections.Object2LongHashMap; @@ -48,6 +54,10 @@ import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaBindingConfig; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaHeaderHelper; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.config.MqttKafkaRouteConfig; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaPublishMetadata.KafkaGroup; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaPublishMetadata.KafkaOffsetMetadata; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaPublishMetadata.KafkaOffsetMetadataHelper; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaPublishMetadata.KafkaTopicPartition; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.Flyweight; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaAckMode; @@ -57,6 +67,7 @@ import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaKeyFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaOffsetFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaOffsetType; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaPartitionFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttExpirySignalFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPayloadFormat; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPayloadFormatFW; @@ -80,16 +91,22 @@ import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaFlushExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaGroupBeginExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaGroupFlushExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaInitProducerIdBeginExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaMergedDataExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaMergedFlushExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaMetaDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaOffsetFetchDataExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaResetExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.KafkaTopicPartitionOffsetFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttBeginExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttDataExFW; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttFlushExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttResetExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttServerCapabilities; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttSessionBeginExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttSessionDataExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttSessionDataKind; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttSessionFlushExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.ResetFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.SignalFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.WindowFW; @@ -121,6 +138,7 @@ public class MqttKafkaSessionFactory implements MqttKafkaStreamFactory private static final OctetsFW EXPIRY_SIGNAL_NAME_OCTETS = new OctetsFW().wrap(EXPIRY_SIGNAL_NAME.value(), 0, EXPIRY_SIGNAL_NAME.length()); private static final OctetsFW EMPTY_OCTETS = new OctetsFW().wrap(new UnsafeBuffer(new byte[0]), 0, 0); + private static final String16FW DEFAULT_REASON = new String16FW(null, UTF_8); private static final int DATA_FLAG_INIT = 0x02; private static final int DATA_FLAG_FIN = 0x01; private static final int DATA_FLAG_COMPLETE = 0x03; @@ -137,6 +155,7 @@ public class MqttKafkaSessionFactory implements MqttKafkaStreamFactory private static final byte MQTT_KAFKA_MAX_QOS = 2; private static final int MQTT_KAFKA_CAPABILITIES = RETAIN_AVAILABLE_MASK | WILDCARD_AVAILABLE_MASK | SUBSCRIPTION_IDS_AVAILABLE_MASK; + public static final String GROUPID_SESSION_SUFFIX = "session"; public static final Int2IntHashMap MQTT_REASON_CODES; public static final Int2ObjectHashMap MQTT_REASONS; @@ -190,12 +209,15 @@ public class MqttKafkaSessionFactory implements MqttKafkaStreamFactory private final ExtensionFW extensionRO = new ExtensionFW(); private final MqttBeginExFW mqttBeginExRO = new MqttBeginExFW(); + private final MqttFlushExFW mqttFlushExRO = new MqttFlushExFW(); private final MqttSessionStateFW mqttSessionStateRO = new MqttSessionStateFW(); private final MqttSessionSignalFW mqttSessionSignalRO = new MqttSessionSignalFW(); private final MqttWillMessageFW mqttWillRO = new MqttWillMessageFW(); private final OctetsFW payloadRO = new OctetsFW(); private final MqttDataExFW mqttDataExRO = new MqttDataExFW(); + private final MqttResetExFW.Builder mqttResetExRW = new MqttResetExFW.Builder(); + private final MqttFlushExFW.Builder mqttFlushExRW = new MqttFlushExFW.Builder(); private final KafkaBeginExFW kafkaBeginExRO = new KafkaBeginExFW(); private final KafkaDataExFW kafkaDataExRO = new KafkaDataExFW(); private final KafkaResetExFW kafkaResetExRO = new KafkaResetExFW(); @@ -238,6 +260,8 @@ public class MqttKafkaSessionFactory implements MqttKafkaStreamFactory private final boolean willAvailable; private final int reconnectDelay; private final Int2ObjectHashMap qosLevels; + private final Long2ObjectHashMap clientMetadata; + private final KafkaOffsetMetadataHelper offsetMetadataHelper; private String serverRef; private int reconnectAttempt; @@ -247,7 +271,8 @@ public MqttKafkaSessionFactory( MqttKafkaConfiguration config, EngineContext context, InstanceId instanceId, - LongFunction supplyBinding) + LongFunction supplyBinding, + Long2ObjectHashMap clientMetadata) { this.kafkaTypeId = context.supplyTypeId(KAFKA_TYPE_NAME); this.mqttTypeId = context.supplyTypeId(MQTT_TYPE_NAME); @@ -282,6 +307,8 @@ public MqttKafkaSessionFactory( this.qosLevels.put(0, new String16FW("0")); this.qosLevels.put(1, new String16FW("1")); this.qosLevels.put(2, new String16FW("2")); + this.clientMetadata = clientMetadata; + this.offsetMetadataHelper = new KafkaOffsetMetadataHelper(new UnsafeBuffer(new byte[context.writeBuffer().capacity()])); } @Override @@ -297,6 +324,7 @@ public MessageConsumer newStream( final long routedId = begin.routedId(); final long initialId = begin.streamId(); final long authorization = begin.authorization(); + final long affinity = begin.affinity(); final MqttKafkaBindingConfig binding = supplyBinding.apply(routedId); @@ -308,8 +336,9 @@ public MessageConsumer newStream( { final long resolvedId = resolved.id; final String16FW sessionTopic = binding.sessionsTopic(); - newStream = new MqttSessionProxy(mqtt, originId, routedId, initialId, resolvedId, - binding.id, sessionTopic)::onMqttMessage; + final MqttSessionProxy proxy = new MqttSessionProxy(mqtt, originId, routedId, initialId, resolvedId, + binding.id, sessionTopic); + newStream = proxy::onMqttMessage; } return newStream; @@ -321,6 +350,7 @@ public void onAttached( { MqttKafkaBindingConfig binding = supplyBinding.apply(bindingId); this.serverRef = binding.options.serverRef; + if (willAvailable && coreIndex == 0) { Optional route = binding.routes.stream().findFirst(); @@ -350,15 +380,24 @@ public void onDetached( private final class MqttSessionProxy { private final MessageConsumer mqtt; + private final long resolvedId; private final long originId; private final long routedId; private final long initialId; private final long replyId; private final String16FW sessionId; private final String16FW sessionsTopic; + private final List metas; + private final List offsetFetches; + private final List initializablePartitions; + private final Long2LongHashMap leaderEpochs; + private final IntArrayQueue unackedPacketIds; + private String lifetimeId; private KafkaSessionStream session; private KafkaGroupStream group; + private KafkaInitProducerStream producerInit; + private KafkaOffsetCommitStream offsetCommit; private int state; private long initialSeq; @@ -372,6 +411,12 @@ private final class MqttSessionProxy private String16FW clientId; private String16FW clientIdMigrate; + private String memberId; + private String groupInstanceId; + private String host; + private int port; + private int generationId; + private int sessionExpiryMillis; private int sessionFlags; private int willPadding; @@ -379,6 +424,13 @@ private final class MqttSessionProxy private String willId; private int delay; private boolean redirect; + private int publishQosMax; + private int unfetchedKafkaTopics; + private MqttKafkaPublishMetadata metadata; + private final Set messagesTopics; + private final String16FW retainedTopic; + private long producerId; + private short producerEpoch; private MqttSessionProxy( MessageConsumer mqtt, @@ -392,11 +444,23 @@ private MqttSessionProxy( this.mqtt = mqtt; this.originId = originId; this.routedId = routedId; + this.resolvedId = resolvedId; this.initialId = initialId; this.replyId = supplyReplyId.applyAsLong(initialId); this.session = new KafkaFetchWillSignalStream(originId, resolvedId, this); this.sessionsTopic = sessionsTopic; this.sessionId = new String16FW(sessionIds.get(bindingId)); + this.leaderEpochs = new Long2LongHashMap(-2); + this.metas = new ArrayList<>(); + this.offsetFetches = new ArrayList<>(); + this.initializablePartitions = new ArrayList<>(); + final MqttKafkaBindingConfig binding = supplyBinding.apply(bindingId); + final String16FW messagesTopic = binding.messagesTopic(); + this.retainedTopic = binding.retainedTopic(); + this.messagesTopics = binding.routes.stream().map(r -> r.messages).collect(Collectors.toSet()); + this.messagesTopics.add(messagesTopic); + this.unfetchedKafkaTopics = messagesTopics.size() + 1; + this.unackedPacketIds = new IntArrayQueue(); } private void onMqttMessage( @@ -411,6 +475,10 @@ private void onMqttMessage( final BeginFW begin = beginRO.wrap(buffer, index, index + length); onMqttBegin(begin); break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onMqttFlush(flush); + break; case DataFW.TYPE_ID: final DataFW data = dataRO.wrap(buffer, index, index + length); onMqttData(data); @@ -466,6 +534,7 @@ private void onMqttBegin( sessionExpiryMillis = (int) SECONDS.toMillis(mqttSessionBeginEx.expiry()); sessionFlags = mqttSessionBeginEx.flags(); redirect = hasRedirectCapability(mqttSessionBeginEx.capabilities()); + publishQosMax = mqttSessionBeginEx.publishQosMax(); if (!isSetWillFlag(sessionFlags) || isSetCleanStart(sessionFlags)) { @@ -482,6 +551,12 @@ private void onMqttBegin( willPadding += expirySignalSize; session.doKafkaBeginIfNecessary(traceId, authorization, affinity); + if (publishQosMax == 2) + { + doMqttWindow(authorization, traceId, 0, 0, 0); + this.metadata = new MqttKafkaPublishMetadata(new Long2ObjectHashMap<>(), new Int2ObjectHashMap<>(), leaderEpochs); + clientMetadata.put(affinity, metadata); + } } private void onMqttData( @@ -537,7 +612,7 @@ private void onMqttData( { String16FW willSignalKey = new String16FW.Builder() .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) - .set(clientId.asString() + WILL_SIGNAL_KEY_POSTFIX, StandardCharsets.UTF_8).build(); + .set(clientId.asString() + WILL_SIGNAL_KEY_POSTFIX, UTF_8).build(); Flyweight willSignalKafkaDataEx = kafkaDataExRW .wrap(extBuffer, 0, extBuffer.capacity()) .typeId(kafkaTypeId) @@ -589,7 +664,7 @@ private void onMqttWillData( { lifetimeId = supplyLifetimeId.get(); } - this.willId = supplyWillId.get(); + this.willId = supplyWillId.get(); MqttWillMessageFW will = mqttWillRO.tryWrap(buffer, offset, limit); this.delay = (int) Math.min(SECONDS.toMillis(will.delay()), sessionExpiryMillis); @@ -617,7 +692,7 @@ private void onMqttWillData( int length = kafkaPayload.sizeof() + payloadSize; String16FW key = new String16FW.Builder().wrap(willKeyBuffer, 0, willKeyBuffer.capacity()) - .set(clientId.asString() + WILL_KEY_POSTFIX + lifetimeId, StandardCharsets.UTF_8).build(); + .set(clientId.asString() + WILL_KEY_POSTFIX + lifetimeId, UTF_8).build(); Flyweight kafkaDataEx = kafkaDataExRW .wrap(extBuffer, 0, extBuffer.capacity()) @@ -665,35 +740,33 @@ private void onMqttStateData( sessionPadding, flags, kafkaPayload, kafkaDataEx); } - private void doFlushProduceAndFetchWithFilter( - long traceId, - long authorization, - long budgetId) + private void onMqttFlush( + FlushFW flush) { - final KafkaFlushExFW kafkaFlushEx = - kafkaFlushExRW.wrap(writeBuffer, FlushFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) - .typeId(kafkaTypeId) - .merged(m -> m.fetch(f -> - { - f.capabilities(c -> c.set(KafkaCapabilities.PRODUCE_AND_FETCH)); - f.filtersItem(fi -> fi.conditionsItem(ci -> - ci.key(kb -> kb.length(clientId.length()) - .value(clientId.value(), 0, clientId.length())))); - f.filtersItem(fi -> - { - fi.conditionsItem(ci -> - ci.key(kb -> kb.length(clientIdMigrate.length()) - .value(clientIdMigrate.value(), 0, clientIdMigrate.length()))); - fi.conditionsItem(i -> i.not(n -> n.condition(c -> c.header(h -> - h.nameLen(SENDER_ID_NAME.length()) - .name(SENDER_ID_NAME.value(), 0, SENDER_ID_NAME.length()) - .valueLen(sessionId.length()) - .value(sessionId.value(), 0, sessionId.length()))))); - }); - })) - .build(); + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); - session.doKafkaFlush(traceId, authorization, budgetId, 0, kafkaFlushEx); + assert acknowledge <= sequence; + assert sequence >= initialSeq; + assert acknowledge >= initialAck; + + initialSeq = sequence; + + assert initialAck <= initialSeq; + + final OctetsFW extension = flush.extension(); + final MqttFlushExFW mqttFlushEx = extension.get(mqttFlushExRO::tryWrap); + + assert mqttFlushEx.kind() == MqttFlushExFW.KIND_SESSION; + final MqttSessionFlushExFW mqttPublishFlushEx = mqttFlushEx.session(); + + final int packetId = mqttPublishFlushEx.packetId(); + + final List partitions = metadata.partitions.get(packetId); + partitions.forEach(partition -> + doCommitOffsetComplete(traceId, authorization, partition.topic, partition.partitionId, packetId)); } private void onMqttEnd( @@ -716,7 +789,7 @@ private void onMqttEnd( { // Cleanup will message + will signal String16FW key = new String16FW.Builder().wrap(willKeyBuffer, 0, willKeyBuffer.capacity()) - .set(clientId.asString() + WILL_KEY_POSTFIX + lifetimeId, StandardCharsets.UTF_8).build(); + .set(clientId.asString() + WILL_KEY_POSTFIX + lifetimeId, UTF_8).build(); Flyweight kafkaWillDataEx = kafkaDataExRW .wrap(extBuffer, 0, extBuffer.capacity()) .typeId(kafkaTypeId) @@ -735,7 +808,7 @@ private void onMqttEnd( String16FW willSignalKey = new String16FW.Builder() .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) - .set(clientId.asString() + WILL_SIGNAL_KEY_POSTFIX, StandardCharsets.UTF_8).build(); + .set(clientId.asString() + WILL_SIGNAL_KEY_POSTFIX, UTF_8).build(); Flyweight willSignalKafkaDataEx = kafkaDataExRW .wrap(extBuffer, 0, extBuffer.capacity()) .typeId(kafkaTypeId) @@ -774,6 +847,18 @@ private void onMqttEnd( { group.doKafkaEnd(traceId, authorization); } + + metas.forEach(m -> m.doKafkaEnd(traceId, authorization)); + offsetFetches.forEach(o -> o.doKafkaEnd(traceId, authorization)); + + if (producerInit != null) + { + producerInit.doKafkaEnd(traceId, authorization); + } + if (offsetCommit != null) + { + offsetCommit.doKafkaEnd(traceId, authorization); + } } private void onMqttAbort( @@ -812,6 +897,16 @@ private void onMqttAbort( { group.doKafkaAbort(traceId, authorization); } + metas.forEach(m -> m.doKafkaAbort(traceId, authorization)); + offsetFetches.forEach(o -> o.doKafkaAbort(traceId, authorization)); + if (producerInit != null) + { + producerInit.doKafkaAbort(traceId, authorization); + } + if (offsetCommit != null) + { + offsetCommit.doKafkaAbort(traceId, authorization); + } } private void onMqttReset( @@ -838,6 +933,17 @@ private void onMqttReset( { group.doKafkaReset(traceId); } + + metas.forEach(m -> m.doKafkaReset(traceId)); + offsetFetches.forEach(o -> o.doKafkaReset(traceId)); + if (producerInit != null) + { + producerInit.doKafkaReset(traceId); + } + if (offsetCommit != null) + { + offsetCommit.doKafkaReset(traceId); + } } private void onMqttWindow( @@ -928,6 +1034,26 @@ private void doMqttData( assert replySeq <= replyAck + replyMax; } + private void doMqttFlush( + long traceId, + long authorization, + long budgetId, + int reserved, + int packetId) + { + if (!metadata.partitions.containsKey(packetId)) + { + final MqttFlushExFW mqttFlushEx = + mqttFlushExRW.wrap(extBuffer, FlushFW.FIELD_OFFSET_EXTENSION, extBuffer.capacity()) + .typeId(mqttTypeId) + .session(p -> p.packetId(packetId)) + .build(); + + doFlush(mqtt, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, authorization, + budgetId, reserved, mqttFlushEx); + } + } + private void doMqttAbort( long traceId, long authorization) @@ -954,6 +1080,18 @@ private void doMqttEnd( } } + private void doMqttReset( + long traceId, + Flyweight extension) + { + if (!MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); + + doReset(mqtt, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, extension); + } + } + private void doMqttWindow( long authorization, long traceId, @@ -968,133 +1106,409 @@ private void doMqttWindow( traceId, authorization, budgetId, willPadding, 0, capabilities); } - private void doMqttReset( + private void openMetaStreams( long traceId, - Flyweight extension) + long authorization) { - if (!MqttKafkaState.initialClosed(state)) + messagesTopics.forEach(t -> { - state = MqttKafkaState.closeInitial(state); + final KafkaMetaStream meta = + new KafkaMetaStream(originId, resolvedId, this, t, false); + metas.add(meta); + meta.doKafkaBegin(traceId, authorization, 0); + }); - doReset(mqtt, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, extension); - } + final KafkaMetaStream retainedMeta = + new KafkaMetaStream(originId, resolvedId, this, retainedTopic, true); + metas.add(retainedMeta); + retainedMeta.doKafkaBegin(traceId, authorization, 0); } - } - - public final class KafkaSignalStream - { - private MessageConsumer kafka; - private final long originId; - private final long routedId; - private final String16FW sessionsTopic; - private final String16FW messagesTopic; - private final String16FW retainedTopic; - private final Object2ObjectHashMap willFetchers; - private final Int2ObjectHashMap expiryClientIds; - private IntHashSet partitions; - private int state; + private void onSessionBegin( + long traceId, + long authorization, + long affinity) + { + if (publishQosMax != 2) + { + Flyweight mqttBeginEx = mqttSessionBeginExRW.wrap(sessionExtBuffer, 0, sessionExtBuffer.capacity()) + .typeId(mqttTypeId) + .session(sessionBuilder -> sessionBuilder + .flags(sessionFlags) + .expiry((int) TimeUnit.MILLISECONDS.toSeconds(sessionExpiryMillis)) + .subscribeQosMax(MQTT_KAFKA_MAX_QOS) + .capabilities(MQTT_KAFKA_CAPABILITIES) + .clientId(clientId)) + .build(); - private long initialId; - private long replyId; - private long replySeq; - private long replyAck; - private int replyMax; - private long reconnectAt; - private int decodeSlot = NO_SLOT; - private int decodeSlotOffset; + doMqttBegin(traceId, authorization, affinity, mqttBeginEx); + } + } - private KafkaSignalStream( - long originId, - long routedId, - String16FW sessionsTopic, - String16FW messagesTopic, - String16FW retainedTopic) + private void onSessionBecomesLeader( + long traceId, + long authorization, + int members, + String memberId, + int generationId) { - this.originId = originId; - this.routedId = routedId; - this.sessionsTopic = sessionsTopic; - this.messagesTopic = messagesTopic; - this.retainedTopic = retainedTopic; - this.willFetchers = new Object2ObjectHashMap<>(); - this.expiryClientIds = new Int2ObjectHashMap<>(); - this.partitions = new IntHashSet(); + if (members > 1) + { + session.sendMigrateSignal(traceId, authorization); + session.sendWillSignal(traceId, authorization); + session.doKafkaEnd(traceId, authorization); + group.doKafkaEnd(traceId, authorization); + } + else + { + session.doKafkaEnd(traceId, authorization); + if (publishQosMax < 2) + { + final long routedId = session.routedId; + session = new KafkaSessionStateProxy(originId, routedId, this); + session.doKafkaBeginIfNecessary(traceId, authorization, 0); + } + else + { + this.memberId = memberId; + this.generationId = generationId; + final String groupId = String.format("%s-%s", clientId.asString(), GROUPID_SESSION_SUFFIX); + this.metadata.group = new KafkaGroup(groupInstanceId, groupId, + memberId, generationId); + openMetaStreams(traceId, authorization); + } + } } - private void doKafkaBegin( - long timeMillis) + private void onPartitionsFetched( + long traceId, + long authorization, + String16FW topic, + Array32FW partitions, + KafkaMetaStream meta) { - this.reconnectAt = signaler.signalAt( - timeMillis, - SIGNAL_CONNECT_WILL_STREAM, - this::onSignalConnectWillStream); + doFetchOffsetMetadata(traceId, authorization, topic, partitions); + metas.remove(meta); } - private void doKafkaBegin( + private void onOffsetFetched( long traceId, long authorization, - long affinity) + String topic, + Array32FW partitions, + KafkaOffsetFetchStream kafkaOffsetFetchStream) { - assert state == 0; + boolean initProducer = !partitions.anyMatch(p -> p.metadata().length() > 0); - state = MqttKafkaState.openingInitial(state); + partitions.forEach(partition -> + { + final long offset = partition.partitionOffset(); + final String16FW metadata = partition.metadata(); + final int partitionId = partition.partitionId(); + final long partitionKey = partitionKey(topic, partitionId); - kafka = newSignalStream(this::onSignalMessage, originId, routedId, initialId, 0, 0, 0, - traceId, authorization, affinity, sessionsTopic); + leaderEpochs.put(partitionKey, partition.leaderEpoch()); + + KafkaOffsetMetadata offsetMetadata; + if (!initProducer) + { + offsetMetadata = offsetMetadataHelper.stringToOffsetMetadata(metadata); + offsetMetadata.sequence = offset; + if (offsetCommit == null) + { + onProducerInit(traceId, authorization); + } + this.metadata.offsets.put(partitionKey, offsetMetadata); + offsetMetadata.packetIds.forEach(p -> this.metadata.partitions.computeIfAbsent(p, ArrayList::new) + .add(new KafkaTopicPartition(topic, partitionId))); + } + else + { + initializablePartitions.add(new KafkaTopicPartition(topic, partition.partitionId())); + } + }); + + unfetchedKafkaTopics--; + + if (unfetchedKafkaTopics == 0 && initProducer) + { + final long routedId = session.routedId; + producerInit = new KafkaInitProducerStream(originId, routedId, this); + producerInit.doKafkaBegin(traceId, authorization, 0); + } + else if (unfetchedKafkaTopics == 0) + { + doCreateSessionStream(traceId, authorization); + } + offsetFetches.remove(kafkaOffsetFetchStream); } - private void doKafkaEnd( + private void onGroupJoined( + String instanceId, + String host, + int port, + int sessionExpiryMillisInRange) + { + this.groupInstanceId = instanceId; + this.host = host; + this.port = port; + if (this.sessionExpiryMillis != sessionExpiryMillisInRange) + { + this.sessionExpiryMillis = sessionExpiryMillisInRange; + } + } + + private void onProducerInit( + long traceId, + long authorization, + long producerId, + short producerEpoch) + { + producerInit = null; + this.producerId = producerId; + this.producerEpoch = producerEpoch; + onProducerInit(traceId, authorization); + } + + private void onProducerInit( long traceId, long authorization) { - if (!MqttKafkaState.initialClosed(state)) - { - state = MqttKafkaState.closeInitial(state); + final long routedId = session.routedId; + offsetCommit = new KafkaOffsetCommitStream(originId, routedId, this); + offsetCommit.doKafkaBegin(traceId, authorization, 0); + } - doEnd(kafka, originId, routedId, initialId, 0, 0, 0, traceId, authorization); + private void onOffsetCommitOpened( + long traceId, + long authorization, + long budgetId) + { + if (!initializablePartitions.isEmpty()) + { + initializablePartitions.forEach(kp -> + { + final long partitionKey = partitionKey(kp.topic, kp.partitionId); + final KafkaOffsetMetadata metadata = new KafkaOffsetMetadata(producerId, producerEpoch); + this.metadata.offsets.put(partitionKey, metadata); + Flyweight initialOffsetCommit = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .offsetCommit(o -> o + .topic(kp.topic) + .progress(p -> p + .partitionId(kp.partitionId) + .partitionOffset(metadata.sequence) + .metadata(offsetMetadataHelper.offsetMetadataToString(metadata))) + .generationId(generationId) + .leaderEpoch((int) leaderEpochs.get(partitionKey))) + .build(); - signaler.cancel(reconnectAt); - reconnectAt = NO_CANCEL_ID; + offsetCommit.doKafkaData(traceId, authorization, budgetId, DATA_FLAG_COMPLETE, initialOffsetCommit); + }); } } - private void doKafkaAbort( + private void onOffsetCommitAck( long traceId, long authorization) { - if (!MqttKafkaState.initialClosed(state)) + if (initializablePartitions.isEmpty()) { - state = MqttKafkaState.closeInitial(state); + final int packetId = unackedPacketIds.remove(); + if (metadata.partitions.containsKey(packetId)) + { + final List partitions = metadata.partitions.get(packetId); + partitions.remove(0); + if (partitions.isEmpty()) + { + metadata.partitions.remove(packetId); + } + } - doAbort(kafka, originId, routedId, initialId, 0, 0, 0, traceId, authorization); + doMqttFlush(traceId, authorization, 0, 0, packetId); + } + else + { + onInitialOffsetCommitAck(traceId, authorization); } } - private void onSignalMessage( - int msgTypeId, - DirectBuffer buffer, - int index, - int length) + private void onInitialOffsetCommitAck( + long traceId, + long authorization) { - switch (msgTypeId) + initializablePartitions.remove(0); + if (initializablePartitions.isEmpty()) { - case BeginFW.TYPE_ID: - final BeginFW begin = beginRO.wrap(buffer, index, index + length); - onKafkaBegin(begin); - break; - case DataFW.TYPE_ID: - final DataFW data = dataRO.wrap(buffer, index, index + length); - onKafkaData(data); - break; - case FlushFW.TYPE_ID: - final FlushFW flush = flushRO.wrap(buffer, index, index + length); - onKafkaFlush(flush); - break; - case EndFW.TYPE_ID: - final EndFW end = endRO.wrap(buffer, index, index + length); - onKafkaEnd(end); - break; + doCreateSessionStream(traceId, authorization); + } + } + + private void doFetchOffsetMetadata( + long traceId, + long authorization, + String16FW topic, + Array32FW partitions) + { + final String topic0 = topic.asString(); + + final KafkaOffsetFetchStream offsetFetch = + new KafkaOffsetFetchStream(originId, resolvedId, this, host, port, topic0, partitions); + offsetFetches.add(offsetFetch); + offsetFetch.doKafkaBegin(traceId, authorization, 0); + } + + private void doCommitOffsetComplete( + long traceId, + long authorization, + String topic, + int partitionId, + int packetId) + { + final long partitionKey = partitionKey(topic, partitionId); + final KafkaOffsetMetadata offsetMetadata = metadata.offsets.get(partitionKey); + offsetMetadata.packetIds.remove((Integer) packetId); + offsetMetadata.sequence++; + Flyweight offsetCommitEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .offsetCommit(o -> o + .topic(topic) + .progress(p -> p + .partitionId(partitionId) + .partitionOffset(offsetMetadata.sequence) + .metadata(offsetMetadataHelper.offsetMetadataToString(offsetMetadata))) + .generationId(generationId) + .leaderEpoch((int) leaderEpochs.get(partitionKey))) + .build(); + + unackedPacketIds.add(packetId); + offsetCommit.doKafkaData(traceId, authorization, 0, DATA_FLAG_COMPLETE, offsetCommitEx); + } + + private void doFlushProduceAndFetchWithFilter( + long traceId, + long authorization, + long budgetId) + { + final KafkaFlushExFW kafkaFlushEx = + kafkaFlushExRW.wrap(writeBuffer, FlushFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.fetch(f -> + { + f.capabilities(c -> c.set(KafkaCapabilities.PRODUCE_AND_FETCH)); + f.filtersItem(fi -> fi.conditionsItem(ci -> + ci.key(kb -> kb.length(clientId.length()) + .value(clientId.value(), 0, clientId.length())))); + f.filtersItem(fi -> + { + fi.conditionsItem(ci -> + ci.key(kb -> kb.length(clientIdMigrate.length()) + .value(clientIdMigrate.value(), 0, clientIdMigrate.length()))); + fi.conditionsItem(i -> i.not(n -> n.condition(c -> c.header(h -> + h.nameLen(SENDER_ID_NAME.length()) + .name(SENDER_ID_NAME.value(), 0, SENDER_ID_NAME.length()) + .valueLen(sessionId.length()) + .value(sessionId.value(), 0, sessionId.length()))))); + }); + })) + .build(); + + session.doKafkaFlush(traceId, authorization, budgetId, 0, kafkaFlushEx); + } + + private void doCreateSessionStream( + long traceId, + long authorization) + { + Flyweight mqttBeginEx = mqttSessionBeginExRW.wrap(sessionExtBuffer, 0, sessionExtBuffer.capacity()) + .typeId(mqttTypeId) + .session(sessionBuilder -> + { + sessionBuilder + .flags(sessionFlags) + .expiry((int) TimeUnit.MILLISECONDS.toSeconds(sessionExpiryMillis)) + .subscribeQosMax(MQTT_KAFKA_MAX_QOS) + .capabilities(MQTT_KAFKA_CAPABILITIES) + .clientId(clientId); + + metadata.offsets.values().forEach(o -> + o.packetIds.forEach(p -> sessionBuilder.appendPacketIds(p.shortValue()))); + }).build(); + + doMqttBegin(traceId, authorization, 0, mqttBeginEx); + session = new KafkaSessionStateProxy(originId, resolvedId, this); + session.doKafkaBeginIfNecessary(traceId, authorization, 0); + } + } + + public final class KafkaSignalStream + { + private MessageConsumer kafka; + private final long originId; + private final long routedId; + private final String16FW sessionsTopic; + private final String16FW messagesTopic; + private final String16FW retainedTopic; + private final Object2ObjectHashMap willFetchers; + private final Int2ObjectHashMap expiryClientIds; + + private IntHashSet partitions; + private int state; + + private long initialId; + private long replyId; + private long replySeq; + private long replyAck; + private int replyMax; + private long reconnectAt; + private int decodeSlot = NO_SLOT; + private int decodeSlotOffset; + + private KafkaSignalStream( + long originId, + long routedId, + String16FW sessionsTopic, + String16FW messagesTopic, + String16FW retainedTopic) + { + this.originId = originId; + this.routedId = routedId; + this.sessionsTopic = sessionsTopic; + this.messagesTopic = messagesTopic; + this.retainedTopic = retainedTopic; + this.willFetchers = new Object2ObjectHashMap<>(); + this.expiryClientIds = new Int2ObjectHashMap<>(); + this.partitions = new IntHashSet(); + + } + + private void onSignalMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onKafkaData(data); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onKafkaFlush(flush); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onKafkaEnd(end); + break; case AbortFW.TYPE_ID: final AbortFW abort = abortRO.wrap(buffer, index, index + length); onKafkaAbort(abort); @@ -1110,41 +1524,6 @@ private void onSignalMessage( } } - private void onSignal(SignalFW signal) - { - final int signalId = signal.signalId(); - - switch (signalId) - { - case SIGNAL_EXPIRE_SESSION: - onKafkaSessionExpirySignal(signal); - break; - default: - break; - } - } - - private void onKafkaSessionExpirySignal( - SignalFW signal) - { - String16FW clientId = expiryClientIds.get(signal.contextId()); - - Flyweight expireSessionKafkaDataEx = kafkaDataExRW - .wrap(extBuffer, 0, extBuffer.capacity()) - .typeId(kafkaTypeId) - .merged(m -> m.produce(mp -> mp - .deferred(0) - .timestamp(System.currentTimeMillis()) - .partition(p -> p.partitionId(-1).partitionOffset(-1)) - .key(b -> b.length(clientId.length()) - .value(clientId.value(), 0, clientId.length())) - .hashKey(b -> b.length(clientId.length()) - .value(clientId.value(), 0, clientId.length())))) - .build(); - - doKafkaData(supplyTraceId.get(), 0, expireSessionKafkaDataEx); - } - private void onKafkaBegin( BeginFW begin) { @@ -1324,11 +1703,12 @@ private void onKafkaFlush( { final long sequence = flush.sequence(); final long acknowledge = flush.acknowledge(); + final long reserved = flush.reserved(); assert acknowledge <= sequence; assert sequence >= replySeq; - replySeq = sequence; + replySeq = sequence + reserved; assert replyAck <= replySeq; @@ -1352,35 +1732,6 @@ private void onKafkaFlush( } } - private void onSignalConnectWillStream( - int signalId) - { - assert signalId == SIGNAL_CONNECT_WILL_STREAM; - - this.reconnectAt = NO_CANCEL_ID; - - reconnectAttempt = 0; - state = 0; - replySeq = 0; - replyAck = 0; - - this.initialId = supplyInitialId.applyAsLong(routedId); - this.replyId = supplyReplyId.applyAsLong(initialId); - - if (decodeSlot != NO_SLOT) - { - bufferPool.release(decodeSlot); - decodeSlot = NO_SLOT; - decodeSlotOffset = 0; - } - final long traceId = supplyTraceId.get(); - - willFetchers.values().forEach(f -> f.cleanup(traceId, 0L)); - willFetchers.clear(); - - doKafkaBegin(traceId, 0, 0); - } - private void onKafkaEnd( EndFW end) { @@ -1467,51 +1818,166 @@ private void onKafkaReset( } } - private void doKafkaReset( - long traceId) + private void onSignal( + SignalFW signal) { - if (!MqttKafkaState.replyClosed(state)) - { - state = MqttKafkaState.closeReply(state); + final int signalId = signal.signalId(); - doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); + switch (signalId) + { + case SIGNAL_EXPIRE_SESSION: + onKafkaSessionExpirySignal(signal); + break; + default: + break; } } - private void doKafkaWindow( - long traceId, - long authorization, - long budgetId, - int padding, - int capabilities) + private void onKafkaSessionExpirySignal( + SignalFW signal) { - replyMax = 8192; + String16FW clientId = expiryClientIds.get(signal.contextId()); - doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, budgetId, padding, 0, capabilities); - } + Flyweight expireSessionKafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.produce(mp -> mp + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(clientId.length()) + .value(clientId.value(), 0, clientId.length())) + .hashKey(b -> b.length(clientId.length()) + .value(clientId.value(), 0, clientId.length())))) + .build(); + doKafkaData(supplyTraceId.get(), 0, expireSessionKafkaDataEx); + } - private void doKafkaData( - long traceId, - long authorization, - Flyweight extension) + private void onSignalConnectWillStream( + int signalId) { + assert signalId == SIGNAL_CONNECT_WILL_STREAM; - doData(kafka, originId, routedId, initialId, 0, 0, 0, - traceId, authorization, 0, DATA_FLAG_COMPLETE, 0, null, extension); - } - } + this.reconnectAt = NO_CANCEL_ID; - private final class KafkaFetchWillStream - { - private final KafkaSignalStream delegate; - private final String16FW topic; - private final String16FW clientId; - private final String lifetimeId; - private final String willId; - private final long deliverAt; - private MessageConsumer kafka; + reconnectAttempt = 0; + state = 0; + replySeq = 0; + replyAck = 0; + + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + + if (decodeSlot != NO_SLOT) + { + bufferPool.release(decodeSlot); + decodeSlot = NO_SLOT; + decodeSlotOffset = 0; + } + final long traceId = supplyTraceId.get(); + + willFetchers.values().forEach(f -> f.cleanup(traceId, 0L)); + willFetchers.clear(); + + doKafkaBegin(traceId, 0, 0); + } + + + private void doKafkaBegin( + long timeMillis) + { + this.reconnectAt = signaler.signalAt( + timeMillis, + SIGNAL_CONNECT_WILL_STREAM, + this::onSignalConnectWillStream); + } + + private void doKafkaBegin( + long traceId, + long authorization, + long affinity) + { + assert state == 0; + + state = MqttKafkaState.openingInitial(state); + + kafka = newSignalStream(this::onSignalMessage, originId, routedId, initialId, 0, 0, 0, + traceId, authorization, affinity, sessionsTopic); + } + + private void doKafkaEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, 0, 0, 0, traceId, authorization); + + signaler.cancel(reconnectAt); + reconnectAt = NO_CANCEL_ID; + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, 0, 0, 0, traceId, authorization); + } + } + + private void doKafkaReset( + long traceId) + { + if (!MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + replyMax = 8192; + + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, 0, capabilities); + } + + + private void doKafkaData( + long traceId, + long authorization, + Flyweight extension) + { + + doData(kafka, originId, routedId, initialId, 0, 0, 0, + traceId, authorization, 0, DATA_FLAG_COMPLETE, 0, null, extension); + } + } + + private final class KafkaFetchWillStream + { + private final KafkaSignalStream delegate; + private final String16FW topic; + private final String16FW clientId; + private final String lifetimeId; + private final String willId; + private final long deliverAt; + private MessageConsumer kafka; private final long originId; private final long routedId; private final long initialId; @@ -1558,64 +2024,6 @@ private KafkaFetchWillStream( this.deliverAt = deliverAt; } - private void doKafkaBegin( - long traceId, - long authorization, - long affinity, - String16FW lifetimeId) - { - if (!MqttKafkaState.initialOpening(state)) - { - state = MqttKafkaState.openingInitial(state); - - kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, affinity, clientId, lifetimeId, topic); - } - } - - private void cleanup( - long traceId, - long authorization) - { - doKafkaEnd(traceId, authorization); - if (willProducer != null) - { - willProducer.doKafkaEnd(traceId, authorization); - } - if (willRetainProducer != null) - { - willRetainProducer.doKafkaEnd(traceId, authorization); - } - bufferPool.release(dataSlot); - dataSlot = NO_SLOT; - messageSlotOffset = 0; - } - - private void doKafkaEnd( - long traceId, - long authorization) - { - if (!MqttKafkaState.initialClosed(state)) - { - state = MqttKafkaState.closeInitial(state); - - doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); - delegate.willFetchers.remove(clientId); - } - } - - private void doKafkaAbort( - long traceId, - long authorization) - { - if (MqttKafkaState.initialOpened(state) && !MqttKafkaState.initialClosed(state)) - { - state = MqttKafkaState.closeInitial(state); - - doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); - } - } - private void onKafkaMessage( int msgTypeId, DirectBuffer buffer, @@ -1766,11 +2174,12 @@ private void onKafkaFlush( final long acknowledge = flush.acknowledge(); final long traceId = flush.traceId(); final long authorization = flush.authorization(); + final long reserved = flush.reserved(); assert acknowledge <= sequence; assert sequence >= replySeq; - replySeq = sequence; + replySeq = sequence + reserved; assert replyAck <= replySeq; @@ -1793,31 +2202,6 @@ private void onKafkaWindow( assert initialAck <= initialSeq; } - private void doKafkaReset( - long traceId) - { - if (MqttKafkaState.initialOpened(state) && !MqttKafkaState.replyClosed(state)) - { - state = MqttKafkaState.closeReply(state); - - doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); - } - } - - private void doKafkaWindow( - long traceId, - long authorization, - long budgetId, - int padding, - int capabilities) - { - replyAck = replySeq; - replyMax = bufferPool.slotCapacity(); - - doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, budgetId, padding, replyPad, capabilities); - } - private void onWillMessageAcked( long traceId, long authorization) @@ -1830,7 +2214,7 @@ private void onWillMessageAcked( // Cleanup will message + will signal String16FW key = new String16FW.Builder().wrap(willKeyBuffer, 0, willKeyBuffer.capacity()) - .set(clientId.asString() + WILL_KEY_POSTFIX + lifetimeId, StandardCharsets.UTF_8).build(); + .set(clientId.asString() + WILL_KEY_POSTFIX + lifetimeId, UTF_8).build(); Flyweight kafkaWillDataEx = kafkaDataExRW .wrap(extBuffer, 0, extBuffer.capacity()) .typeId(kafkaTypeId) @@ -1848,7 +2232,7 @@ private void onWillMessageAcked( String16FW willSignalKey = new String16FW.Builder() .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) - .set(clientId.asString() + WILL_SIGNAL_KEY_POSTFIX, StandardCharsets.UTF_8).build(); + .set(clientId.asString() + WILL_SIGNAL_KEY_POSTFIX, UTF_8).build(); Flyweight willSignalKafkaDataEx = kafkaDataExRW .wrap(extBuffer, 0, extBuffer.capacity()) .typeId(kafkaTypeId) @@ -1872,97 +2256,55 @@ private void onWillMessageAcked( doKafkaEnd(traceId, authorization); } } - } - - private final class KafkaProduceWillStream - { - private MessageConsumer kafka; - private final long originId; - private final long routedId; - private final long initialId; - private final String16FW kafkaTopic; - private final long deliverAt; - private final long replyId; - private final KafkaFetchWillStream delegate; - private final int flags; - private final int qos; - - private int state; - - private long initialSeq; - private long initialAck; - private int initialMax; - - private long replySeq; - private long replyAck; - private int replyMax; - private int replyPad; - - private KafkaProduceWillStream( - long originId, - long routedId, - KafkaFetchWillStream delegate, - String16FW kafkaTopic, - int qos, - long deliverAt, - int flags) - { - this.originId = originId; - this.routedId = routedId; - this.delegate = delegate; - this.initialId = supplyInitialId.applyAsLong(routedId); - this.kafkaTopic = kafkaTopic; - this.qos = qos; - this.deliverAt = deliverAt; - this.replyId = supplyReplyId.applyAsLong(initialId); - this.flags = flags; - } private void doKafkaBegin( long traceId, long authorization, - long affinity) + long affinity, + String16FW lifetimeId) { - initialSeq = delegate.initialSeq; - initialAck = delegate.initialAck; - initialMax = delegate.initialMax; - state = MqttKafkaState.openingInitial(state); - - kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, affinity, kafkaTopic, qos); + if (!MqttKafkaState.initialOpening(state)) + { + state = MqttKafkaState.openingInitial(state); + + kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, clientId, lifetimeId, topic); + } } - private void doKafkaData( + private void doKafkaEnd( long traceId, - long authorization, - long budgetId, - int reserved, - int flags, - OctetsFW payload, - Flyweight extension) + long authorization) { - if ((flags & DATA_FLAG_FIN) != 0) + if (!MqttKafkaState.initialClosed(state)) { - willDeliverIds.remove(delegate.clientId); - } - - doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, flags, reserved, payload, extension); - - initialSeq += reserved; + state = MqttKafkaState.closeInitial(state); - assert initialSeq <= initialAck + initialMax; + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + delegate.willFetchers.remove(clientId); + } } - private void doKafkaEnd( + private void doKafkaAbort( long traceId, long authorization) { - if (!MqttKafkaState.initialClosed(state)) + if (MqttKafkaState.initialOpened(state) && !MqttKafkaState.initialClosed(state)) { state = MqttKafkaState.closeInitial(state); - doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaReset( + long traceId) + { + if (MqttKafkaState.initialOpened(state) && !MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); } } @@ -1973,10 +2315,76 @@ private void doKafkaWindow( int padding, int capabilities) { + replyAck = replySeq; + replyMax = bufferPool.slotCapacity(); + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, authorization, budgetId, padding, replyPad, capabilities); } + private void cleanup( + long traceId, + long authorization) + { + doKafkaEnd(traceId, authorization); + if (willProducer != null) + { + willProducer.doKafkaEnd(traceId, authorization); + } + if (willRetainProducer != null) + { + willRetainProducer.doKafkaEnd(traceId, authorization); + } + bufferPool.release(dataSlot); + dataSlot = NO_SLOT; + messageSlotOffset = 0; + } + } + + private final class KafkaProduceWillStream + { + private MessageConsumer kafka; + private final long originId; + private final long routedId; + private final long initialId; + private final String16FW kafkaTopic; + private final long deliverAt; + private final long replyId; + private final KafkaFetchWillStream delegate; + private final int flags; + private final int qos; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private KafkaProduceWillStream( + long originId, + long routedId, + KafkaFetchWillStream delegate, + String16FW kafkaTopic, + int qos, + long deliverAt, + int flags) + { + this.originId = originId; + this.routedId = routedId; + this.delegate = delegate; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.kafkaTopic = kafkaTopic; + this.qos = qos; + this.deliverAt = deliverAt; + this.replyId = supplyReplyId.applyAsLong(initialId); + this.flags = flags; + } + private void onKafkaMessage( int msgTypeId, DirectBuffer buffer, @@ -2004,21 +2412,6 @@ private void onKafkaMessage( } } - private void onKafkaSignal( - SignalFW signal) - { - final int signalId = signal.signalId(); - - switch (signalId) - { - case SIGNAL_DELIVER_WILL_MESSAGE: - onWillDeliverSignal(signal); - break; - default: - break; - } - } - private void onKafkaBegin( BeginFW begin) { @@ -2062,6 +2455,28 @@ private void onKafkaData( doKafkaReset(traceId); } + private void onKafkaSignal( + SignalFW signal) + { + final int signalId = signal.signalId(); + + switch (signalId) + { + case SIGNAL_DELIVER_WILL_MESSAGE: + onWillDeliverSignal(signal); + break; + default: + break; + } + } + + + private void onWillDeliverSignal( + SignalFW signal) + { + sendWill(signal.traceId(), signal.authorization(), 0); + } + private void onKafkaWindow( WindowFW window) { @@ -2098,10 +2513,74 @@ private void onKafkaWindow( } } + private void doKafkaBegin( + long traceId, + long authorization, + long affinity) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.openingInitial(state); + + kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, kafkaTopic, qos); + } + + private void doKafkaData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + OctetsFW payload, + Flyweight extension) + { + if ((flags & DATA_FLAG_FIN) != 0) + { + willDeliverIds.remove(delegate.clientId); + } + + doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, payload, extension); + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; + } - private void onWillDeliverSignal(SignalFW signal) + private void doKafkaEnd( + long traceId, + long authorization) { - sendWill(signal.traceId(), signal.authorization(), 0); + if (!MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, replyPad, capabilities); + } + + private void doKafkaReset( + long traceId) + { + if (!MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); + } } private void sendWill( @@ -2197,17 +2676,6 @@ private void sendWill( delegate.doKafkaWindow(traceId, authorization, 0, 0, 0); } - private void doKafkaReset( - long traceId) - { - if (!MqttKafkaState.replyClosed(state)) - { - state = MqttKafkaState.closeReply(state); - - doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); - } - } - private void addHeader( OctetsFW key, OctetsFW value) @@ -2316,6 +2784,15 @@ private static boolean hasRedirectCapability( return (flags & REDIRECT_AVAILABLE_MASK) != 0; } + + private static long partitionKey( + String topic, + int partitionId) + { + final int topicHashCode = System.identityHashCode(topic.intern()); + return ((long) topicHashCode << 32) | (partitionId & 0xFFFFFFFFL); + } + private static boolean isSetWillFlag( int flags) { @@ -2360,225 +2837,13 @@ private KafkaSessionStream( this.replyId = supplyReplyId.applyAsLong(initialId); } - private void doKafkaBeginIfNecessary( - long traceId, - long authorization, - long affinity) + private void onKafkaMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) { - if (!MqttKafkaState.initialOpening(state)) - { - doKafkaBegin(traceId, authorization, affinity); - } - } - - protected final void doKafkaData( - long traceId, - long authorization, - long budgetId, - int reserved, - int padding, - int flags, - DirectBuffer buffer, - int offset, - int limit, - Flyweight extension) - { - - doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, flags, reserved, buffer, offset, limit, extension); - - initialSeq += reserved; - - assert initialSeq - padding <= initialAck + initialMax; - } - - protected final void doKafkaData( - long traceId, - long authorization, - long budgetId, - int reserved, - int flags, - OctetsFW payload, - Flyweight extension) - { - doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, flags, reserved, payload, extension); - - initialSeq += reserved; - - assert initialSeq <= initialAck + initialMax; - } - - protected final void cancelExpirySignal( - long authorization, - long traceId) - { - String16FW expirySignalKey = new String16FW.Builder() - .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) - .set(delegate.clientId.asString() + EXPIRY_SIGNAL_KEY_POSTFIX, StandardCharsets.UTF_8).build(); - Flyweight expirySignalKafkaDataEx = kafkaDataExRW - .wrap(extBuffer, 0, extBuffer.capacity()) - .typeId(kafkaTypeId) - .merged(m -> m.produce(mp -> mp - .deferred(0) - .timestamp(System.currentTimeMillis()) - .partition(p -> p.partitionId(-1).partitionOffset(-1)) - .key(b -> b.length(expirySignalKey.length()) - .value(expirySignalKey.value(), 0, expirySignalKey.length())) - .hashKey(b -> b.length(delegate.clientId.length()) - .value(delegate.clientId.value(), 0, delegate.clientId.length())) - .headersItem(h -> - h.nameLen(TYPE_HEADER_NAME_OCTETS.sizeof()) - .name(TYPE_HEADER_NAME_OCTETS) - .valueLen(EXPIRY_SIGNAL_NAME_OCTETS.sizeof()) - .value(EXPIRY_SIGNAL_NAME_OCTETS)))) - .build(); - - doKafkaData(traceId, authorization, 0, 0, DATA_FLAG_COMPLETE, - null, expirySignalKafkaDataEx); - } - - protected final void sendExpirySignal( - long authorization, - long traceId, - Flyweight payload) - { - String16FW expirySignalKey = new String16FW.Builder() - .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) - .set(delegate.clientId.asString() + EXPIRY_SIGNAL_KEY_POSTFIX, StandardCharsets.UTF_8).build(); - Flyweight expirySignalKafkaDataEx = kafkaDataExRW - .wrap(extBuffer, 0, extBuffer.capacity()) - .typeId(kafkaTypeId) - .merged(m -> m.produce(mp -> mp - .deferred(0) - .timestamp(System.currentTimeMillis()) - .partition(p -> p.partitionId(-1).partitionOffset(-1)) - .key(b -> b.length(expirySignalKey.length()) - .value(expirySignalKey.value(), 0, expirySignalKey.length())) - .hashKey(b -> b.length(delegate.clientId.length()) - .value(delegate.clientId.value(), 0, delegate.clientId.length())) - .headersItem(h -> - h.nameLen(TYPE_HEADER_NAME_OCTETS.sizeof()) - .name(TYPE_HEADER_NAME_OCTETS) - .valueLen(EXPIRY_SIGNAL_NAME_OCTETS.sizeof()) - .value(EXPIRY_SIGNAL_NAME_OCTETS)))) - .build(); - - doKafkaData(traceId, authorization, 0, payload.sizeof(), delegate.sessionPadding, DATA_FLAG_COMPLETE, - payload, expirySignalKafkaDataEx); - } - - private void sendWillSignal( - long traceId, - long authorization) - { - String16FW willSignalKey = new String16FW.Builder() - .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) - .set(delegate.clientId.asString() + WILL_SIGNAL_KEY_POSTFIX, StandardCharsets.UTF_8).build(); - Flyweight willSignalKafkaDataEx = kafkaDataExRW - .wrap(extBuffer, 0, extBuffer.capacity()) - .typeId(kafkaTypeId) - .merged(m -> m.produce(mp -> mp - .deferred(0) - .timestamp(System.currentTimeMillis()) - .partition(p -> p.partitionId(-1).partitionOffset(-1)) - .key(b -> b.length(willSignalKey.length()) - .value(willSignalKey.value(), 0, willSignalKey.length())) - .hashKey(b -> b.length(delegate.clientId.length()) - .value(delegate.clientId.value(), 0, delegate.clientId.length())) - .headersItem(h -> - h.nameLen(TYPE_HEADER_NAME_OCTETS.sizeof()) - .name(TYPE_HEADER_NAME_OCTETS) - .valueLen(WILL_SIGNAL_NAME_OCTETS.sizeof()) - .value(WILL_SIGNAL_NAME_OCTETS)))) - .build(); - - final MqttSessionSignalFW willSignal = - mqttSessionSignalRW.wrap(sessionSignalBuffer, 0, sessionSignalBuffer.capacity()) - .will(w -> w - .instanceId(instanceId.instanceId()) - .clientId(delegate.clientId) - .delay(delegate.delay) - .deliverAt(supplyTime.getAsLong() + delegate.delay) - .lifetimeId(delegate.lifetimeId) - .willId(delegate.willId)) - .build(); - - doKafkaData(traceId, authorization, 0, willSignal.sizeof(), delegate.sessionPadding, DATA_FLAG_COMPLETE, - willSignal, willSignalKafkaDataEx); - } - - protected void doKafkaData( - long traceId, - long authorization, - long budgetId, - int reserved, - int padding, - int flags, - Flyweight payload, - Flyweight extension) - { - final DirectBuffer buffer = payload.buffer(); - final int offset = payload.offset(); - final int limit = payload.limit(); - final int length = limit - offset; - - doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, flags, reserved, buffer, offset, length, extension); - - initialSeq += reserved; - - assert initialSeq - padding <= initialAck + initialMax; - } - - private void doKafkaFlush( - long traceId, - long authorization, - long budgetId, - int reserved, - Flyweight extension) - { - doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, reserved, extension); - } - - private void doKafkaEnd( - long traceId, - long authorization) - { - if (!MqttKafkaState.initialClosed(state)) - { - initialSeq = delegate.initialSeq; - initialAck = delegate.initialAck; - initialMax = delegate.initialMax; - state = MqttKafkaState.closeInitial(state); - - doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); - } - } - - private void doKafkaAbort( - long traceId, - long authorization) - { - if (!MqttKafkaState.initialClosed(state)) - { - initialSeq = delegate.initialSeq; - initialAck = delegate.initialAck; - initialMax = delegate.initialMax; - state = MqttKafkaState.closeInitial(state); - - doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); - } - } - - private void onKafkaMessage( - int msgTypeId, - DirectBuffer buffer, - int index, - int length) - { - switch (msgTypeId) + switch (msgTypeId) { case BeginFW.TYPE_ID: final BeginFW begin = beginRO.wrap(buffer, index, index + length); @@ -2639,7 +2904,7 @@ private void onKafkaBegin( .session(sessionBuilder -> sessionBuilder .flags(delegate.sessionFlags) .expiry((int) TimeUnit.MILLISECONDS.toSeconds(delegate.sessionExpiryMillis)) - .qosMax(MQTT_KAFKA_MAX_QOS) + .subscribeQosMax(MQTT_KAFKA_MAX_QOS) .capabilities(MQTT_KAFKA_CAPABILITIES) .clientId(delegate.clientId)) .build(); @@ -2672,34 +2937,16 @@ private void onKafkaData( } else { - handleKafkaData(data); + onKafkaDataImpl(data); } } - protected abstract void doKafkaBegin( - long traceId, - long authorization, - long affinity); - - protected abstract void handleKafkaData( + protected abstract void onKafkaDataImpl( DataFW data); - protected void onKafkaWindow( - WindowFW window) + protected void onKafkaFlush( + FlushFW flush) { - final long sequence = window.sequence(); - final long acknowledge = window.acknowledge(); - final int maximum = window.maximum(); - - assert acknowledge <= sequence; - assert acknowledge >= delegate.initialAck; - assert maximum >= delegate.initialMax; - - initialAck = acknowledge; - initialMax = maximum; - state = MqttKafkaState.openInitial(state); - - assert initialAck <= initialSeq; } protected void onKafkaEnd( @@ -2707,11 +2954,6 @@ protected void onKafkaEnd( { } - protected void onKafkaFlush( - FlushFW flush) - { - } - private void onKafkaAbort( AbortFW abort) { @@ -2731,31 +2973,6 @@ private void onKafkaAbort( delegate.doMqttAbort(traceId, authorization); } - protected void sendMigrateSignal( - long traceId, - long authorization) - { - Flyweight kafkaMigrateDataEx = kafkaDataExRW - .wrap(extBuffer, 0, extBuffer.capacity()) - .typeId(kafkaTypeId) - .merged(m -> m.produce(mp -> mp - .deferred(0) - .timestamp(System.currentTimeMillis()) - .partition(p -> p.partitionId(-1).partitionOffset(-1)) - .key(b -> b.length(delegate.clientIdMigrate.length()) - .value(delegate.clientIdMigrate.value(), 0, delegate.clientIdMigrate.length())) - .hashKey(b -> b.length(delegate.clientId.length()) - .value(delegate.clientId.value(), 0, delegate.clientId.length())) - .headersItem(c -> c.nameLen(SENDER_ID_NAME.length()) - .name(SENDER_ID_NAME.value(), 0, SENDER_ID_NAME.length()) - .valueLen(delegate.sessionId.length()) - .value(delegate.sessionId.value(), 0, delegate.sessionId.length())))) - .build(); - - doKafkaData(traceId, authorization, 0, 0, DATA_FLAG_COMPLETE, - EMPTY_OCTETS, kafkaMigrateDataEx); - } - protected void onKafkaReset( ResetFW reset) { @@ -2786,154 +3003,396 @@ protected void onKafkaReset( delegate.doMqttReset(traceId, mqttResetEx); } - private void doKafkaReset( - long traceId) + protected void onKafkaWindow( + WindowFW window) { - if (!MqttKafkaState.replyClosed(state)) - { - state = MqttKafkaState.closeReply(state); + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); - doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); + assert acknowledge <= sequence; + assert acknowledge >= delegate.initialAck; + assert maximum >= delegate.initialMax; + + initialAck = acknowledge; + initialMax = maximum; + state = MqttKafkaState.openInitial(state); + + assert initialAck <= initialSeq; + } + + private void doKafkaBeginIfNecessary( + long traceId, + long authorization, + long affinity) + { + if (!MqttKafkaState.initialOpening(state)) + { + doKafkaBegin(traceId, authorization, affinity); } } - private void doKafkaWindow( + protected abstract void doKafkaBegin( + long traceId, + long authorization, + long affinity); + + protected final void doKafkaData( long traceId, long authorization, long budgetId, - int capabilities) + int reserved, + int padding, + int flags, + DirectBuffer buffer, + int offset, + int limit, + Flyweight extension) { - replyAck = delegate.replyAck; - replyMax = delegate.replyMax; - replyPad = delegate.replyPad; - doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, budgetId, replyPad, 0, capabilities); + doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, buffer, offset, limit, extension); + + initialSeq += reserved; + + assert initialSeq - padding <= initialAck + initialMax; } - } - private final class KafkaSessionSignalStream extends KafkaSessionStream - { - private KafkaSessionSignalStream( - long originId, - long routedId, - MqttSessionProxy delegate) + protected final void doKafkaData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + OctetsFW payload, + Flyweight extension) { - super(originId, routedId, delegate); + doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, payload, extension); + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; } - @Override - protected void doKafkaBegin(long traceId, long authorization, long affinity) + protected void doKafkaData( + long traceId, + long authorization, + long budgetId, + int reserved, + int padding, + int flags, + Flyweight payload, + Flyweight extension) { - assert state == 0; + final DirectBuffer buffer = payload.buffer(); + final int offset = payload.offset(); + final int limit = payload.limit(); + final int length = limit - offset; - this.initialId = supplyInitialId.applyAsLong(routedId); - this.replyId = supplyReplyId.applyAsLong(initialId); + doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, buffer, offset, length, extension); - state = MqttKafkaState.openingInitial(state); + initialSeq += reserved; - final String server = delegate.redirect ? serverRef : null; - kafka = newKafkaStream(super::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, affinity, delegate.sessionsTopic, null, delegate.clientIdMigrate, - delegate.sessionId, server, KafkaCapabilities.PRODUCE_AND_FETCH); + assert initialSeq - padding <= initialAck + initialMax; } - @Override - protected void handleKafkaData(DataFW data) + private void doKafkaFlush( + long traceId, + long authorization, + long budgetId, + int reserved, + Flyweight extension) { - final long traceId = data.traceId(); - final long authorization = data.authorization(); - final long budgetId = data.budgetId(); - final int reserved = data.reserved(); - - final OctetsFW extension = data.extension(); - final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); - final KafkaDataExFW kafkaDataEx = - dataEx != null && dataEx.typeId() == kafkaTypeId ? extension.get(kafkaDataExRO::tryWrap) : null; - final KafkaMergedDataExFW kafkaMergedDataEx = - kafkaDataEx != null && kafkaDataEx.kind() == KafkaDataExFW.KIND_MERGED ? kafkaDataEx.merged() : null; - final KafkaKeyFW key = kafkaMergedDataEx != null ? kafkaMergedDataEx.fetch().key() : null; + doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, reserved, extension); + } - if (delegate.group != null && key != null) + private void doKafkaEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) { - delegate.group.doKafkaFlush(traceId, authorization, budgetId, reserved); + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); } } - @Override - protected void onKafkaWindow( - WindowFW window) + private void doKafkaAbort( + long traceId, + long authorization) { - final long sequence = window.sequence(); - final long acknowledge = window.acknowledge(); - final int maximum = window.maximum(); - final long authorization = window.authorization(); - final long traceId = window.traceId(); - final boolean wasOpen = MqttKafkaState.initialOpened(state); - - assert acknowledge <= sequence; - assert acknowledge >= delegate.initialAck; - assert maximum >= delegate.initialMax; - - initialAck = acknowledge; - initialMax = maximum; - state = MqttKafkaState.openInitial(state); - - assert initialAck <= initialSeq; - - if (!wasOpen) + if (!MqttKafkaState.initialClosed(state)) { - final long routedId = delegate.session.routedId; - - delegate.group = new KafkaGroupStream(originId, routedId, delegate); - delegate.group.doKafkaBegin(traceId, authorization, 0); + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); - sendMigrateSignal(traceId, authorization); + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); } } - } - private final class KafkaSessionStateProxy extends KafkaSessionStream - { - private KafkaSessionStateProxy( - long originId, - long routedId, - MqttSessionProxy delegate) + private void doKafkaReset( + long traceId) { - super(originId, routedId, delegate); + if (!MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); + } } - @Override - protected void doKafkaBegin( + private void doKafkaWindow( long traceId, long authorization, - long affinity) + long budgetId, + int capabilities) { - assert state == 0; + replyAck = delegate.replyAck; + replyMax = delegate.replyMax; + replyPad = delegate.replyPad; - this.initialId = supplyInitialId.applyAsLong(routedId); - this.replyId = supplyReplyId.applyAsLong(initialId); + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, replyPad, 0, capabilities); + } - state = MqttKafkaState.openingInitial(state); + protected void sendMigrateSignal( + long traceId, + long authorization) + { + Flyweight kafkaMigrateDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.produce(mp -> mp + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(delegate.clientIdMigrate.length()) + .value(delegate.clientIdMigrate.value(), 0, delegate.clientIdMigrate.length())) + .hashKey(b -> b.length(delegate.clientId.length()) + .value(delegate.clientId.value(), 0, delegate.clientId.length())) + .headersItem(c -> c.nameLen(SENDER_ID_NAME.length()) + .name(SENDER_ID_NAME.value(), 0, SENDER_ID_NAME.length()) + .valueLen(delegate.sessionId.length()) + .value(delegate.sessionId.value(), 0, delegate.sessionId.length())))) + .build(); - KafkaCapabilities capabilities = isSetWillFlag(delegate.sessionFlags) ? - KafkaCapabilities.PRODUCE_ONLY : KafkaCapabilities.PRODUCE_AND_FETCH; - final String server = delegate.redirect ? serverRef : null; - kafka = newKafkaStream(super::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, affinity, delegate.sessionsTopic, delegate.clientId, delegate.clientIdMigrate, - delegate.sessionId, server, capabilities); + doKafkaData(traceId, authorization, 0, 0, DATA_FLAG_COMPLETE, + EMPTY_OCTETS, kafkaMigrateDataEx); } - @Override - protected void handleKafkaData( - DataFW data) + protected final void cancelExpirySignal( + long authorization, + long traceId) { - final long traceId = data.traceId(); - final long authorization = data.authorization(); - final long budgetId = data.budgetId(); - final int reserved = data.reserved(); + String16FW expirySignalKey = new String16FW.Builder() + .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) + .set(delegate.clientId.asString() + EXPIRY_SIGNAL_KEY_POSTFIX, UTF_8).build(); + Flyweight expirySignalKafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.produce(mp -> mp + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(expirySignalKey.length()) + .value(expirySignalKey.value(), 0, expirySignalKey.length())) + .hashKey(b -> b.length(delegate.clientId.length()) + .value(delegate.clientId.value(), 0, delegate.clientId.length())) + .headersItem(h -> + h.nameLen(TYPE_HEADER_NAME_OCTETS.sizeof()) + .name(TYPE_HEADER_NAME_OCTETS) + .valueLen(EXPIRY_SIGNAL_NAME_OCTETS.sizeof()) + .value(EXPIRY_SIGNAL_NAME_OCTETS)))) + .build(); - final int flags = data.flags(); + doKafkaData(traceId, authorization, 0, 0, DATA_FLAG_COMPLETE, + null, expirySignalKafkaDataEx); + } + + protected final void sendExpirySignal( + long authorization, + long traceId, + Flyweight payload) + { + String16FW expirySignalKey = new String16FW.Builder() + .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) + .set(delegate.clientId.asString() + EXPIRY_SIGNAL_KEY_POSTFIX, UTF_8).build(); + Flyweight expirySignalKafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.produce(mp -> mp + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(expirySignalKey.length()) + .value(expirySignalKey.value(), 0, expirySignalKey.length())) + .hashKey(b -> b.length(delegate.clientId.length()) + .value(delegate.clientId.value(), 0, delegate.clientId.length())) + .headersItem(h -> + h.nameLen(TYPE_HEADER_NAME_OCTETS.sizeof()) + .name(TYPE_HEADER_NAME_OCTETS) + .valueLen(EXPIRY_SIGNAL_NAME_OCTETS.sizeof()) + .value(EXPIRY_SIGNAL_NAME_OCTETS)))) + .build(); + + doKafkaData(traceId, authorization, 0, payload.sizeof(), delegate.sessionPadding, DATA_FLAG_COMPLETE, + payload, expirySignalKafkaDataEx); + } + + private void sendWillSignal( + long traceId, + long authorization) + { + String16FW willSignalKey = new String16FW.Builder() + .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) + .set(delegate.clientId.asString() + WILL_SIGNAL_KEY_POSTFIX, UTF_8).build(); + Flyweight willSignalKafkaDataEx = kafkaDataExRW + .wrap(extBuffer, 0, extBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.produce(mp -> mp + .deferred(0) + .timestamp(System.currentTimeMillis()) + .partition(p -> p.partitionId(-1).partitionOffset(-1)) + .key(b -> b.length(willSignalKey.length()) + .value(willSignalKey.value(), 0, willSignalKey.length())) + .hashKey(b -> b.length(delegate.clientId.length()) + .value(delegate.clientId.value(), 0, delegate.clientId.length())) + .headersItem(h -> + h.nameLen(TYPE_HEADER_NAME_OCTETS.sizeof()) + .name(TYPE_HEADER_NAME_OCTETS) + .valueLen(WILL_SIGNAL_NAME_OCTETS.sizeof()) + .value(WILL_SIGNAL_NAME_OCTETS)))) + .build(); + + final MqttSessionSignalFW willSignal = + mqttSessionSignalRW.wrap(sessionSignalBuffer, 0, sessionSignalBuffer.capacity()) + .will(w -> w + .instanceId(instanceId.instanceId()) + .clientId(delegate.clientId) + .delay(delegate.delay) + .deliverAt(supplyTime.getAsLong() + delegate.delay) + .lifetimeId(delegate.lifetimeId) + .willId(delegate.willId)) + .build(); + + doKafkaData(traceId, authorization, 0, willSignal.sizeof(), delegate.sessionPadding, DATA_FLAG_COMPLETE, + willSignal, willSignalKafkaDataEx); + } + } + + private final class KafkaSessionSignalStream extends KafkaSessionStream + { + private KafkaSessionSignalStream( + long originId, + long routedId, + MqttSessionProxy delegate) + { + super(originId, routedId, delegate); + } + + @Override + protected void onKafkaWindow( + WindowFW window) + { + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final long authorization = window.authorization(); + final long traceId = window.traceId(); + final boolean wasOpen = MqttKafkaState.initialOpened(state); + + assert acknowledge <= sequence; + assert acknowledge >= delegate.initialAck; + assert maximum >= delegate.initialMax; + + initialAck = acknowledge; + initialMax = maximum; + state = MqttKafkaState.openInitial(state); + + assert initialAck <= initialSeq; + + if (!wasOpen) + { + final long routedId = delegate.session.routedId; + + delegate.group = new KafkaGroupStream(originId, routedId, delegate); + delegate.group.doKafkaBegin(traceId, authorization, 0); + + sendMigrateSignal(traceId, authorization); + } + } + + @Override + protected void doKafkaBegin( + long traceId, + long authorization, + long affinity) + { + assert state == 0; + + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + + state = MqttKafkaState.openingInitial(state); + + final String server = delegate.redirect ? serverRef : null; + kafka = newKafkaStream(super::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, delegate.sessionsTopic, null, delegate.clientIdMigrate, + delegate.sessionId, server, KafkaCapabilities.PRODUCE_AND_FETCH); + } + + @Override + protected void onKafkaDataImpl(DataFW data) + { + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + + final OctetsFW extension = data.extension(); + final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); + final KafkaDataExFW kafkaDataEx = + dataEx != null && dataEx.typeId() == kafkaTypeId ? extension.get(kafkaDataExRO::tryWrap) : null; + final KafkaMergedDataExFW kafkaMergedDataEx = + kafkaDataEx != null && kafkaDataEx.kind() == KafkaDataExFW.KIND_MERGED ? kafkaDataEx.merged() : null; + final KafkaKeyFW key = kafkaMergedDataEx != null ? kafkaMergedDataEx.fetch().key() : null; + + if (delegate.group != null && key != null) + { + delegate.group.doKafkaFlush(traceId, authorization, budgetId, reserved); + } + } + } + + private final class KafkaSessionStateProxy extends KafkaSessionStream + { + private KafkaSessionStateProxy( + long originId, + long routedId, + MqttSessionProxy delegate) + { + super(originId, routedId, delegate); + } + + @Override + protected void onKafkaDataImpl( + DataFW data) + { + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final long budgetId = data.budgetId(); + final int reserved = data.reserved(); + + final int flags = data.flags(); final OctetsFW payload = data.payload(); final OctetsFW extension = data.extension(); final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); @@ -2962,6 +3421,47 @@ else if (keyLen == delegate.clientIdMigrate.length()) } } + @Override + protected void onKafkaFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + final long budgetId = flush.budgetId(); + final int reserved = flush.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + + delegate.doMqttData(traceId, authorization, budgetId, 0, DATA_FLAG_COMPLETE, EMPTY_OCTETS); + } + + @Override + protected void onKafkaEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttEnd(traceId, authorization); + } + @Override protected void onKafkaWindow( WindowFW window) @@ -3013,13 +3513,34 @@ protected void onKafkaWindow( delegate.doMqttWindow(authorization, traceId, budgetId, mqttAck, capabilities); } + @Override + protected void doKafkaBegin( + long traceId, + long authorization, + long affinity) + { + assert state == 0; + + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + + state = MqttKafkaState.openingInitial(state); + + KafkaCapabilities capabilities = isSetWillFlag(delegate.sessionFlags) ? + KafkaCapabilities.PRODUCE_ONLY : KafkaCapabilities.PRODUCE_AND_FETCH; + final String server = delegate.redirect ? serverRef : null; + kafka = newKafkaStream(super::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, delegate.sessionsTopic, delegate.clientId, delegate.clientIdMigrate, + delegate.sessionId, server, capabilities); + } + private void cancelWillSignal( long authorization, long traceId) { String16FW willSignalKey = new String16FW.Builder() .wrap(sessionSignalKeyBuffer, 0, sessionSignalKeyBuffer.capacity()) - .set(delegate.clientId.asString() + WILL_SIGNAL_KEY_POSTFIX, StandardCharsets.UTF_8).build(); + .set(delegate.clientId.asString() + WILL_SIGNAL_KEY_POSTFIX, UTF_8).build(); Flyweight willSignalKafkaDataEx = kafkaDataExRW .wrap(extBuffer, 0, extBuffer.capacity()) .typeId(kafkaTypeId) @@ -3041,36 +3562,785 @@ private void cancelWillSignal( doKafkaData(traceId, authorization, 0, 0, DATA_FLAG_COMPLETE, null, willSignalKafkaDataEx); } + } - @Override - protected void onKafkaFlush( - FlushFW flush) + private final class KafkaFetchWillSignalStream extends KafkaSessionStream + { + private KafkaFetchWillSignalStream( + long originId, + long routedId, + MqttSessionProxy delegate) { - final long sequence = flush.sequence(); - final long acknowledge = flush.acknowledge(); - final long traceId = flush.traceId(); - final long authorization = flush.authorization(); - final long budgetId = flush.budgetId(); - final int reserved = flush.reserved(); + super(originId, routedId, delegate); + } - assert acknowledge <= sequence; + @Override + protected void onKafkaDataImpl( + DataFW data) + { + final OctetsFW extension = data.extension(); + final OctetsFW payload = data.payload(); + final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); + final KafkaDataExFW kafkaDataEx = + dataEx != null && dataEx.typeId() == kafkaTypeId ? extension.get(kafkaDataExRO::tryWrap) : null; + final KafkaMergedDataExFW kafkaMergedDataEx = + kafkaDataEx != null && kafkaDataEx.kind() == KafkaDataExFW.KIND_MERGED ? kafkaDataEx.merged() : null; + final KafkaKeyFW key = kafkaMergedDataEx != null ? kafkaMergedDataEx.fetch().key() : null; + + if (key != null && payload != null) + { + MqttSessionSignalFW sessionSignal = + mqttSessionSignalRO.wrap(payload.buffer(), payload.offset(), payload.limit()); + if (sessionSignal != null) + { + delegate.lifetimeId = sessionSignal.will().lifetimeId().asString(); + } + } + } + + @Override + protected void onKafkaFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + final long reserved = flush.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + + delegate.session.doKafkaEnd(traceId, authorization); + final long routedId = delegate.session.routedId; + + delegate.session = new KafkaSessionSignalStream(originId, routedId, delegate); + delegate.session.doKafkaBeginIfNecessary(traceId, authorization, 0); + } + + @Override + protected void doKafkaBegin( + long traceId, + long authorization, + long affinity) + { + if (!MqttKafkaState.initialOpening(state)) + { + state = MqttKafkaState.openingInitial(state); + + final String server = delegate.redirect ? serverRef : null; + kafka = newKafkaStream(super::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, delegate.sessionsTopic, delegate.clientId, server); + } + } + } + + private final class KafkaGroupStream + { + private MessageConsumer kafka; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final MqttSessionProxy delegate; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private KafkaGroupStream( + long originId, + long routedId, + MqttSessionProxy delegate) + { + this.originId = originId; + this.routedId = routedId; + this.delegate = delegate; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + } + + private void onGroupMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onKafkaData(data); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onKafkaFlush(flush); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onKafkaEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onKafkaAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onKafkaReset(reset); + break; + } + } + + private void onKafkaBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + assert acknowledge >= replyAck; + + replySeq = sequence; + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.openingReply(state); + + assert replyAck <= replySeq; + + final OctetsFW extension = begin.extension(); + + int sessionExpiryMillisInRange; + if (extension.sizeof() > 0) + { + final KafkaBeginExFW kafkaBeginEx = extension.get(kafkaBeginExRO::tryWrap); + + assert kafkaBeginEx.kind() == KafkaBeginExFW.KIND_GROUP; + final KafkaGroupBeginExFW kafkaGroupBeginEx = kafkaBeginEx.group(); + + sessionExpiryMillisInRange = kafkaGroupBeginEx.timeout(); + delegate.onGroupJoined(kafkaGroupBeginEx.instanceId().asString(), kafkaGroupBeginEx.host().asString(), + kafkaGroupBeginEx.port(), sessionExpiryMillisInRange); + } + + delegate.onSessionBegin(traceId, authorization, affinity); + doKafkaWindow(traceId, authorization, 0, 0, 0); + } + + private void onKafkaData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final int reserved = data.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + if (replySeq > replyAck + replyMax) + { + doKafkaReset(traceId); + delegate.doMqttAbort(traceId, authorization); + } + } + + private void onKafkaFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + final long reserved = flush.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + + final OctetsFW extension = flush.extension(); + final ExtensionFW flushEx = extension.get(extensionRO::tryWrap); + final KafkaFlushExFW kafkaFlushEx = + flushEx != null && flushEx.typeId() == kafkaTypeId ? extension.get(kafkaFlushExRO::tryWrap) : null; + final KafkaGroupFlushExFW kafkaGroupFlushEx = + kafkaFlushEx != null && kafkaFlushEx.kind() == KafkaFlushExFW.KIND_GROUP ? kafkaFlushEx.group() : null; + final String16FW leaderId = kafkaGroupFlushEx != null ? kafkaGroupFlushEx.leaderId() : null; + final String16FW memberId = kafkaGroupFlushEx != null ? kafkaGroupFlushEx.memberId() : null; + final int members = kafkaGroupFlushEx != null ? kafkaGroupFlushEx.members().fieldCount() : 0; + final int generationId = kafkaGroupFlushEx != null ? kafkaGroupFlushEx.generationId() : 0; + + if (leaderId.equals(memberId)) + { + delegate.onSessionBecomesLeader(traceId, authorization, members, memberId.asString(), generationId); + } + + if (!MqttKafkaState.initialClosed(state)) + { + doKafkaData(traceId, authorization, 0, 0, DATA_FLAG_COMPLETE, EMPTY_OCTETS, EMPTY_OCTETS); + } + } + + private void onKafkaEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttEnd(traceId, authorization); + } + + private void onKafkaAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttAbort(traceId, authorization); + } + + private void onKafkaReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + final OctetsFW extension = reset.extension(); + + assert acknowledge <= sequence; + + + final KafkaResetExFW kafkaResetEx = extension.get(kafkaResetExRO::tryWrap); + final int error = kafkaResetEx != null ? kafkaResetEx.error() : -1; + + Flyweight mqttResetEx = EMPTY_OCTETS; + if (error != -1) + { + mqttResetEx = + mqttSessionResetExRW.wrap(sessionExtBuffer, 0, sessionExtBuffer.capacity()) + .typeId(mqttTypeId) + .reasonCode(MQTT_REASON_CODES.get(error)) + .reason(MQTT_REASONS.getOrDefault(error, DEFAULT_REASON)) + .build(); + } + delegate.doMqttReset(traceId, mqttResetEx); + } + + private void doKafkaBegin( + long traceId, + long authorization, + long affinity) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.openingInitial(state); + + kafka = newGroupStream(this::onGroupMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, delegate.clientId, delegate.sessionExpiryMillis); + } + + private void doKafkaFlush( + long traceId, + long authorization, + long budgetId, + int reserved) + { + initialSeq = delegate.initialSeq; + + doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, reserved, EMPTY_OCTETS); + } + + private void doKafkaEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaReset( + long traceId) + { + if (!MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + replyAck = delegate.replyAck; + replyMax = delegate.replyMax; + replyPad = delegate.replyPad; + + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, replyPad, capabilities); + } + + private void doKafkaData( + long traceId, + long authorization, + long budgetId, + int reserved, + int flags, + OctetsFW payload, + Flyweight extension) + { + doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, reserved, payload, extension); + + initialSeq += reserved; + + assert initialSeq <= initialAck + initialMax; + } + } + + private final class KafkaMetaStream + { + private MessageConsumer kafka; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final MqttSessionProxy delegate; + private final String16FW topic; + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private KafkaMetaStream( + long originId, + long routedId, + MqttSessionProxy delegate, + String16FW topic, + boolean retained) + { + this.originId = originId; + this.routedId = routedId; + this.delegate = delegate; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + this.topic = topic; + } + + private void onMetaMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onKafkaData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onKafkaEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onKafkaAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onKafkaReset(reset); + break; + } + } + + private void onKafkaBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + assert acknowledge >= replyAck; + + replySeq = sequence; + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.openingReply(state); + + assert replyAck <= replySeq; + + doKafkaWindow(traceId, authorization, 0, 0, 0); + } + + private void onKafkaData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final int reserved = data.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + if (replySeq > replyAck + replyMax) + { + doKafkaReset(traceId); + delegate.doMqttAbort(traceId, authorization); + } + + final OctetsFW extension = data.extension(); + final KafkaDataExFW kafkaDataEx = extension.get(kafkaDataExRO::tryWrap); + final KafkaMetaDataExFW kafkaMetaDataEx = kafkaDataEx.meta(); + final Array32FW partitions = kafkaMetaDataEx.partitions(); + + delegate.onPartitionsFetched(traceId, authorization, topic, partitions, this); + doKafkaEnd(traceId, authorization); + } + + private void onKafkaEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + } + + private void onKafkaAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttAbort(traceId, authorization); + } + + private void onKafkaReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + + delegate.doMqttReset(traceId, EMPTY_OCTETS); + } + + private void doKafkaBegin( + long traceId, + long authorization, + long affinity) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.openingInitial(state); + + kafka = newMetaStream(this::onMetaMessage, originId, routedId, initialId, initialSeq, initialAck, + initialMax, traceId, authorization, affinity, topic); + } + + private void doKafkaEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaReset( + long traceId) + { + if (!MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + replyAck = delegate.replyAck; + replyMax = delegate.replyMax; + replyPad = delegate.replyPad; + + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, replyPad, capabilities); + } + } + + private final class KafkaOffsetFetchStream + { + private MessageConsumer kafka; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final MqttSessionProxy delegate; + private final String host; + private final int port; + private final String topic; + private final Array32FW partitions; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private KafkaOffsetFetchStream( + long originId, + long routedId, + MqttSessionProxy delegate, + String host, + int port, + String topic, + Array32FW partitions) + { + this.originId = originId; + this.routedId = routedId; + this.delegate = delegate; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + this.host = host; + this.port = port; + this.topic = topic; + this.partitions = partitions; + } + + private void onOffsetFetchMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) + { + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onKafkaData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onKafkaEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onKafkaAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onKafkaReset(reset); + break; + } + } + + private void onKafkaBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; assert sequence >= replySeq; + assert acknowledge >= replyAck; replySeq = sequence; + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.openingReply(state); assert replyAck <= replySeq; - delegate.doMqttData(traceId, authorization, budgetId, 0, DATA_FLAG_COMPLETE, EMPTY_OCTETS); + doKafkaWindow(traceId, authorization, 0, 0, 0); } - @Override - protected void onKafkaEnd( + private void onKafkaData( + DataFW data) + { + final long sequence = data.sequence(); + final long acknowledge = data.acknowledge(); + final long traceId = data.traceId(); + final long authorization = data.authorization(); + final int reserved = data.reserved(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence + reserved; + + assert replyAck <= replySeq; + if (replySeq > replyAck + replyMax) + { + doKafkaReset(traceId); + delegate.doMqttAbort(traceId, authorization); + } + + final OctetsFW extension = data.extension(); + final KafkaDataExFW kafkaDataEx = extension.get(kafkaDataExRO::tryWrap); + final KafkaOffsetFetchDataExFW kafkaOffsetFetchDataEx = kafkaDataEx.offsetFetch(); + final Array32FW partitions = kafkaOffsetFetchDataEx.partitions(); + + delegate.onOffsetFetched(traceId, authorization, topic, partitions, this); + doKafkaEnd(traceId, authorization); + } + + private void onKafkaEnd( EndFW end) { final long sequence = end.sequence(); final long acknowledge = end.acknowledge(); - final long traceId = end.traceId(); - final long authorization = end.authorization(); assert acknowledge <= sequence; assert sequence >= replySeq; @@ -3079,115 +4349,250 @@ protected void onKafkaEnd( state = MqttKafkaState.closeReply(state); assert replyAck <= replySeq; + } - delegate.doMqttEnd(traceId, authorization); + private void onKafkaAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + delegate.doMqttAbort(traceId, authorization); + } + + private void onKafkaReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + + delegate.doMqttReset(traceId, EMPTY_OCTETS); + } + + private void doKafkaBegin( + long traceId, + long authorization, + long affinity) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.openingInitial(state); + + kafka = newOffsetFetchStream(this::onOffsetFetchMessage, originId, routedId, initialId, initialSeq, initialAck, + initialMax, traceId, authorization, affinity, delegate.clientId, host, port, topic, partitions); + } + + private void doKafkaEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaReset( + long traceId) + { + if (!MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + replyAck = delegate.replyAck; + replyMax = delegate.replyMax; + replyPad = delegate.replyPad; + + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, replyPad, capabilities); } } - private final class KafkaFetchWillSignalStream extends KafkaSessionStream + private final class KafkaInitProducerStream { - private KafkaFetchWillSignalStream( + private MessageConsumer kafka; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final MqttSessionProxy delegate; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private KafkaInitProducerStream( long originId, long routedId, MqttSessionProxy delegate) { - super(originId, routedId, delegate); + this.originId = originId; + this.routedId = routedId; + this.delegate = delegate; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); } - @Override - protected void doKafkaBegin( - long traceId, - long authorization, - long affinity) + private void onInitProducerMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) { - if (!MqttKafkaState.initialOpening(state)) + switch (msgTypeId) { - state = MqttKafkaState.openingInitial(state); - - final String server = delegate.redirect ? serverRef : null; - kafka = newKafkaStream(super::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, affinity, delegate.sessionsTopic, delegate.clientId, server); + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onKafkaEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onKafkaAbort(abort); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onKafkaReset(reset); + break; } } - @Override - protected void handleKafkaData( - DataFW data) - { - final OctetsFW extension = data.extension(); - final OctetsFW payload = data.payload(); - final ExtensionFW dataEx = extension.get(extensionRO::tryWrap); - final KafkaDataExFW kafkaDataEx = - dataEx != null && dataEx.typeId() == kafkaTypeId ? extension.get(kafkaDataExRO::tryWrap) : null; - final KafkaMergedDataExFW kafkaMergedDataEx = - kafkaDataEx != null && kafkaDataEx.kind() == KafkaDataExFW.KIND_MERGED ? kafkaDataEx.merged() : null; - final KafkaKeyFW key = kafkaMergedDataEx != null ? kafkaMergedDataEx.fetch().key() : null; + private void onKafkaBegin( + BeginFW begin) + { + final long sequence = begin.sequence(); + final long acknowledge = begin.acknowledge(); + final int maximum = begin.maximum(); + final long traceId = begin.traceId(); + final long authorization = begin.authorization(); + final long affinity = begin.affinity(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + assert acknowledge >= replyAck; + + replySeq = sequence; + replyAck = acknowledge; + replyMax = maximum; + state = MqttKafkaState.openingReply(state); + + assert replyAck <= replySeq; + + final OctetsFW extension = begin.extension(); + + final KafkaBeginExFW kafkaBeginEx = extension.get(kafkaBeginExRO::tryWrap); + + assert kafkaBeginEx.kind() == KafkaBeginExFW.KIND_INIT_PRODUCER_ID; + final KafkaInitProducerIdBeginExFW kafkaInitProducerIdBeginEx = kafkaBeginEx.initProducerId(); - if (key != null && payload != null) - { - MqttSessionSignalFW sessionSignal = - mqttSessionSignalRO.wrap(payload.buffer(), payload.offset(), payload.limit()); - if (sessionSignal != null) - { - delegate.lifetimeId = sessionSignal.will().lifetimeId().asString(); - } - } + long producerId = kafkaInitProducerIdBeginEx.producerId(); + short producerEpoch = kafkaInitProducerIdBeginEx.producerEpoch(); + + delegate.onProducerInit(traceId, authorization, producerId, producerEpoch); + + doKafkaWindow(traceId, authorization, 0, 0, 0); + doKafkaEnd(traceId, authorization); } - @Override - protected void onKafkaFlush( - FlushFW flush) + private void onKafkaEnd( + EndFW end) { - final long sequence = flush.sequence(); - final long acknowledge = flush.acknowledge(); - final long traceId = flush.traceId(); - final long authorization = flush.authorization(); + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); assert acknowledge <= sequence; assert sequence >= replySeq; replySeq = sequence; + state = MqttKafkaState.closeReply(state); assert replyAck <= replySeq; - - delegate.session.doKafkaEnd(traceId, authorization); - final long routedId = delegate.session.routedId; - - delegate.session = new KafkaSessionSignalStream(originId, routedId, delegate); - delegate.session.doKafkaBeginIfNecessary(traceId, authorization, 0); } - } - private final class KafkaGroupStream - { - private MessageConsumer kafka; - private final long originId; - private final long routedId; - private final long initialId; - private final long replyId; - private final MqttSessionProxy delegate; + private void onKafkaAbort( + AbortFW abort) + { + final long sequence = abort.sequence(); + final long acknowledge = abort.acknowledge(); + final long traceId = abort.traceId(); + final long authorization = abort.authorization(); - private int state; + assert acknowledge <= sequence; + assert sequence >= replySeq; - private long initialSeq; - private long initialAck; - private int initialMax; + replySeq = sequence; + state = MqttKafkaState.closeReply(state); - private long replySeq; - private long replyAck; - private int replyMax; - private int replyPad; + assert replyAck <= replySeq; - private KafkaGroupStream( - long originId, - long routedId, - MqttSessionProxy delegate) + delegate.doMqttAbort(traceId, authorization); + } + + private void onKafkaReset( + ResetFW reset) { - this.originId = originId; - this.routedId = routedId; - this.delegate = delegate; - this.initialId = supplyInitialId.applyAsLong(routedId); - this.replyId = supplyReplyId.applyAsLong(initialId); + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + + delegate.doMqttReset(traceId, EMPTY_OCTETS); } private void doKafkaBegin( @@ -3200,20 +4605,8 @@ private void doKafkaBegin( initialMax = delegate.initialMax; state = MqttKafkaState.openingInitial(state); - kafka = newGroupStream(this::onGroupMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, affinity, delegate.clientId, delegate.sessionExpiryMillis); - } - - private void doKafkaFlush( - long traceId, - long authorization, - long budgetId, - int reserved) - { - initialSeq = delegate.initialSeq; - - doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, reserved, EMPTY_OCTETS); + kafka = newInitProducerStream(this::onInitProducerMessage, originId, routedId, initialId, initialSeq, initialAck, + initialMax, traceId, authorization, affinity); } private void doKafkaEnd( @@ -3246,7 +4639,66 @@ private void doKafkaAbort( } } - private void onGroupMessage( + private void doKafkaReset( + long traceId) + { + if (!MqttKafkaState.replyClosed(state)) + { + state = MqttKafkaState.closeReply(state); + + doReset(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, traceId, EMPTY_OCTETS); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + replyAck = delegate.replyAck; + replyMax = delegate.replyMax; + replyPad = delegate.replyPad; + + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, replyPad, capabilities); + } + } + + private final class KafkaOffsetCommitStream + { + private MessageConsumer kafka; + private final long originId; + private final long routedId; + private final long initialId; + private final long replyId; + private final MqttSessionProxy delegate; + + private int state; + + private long initialSeq; + private long initialAck; + private int initialMax; + + private long replySeq; + private long replyAck; + private int replyMax; + private int replyPad; + + private KafkaOffsetCommitStream( + long originId, + long routedId, + MqttSessionProxy delegate) + { + this.originId = originId; + this.routedId = routedId; + this.delegate = delegate; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + } + + private void onOffsetCommitMessage( int msgTypeId, DirectBuffer buffer, int index, @@ -3258,14 +4710,6 @@ private void onGroupMessage( final BeginFW begin = beginRO.wrap(buffer, index, index + length); onKafkaBegin(begin); break; - case DataFW.TYPE_ID: - final DataFW data = dataRO.wrap(buffer, index, index + length); - onKafkaData(data); - break; - case FlushFW.TYPE_ID: - final FlushFW flush = flushRO.wrap(buffer, index, index + length); - onKafkaFlush(flush); - break; case EndFW.TYPE_ID: final EndFW end = endRO.wrap(buffer, index, index + length); onKafkaEnd(end); @@ -3278,55 +4722,10 @@ private void onGroupMessage( final ResetFW reset = resetRO.wrap(buffer, index, index + length); onKafkaReset(reset); break; - } - } - - private void onKafkaFlush( - FlushFW flush) - { - final long sequence = flush.sequence(); - final long acknowledge = flush.acknowledge(); - final long traceId = flush.traceId(); - final long authorization = flush.authorization(); - - assert acknowledge <= sequence; - assert sequence >= replySeq; - - replySeq = sequence; - - assert replyAck <= replySeq; - - final OctetsFW extension = flush.extension(); - final ExtensionFW flushEx = extension.get(extensionRO::tryWrap); - final KafkaFlushExFW kafkaFlushEx = - flushEx != null && flushEx.typeId() == kafkaTypeId ? extension.get(kafkaFlushExRO::tryWrap) : null; - final KafkaGroupFlushExFW kafkaGroupDataEx = - kafkaFlushEx != null && kafkaFlushEx.kind() == KafkaFlushExFW.KIND_GROUP ? kafkaFlushEx.group() : null; - final String16FW leaderId = kafkaGroupDataEx != null ? kafkaGroupDataEx.leaderId() : null; - final String16FW memberId = kafkaGroupDataEx != null ? kafkaGroupDataEx.memberId() : null; - final int members = kafkaGroupDataEx != null ? kafkaGroupDataEx.members().fieldCount() : 0; - - if (leaderId.equals(memberId)) - { - if (members > 1) - { - delegate.session.sendMigrateSignal(traceId, authorization); - delegate.session.sendWillSignal(traceId, authorization); - delegate.session.doKafkaEnd(traceId, authorization); - doKafkaEnd(traceId, authorization); - } - else - { - delegate.session.doKafkaEnd(traceId, authorization); - final long routedId = delegate.session.routedId; - delegate.session = new KafkaSessionStateProxy(originId, routedId, delegate); - delegate.session.doKafkaBeginIfNecessary(traceId, authorization, 0); - } - } - - if (!MqttKafkaState.initialClosed(state)) - { - doKafkaData(traceId, authorization, 0, 0, DATA_FLAG_COMPLETE, EMPTY_OCTETS, EMPTY_OCTETS); + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onKafkaWindow(window); + break; } } @@ -3348,61 +4747,10 @@ private void onKafkaBegin( replyAck = acknowledge; replyMax = maximum; state = MqttKafkaState.openingReply(state); - - assert replyAck <= replySeq; - - final OctetsFW extension = begin.extension(); - - int sessionExpiryMillisInRange = delegate.sessionExpiryMillis; - if (extension.sizeof() > 0) - { - final KafkaBeginExFW kafkaBeginEx = extension.get(kafkaBeginExRO::tryWrap); - - assert kafkaBeginEx.kind() == KafkaBeginExFW.KIND_GROUP; - final KafkaGroupBeginExFW kafkaGroupBeginEx = kafkaBeginEx.group(); - - sessionExpiryMillisInRange = kafkaGroupBeginEx.timeout(); - } - - if (delegate.sessionExpiryMillis != sessionExpiryMillisInRange) - { - delegate.sessionExpiryMillis = sessionExpiryMillisInRange; - } - - Flyweight mqttBeginEx = mqttSessionBeginExRW.wrap(sessionExtBuffer, 0, sessionExtBuffer.capacity()) - .typeId(mqttTypeId) - .session(sessionBuilder -> sessionBuilder - .flags(delegate.sessionFlags) - .expiry((int) TimeUnit.MILLISECONDS.toSeconds(delegate.sessionExpiryMillis)) - .qosMax(MQTT_KAFKA_MAX_QOS) - .capabilities(MQTT_KAFKA_CAPABILITIES) - .clientId(delegate.clientId)) - .build(); - - delegate.doMqttBegin(traceId, authorization, affinity, mqttBeginEx); - doKafkaWindow(traceId, authorization, 0, 0, 0); - } - - private void onKafkaData( - DataFW data) - { - final long sequence = data.sequence(); - final long acknowledge = data.acknowledge(); - final long traceId = data.traceId(); - final long authorization = data.authorization(); - final int reserved = data.reserved(); - - assert acknowledge <= sequence; - assert sequence >= replySeq; - - replySeq = sequence + reserved; - - assert replyAck <= replySeq; - if (replySeq > replyAck + replyMax) - { - doKafkaReset(traceId); - delegate.doMqttAbort(traceId, authorization); - } + + assert replyAck <= replySeq; + + doKafkaWindow(traceId, authorization, 0, 0, 0); } private void onKafkaEnd( @@ -3410,8 +4758,6 @@ private void onKafkaEnd( { final long sequence = end.sequence(); final long acknowledge = end.acknowledge(); - final long traceId = end.traceId(); - final long authorization = end.authorization(); assert acknowledge <= sequence; assert sequence >= replySeq; @@ -3420,8 +4766,6 @@ private void onKafkaEnd( state = MqttKafkaState.closeReply(state); assert replyAck <= replySeq; - - delegate.doMqttEnd(traceId, authorization); } private void onKafkaAbort( @@ -3449,25 +4793,54 @@ private void onKafkaReset( final long sequence = reset.sequence(); final long acknowledge = reset.acknowledge(); final long traceId = reset.traceId(); - final OctetsFW extension = reset.extension(); assert acknowledge <= sequence; + delegate.doMqttReset(traceId, EMPTY_OCTETS); + } - final KafkaResetExFW kafkaResetEx = extension.get(kafkaResetExRO::tryWrap); - final int error = kafkaResetEx != null ? kafkaResetEx.error() : -1; + private void onKafkaWindow( + WindowFW window) + { + final long traceId = window.traceId(); + final long authorization = window.authorization(); + final long budgetId = window.budgetId(); + final long sequence = window.sequence(); + final long acknowledge = window.acknowledge(); + final int maximum = window.maximum(); + final boolean wasOpen = MqttKafkaState.initialOpened(state); - Flyweight mqttResetEx = EMPTY_OCTETS; - if (error != -1) + assert acknowledge <= sequence; + assert acknowledge >= delegate.initialAck; + assert maximum >= delegate.initialMax; + + initialAck = acknowledge; + initialMax = maximum; + state = MqttKafkaState.openInitial(state); + + assert initialAck <= initialSeq; + + if (!wasOpen) { - mqttResetEx = - mqttSessionResetExRW.wrap(sessionExtBuffer, 0, sessionExtBuffer.capacity()) - .typeId(mqttTypeId) - .reasonCode(MQTT_REASON_CODES.get(error)) - .reason(MQTT_REASONS.get(error)) - .build(); + delegate.onOffsetCommitOpened(traceId, authorization, budgetId); } - delegate.doMqttReset(traceId, mqttResetEx); + else + { + delegate.onOffsetCommitAck(traceId, authorization); + } + } + + private void doKafkaData( + long traceId, + long authorization, + long budgetId, + int flags, + Flyweight extension) + { + doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, flags, 0, EMPTY_OCTETS, extension); + + assert initialSeq <= initialAck + initialMax; } private void doKafkaReset( @@ -3496,25 +4869,50 @@ private void doKafkaWindow( traceId, authorization, budgetId, padding, replyPad, capabilities); } - private void doKafkaData( + private void doKafkaBegin( long traceId, long authorization, - long budgetId, - int reserved, - int flags, - OctetsFW payload, - Flyweight extension) + long affinity) { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.openingInitial(state); - doData(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, flags, reserved, payload, extension); + kafka = newOffsetCommitStream(this::onOffsetCommitMessage, originId, routedId, initialId, initialSeq, initialAck, + initialMax, traceId, authorization, affinity, delegate.clientId, delegate.memberId, delegate.groupInstanceId); + } - initialSeq += reserved; + private void doKafkaEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); - assert initialSeq <= initialAck + initialMax; + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } } - } + private void doKafkaAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = delegate.initialSeq; + initialAck = delegate.initialAck; + initialMax = delegate.initialMax; + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + } private void doBegin( MessageConsumer receiver, @@ -4030,6 +5428,186 @@ private MessageConsumer newGroupStream( return receiver; } + private MessageConsumer newMetaStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + String16FW topic) + { + final KafkaBeginExFW kafkaBeginEx = + kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .meta(m -> m + .topic(topic)) + .build(); + + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(kafkaBeginEx.buffer(), kafkaBeginEx.offset(), kafkaBeginEx.sizeof()) + .build(); + + MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private MessageConsumer newOffsetFetchStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + String16FW clientId, + String host, + int port, + String topic, + Array32FW partitions) + { + final String groupId = String.format("%s-%s", clientId.asString(), GROUPID_SESSION_SUFFIX); + + final KafkaBeginExFW kafkaBeginEx = + kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .offsetFetch(o -> o + .groupId(groupId) + .host(host) + .port(port) + .topic(topic) + .partitions(ps -> partitions.forEach(p -> ps.item(tp -> tp.partitionId(p.partitionId()))))) + .build(); + + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(kafkaBeginEx.buffer(), kafkaBeginEx.offset(), kafkaBeginEx.sizeof()) + .build(); + + MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private MessageConsumer newInitProducerStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity) + { + final KafkaBeginExFW kafkaBeginEx = + kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .initProducerId(p -> p + .producerId(0) + .producerEpoch((short) 0)) + .build(); + + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(kafkaBeginEx.buffer(), kafkaBeginEx.offset(), kafkaBeginEx.sizeof()) + .build(); + + MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + + private MessageConsumer newOffsetCommitStream( + MessageConsumer sender, + long originId, + long routedId, + long streamId, + long sequence, + long acknowledge, + int maximum, + long traceId, + long authorization, + long affinity, + String16FW clientId, + String memberId, + String instanceId) + { + final String groupId = String.format("%s-%s", clientId.asString(), GROUPID_SESSION_SUFFIX); + + final KafkaBeginExFW kafkaBeginEx = + kafkaBeginExRW.wrap(writeBuffer, BeginFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .offsetCommit(o -> o + .groupId(groupId) + .memberId(memberId) + .instanceId(instanceId)) + .build(); + + final BeginFW begin = beginRW.wrap(writeBuffer, 0, writeBuffer.capacity()) + .originId(originId) + .routedId(routedId) + .streamId(streamId) + .sequence(sequence) + .acknowledge(acknowledge) + .maximum(maximum) + .traceId(traceId) + .authorization(authorization) + .affinity(affinity) + .extension(kafkaBeginEx.buffer(), kafkaBeginEx.offset(), kafkaBeginEx.sizeof()) + .build(); + + MessageConsumer receiver = + streamFactory.newStream(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof(), sender); + + receiver.accept(begin.typeId(), begin.buffer(), begin.offset(), begin.sizeof()); + + return receiver; + } + private void doWindow( MessageConsumer sender, long originId, diff --git a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeFactory.java b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeFactory.java index 7d067e11ab..fde1562c52 100644 --- a/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeFactory.java +++ b/runtime/binding-mqtt-kafka/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSubscribeFactory.java @@ -62,6 +62,7 @@ import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.KafkaSkip; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttPayloadFormat; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttQoS; +import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttSubscribeOffsetMetadataFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.MqttTopicFilterFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.OctetsFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.String16FW; @@ -83,7 +84,6 @@ import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttBeginExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttDataExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttFlushExFW; -import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttOffsetMetadataFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttOffsetStateFlags; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttSubscribeBeginExFW; import io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.types.stream.MqttSubscribeFlushExFW; @@ -131,7 +131,7 @@ public class MqttKafkaSubscribeFactory implements MqttKafkaStreamFactory private final WindowFW.Builder windowRW = new WindowFW.Builder(); private final ResetFW.Builder resetRW = new ResetFW.Builder(); private final MqttSubscribeMessageFW.Builder mqttSubscribeMessageRW = new MqttSubscribeMessageFW.Builder(); - private final MqttOffsetMetadataFW.Builder mqttOffsetMetadataRW = new MqttOffsetMetadataFW.Builder(); + private final MqttSubscribeOffsetMetadataFW.Builder mqttOffsetMetadataRW = new MqttSubscribeOffsetMetadataFW.Builder(); private final ExtensionFW extensionRO = new ExtensionFW(); private final MqttBeginExFW mqttBeginExRO = new MqttBeginExFW(); @@ -141,7 +141,7 @@ public class MqttKafkaSubscribeFactory implements MqttKafkaStreamFactory private final KafkaFlushExFW kafkaFlushExRO = new KafkaFlushExFW(); private final KafkaHeaderFW kafkaHeaderRO = new KafkaHeaderFW(); private final MqttSubscribeMessageFW mqttSubscribeMessageRO = new MqttSubscribeMessageFW(); - private final MqttOffsetMetadataFW mqttOffsetMetadataRO = new MqttOffsetMetadataFW(); + private final MqttSubscribeOffsetMetadataFW mqttOffsetMetadataRO = new MqttSubscribeOffsetMetadataFW(); private final MqttDataExFW.Builder mqttDataExRW = new MqttDataExFW.Builder(); private final MqttFlushExFW.Builder mqttFlushExRW = new MqttFlushExFW.Builder(); @@ -549,36 +549,6 @@ else if (qos == MqttQoS.EXACTLY_ONCE.value() && state != MqttOffsetStateFlags.IN } } - private void commitDeferredOffsets( - long traceId, - long authorization, - long budgetId, - int reserved, - OffsetHighWaterMark highWaterMark) - { - long offset = highWaterMark.offset; - DeferredOffsetCommit deferredOffsetCommit = highWaterMark.deferredOffsetCommits.get(offset); - - while (deferredOffsetCommit != null) - { - deferredOffsetCommit.commit(traceId, authorization, budgetId, reserved); - highWaterMark.deferredOffsetCommits.remove(offset); - offset = highWaterMark.increase(); - deferredOffsetCommit = highWaterMark.deferredOffsetCommits.get(highWaterMark.offset); - } - } - - private void commitOffset( - long traceId, - long authorization, - long budgetId, - int reserved, - KafkaProxy proxy, - OffsetCommit offsetCommit) - { - proxy.doKafkaConsumerFlush(traceId, authorization, budgetId, reserved, offsetCommit); - } - private void onMqttData( DataFW data) { @@ -814,6 +784,36 @@ private void doMqttReset( } } + private void commitDeferredOffsets( + long traceId, + long authorization, + long budgetId, + int reserved, + OffsetHighWaterMark highWaterMark) + { + long offset = highWaterMark.offset; + DeferredOffsetCommit deferredOffsetCommit = highWaterMark.deferredOffsetCommits.get(offset); + + while (deferredOffsetCommit != null) + { + deferredOffsetCommit.commit(traceId, authorization, budgetId, reserved); + highWaterMark.deferredOffsetCommits.remove(offset); + offset = highWaterMark.increase(); + deferredOffsetCommit = highWaterMark.deferredOffsetCommits.get(highWaterMark.offset); + } + } + + private void commitOffset( + long traceId, + long authorization, + long budgetId, + int reserved, + KafkaProxy proxy, + OffsetCommit offsetCommit) + { + proxy.doKafkaConsumerFlush(traceId, authorization, budgetId, reserved, offsetCommit); + } + public int replyPendingAck() { return (int)(replySeq - replyAck); @@ -860,76 +860,6 @@ private KafkaMessagesBootstrap( this.replyId = supplyReplyId.applyAsLong(initialId); } - private void doKafkaBeginAt( - long timeMillis) - { - this.reconnectAt = signaler.signalAt( - timeMillis, - SIGNAL_CONNECT_BOOTSTRAP_STREAM, - this::onSignalConnectBootstrapStream); - } - - private void onSignalConnectBootstrapStream( - int signalId) - { - assert signalId == SIGNAL_CONNECT_BOOTSTRAP_STREAM; - - this.reconnectAt = NO_CANCEL_ID; - doKafkaBegin(supplyTraceId.get(), 0, 0); - } - - private void doKafkaBegin( - long traceId, - long authorization, - long affinity) - { - reconnectAttempt = 0; - state = MqttKafkaState.openingInitial(state); - - kafka = newKafkaBootstrapStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, - initialMax, traceId, authorization, affinity, topic, serverRef); - } - - private void doKafkaEnd( - long traceId, - long authorization) - { - if (!MqttKafkaState.initialClosed(state)) - { - state = MqttKafkaState.closeInitial(state); - - doEnd(kafka, originId, routedId, initialId, 0, 0, 0, traceId, authorization); - - signaler.cancel(reconnectAt); - reconnectAt = NO_CANCEL_ID; - } - } - - private void doKafkaAbort( - long traceId, - long authorization) - { - if (!MqttKafkaState.initialClosed(state)) - { - state = MqttKafkaState.closeInitial(state); - - doAbort(kafka, originId, routedId, initialId, 0, 0, 0, traceId, authorization); - } - } - - private void doKafkaWindow( - long traceId, - long authorization, - long budgetId, - int padding, - int capabilities) - { - replyMax = 8192; - - doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, - traceId, authorization, budgetId, padding, 0, capabilities); - } - private void onKafkaMessage( int msgTypeId, DirectBuffer buffer, @@ -1065,6 +995,77 @@ private void onKafkaReset( this::onSignalConnectBootstrapStream); } } + + + private void doKafkaBeginAt( + long timeMillis) + { + this.reconnectAt = signaler.signalAt( + timeMillis, + SIGNAL_CONNECT_BOOTSTRAP_STREAM, + this::onSignalConnectBootstrapStream); + } + + private void doKafkaBegin( + long traceId, + long authorization, + long affinity) + { + reconnectAttempt = 0; + state = MqttKafkaState.openingInitial(state); + + kafka = newKafkaBootstrapStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, + initialMax, traceId, authorization, affinity, topic, serverRef); + } + + private void doKafkaEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, 0, 0, 0, traceId, authorization); + + signaler.cancel(reconnectAt); + reconnectAt = NO_CANCEL_ID; + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, 0, 0, 0, traceId, authorization); + } + } + + private void doKafkaWindow( + long traceId, + long authorization, + long budgetId, + int padding, + int capabilities) + { + replyMax = 8192; + + doWindow(kafka, originId, routedId, replyId, replySeq, replyAck, replyMax, + traceId, authorization, budgetId, padding, 0, capabilities); + } + + private void onSignalConnectBootstrapStream( + int signalId) + { + assert signalId == SIGNAL_CONNECT_BOOTSTRAP_STREAM; + + this.reconnectAt = NO_CANCEL_ID; + doKafkaBegin(supplyTraceId.get(), 0, 0); + } } abstract class KafkaProxy @@ -1126,249 +1127,47 @@ private KafkaMessagesProxy( this.incompletePacketIds = new Int2ObjectHashMap<>(); } - public boolean matchesTopicFilter( - String topicFilter) + private void onKafkaMessage( + int msgTypeId, + DirectBuffer buffer, + int index, + int length) { - return routeConfig.matches(topicFilter, MqttKafkaConditionKind.SUBSCRIBE); + switch (msgTypeId) + { + case BeginFW.TYPE_ID: + final BeginFW begin = beginRO.wrap(buffer, index, index + length); + onKafkaBegin(begin); + break; + case DataFW.TYPE_ID: + final DataFW data = dataRO.wrap(buffer, index, index + length); + onKafkaData(data); + break; + case EndFW.TYPE_ID: + final EndFW end = endRO.wrap(buffer, index, index + length); + onKafkaEnd(end); + break; + case AbortFW.TYPE_ID: + final AbortFW abort = abortRO.wrap(buffer, index, index + length); + onKafkaAbort(abort); + break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onKafkaFlush(flush); + break; + case WindowFW.TYPE_ID: + final WindowFW window = windowRO.wrap(buffer, index, index + length); + onKafkaWindow(window); + break; + case ResetFW.TYPE_ID: + final ResetFW reset = resetRO.wrap(buffer, index, index + length); + onKafkaReset(reset); + break; + } } - private void doKafkaBegin( - long traceId, - long authorization, - long affinity, - Array32FW filters) - { - if (!MqttKafkaState.initialOpening(state)) - { - final Array32FW.Builder filterBuilder = - filtersRW.wrap(filterBuffer, 0, filterBuffer.capacity()); - - filters.forEach(f -> - { - if (matchesTopicFilter(f.pattern().asString())) - { - int subscriptionId = (int) f.subscriptionId(); - if (!messagesSubscriptionIds.contains(subscriptionId)) - { - messagesSubscriptionIds.add(subscriptionId); - } - filterBuilder.item(fb -> fb - .subscriptionId(subscriptionId).qos(f.qos()).flags(f.flags()).pattern(f.pattern())); - } - }); - - initialSeq = mqtt.initialSeq; - initialAck = mqtt.initialAck; - initialMax = mqtt.initialMax; - state = MqttKafkaState.openingInitial(state); - - kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, affinity, mqtt.clientId, topic, filterBuilder.build(), mqtt.qos, - KafkaOffsetType.LIVE); - } - } - - @Override - protected void doKafkaConsumerFlush( - long traceId, - long authorization, - long budgetId, - int reserved, - OffsetCommit offsetCommit) - { - final int qos = offsetCommit.qos; - final PartitionOffset offset = offsetCommit.partitionOffset; - final MqttOffsetStateFlags state = offsetCommit.state; - final int packetId = offsetCommit.packetId; - - - if (qos == MqttQoS.EXACTLY_ONCE.value() && state == MqttOffsetStateFlags.COMPLETE) - { - incompletePacketIds.computeIfAbsent(offset.partitionId, c -> new IntArrayList()).removeInt(packetId); - } - else if (state == MqttOffsetStateFlags.INCOMPLETE) - { - incompletePacketIds.computeIfAbsent(offset.partitionId, c -> new IntArrayList()).add(packetId); - } - - final int correlationId = state == MqttOffsetStateFlags.INCOMPLETE ? packetId : -1; - - final KafkaFlushExFW kafkaFlushEx = - kafkaFlushExRW.wrap(writeBuffer, FlushFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) - .typeId(kafkaTypeId) - .merged(m -> m.consumer(f -> - { - f.progress(p -> - { - p.partitionId(offset.partitionId).partitionOffset(offset.offset + 1); - final IntArrayList incomplete = incompletePacketIds.get(offset.partitionId); - final String16FW partitionMetadata = incomplete == null || incomplete.isEmpty() ? - EMPTY_STRING : offsetMetadataListToString(incomplete); - p.metadata(partitionMetadata); - }); - f.correlationId(correlationId); - })) - .build(); - - doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, reserved, kafkaFlushEx); - } - - private void doKafkaFlush( - long traceId, - long authorization, - long budgetId, - int reserved, - int qos, - Array32FW filters) - { - initialSeq = mqtt.initialSeq; - - messagesSubscriptionIds.clear(); - - final KafkaFlushExFW kafkaFlushEx = - kafkaFlushExRW.wrap(writeBuffer, FlushFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) - .typeId(kafkaTypeId) - .merged(m -> m.fetch(f -> - { - f.capabilities(c -> c.set(KafkaCapabilities.FETCH_ONLY)); - filters.forEach(filter -> - { - if (matchesTopicFilter(filter.pattern().asString())) - { - final int subscriptionId = (int) filter.subscriptionId(); - if (!messagesSubscriptionIds.contains(subscriptionId)) - { - messagesSubscriptionIds.add(subscriptionId); - } - if ((filter.flags() & SEND_RETAIN_FLAG) != 0) - { - mqtt.retainAvailable = true; - } - f.filtersItem(fi -> - { - fi.conditionsItem(ci -> buildHeaders(ci, filter.pattern().asString())); - - final boolean noLocal = (filter.flags() & NO_LOCAL_FLAG) != 0; - if (noLocal) - { - final DirectBuffer valueBuffer = mqtt.clientId.value(); - fi.conditionsItem(i -> i.not(n -> n.condition(c -> c.header(h -> - h.nameLen(helper.kafkaLocalHeaderName.sizeof()) - .name(helper.kafkaLocalHeaderName) - .valueLen(valueBuffer.capacity()) - .value(valueBuffer, 0, valueBuffer.capacity()))))); - } - - final int maxQos = filter.qos(); - if (maxQos != qos || maxQos == MqttQoS.EXACTLY_ONCE.value()) - { - for (int level = 0; level <= MqttQoS.EXACTLY_ONCE.value(); level++) - { - if (level != qos) - { - final DirectBuffer valueBuffer = qosNames.get(level).value(); - fi.conditionsItem(i -> i.not(n -> n.condition(c -> c.header(h -> - h.nameLen(helper.kafkaQosHeaderName.sizeof()) - .name(helper.kafkaQosHeaderName) - .valueLen(valueBuffer.capacity()) - .value(valueBuffer, 0, valueBuffer.capacity()))))); - } - } - } - else - { - for (int level = 0; level < maxQos; level++) - { - final DirectBuffer valueBuffer = qosNames.get(level).value(); - fi.conditionsItem(i -> i.not(n -> n.condition(c -> c.header(h -> - h.nameLen(helper.kafkaQosHeaderName.sizeof()) - .name(helper.kafkaQosHeaderName) - .valueLen(valueBuffer.capacity()) - .value(valueBuffer, 0, valueBuffer.capacity()))))); - } - } - }); - } - }); - })) - .build(); - - doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, reserved, kafkaFlushEx); - } - - private void doKafkaEnd( - long traceId, - long authorization) - { - if (MqttKafkaState.initialOpened(state) && !MqttKafkaState.initialClosed(state)) - { - initialSeq = mqtt.initialSeq; - initialAck = mqtt.initialAck; - initialMax = mqtt.initialMax; - state = MqttKafkaState.closeInitial(state); - - doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); - } - } - - private void doKafkaAbort( - long traceId, - long authorization) - { - if (MqttKafkaState.initialOpened(state) && !MqttKafkaState.initialClosed(state)) - { - initialSeq = mqtt.initialSeq; - initialAck = mqtt.initialAck; - initialMax = mqtt.initialMax; - state = MqttKafkaState.closeInitial(state); - - doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); - } - } - - private void onKafkaMessage( - int msgTypeId, - DirectBuffer buffer, - int index, - int length) - { - switch (msgTypeId) - { - case BeginFW.TYPE_ID: - final BeginFW begin = beginRO.wrap(buffer, index, index + length); - onKafkaBegin(begin); - break; - case DataFW.TYPE_ID: - final DataFW data = dataRO.wrap(buffer, index, index + length); - onKafkaData(data); - break; - case EndFW.TYPE_ID: - final EndFW end = endRO.wrap(buffer, index, index + length); - onKafkaEnd(end); - break; - case AbortFW.TYPE_ID: - final AbortFW abort = abortRO.wrap(buffer, index, index + length); - onKafkaAbort(abort); - break; - case FlushFW.TYPE_ID: - final FlushFW flush = flushRO.wrap(buffer, index, index + length); - onKafkaFlush(flush); - break; - case WindowFW.TYPE_ID: - final WindowFW window = windowRO.wrap(buffer, index, index + length); - onKafkaWindow(window); - break; - case ResetFW.TYPE_ID: - final ResetFW reset = resetRO.wrap(buffer, index, index + length); - onKafkaReset(reset); - break; - } - } - - private void onKafkaBegin( - BeginFW begin) + private void onKafkaBegin( + BeginFW begin) { final long sequence = begin.sequence(); final long acknowledge = begin.acknowledge(); @@ -1601,77 +1400,24 @@ private void onKafkaData( } } - private void flushData( - long traceId, - long authorization, - long budgetId) + private void onKafkaFlush( + FlushFW flush) { - int length = Math.max(Math.min(mqtt.replyWindow() - mqtt.replyPad, messageSlotLimit - messageSlotOffset), 0); - int reserved = length + mqtt.replyPad; - if (length > 0) - { - final MutableDirectBuffer dataBuffer = bufferPool.buffer(dataSlot); - final MqttSubscribeMessageFW message = mqttSubscribeMessageRO.wrap(dataBuffer, messageSlotOffset, - dataBuffer.capacity()); - mqtt.doMqttData(traceId, authorization, budgetId, reserved, bufferedDataFlags, message.payload(), - message.extension()); - - messageSlotOffset += message.sizeof(); - if (messageSlotOffset == messageSlotLimit) - { - bufferPool.release(dataSlot); - dataSlot = NO_SLOT; - messageSlotLimit = 0; - messageSlotOffset = 0; - } - } - } - - private void cleanup( - long traceId, - long authorization) - { - mqtt.doMqttAbort(traceId, authorization); - doKafkaAbort(traceId, authorization); - } - - private void onKafkaEnd( - EndFW end) - { - final long sequence = end.sequence(); - final long acknowledge = end.acknowledge(); - final long traceId = end.traceId(); - final long authorization = end.authorization(); + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + final long budgetId = flush.budgetId(); + final int reserved = flush.reserved(); + final OctetsFW extension = flush.extension(); + final ExtensionFW flushEx = extension.get(extensionRO::tryWrap); + final KafkaFlushExFW kafkaFlushEx = + flushEx != null && flushEx.typeId() == kafkaTypeId ? extension.get(kafkaFlushExRO::tryWrap) : null; assert acknowledge <= sequence; assert sequence >= replySeq; - replySeq = sequence; - state = MqttKafkaState.closeReply(state); - - assert replyAck <= replySeq; - - mqtt.doMqttEnd(traceId, authorization); - } - - private void onKafkaFlush( - FlushFW flush) - { - final long sequence = flush.sequence(); - final long acknowledge = flush.acknowledge(); - final long traceId = flush.traceId(); - final long authorization = flush.authorization(); - final long budgetId = flush.budgetId(); - final int reserved = flush.reserved(); - final OctetsFW extension = flush.extension(); - final ExtensionFW flushEx = extension.get(extensionRO::tryWrap); - final KafkaFlushExFW kafkaFlushEx = - flushEx != null && flushEx.typeId() == kafkaTypeId ? extension.get(kafkaFlushExRO::tryWrap) : null; - - assert acknowledge <= sequence; - assert sequence >= replySeq; - - replySeq = sequence; + replySeq = sequence + reserved; assert replyAck <= replySeq; final KafkaMergedConsumerFlushExFW kafkaConsumerFlushEx = kafkaFlushEx != null && @@ -1708,6 +1454,25 @@ private void onKafkaFlush( } } + private void onKafkaEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + mqtt.doMqttEnd(traceId, authorization); + } + private void onKafkaAbort( AbortFW abort) { @@ -1727,6 +1492,23 @@ private void onKafkaAbort( mqtt.doMqttAbort(traceId, authorization); } + private void onKafkaReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert acknowledge >= mqtt.initialAck; + + mqtt.initialAck = acknowledge; + + assert mqtt.initialAck <= mqtt.initialSeq; + + mqtt.doMqttReset(traceId); + } + private void onKafkaWindow( WindowFW window) { @@ -1752,21 +1534,200 @@ private void onKafkaWindow( mqtt.doMqttWindow(authorization, traceId, budgetId, padding, capabilities); } - private void onKafkaReset( - ResetFW reset) + private void doKafkaBegin( + long traceId, + long authorization, + long affinity, + Array32FW filters) { - final long sequence = reset.sequence(); - final long acknowledge = reset.acknowledge(); - final long traceId = reset.traceId(); + if (!MqttKafkaState.initialOpening(state)) + { + final Array32FW.Builder filterBuilder = + filtersRW.wrap(filterBuffer, 0, filterBuffer.capacity()); - assert acknowledge <= sequence; - assert acknowledge >= mqtt.initialAck; + filters.forEach(f -> + { + if (matchesTopicFilter(f.pattern().asString())) + { + int subscriptionId = (int) f.subscriptionId(); + if (!messagesSubscriptionIds.contains(subscriptionId)) + { + messagesSubscriptionIds.add(subscriptionId); + } + filterBuilder.item(fb -> fb + .subscriptionId(subscriptionId).qos(f.qos()).flags(f.flags()).pattern(f.pattern())); + } + }); - mqtt.initialAck = acknowledge; + initialSeq = mqtt.initialSeq; + initialAck = mqtt.initialAck; + initialMax = mqtt.initialMax; + state = MqttKafkaState.openingInitial(state); - assert mqtt.initialAck <= mqtt.initialSeq; + kafka = newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, mqtt.clientId, topic, filterBuilder.build(), mqtt.qos, + KafkaOffsetType.LIVE); + } + } - mqtt.doMqttReset(traceId); + @Override + protected void doKafkaConsumerFlush( + long traceId, + long authorization, + long budgetId, + int reserved, + OffsetCommit offsetCommit) + { + final int qos = offsetCommit.qos; + final PartitionOffset offset = offsetCommit.partitionOffset; + final MqttOffsetStateFlags state = offsetCommit.state; + final int packetId = offsetCommit.packetId; + + + if (qos == MqttQoS.EXACTLY_ONCE.value() && state == MqttOffsetStateFlags.COMPLETE) + { + incompletePacketIds.computeIfAbsent(offset.partitionId, c -> new IntArrayList()).removeInt(packetId); + } + else if (state == MqttOffsetStateFlags.INCOMPLETE) + { + incompletePacketIds.computeIfAbsent(offset.partitionId, c -> new IntArrayList()).add(packetId); + } + + final int correlationId = state == MqttOffsetStateFlags.INCOMPLETE ? packetId : -1; + + final KafkaFlushExFW kafkaFlushEx = + kafkaFlushExRW.wrap(writeBuffer, FlushFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.consumer(f -> + { + f.progress(p -> + { + p.partitionId(offset.partitionId).partitionOffset(offset.offset + 1); + final IntArrayList incomplete = incompletePacketIds.get(offset.partitionId); + final String16FW partitionMetadata = incomplete == null || incomplete.isEmpty() ? + EMPTY_STRING : offsetMetadataListToString(incomplete); + p.metadata(partitionMetadata); + }); + f.correlationId(correlationId); + })) + .build(); + + doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, reserved, kafkaFlushEx); + } + + private void doKafkaFlush( + long traceId, + long authorization, + long budgetId, + int reserved, + int qos, + Array32FW filters) + { + initialSeq = mqtt.initialSeq; + + messagesSubscriptionIds.clear(); + + final KafkaFlushExFW kafkaFlushEx = + kafkaFlushExRW.wrap(writeBuffer, FlushFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.fetch(f -> + { + f.capabilities(c -> c.set(KafkaCapabilities.FETCH_ONLY)); + filters.forEach(filter -> + { + if (matchesTopicFilter(filter.pattern().asString())) + { + final int subscriptionId = (int) filter.subscriptionId(); + if (!messagesSubscriptionIds.contains(subscriptionId)) + { + messagesSubscriptionIds.add(subscriptionId); + } + if ((filter.flags() & SEND_RETAIN_FLAG) != 0) + { + mqtt.retainAvailable = true; + } + f.filtersItem(fi -> + { + fi.conditionsItem(ci -> buildHeaders(ci, filter.pattern().asString())); + + final boolean noLocal = (filter.flags() & NO_LOCAL_FLAG) != 0; + if (noLocal) + { + final DirectBuffer valueBuffer = mqtt.clientId.value(); + fi.conditionsItem(i -> i.not(n -> n.condition(c -> c.header(h -> + h.nameLen(helper.kafkaLocalHeaderName.sizeof()) + .name(helper.kafkaLocalHeaderName) + .valueLen(valueBuffer.capacity()) + .value(valueBuffer, 0, valueBuffer.capacity()))))); + } + + final int maxQos = filter.qos(); + if (maxQos != qos || maxQos == MqttQoS.EXACTLY_ONCE.value()) + { + for (int level = 0; level <= MqttQoS.EXACTLY_ONCE.value(); level++) + { + if (level != qos) + { + final DirectBuffer valueBuffer = qosNames.get(level).value(); + fi.conditionsItem(i -> i.not(n -> n.condition(c -> c.header(h -> + h.nameLen(helper.kafkaQosHeaderName.sizeof()) + .name(helper.kafkaQosHeaderName) + .valueLen(valueBuffer.capacity()) + .value(valueBuffer, 0, valueBuffer.capacity()))))); + } + } + } + else + { + for (int level = 0; level < maxQos; level++) + { + final DirectBuffer valueBuffer = qosNames.get(level).value(); + fi.conditionsItem(i -> i.not(n -> n.condition(c -> c.header(h -> + h.nameLen(helper.kafkaQosHeaderName.sizeof()) + .name(helper.kafkaQosHeaderName) + .valueLen(valueBuffer.capacity()) + .value(valueBuffer, 0, valueBuffer.capacity()))))); + } + } + }); + } + }); + })) + .build(); + + doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, reserved, kafkaFlushEx); + } + + private void doKafkaEnd( + long traceId, + long authorization) + { + if (MqttKafkaState.initialOpened(state) && !MqttKafkaState.initialClosed(state)) + { + initialSeq = mqtt.initialSeq; + initialAck = mqtt.initialAck; + initialMax = mqtt.initialMax; + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (MqttKafkaState.initialOpened(state) && !MqttKafkaState.initialClosed(state)) + { + initialSeq = mqtt.initialSeq; + initialAck = mqtt.initialAck; + initialMax = mqtt.initialMax; + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } } private void doKafkaReset( @@ -1815,7 +1776,7 @@ private void doKafkaWindow( } } - public void flushDataIfNecessary( + private void flushDataIfNecessary( long traceId, long authorization, long budgetId) @@ -1825,6 +1786,46 @@ public void flushDataIfNecessary( flushData(traceId, authorization, budgetId); } } + + private void flushData( + long traceId, + long authorization, + long budgetId) + { + int length = Math.max(Math.min(mqtt.replyWindow() - mqtt.replyPad, messageSlotLimit - messageSlotOffset), 0); + int reserved = length + mqtt.replyPad; + if (length > 0) + { + final MutableDirectBuffer dataBuffer = bufferPool.buffer(dataSlot); + final MqttSubscribeMessageFW message = mqttSubscribeMessageRO.wrap(dataBuffer, messageSlotOffset, + dataBuffer.capacity()); + mqtt.doMqttData(traceId, authorization, budgetId, reserved, bufferedDataFlags, message.payload(), + message.extension()); + + messageSlotOffset += message.sizeof(); + if (messageSlotOffset == messageSlotLimit) + { + bufferPool.release(dataSlot); + dataSlot = NO_SLOT; + messageSlotLimit = 0; + messageSlotOffset = 0; + } + } + } + + private boolean matchesTopicFilter( + String topicFilter) + { + return routeConfig.matches(topicFilter, MqttKafkaConditionKind.SUBSCRIBE); + } + + private void cleanup( + long traceId, + long authorization) + { + mqtt.doMqttAbort(traceId, authorization); + doKafkaAbort(traceId, authorization); + } } private IntArrayList stringToOffsetMetadataList( @@ -1832,7 +1833,7 @@ private IntArrayList stringToOffsetMetadataList( { final IntArrayList metadataList = new IntArrayList(); UnsafeBuffer buffer = new UnsafeBuffer(BitUtil.fromHex(metadata.asString())); - final MqttOffsetMetadataFW offsetMetadata = mqttOffsetMetadataRO.wrap(buffer, 0, buffer.capacity()); + final MqttSubscribeOffsetMetadataFW offsetMetadata = mqttOffsetMetadataRO.wrap(buffer, 0, buffer.capacity()); offsetMetadata.packetIds().forEachRemaining((IntConsumer) metadataList::add); return metadataList; } @@ -1843,7 +1844,7 @@ private String16FW offsetMetadataListToString( mqttOffsetMetadataRW.wrap(offsetBuffer, 0, offsetBuffer.capacity()); mqttOffsetMetadataRW.version(OFFSET_METADATA_VERSION); metadataList.forEach(p -> mqttOffsetMetadataRW.appendPacketIds(p.shortValue())); - final MqttOffsetMetadataFW offsetMetadata = mqttOffsetMetadataRW.build(); + final MqttSubscribeOffsetMetadataFW offsetMetadata = mqttOffsetMetadataRW.build(); return new String16FW(BitUtil.toHex(offsetMetadata.buffer().byteArray(), offsetMetadata.offset(), offsetMetadata.limit())); } @@ -1871,192 +1872,24 @@ final class KafkaRetainedProxy extends KafkaProxy private int replyMax; private int replyPad; - private int unAckedPackets; - private boolean expiredMessage; - - private KafkaRetainedProxy( - long originId, - long routedId, - String16FW topic, - MqttSubscribeProxy mqtt) - { - this.originId = originId; - this.routedId = routedId; - this.topic = topic; - this.topicKey = System.identityHashCode(topic.asString().intern()); - this.mqtt = mqtt; - this.initialId = supplyInitialId.applyAsLong(routedId); - this.replyId = supplyReplyId.applyAsLong(initialId); - this.incompletePacketIds = new Int2ObjectHashMap<>(); - this.unAckedPackets = 0; - } - - private void doKafkaBegin( - long traceId, - long authorization, - long affinity, - List newRetainedFilters) - { - state = 0; - replySeq = 0; - replyAck = 0; - replyMax = 0; - - final Array32FW.Builder filterBuilder = - filtersRW.wrap(filterBuffer, 0, filterBuffer.capacity()); - - newRetainedFilters.forEach(f -> - { - final int subscriptionId = f.id; - if (!mqtt.retainedSubscriptionIds.contains(subscriptionId)) - { - mqtt.retainedSubscriptionIds.add(subscriptionId); - } - filterBuilder.item(fb -> fb - .subscriptionId(subscriptionId).qos(f.qos).flags(f.flags).pattern(f.filter)); - final boolean rap = (f.flags & RETAIN_AS_PUBLISHED_FLAG) != 0; - mqtt.retainAsPublished.put(f.id, rap); - }); - mqtt.retainedSubscriptions.addAll(newRetainedFilters); - - Array32FW retainedFilters = filterBuilder.build(); - - initialSeq = mqtt.initialSeq; - initialAck = mqtt.initialAck; - initialMax = mqtt.initialMax; - - state = MqttKafkaState.openingInitial(state); - - kafka = - newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, affinity, mqtt.clientId, topic, retainedFilters, mqtt.qos, - KafkaOffsetType.HISTORICAL); - } - - @Override - protected void doKafkaConsumerFlush( - long traceId, - long authorization, - long budgetId, - int reserved, - OffsetCommit offsetCommit) - { - final int qos = offsetCommit.qos; - final PartitionOffset offset = offsetCommit.partitionOffset; - final MqttOffsetStateFlags state = offsetCommit.state; - final int packetId = offsetCommit.packetId; - - if (qos == MqttQoS.EXACTLY_ONCE.value() && state == MqttOffsetStateFlags.COMPLETE) - { - final IntArrayList incompletes = incompletePacketIds.get(offset.partitionId); - incompletes.removeInt(packetId); - if (incompletes.isEmpty()) - { - incompletePacketIds.remove(offset.partitionId); - } - } - - if (state == MqttOffsetStateFlags.INCOMPLETE) - { - incompletePacketIds.computeIfAbsent(offset.partitionId, c -> new IntArrayList()).add(packetId); - } - - final int correlationId = state == MqttOffsetStateFlags.INCOMPLETE ? packetId : -1; - - final KafkaFlushExFW kafkaFlushEx = - kafkaFlushExRW.wrap(writeBuffer, FlushFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) - .typeId(kafkaTypeId) - .merged(m -> m.consumer(f -> - { - f.progress(p -> - { - p.partitionId(offset.partitionId).partitionOffset(offset.offset + 1); - final IntArrayList incomplete = incompletePacketIds.get(offset.partitionId); - final String16FW partitionMetadata = incomplete == null || incomplete.isEmpty() ? - EMPTY_STRING : offsetMetadataListToString(incomplete); - p.metadata(partitionMetadata); - }); - f.correlationId(correlationId); - })) - .build(); - - doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, reserved, kafkaFlushEx); - } - - private void doKafkaFlush( - long traceId, - long authorization, - long budgetId, - int reserved, - int qos, - List retainedFiltersList) - { - initialSeq = mqtt.initialSeq; - - final Array32FW.Builder filterBuilder = - filtersRW.wrap(filterBuffer, 0, filterBuffer.capacity()); - - retainedFiltersList.forEach(f -> - { - final int subscriptionId = f.id; - if (!mqtt.retainedSubscriptionIds.contains(subscriptionId)) - { - mqtt.retainedSubscriptionIds.add(subscriptionId); - } - filterBuilder.item(fb -> fb - .subscriptionId(subscriptionId).qos(f.qos).flags(f.flags).pattern(f.filter)); - final boolean rap = (f.flags & RETAIN_AS_PUBLISHED_FLAG) != 0; - mqtt.retainAsPublished.put(f.id, rap); - }); - - Array32FW retainedFilters = filterBuilder.build(); - - final KafkaFlushExFW retainedKafkaFlushEx = - kafkaFlushExRW.wrap(writeBuffer, FlushFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) - .typeId(kafkaTypeId) - .merged(m -> m.fetch(f -> - { - f.capabilities(c -> c.set(KafkaCapabilities.FETCH_ONLY)); - retainedFilters.forEach(filter -> - f.filtersItem(fi -> - fi.conditionsItem(ci -> - buildHeaders(ci, filter.pattern().asString())))); - })) - .build(); - - doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, - traceId, authorization, budgetId, reserved, retainedKafkaFlushEx); - } - - private void doKafkaEnd( - long traceId, - long authorization) - { - if (!MqttKafkaState.initialClosed(state)) - { - initialSeq = mqtt.initialSeq; - initialAck = mqtt.initialAck; - initialMax = mqtt.initialMax; - state = MqttKafkaState.closeInitial(state); - - doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); - } - } + private int unAckedPackets; + private boolean expiredMessage; - private void doKafkaAbort( - long traceId, - long authorization) + private KafkaRetainedProxy( + long originId, + long routedId, + String16FW topic, + MqttSubscribeProxy mqtt) { - if (!MqttKafkaState.initialClosed(state)) - { - initialSeq = mqtt.initialSeq; - initialAck = mqtt.initialAck; - initialMax = mqtt.initialMax; - state = MqttKafkaState.closeInitial(state); - - doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); - } + this.originId = originId; + this.routedId = routedId; + this.topic = topic; + this.topicKey = System.identityHashCode(topic.asString().intern()); + this.mqtt = mqtt; + this.initialId = supplyInitialId.applyAsLong(routedId); + this.replyId = supplyReplyId.applyAsLong(initialId); + this.incompletePacketIds = new Int2ObjectHashMap<>(); + this.unAckedPackets = 0; } private void onKafkaMessage( @@ -2300,25 +2133,6 @@ private void onKafkaData( } } - private void onKafkaEnd( - EndFW end) - { - final long sequence = end.sequence(); - final long acknowledge = end.acknowledge(); - final long traceId = end.traceId(); - final long authorization = end.authorization(); - - assert acknowledge <= sequence; - assert sequence >= replySeq; - - replySeq = sequence; - state = MqttKafkaState.closeReply(state); - - assert replyAck <= replySeq; - - mqtt.messages.values().forEach(m -> m.flushData(traceId, authorization, mqtt.replyBud)); - } - private void onKafkaFlush( FlushFW flush) { @@ -2337,7 +2151,7 @@ private void onKafkaFlush( assert acknowledge <= sequence; assert sequence >= replySeq; - replySeq = sequence; + replySeq = sequence + reserved; assert replyAck <= replySeq; @@ -2378,6 +2192,25 @@ private void onKafkaFlush( } } + private void onKafkaEnd( + EndFW end) + { + final long sequence = end.sequence(); + final long acknowledge = end.acknowledge(); + final long traceId = end.traceId(); + final long authorization = end.authorization(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + state = MqttKafkaState.closeReply(state); + + assert replyAck <= replySeq; + + mqtt.messages.values().forEach(m -> m.flushData(traceId, authorization, mqtt.replyBud)); + } + private void onKafkaAbort( AbortFW abort) { @@ -2397,6 +2230,23 @@ private void onKafkaAbort( mqtt.doMqttAbort(traceId, authorization); } + private void onKafkaReset( + ResetFW reset) + { + final long sequence = reset.sequence(); + final long acknowledge = reset.acknowledge(); + final long traceId = reset.traceId(); + + assert acknowledge <= sequence; + assert acknowledge >= mqtt.initialAck; + + mqtt.initialAck = acknowledge; + + assert mqtt.initialAck <= mqtt.initialSeq; + + mqtt.doMqttReset(traceId); + } + private void onKafkaWindow( WindowFW window) { @@ -2422,21 +2272,172 @@ private void onKafkaWindow( mqtt.doMqttWindow(authorization, traceId, budgetId, padding, capabilities); } - private void onKafkaReset( - ResetFW reset) + private void doKafkaBegin( + long traceId, + long authorization, + long affinity, + List newRetainedFilters) { - final long sequence = reset.sequence(); - final long acknowledge = reset.acknowledge(); - final long traceId = reset.traceId(); + state = 0; + replySeq = 0; + replyAck = 0; + replyMax = 0; - assert acknowledge <= sequence; - assert acknowledge >= mqtt.initialAck; + final Array32FW.Builder filterBuilder = + filtersRW.wrap(filterBuffer, 0, filterBuffer.capacity()); - mqtt.initialAck = acknowledge; + newRetainedFilters.forEach(f -> + { + final int subscriptionId = f.id; + if (!mqtt.retainedSubscriptionIds.contains(subscriptionId)) + { + mqtt.retainedSubscriptionIds.add(subscriptionId); + } + filterBuilder.item(fb -> fb + .subscriptionId(subscriptionId).qos(f.qos).flags(f.flags).pattern(f.filter)); + final boolean rap = (f.flags & RETAIN_AS_PUBLISHED_FLAG) != 0; + mqtt.retainAsPublished.put(f.id, rap); + }); + mqtt.retainedSubscriptions.addAll(newRetainedFilters); - assert mqtt.initialAck <= mqtt.initialSeq; + Array32FW retainedFilters = filterBuilder.build(); - mqtt.doMqttReset(traceId); + initialSeq = mqtt.initialSeq; + initialAck = mqtt.initialAck; + initialMax = mqtt.initialMax; + + state = MqttKafkaState.openingInitial(state); + + kafka = + newKafkaStream(this::onKafkaMessage, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, affinity, mqtt.clientId, topic, retainedFilters, mqtt.qos, + KafkaOffsetType.HISTORICAL); + } + + @Override + protected void doKafkaConsumerFlush( + long traceId, + long authorization, + long budgetId, + int reserved, + OffsetCommit offsetCommit) + { + final int qos = offsetCommit.qos; + final PartitionOffset offset = offsetCommit.partitionOffset; + final MqttOffsetStateFlags state = offsetCommit.state; + final int packetId = offsetCommit.packetId; + + if (qos == MqttQoS.EXACTLY_ONCE.value() && state == MqttOffsetStateFlags.COMPLETE) + { + final IntArrayList incompletes = incompletePacketIds.get(offset.partitionId); + incompletes.removeInt(packetId); + if (incompletes.isEmpty()) + { + incompletePacketIds.remove(offset.partitionId); + } + } + + if (state == MqttOffsetStateFlags.INCOMPLETE) + { + incompletePacketIds.computeIfAbsent(offset.partitionId, c -> new IntArrayList()).add(packetId); + } + + final int correlationId = state == MqttOffsetStateFlags.INCOMPLETE ? packetId : -1; + + final KafkaFlushExFW kafkaFlushEx = + kafkaFlushExRW.wrap(writeBuffer, FlushFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.consumer(f -> + { + f.progress(p -> + { + p.partitionId(offset.partitionId).partitionOffset(offset.offset + 1); + final IntArrayList incomplete = incompletePacketIds.get(offset.partitionId); + final String16FW partitionMetadata = incomplete == null || incomplete.isEmpty() ? + EMPTY_STRING : offsetMetadataListToString(incomplete); + p.metadata(partitionMetadata); + }); + f.correlationId(correlationId); + })) + .build(); + + doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, reserved, kafkaFlushEx); + } + + private void doKafkaFlush( + long traceId, + long authorization, + long budgetId, + int reserved, + int qos, + List retainedFiltersList) + { + initialSeq = mqtt.initialSeq; + + final Array32FW.Builder filterBuilder = + filtersRW.wrap(filterBuffer, 0, filterBuffer.capacity()); + + retainedFiltersList.forEach(f -> + { + final int subscriptionId = f.id; + if (!mqtt.retainedSubscriptionIds.contains(subscriptionId)) + { + mqtt.retainedSubscriptionIds.add(subscriptionId); + } + filterBuilder.item(fb -> fb + .subscriptionId(subscriptionId).qos(f.qos).flags(f.flags).pattern(f.filter)); + final boolean rap = (f.flags & RETAIN_AS_PUBLISHED_FLAG) != 0; + mqtt.retainAsPublished.put(f.id, rap); + }); + + Array32FW retainedFilters = filterBuilder.build(); + + final KafkaFlushExFW retainedKafkaFlushEx = + kafkaFlushExRW.wrap(writeBuffer, FlushFW.FIELD_OFFSET_EXTENSION, writeBuffer.capacity()) + .typeId(kafkaTypeId) + .merged(m -> m.fetch(f -> + { + f.capabilities(c -> c.set(KafkaCapabilities.FETCH_ONLY)); + retainedFilters.forEach(filter -> + f.filtersItem(fi -> + fi.conditionsItem(ci -> + buildHeaders(ci, filter.pattern().asString())))); + })) + .build(); + + doFlush(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, authorization, budgetId, reserved, retainedKafkaFlushEx); + } + + private void doKafkaEnd( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = mqtt.initialSeq; + initialAck = mqtt.initialAck; + initialMax = mqtt.initialMax; + state = MqttKafkaState.closeInitial(state); + + doEnd(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } + } + + private void doKafkaAbort( + long traceId, + long authorization) + { + if (!MqttKafkaState.initialClosed(state)) + { + initialSeq = mqtt.initialSeq; + initialAck = mqtt.initialAck; + initialMax = mqtt.initialMax; + state = MqttKafkaState.closeInitial(state); + + doAbort(kafka, originId, routedId, initialId, initialSeq, initialAck, initialMax, traceId, authorization); + } } private void doKafkaReset( diff --git a/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaConfigurationTest.java b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaConfigurationTest.java index d1573b664c..fccc240c61 100644 --- a/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaConfigurationTest.java +++ b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/MqttKafkaConfigurationTest.java @@ -35,6 +35,7 @@ public class MqttKafkaConfigurationTest public static final String WILL_STREAM_RECONNECT_DELAY_NAME = "zilla.binding.mqtt.kafka.will.stream.reconnect"; public static final String BOOTSTRAP_AVAILABLE_NAME = "zilla.binding.mqtt.kafka.bootstrap.available"; public static final String BOOTSTRAP_STREAM_RECONNECT_DELAY_NAME = "zilla.binding.mqtt.kafka.bootstrap.stream.reconnect"; + public static final String PUBLISH_MAX_QOS_NAME = "zilla.binding.mqtt.kafka.publish.max.qos"; public static final String SESSION_ID_NAME = "zilla.binding.mqtt.kafka.session.id"; public static final String WILL_ID_NAME = "zilla.binding.mqtt.kafka.will.id"; public static final String LIFETIME_ID_NAME = "zilla.binding.mqtt.kafka.lifetime.id"; diff --git a/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishProxyIT.java b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishProxyIT.java index f39c48a682..6e169835a7 100644 --- a/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishProxyIT.java +++ b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaPublishProxyIT.java @@ -15,6 +15,8 @@ package io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream; import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.BOOTSTRAP_AVAILABLE_NAME; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.INSTANCE_ID_NAME; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.SESSION_ID_NAME; import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.WILL_AVAILABLE_NAME; import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_BUFFER_SLOT_CAPACITY; import static io.aklivity.zilla.runtime.engine.test.EngineRule.ENGINE_BUFFER_SLOT_CAPACITY_NAME; @@ -45,6 +47,10 @@ public class MqttKafkaPublishProxyIT .directory("target/zilla-itests") .countersBufferCapacity(8192) .configure(ENGINE_BUFFER_SLOT_CAPACITY, 8192) + .configure(SESSION_ID_NAME, + "io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaSessionProxyIT::supplySessionId") + .configure(INSTANCE_ID_NAME, + "io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaSessionProxyIT::supplyInstanceId") .configurationRoot("io/aklivity/zilla/specs/binding/mqtt/kafka/config") .external("kafka0") .clean(); @@ -85,17 +91,6 @@ public void shouldReceiveServerSentAbort() throws Exception k3po.finish(); } - @Test - @Configuration("proxy.yaml") - @Configure(name = WILL_AVAILABLE_NAME, value = "false") - @Specification({ - "${mqtt}/publish.server.sent.flush/client", - "${kafka}/publish.server.sent.flush/server"}) - public void shouldReceiveServerSentFlush() throws Exception - { - k3po.finish(); - } - @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") @@ -129,17 +124,6 @@ public void shouldPublishRetainedThenReceiveServerSentAbort() throws Exception k3po.finish(); } - @Test - @Configuration("proxy.yaml") - @Configure(name = WILL_AVAILABLE_NAME, value = "false") - @Specification({ - "${mqtt}/publish.retained.server.sent.flush/client", - "${kafka}/publish.retained.server.sent.flush/server"}) - public void shouldPublishRetainedThenReceiveServerSentFlush() throws Exception - { - k3po.finish(); - } - @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") @@ -306,6 +290,83 @@ public void shouldSendMessageQos2() throws Exception k3po.finish(); } + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.qos2.retained/client", + "${kafka}/publish.qos2.retained/server"}) + public void shouldSendMessageQos2Retained() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.qos2.recovery/client", + "${kafka}/publish.qos2.recovery/server"}) + public void shouldSendMessageQos2DuringRecovery() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.qos2.abort/client", + "${kafka}/publish.qos2.meta.abort/server"}) + public void shouldSessionReceiveQos2MetaSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.qos2.abort/client", + "${kafka}/publish.qos2.offset.fetch.abort/server"}) + public void shouldSessionReceiveQos2OffsetFetchSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.qos2.abort/client", + "${kafka}/publish.qos2.init.producer.abort/server"}) + public void shouldSessionReceiveQos2InitProducerSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.qos2.offset.commit.abort.phase1/client", + "${kafka}/publish.qos2.offset.commit.abort.phase1/server"}) + public void shouldPublishReceiveQos2OffsetCommitSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Configuration("proxy.yaml") + @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Specification({ + "${mqtt}/publish.qos2.offset.commit.abort.phase2/client", + "${kafka}/publish.qos2.offset.commit.abort.phase2/server"}) + public void shouldSessionReceiveQos2OffsetCommitSentAbort() throws Exception + { + k3po.finish(); + } + @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") diff --git a/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSessionProxyIT.java b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSessionProxyIT.java index ca16c879ac..945b86d372 100644 --- a/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSessionProxyIT.java +++ b/runtime/binding-mqtt-kafka/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/kafka/internal/stream/MqttKafkaSessionProxyIT.java @@ -16,6 +16,7 @@ import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.INSTANCE_ID_NAME; import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.LIFETIME_ID_NAME; +import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.PUBLISH_MAX_QOS_NAME; import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.SESSION_ID_NAME; import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.TIME_NAME; import static io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.MqttKafkaConfigurationTest.WILL_AVAILABLE_NAME; @@ -72,6 +73,7 @@ public class MqttKafkaSessionProxyIT @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.connect.override.max.session.expiry/client", "${kafka}/session.connect.override.max.session.expiry/server"}) @@ -83,6 +85,7 @@ public void shouldConnectServerOverridesSessionExpiryTooBig() throws Exception @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.connect.override.min.session.expiry/client", "${kafka}/session.connect.override.min.session.expiry/server"}) @@ -94,6 +97,7 @@ public void shouldConnectServerOverridesSessionExpiryTooSmall() throws Exception @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.abort.reconnect.non.clean.start/client", "${kafka}/session.abort.reconnect.non.clean.start/server"}) @@ -105,6 +109,7 @@ public void shouldReconnectNonCleanStart() throws Exception @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.client.takeover/client", "${kafka}/session.client.takeover/server"}) @@ -116,6 +121,7 @@ public void shouldTakeOverSession() throws Exception @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.exists.clean.start/client", "${kafka}/session.exists.clean.start/server"}) @@ -127,6 +133,8 @@ public void shouldRemoveSessionAtCleanStart() throws Exception @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "0") @Specification({ "${mqtt}/session.subscribe/client", "${kafka}/session.subscribe/server"}) @@ -138,6 +146,7 @@ public void shouldSubscribeSaveSubscriptionsInSession() throws Exception @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.subscribe.via.session.state/client", "${kafka}/session.subscribe.via.session.state/server"}) @@ -149,6 +158,7 @@ public void shouldReceiveMessageSubscribedViaSessionState() throws Exception @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.unsubscribe.after.subscribe/client", "${kafka}/session.unsubscribe.after.subscribe/server"}) @@ -160,6 +170,7 @@ public void shouldUnsubscribeAndUpdateSessionState() throws Exception @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.unsubscribe.via.session.state/client", "${kafka}/session.unsubscribe.via.session.state/server"}) @@ -171,6 +182,7 @@ public void shouldUnsubscribeViaSessionState() throws Exception @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.client.sent.reset/client", "${kafka}/session.client.sent.reset/server"}) @@ -182,6 +194,7 @@ public void shouldSessionStreamReceiveClientSentReset() throws Exception @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.server.sent.reset/client", "${kafka}/session.server.sent.reset/server"}) @@ -193,6 +206,7 @@ public void shouldSessionStreamReceiveServerSentReset() throws Exception @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.server.sent.reset/client", "${kafka}/session.group.server.sent.reset/server"}) @@ -205,6 +219,7 @@ public void shouldGroupStreamReceiveServerSentReset() throws Exception @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.group.reset.not.authorized/client", "${kafka}/session.group.reset.not.authorized/server"}) @@ -217,6 +232,7 @@ public void shouldGroupStreamReceiveResetNotAuthorized() throws Exception @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.group.reset.invalid.session.timeout/client", "${kafka}/session.group.reset.invalid.session.timeout/server"}) @@ -229,6 +245,7 @@ public void shouldGroupStreamReceiveResetInvalidSessionTimeout() throws Exceptio @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.group.reset.invalid.describe.config/client", "${kafka}/session.group.reset.invalid.describe.config/server"}) @@ -240,6 +257,7 @@ public void shouldGroupStreamReceiveResetInvalidDescribeConfig() throws Exceptio @Test @Configuration("proxy.yaml") @Configure(name = WILL_AVAILABLE_NAME, value = "false") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Configure(name = SESSION_ID_NAME, value = "io.aklivity.zilla.runtime.binding.mqtt.kafka.internal.stream.MqttKafkaSessionProxyIT::supplySessionId") @Specification({ @@ -252,6 +270,7 @@ public void shouldRedirect() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.close.expire.session.state/client", "${kafka}/session.close.expire.session.state/server"}) @@ -262,6 +281,7 @@ public void shouldExpireSessionOnClose() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.abort.expire.session.state/client", "${kafka}/session.abort.expire.session.state/server"}) @@ -272,6 +292,7 @@ public void shouldExpireSessionOnAbort() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${kafka}/session.cancel.session.expiry/server"}) public void shouldCancelSessionExpiry() throws Exception @@ -281,6 +302,7 @@ public void shouldCancelSessionExpiry() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${kafka}/session.session.expiry.fragmented/server"}) public void shouldDecodeSessionExpirySignalFragmented() throws Exception @@ -290,6 +312,7 @@ public void shouldDecodeSessionExpirySignalFragmented() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${kafka}/session.expiry.after.signal.stream.restart/server"}) public void shouldExpireSessionAfterSignalStreamRestart() throws Exception @@ -299,6 +322,7 @@ public void shouldExpireSessionAfterSignalStreamRestart() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.will.message.normal.disconnect/client", "${kafka}/session.will.message.normal.disconnect/server"}) @@ -309,6 +333,7 @@ public void shouldNotSendWillMessageOnNormalDisconnect() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.will.message.clean.start/client", "${kafka}/session.will.message.clean.start/server"}) @@ -319,6 +344,7 @@ public void shouldGenerateLifeTimeIdOnCleanStart() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.will.message.abort.deliver.will/client", "${kafka}/session.will.message.abort.deliver.will/server"}) @@ -329,6 +355,7 @@ public void shouldSendWillMessageOnAbort() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.will.message.10k.abort.deliver.will/client", "${kafka}/session.will.message.10k.abort.deliver.will/server"}) @@ -339,6 +366,7 @@ public void shouldSendWillMessage10kOnAbort() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.will.message.abort.deliver.will/client", "${kafka}/session.will.message.will.id.mismatch.skip.delivery/server"}) @@ -349,6 +377,7 @@ public void shouldNotSendWillMessageOnWillIdMismatch() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.will.message.abort.deliver.will.retain/client", "${kafka}/session.will.message.abort.deliver.will.retain/server"}) @@ -359,6 +388,7 @@ public void shouldSaveWillMessageAsRetain() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${mqtt}/session.will.message.takeover.deliver.will/client", "${kafka}/session.will.message.takeover.deliver.will/server"}) @@ -369,6 +399,7 @@ public void shouldDeliverWillMessageOnSessionTakeover() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Specification({ "${kafka}/session.will.message.cancel.delivery/server"}) public void shouldCancelWillDelivery() throws Exception @@ -381,6 +412,7 @@ public void shouldCancelWillDelivery() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Configure(name = WILL_STREAM_RECONNECT_DELAY_NAME, value = "1") @Specification({ "${kafka}/session.will.stream.end.reconnect/server"}) @@ -391,6 +423,7 @@ public void shouldReconnectWillStreamOnKafkaEnd() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Configure(name = WILL_STREAM_RECONNECT_DELAY_NAME, value = "1") @Specification({ "${kafka}/session.will.stream.abort.reconnect/server"}) @@ -401,6 +434,7 @@ public void shouldReconnectWillStreamOnKafkaAbort() throws Exception @Test @Configuration("proxy.yaml") + @Configure(name = PUBLISH_MAX_QOS_NAME, value = "1") @Configure(name = WILL_STREAM_RECONNECT_DELAY_NAME, value = "1") @Specification({ "${kafka}/session.will.stream.reset.reconnect/server"}) diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBinding.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBinding.java index bc85f1747e..a29b96e302 100644 --- a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBinding.java +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBinding.java @@ -16,10 +16,6 @@ package io.aklivity.zilla.runtime.binding.mqtt.internal; import java.net.URL; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import org.agrona.collections.IntArrayList; import io.aklivity.zilla.runtime.engine.EngineContext; import io.aklivity.zilla.runtime.engine.binding.Binding; @@ -31,13 +27,11 @@ public final class MqttBinding implements Binding private final MqttConfiguration config; - private final ConcurrentMap unreleasedPacketIdsByClientId; MqttBinding( MqttConfiguration config) { this.config = config; - this.unreleasedPacketIdsByClientId = new ConcurrentHashMap<>(); } @Override @@ -70,6 +64,6 @@ public String routedType( public MqttBindingContext supply( EngineContext context) { - return new MqttBindingContext(config, context, unreleasedPacketIdsByClientId); + return new MqttBindingContext(config, context); } } diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBindingContext.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBindingContext.java index 20ab283eea..3b45fb60e5 100644 --- a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBindingContext.java +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/MqttBindingContext.java @@ -20,9 +20,6 @@ import java.util.EnumMap; import java.util.Map; -import java.util.concurrent.ConcurrentMap; - -import org.agrona.collections.IntArrayList; import io.aklivity.zilla.runtime.binding.mqtt.internal.stream.MqttClientFactory; import io.aklivity.zilla.runtime.binding.mqtt.internal.stream.MqttServerFactory; @@ -40,11 +37,10 @@ final class MqttBindingContext implements BindingContext MqttBindingContext( MqttConfiguration config, - EngineContext context, - ConcurrentMap unreleasedPacketIdsByClientId) + EngineContext context) { final EnumMap factories = new EnumMap<>(KindConfig.class); - factories.put(SERVER, new MqttServerFactory(config, context, unreleasedPacketIdsByClientId)); + factories.put(SERVER, new MqttServerFactory(config, context)); factories.put(CLIENT, new MqttClientFactory(config, context)); this.factories = factories; } diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttClientFactory.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttClientFactory.java index 201b86f7f9..69e6367e3c 100644 --- a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttClientFactory.java +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttClientFactory.java @@ -1567,7 +1567,7 @@ private int onDecodeConnack( .session(sessionBuilder -> sessionBuilder .flags(flags) .expiry((int) TimeUnit.MILLISECONDS.toSeconds(sessionExpiry)) - .qosMax(maximumQos) + .subscribeQosMax(maximumQos) .packetSizeMax(maximumPacketSize) .capabilities(capabilities) .clientId(clientId)) @@ -1593,7 +1593,7 @@ private int onDecodeConnack( .session(sessionBuilder -> sessionBuilder .flags(flags) .expiry(sessionExpiry) - .qosMax(maximumQos) + .subscribeQosMax(maximumQos) .packetSizeMax(maximumPacketSize) .capabilities(capabilities) .clientId(clientId)) diff --git a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttServerFactory.java b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttServerFactory.java index f10ca15d85..0250f6fce9 100644 --- a/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttServerFactory.java +++ b/runtime/binding-mqtt/src/main/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/MqttServerFactory.java @@ -79,17 +79,17 @@ import java.util.EnumMap; import java.util.HashMap; import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.PrimitiveIterator; import java.util.UUID; -import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.IntConsumer; import java.util.function.IntSupplier; import java.util.function.LongFunction; import java.util.function.LongSupplier; @@ -102,6 +102,7 @@ import org.agrona.collections.Int2IntHashMap; import org.agrona.collections.Int2ObjectHashMap; import org.agrona.collections.IntArrayList; +import org.agrona.collections.Long2LongHashMap; import org.agrona.collections.Long2ObjectHashMap; import org.agrona.collections.MutableBoolean; import org.agrona.collections.Object2IntHashMap; @@ -287,7 +288,7 @@ public final class MqttServerFactory implements MqttStreamFactory private final FlushFW.Builder flushRW = new FlushFW.Builder(); private final MqttDataExFW mqttSubscribeDataExRO = new MqttDataExFW(); - private final MqttFlushExFW mqttSubscribeFlushExRO = new MqttFlushExFW(); + private final MqttFlushExFW mqttFlushExRO = new MqttFlushExFW(); private final MqttResetExFW mqttResetExRO = new MqttResetExFW(); private final MqttBeginExFW mqttBeginExRO = new MqttBeginExFW(); @@ -477,12 +478,10 @@ public final class MqttServerFactory implements MqttStreamFactory private final Supplier supplyClientId; private final MqttValidator validator; private final CharsetDecoder utf8Decoder; - private final ConcurrentMap unreleasedPacketIdsByClientId; public MqttServerFactory( MqttConfiguration config, - EngineContext context, - ConcurrentMap unreleasedPacketIdsByClientId) + EngineContext context) { this.writeBuffer = context.writeBuffer(); this.extBuffer = new UnsafeBuffer(new byte[writeBuffer.capacity()]); @@ -524,7 +523,6 @@ public MqttServerFactory( this.decodePacketTypeByVersion = new Int2ObjectHashMap<>(); this.decodePacketTypeByVersion.put(MQTT_PROTOCOL_VERSION_4, this::decodePacketTypeV4); this.decodePacketTypeByVersion.put(MQTT_PROTOCOL_VERSION_5, this::decodePacketTypeV5); - this.unreleasedPacketIdsByClientId = unreleasedPacketIdsByClientId; } @Override @@ -1247,7 +1245,7 @@ private int decodePublishV4( String16FW topicName; int publishLimit; - int packetId = -1; + int packetId = 0; if (qos > 0) { final MqttPublishQosV4FW publish = @@ -1351,7 +1349,7 @@ private int decodePublishV5( String16FW topicName; MqttPropertiesFW properties; int publishLimit; - int packetId = -1; + int packetId = 0; if (qos > 0) { final MqttPublishQosV5FW publish = @@ -1483,7 +1481,7 @@ private int decodePublishPayload( boolean canPublish = MqttState.initialOpened(publisher.state); final int maximum = publishablePayloadSize; - final int minimum = Math.min(maximum, 1024); + final int minimum = Math.min(maximum, Math.max(publisher.initialMin, 1024)); int valueClaimed = maximum; @@ -2437,7 +2435,7 @@ private final class MqttServer private long keepAliveTimeoutId = NO_CANCEL_ID; private long keepAliveTimeoutAt; - private int maximumQos; + private int subscribeQosMax; private int packetSizeMax; private int capabilities = RETAIN_AVAILABLE_MASK | SUBSCRIPTION_IDS_AVAILABLE_MASK | WILDCARD_AVAILABLE_MASK; private boolean serverDefinedKeepAlive = false; @@ -2457,8 +2455,8 @@ private final class MqttServer private int decodableRemainingBytes; private final Int2ObjectHashMap qos1Subscribes; private final Int2ObjectHashMap qos2Subscribes; - private final LinkedHashMap unAckedReceivedQos1PacketIds; - private final LinkedHashMap unAckedReceivedQos2PacketIds; + private final Long2LongHashMap unAckedReceivedQos1PacketIds; + private final Long2LongHashMap unAckedReceivedQos2PacketIds; private IntArrayList unreleasedPacketIds; @@ -2501,10 +2499,11 @@ private MqttServer( this.topicAliases = new Int2ObjectHashMap<>(); this.subscribePacketIds = new Int2IntHashMap(-1); this.unsubscribePacketIds = new Object2IntHashMap<>(-1); - this.unAckedReceivedQos1PacketIds = new LinkedHashMap<>(); - this.unAckedReceivedQos2PacketIds = new LinkedHashMap<>(); + this.unAckedReceivedQos1PacketIds = new Long2LongHashMap(-1); + this.unAckedReceivedQos2PacketIds = new Long2LongHashMap(-1); this.qos1Subscribes = new Int2ObjectHashMap<>(); this.qos2Subscribes = new Int2ObjectHashMap<>(); + this.unreleasedPacketIds = new IntArrayList(); this.supplyValidator = context::supplyValidator; } @@ -2860,8 +2859,6 @@ private int onDecodeConnect( this.clientId = new String16FW(clientIdentifier.asString()); } - unreleasedPacketIds = unreleasedPacketIdsByClientId.computeIfAbsent(clientId.asString(), c -> new IntArrayList()); - this.keepAlive = (short) Math.min(Math.max(keepAlive, keepAliveMinimum), keepAliveMaximum); serverDefinedKeepAlive = this.keepAlive != keepAlive; keepAliveTimeout = Math.round(TimeUnit.SECONDS.toMillis(keepAlive) * 1.5); @@ -2940,9 +2937,10 @@ else if (this.authField.equals(MqttConnectProperty.PASSWORD)) .session(s -> s .flags(connectFlags & (CLEAN_START_FLAG_MASK | WILL_FLAG_MASK)) .expiry(sessionExpiry) + .publishQosMax(MqttQoS.EXACTLY_ONCE.value()) .capabilities(capabilities) - .clientId(clientId) - ); + .clientId(clientId)); + session.doSessionBegin(traceId, affinity, builder.build()); if (willFlagSet) @@ -3018,7 +3016,7 @@ private int onDecodeConnectWillMessage( final int flags = connectFlags; final int willQos = decodeWillQos(flags); - if (willQos > maximumQos) + if (willQos > subscribeQosMax) { reasonCode = QOS_NOT_SUPPORTED; break decode; @@ -3174,7 +3172,7 @@ private void onDecodePublish( { int reasonCode = SUCCESS; - if (qos > maximumQos) + if (qos > subscribeQosMax) { reasonCode = QOS_NOT_SUPPORTED; } @@ -3250,11 +3248,6 @@ private void onDecodePublishPayload( if (publishPayloadDeferred == 0) { - if (qos == 2) - { - unreleasedPacketIds.add(packetId); - } - publishPayloadDeferred = publishPayloadBytes - length; final Flyweight dataEx = mqttPublishDataExRW.wrap(dataExtBuffer, 0, dataExtBuffer.capacity()) .typeId(mqttTypeId) @@ -3263,6 +3256,7 @@ private void onDecodePublishPayload( p.deferred(publishPayloadDeferred) .qos(qos) .flags(flags) + .packetId(packetId) .expiryInterval(expiryInterval) .contentType(contentType) .format(f -> f.set(payloadFormat)) @@ -3338,16 +3332,7 @@ private void onDecodePubrel( int limit, int packetId) { - unreleasedPacketIds.removeInt(packetId); - switch (version) - { - case 4: - doEncodePubcompV4(traceId, authorization, packetId); - break; - case 5: - doEncodePubcompV5(traceId, authorization, packetId); - break; - } + session.doSessionFlush(traceId, 0, packetId); doSignalKeepAliveTimeout(traceId); } @@ -4505,10 +4490,10 @@ private void doEncodeConnackV5( propertiesSize = mqttProperty.limit(); } - if (0 <= maximumQos && maximumQos < 2) + if (0 <= subscribeQosMax && subscribeQosMax < 2) { mqttProperty = mqttPropertyRW.wrap(propertyBuffer, propertiesSize, propertyBuffer.capacity()) - .maximumQoS((byte) maximumQos) + .maximumQoS((byte) subscribeQosMax) .build(); propertiesSize = mqttProperty.limit(); } @@ -5084,6 +5069,10 @@ private void onSession( final BeginFW begin = beginRO.wrap(buffer, index, index + length); onSessionBegin(begin); break; + case FlushFW.TYPE_ID: + final FlushFW flush = flushRO.wrap(buffer, index, index + length); + onSessionFlush(flush); + break; case DataFW.TYPE_ID: final DataFW data = dataRO.wrap(buffer, index, index + length); onSessionData(data); @@ -5213,15 +5202,54 @@ private void onSessionBegin( assert mqttBeginEx.kind() == MqttBeginExFW.KIND_SESSION; final MqttSessionBeginExFW mqttSessionBeginEx = mqttBeginEx.session(); + final PrimitiveIterator.OfInt packetIds = mqttSessionBeginEx.packetIds(); sessionExpiry = mqttSessionBeginEx.expiry(); capabilities = mqttSessionBeginEx.capabilities(); - maximumQos = mqttSessionBeginEx.qosMax(); + subscribeQosMax = mqttSessionBeginEx.subscribeQosMax(); + if (packetIds != null) + { + packetIds.forEachRemaining((IntConsumer) p -> unreleasedPacketIds.add(p)); + } } doSessionWindow(traceId, encodeSlotOffset, encodeBudgetMax); } + private void onSessionFlush( + FlushFW flush) + { + final long sequence = flush.sequence(); + final long acknowledge = flush.acknowledge(); + final long traceId = flush.traceId(); + final long authorization = flush.authorization(); + final OctetsFW extension = flush.extension(); + + assert acknowledge <= sequence; + assert sequence >= replySeq; + + replySeq = sequence; + + assert replyAck <= replySeq; + + if (extension.sizeof() > 0) + { + final MqttFlushExFW sessionFlushEx = extension.get(mqttFlushExRO::tryWrap); + final int packetId = sessionFlushEx.session().packetId(); + + unreleasedPacketIds.removeInt(packetId); + switch (version) + { + case 4: + doEncodePubcompV4(traceId, authorization, packetId); + break; + case 5: + doEncodePubcompV5(traceId, authorization, packetId); + break; + } + } + } + private void onSessionData( DataFW data) { @@ -5395,6 +5423,23 @@ private void doSessionBegin( } } + private void doSessionFlush( + long traceId, + int reserved, + int packetId) + { + doFlush(application, originId, routedId, initialId, initialSeq, initialAck, initialMax, + traceId, sessionId, 0L, reserved, + ex -> ex.set((b, o, l) -> mqttFlushExRW.wrap(b, o, l) + .typeId(mqttTypeId) + .session(sessionBuilder -> sessionBuilder.packetId(packetId)) + .build() + .sizeof())); + + initialSeq += reserved; + assert initialSeq <= initialAck + initialMax; + } + private boolean hasSessionWindow( int length) { @@ -5577,6 +5622,7 @@ private class MqttPublishStream private long initialSeq; private long initialAck; private int initialMax; + private int initialMin; private int initialPad; private int decodablePayloadSize; @@ -5781,6 +5827,7 @@ private void onPublishWindow( final long sequence = window.sequence(); final long acknowledge = window.acknowledge(); final int maximum = window.maximum(); + final int minimum = window.minimum(); final long traceId = window.traceId(); final long authorization = window.authorization(); final long budgetId = window.budgetId(); @@ -5796,6 +5843,7 @@ private void onPublishWindow( initialAck = acknowledge; initialMax = maximum; + initialMin = minimum; initialPad = padding; assert initialAck <= initialSeq; @@ -5823,17 +5871,17 @@ private void acknowledgePublishPackets( long traceId, long authorization) { - for (Map.Entry e : unAckedReceivedQos1PacketIds.entrySet()) + for (Map.Entry e : unAckedReceivedQos1PacketIds.entrySet()) { if (e.getKey() <= acknowledge) { switch (version) { case 4: - doEncodePubackV4(traceId, authorization, e.getValue()); + doEncodePubackV4(traceId, authorization, e.getValue().intValue()); break; case 5: - doEncodePubackV5(traceId, authorization, e.getValue()); + doEncodePubackV5(traceId, authorization, e.getValue().intValue()); break; } unAckedReceivedQos1PacketIds.remove(e.getKey()); @@ -5844,20 +5892,22 @@ private void acknowledgePublishPackets( } } - for (Map.Entry e : unAckedReceivedQos2PacketIds.entrySet()) + for (Map.Entry e : unAckedReceivedQos2PacketIds.entrySet()) { if (e.getKey() <= acknowledge) { + final int packetId = e.getValue().intValue(); switch (version) { case 4: - doEncodePubrecV4(traceId, authorization, e.getValue()); + doEncodePubrecV4(traceId, authorization, packetId); break; case 5: - doEncodePubrecV5(traceId, authorization, e.getValue()); + doEncodePubrecV5(traceId, authorization, packetId); break; } unAckedReceivedQos2PacketIds.remove(e.getKey()); + unreleasedPacketIds.add(packetId); } else { @@ -6394,7 +6444,7 @@ private void onSubscribeFlush( if (extension.sizeof() > 0) { - final MqttFlushExFW subscribeFlushEx = extension.get(mqttSubscribeFlushExRO::tryWrap); + final MqttFlushExFW subscribeFlushEx = extension.get(mqttFlushExRO::tryWrap); final int packetId = subscribeFlushEx.subscribe().packetId(); switch (version) diff --git a/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/v5/PublishIT.java b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/v5/PublishIT.java index 11cc3d34d8..629bd42105 100644 --- a/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/v5/PublishIT.java +++ b/runtime/binding-mqtt/src/test/java/io/aklivity/zilla/runtime/binding/mqtt/internal/stream/server/v5/PublishIT.java @@ -423,6 +423,16 @@ public void shouldPublishQoS2MessageAckWithReasoncode() throws Exception k3po.finish(); } + @Test + @Configuration("server.yaml") + @Specification({ + "${net}/publish.qos2.recovery/client", + "${app}/publish.qos2.recovery/server"}) + public void shouldReleaseQos2PacketIdDuringRecovery() throws Exception + { + k3po.finish(); + } + @Test @Configuration("server.yaml") @Specification({ diff --git a/specs/binding-kafka.spec/src/main/java/io/aklivity/zilla/specs/binding/kafka/internal/KafkaFunctions.java b/specs/binding-kafka.spec/src/main/java/io/aklivity/zilla/specs/binding/kafka/internal/KafkaFunctions.java index 9d53ec0521..8800b4dfba 100644 --- a/specs/binding-kafka.spec/src/main/java/io/aklivity/zilla/specs/binding/kafka/internal/KafkaFunctions.java +++ b/specs/binding-kafka.spec/src/main/java/io/aklivity/zilla/specs/binding/kafka/internal/KafkaFunctions.java @@ -2546,6 +2546,18 @@ private KafkaOffsetFetchDataExBuilder() offsetFetchDataExRW.wrap(writeBuffer, KafkaDataExFW.FIELD_OFFSET_OFFSET_FETCH, writeBuffer.capacity()); } + public KafkaOffsetFetchDataExBuilder partition( + int partitionId, + long partitionOffset, + int leaderEpoch) + { + offsetFetchDataExRW.partitionsItem(o -> o + .partitionId(partitionId) + .partitionOffset(partitionOffset) + .leaderEpoch(leaderEpoch)); + return this; + } + public KafkaOffsetFetchDataExBuilder partition( int partitionId, long partitionOffset, diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/produce/message.values.producer.id.changes/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/produce/message.values.producer.id.changes/client.rpt index 86f89d8a07..4b980edead 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/produce/message.values.producer.id.changes/client.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/produce/message.values.producer.id.changes/client.rpt @@ -77,6 +77,7 @@ write zilla:data.ext ${kafka:dataEx() .producerId(1) .producerEpoch(1) .sequence(0) + .header("header1", "value1") .build() .build()} write "Hello, world" @@ -89,6 +90,7 @@ write zilla:data.ext ${kafka:dataEx() .producerId(2) .producerEpoch(2) .sequence(0) + .header("header1", "value1") .build() .build()} write "Hello, again" diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/produce/message.values.producer.id.changes/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/produce/message.values.producer.id.changes/server.rpt index 80a632c830..dd64a9c5d6 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/produce/message.values.producer.id.changes/server.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/application/produce/message.values.producer.id.changes/server.rpt @@ -74,6 +74,7 @@ read zilla:data.ext ${kafka:matchDataEx() .producerId(1) .producerEpoch(1) .sequence(0) + .header("header1", "value1") .build() .build()} @@ -85,6 +86,7 @@ read zilla:data.ext ${kafka:matchDataEx() .producerId(2) .producerEpoch(2) .sequence(0) + .header("header1", "value1") .build() .build()} diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.plain/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.plain/client.rpt index 4c5d98077f..7db462fc04 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.plain/client.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.plain/client.rpt @@ -59,7 +59,7 @@ read 20 # size write 31 # size 22s # init producer id - 4s # v4 + 1s # v1 ${newRequestId} 5s "zilla" # client id -1s # transaction diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.plain/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.plain/server.rpt index 784b3d2b8e..386cf6820d 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.plain/server.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.plain/server.rpt @@ -56,7 +56,7 @@ write 20 # size read 31 # size 22s # init producer id - 4s # v4 + 1s # v1 (int:newRequestId) 5s "zilla" # client id -1s # transaction diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.scram/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.scram/client.rpt index 572339d077..fd58b8e112 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.scram/client.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.scram/client.rpt @@ -73,7 +73,7 @@ read 52 # size write 31 # size 22s # init producer id - 4s # v4 + 1s # v1 ${newRequestId} 5s "zilla" # client id -1s # transaction diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.scram/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.scram/server.rpt index 6c63bb07c8..3cd927885b 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.scram/server.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4.sasl.handshake.v1/produce.new.id.sasl.scram/server.rpt @@ -70,7 +70,7 @@ write 52 # size read 31 # size 22s # init producer id - 4s # v4 + 1s # v1 (int:newRequestId) 5s "zilla" # client id -1s # transaction diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4/produce.new.id/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4/produce.new.id/client.rpt index 3044b68ae9..595654cba8 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4/produce.new.id/client.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4/produce.new.id/client.rpt @@ -30,7 +30,7 @@ connected write 31 # size 22s # init producer id - 4s # v4 + 1s # v1 ${newRequestId} 5s "zilla" # client id -1s # transaction diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4/produce.new.id/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4/produce.new.id/server.rpt index 06402aac80..4786dd1b8f 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4/produce.new.id/server.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/init.producer.id.v4/produce.new.id/server.rpt @@ -27,7 +27,7 @@ connected read 31 # size 22s # init producer id - 4s # v4 + 1s # v1 (int:newRequestId) 5s "zilla" # client id -1s # transaction diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/produce.v3/message.values.producer.id.changes/client.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/produce.v3/message.values.producer.id.changes/client.rpt index 01d3e62f46..f452e74075 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/produce.v3/message.values.producer.id.changes/client.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/produce.v3/message.values.producer.id.changes/client.rpt @@ -81,7 +81,7 @@ write zilla:begin.ext ${proxy:beginEx() connected -write 125 # size +write 140 # size 0s # produce 3s # v3 ${newRequestId} @@ -93,9 +93,9 @@ write 125 # size 4s "test" 1 0 # partition - 80 # record set size + 95 # record set size 0L # first offset - 68 # length + 83 # length -1 [0x02] 0x4e8723aa @@ -107,14 +107,18 @@ write 125 # size 1s 0 1 # records - ${kafka:varint(18)} + ${kafka:varint(33)} [0x00] ${kafka:varint(0)} ${kafka:varint(0)} ${kafka:varint(-1)} # key ${kafka:varint(12)} # value "Hello, world" - ${kafka:varint(0)} # headers + ${kafka:varint(1)} # headers + ${kafka:varint(7)} # key size + "header1" # key bytes + ${kafka:varint(6)} # value size + "value1" # value bytes read 44 ${newRequestId} @@ -127,7 +131,7 @@ read 44 [0..8] # log append time [0..4] # throttle ms -write 125 # size +write 140 # size 0s # produce 3s # v3 ${newRequestId} @@ -139,9 +143,9 @@ write 125 # size 4s "test" 1 0 # partition - 80 # record set size + 95 # record set size 0L # first offset - 68 # length + 83 # length -1 [0x02] 0x4e8723aa @@ -153,14 +157,18 @@ write 125 # size 2s 0 1 # records - ${kafka:varint(18)} + ${kafka:varint(33)} [0x00] ${kafka:varint(0)} ${kafka:varint(0)} ${kafka:varint(-1)} # key ${kafka:varint(12)} # value "Hello, again" - ${kafka:varint(0)} # headers + ${kafka:varint(1)} # headers + ${kafka:varint(7)} # key size + "header1" # key bytes + ${kafka:varint(6)} # value size + "value1" # value bytes read 44 ${newRequestId} diff --git a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/produce.v3/message.values.producer.id.changes/server.rpt b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/produce.v3/message.values.producer.id.changes/server.rpt index 2d8dc04b47..f9741db993 100644 --- a/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/produce.v3/message.values.producer.id.changes/server.rpt +++ b/specs/binding-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/kafka/streams/network/produce.v3/message.values.producer.id.changes/server.rpt @@ -77,7 +77,7 @@ read zilla:begin.ext ${proxy:matchBeginEx() connected -read 125 +read 140 0s 3s (int:requestId) @@ -89,9 +89,9 @@ read 125 4s "test" 1 0 - 80 # record set size + 95 # record set size 0L # first offset - 68 # length + 83 # length -1 [0x02] [0..4] @@ -103,14 +103,18 @@ read 125 1s 0 1 # records - ${kafka:varint(18)} + ${kafka:varint(33)} [0x00] ${kafka:varint(0)} ${kafka:varint(0)} - ${kafka:varint(-1)} # key - ${kafka:varint(12)} # value + ${kafka:varint(-1)} + ${kafka:varint(12)} "Hello, world" - ${kafka:varint(0)} # headers + ${kafka:varint(1)} # headers + ${kafka:varint(7)} # key size + "header1" # key bytes + ${kafka:varint(6)} # value size + "value1" # value bytes write 44 ${requestId} @@ -123,7 +127,7 @@ write 44 0L # log append time 0 # throttle -read 125 +read 140 0s 3s (int:requestId) @@ -135,9 +139,9 @@ read 125 4s "test" 1 0 - 80 # record set size + 95 # record set size 0L # first offset - 68 # length + 83 # length -1 [0x02] [0..4] @@ -149,14 +153,18 @@ read 125 2s 0 1 # records - ${kafka:varint(18)} + ${kafka:varint(33)} [0x00] ${kafka:varint(0)} ${kafka:varint(0)} - ${kafka:varint(-1)} # key - ${kafka:varint(12)} # value + ${kafka:varint(-1)} + ${kafka:varint(12)} "Hello, again" - ${kafka:varint(0)} # headers + ${kafka:varint(1)} # headers + ${kafka:varint(7)} # key size + "header1" # key bytes + ${kafka:varint(6)} # value size + "value1" # value bytes write 44 ${requestId} diff --git a/specs/binding-mqtt-kafka.spec/pom.xml b/specs/binding-mqtt-kafka.spec/pom.xml index f19bfcfb9d..517559d0d0 100644 --- a/specs/binding-mqtt-kafka.spec/pom.xml +++ b/specs/binding-mqtt-kafka.spec/pom.xml @@ -88,7 +88,7 @@ flyweight-maven-plugin ${project.version} - core mqtt kafka + core mqtt kafka mqtt_kafka io.aklivity.zilla.specs.binding.mqtt.kafka.internal.types diff --git a/specs/binding-mqtt-kafka.spec/src/main/java/io/aklivity/zilla/specs/binding/mqtt/kafka/internal/MqttKafkaFunctions.java b/specs/binding-mqtt-kafka.spec/src/main/java/io/aklivity/zilla/specs/binding/mqtt/kafka/internal/MqttKafkaFunctions.java new file mode 100644 index 0000000000..4d6b9f34c0 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/java/io/aklivity/zilla/specs/binding/mqtt/kafka/internal/MqttKafkaFunctions.java @@ -0,0 +1,123 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package io.aklivity.zilla.specs.binding.mqtt.kafka.internal; + +import org.agrona.BitUtil; +import org.agrona.MutableDirectBuffer; +import org.agrona.concurrent.UnsafeBuffer; +import org.kaazing.k3po.lang.el.Function; +import org.kaazing.k3po.lang.el.spi.FunctionMapperSpi; + +import io.aklivity.zilla.specs.binding.mqtt.kafka.internal.types.MqttPublishOffsetMetadataFW; +import io.aklivity.zilla.specs.binding.mqtt.kafka.internal.types.MqttSubscribeOffsetMetadataFW; + +public final class MqttKafkaFunctions +{ + @Function + public static MqttSubscribeOffsetMetadataBuilder subscribeMetadata() + { + return new MqttSubscribeOffsetMetadataBuilder(); + } + + @Function + public static MqttPublishOffsetMetadataBuilder publishMetadata() + { + return new MqttPublishOffsetMetadataBuilder(); + } + + public static final class MqttSubscribeOffsetMetadataBuilder + { + private final MqttSubscribeOffsetMetadataFW.Builder offsetMetadataRW = new MqttSubscribeOffsetMetadataFW.Builder(); + + byte version = 1; + + + private MqttSubscribeOffsetMetadataBuilder() + { + MutableDirectBuffer writeBuffer = new UnsafeBuffer(new byte[1024 * 8]); + offsetMetadataRW.wrap(writeBuffer, 0, writeBuffer.capacity()); + offsetMetadataRW.version(version); + } + + public MqttSubscribeOffsetMetadataBuilder metadata( + int packetId) + { + offsetMetadataRW.appendPacketIds((short) packetId); + return this; + } + + public String build() + { + final MqttSubscribeOffsetMetadataFW offsetMetadata = offsetMetadataRW.build(); + return BitUtil.toHex(offsetMetadata.buffer().byteArray(), offsetMetadata.offset(), offsetMetadata.limit()); + } + } + + public static final class MqttPublishOffsetMetadataBuilder + { + private final MqttPublishOffsetMetadataFW.Builder offsetMetadataRW = new MqttPublishOffsetMetadataFW.Builder(); + + byte version = 1; + + + private MqttPublishOffsetMetadataBuilder() + { + MutableDirectBuffer writeBuffer = new UnsafeBuffer(new byte[1024 * 8]); + offsetMetadataRW.wrap(writeBuffer, 0, writeBuffer.capacity()); + offsetMetadataRW.version(version); + } + + public MqttPublishOffsetMetadataBuilder packetId( + int packetId) + { + offsetMetadataRW.appendPacketIds((short) packetId); + return this; + } + + public MqttPublishOffsetMetadataBuilder producer( + long producerId, + short producerEpoch) + { + offsetMetadataRW.producerId(producerId).producerEpoch(producerEpoch); + return this; + } + + public String build() + { + final MqttPublishOffsetMetadataFW offsetMetadata = offsetMetadataRW.build(); + return BitUtil.toHex(offsetMetadata.buffer().byteArray(), offsetMetadata.offset(), offsetMetadata.limit()); + } + } + + public static class Mapper extends FunctionMapperSpi.Reflective + { + public Mapper() + { + super(MqttKafkaFunctions.class); + } + + @Override + public String getPrefixName() + { + return "mqtt_kafka"; + } + } + + private MqttKafkaFunctions() + { + /* utility */ + } +} diff --git a/specs/binding-mqtt-kafka.spec/src/main/resources/META-INF/services/org.kaazing.k3po.lang.el.spi.FunctionMapperSpi b/specs/binding-mqtt-kafka.spec/src/main/resources/META-INF/services/org.kaazing.k3po.lang.el.spi.FunctionMapperSpi new file mode 100644 index 0000000000..cf4d32ef12 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/resources/META-INF/services/org.kaazing.k3po.lang.el.spi.FunctionMapperSpi @@ -0,0 +1 @@ +io.aklivity.zilla.specs.binding.mqtt.kafka.internal.MqttKafkaFunctions$Mapper diff --git a/specs/binding-mqtt-kafka.spec/src/main/resources/META-INF/zilla/mqtt_kafka.idl b/specs/binding-mqtt-kafka.spec/src/main/resources/META-INF/zilla/mqtt_kafka.idl new file mode 100644 index 0000000000..74a792a173 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/resources/META-INF/zilla/mqtt_kafka.idl @@ -0,0 +1,33 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +scope mqtt_kafka +{ + struct MqttSubscribeOffsetMetadata + { + uint8 version = 1; + int8 length; + int16[length] packetIds = null; + } + + struct MqttPublishOffsetMetadata + { + uint8 version = 1; + int64 producerId = 0; + int16 producerEpoch = 0; + int8 length; + int16[length] packetIds = null; + } +} \ No newline at end of file diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.mixture.qos/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.mixture.qos/client.rpt index 85102c2f56..76deba4b17 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.mixture.qos/client.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.mixture.qos/client.rpt @@ -17,6 +17,354 @@ connect "zilla://streams/kafka0" option zilla:window 8192 option zilla:transmission "duplex" +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_MIGRATE_SIGNAL + + +connect await SENT_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER + +write zilla:data.empty +write flush + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} + +write close + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +read notify RECEIVED_PARTITION_METADATA + +write close + + +connect await RECEIVED_PARTITION_METADATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .partition(1, 1, 0) + .build() + .build()} +read zilla:data.empty + +write close +read closed + + +connect await RECEIVED_PARTITION_METADATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-retained") + .partition(0) + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .build() + .build()} +read zilla:data.empty +read notify RECEIVED_INITIAL_OFFSETS + +write close +read closed + + +connect await RECEIVED_INITIAL_OFFSETS + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(0) + .producerEpoch(0) + .build() + .build()} + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(1) + .producerEpoch(1) + .build() + .build()} +read notify RECEIVED_PRODUCER + +connected + +write close +read closed + + +connect await RECEIVED_PRODUCER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(1, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-retained") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write notify SENT_INITIAL_OFFSET_COMMIT + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 2, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write flush + + +connect await SENT_INITIAL_OFFSET_COMMIT + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client") + .build() + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read advised zilla:flush +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + write zilla:begin.ext ${kafka:beginEx() .typeId(zilla:id("kafka")) .merged() @@ -46,7 +394,40 @@ write "message1" write flush -connect "zilla://streams/kafka0" +connect await RECEIVED_SESSION_STATE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .packetId(1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write flush + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/kafka0" option zilla:window 8192 option zilla:transmission "duplex" @@ -62,12 +443,31 @@ write zilla:begin.ext ${kafka:beginEx() connected +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .partitionId(0) + .build() + .build()} + write zilla:data.ext ${kafka:dataEx() .typeId(zilla:id("kafka")) .merged() .produce() .deferred(0) - .partition(-1, -1) + .producerId(1) + .producerEpoch(1) + .partition(-1, 1) .key("sensor/one") .header("zilla:filter", "sensor") .header("zilla:filter", "one") @@ -79,7 +479,8 @@ write "message2" write flush -connect "zilla://streams/kafka0" +connect await RECEIVED_SESSION_STATE + "zilla://streams/kafka0" option zilla:window 8192 option zilla:transmission "duplex" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.mixture.qos/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.mixture.qos/server.rpt index 170fd2677a..ee9f51ca3d 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.mixture.qos/server.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.mixture.qos/server.rpt @@ -17,6 +17,329 @@ accept "zilla://streams/kafka0" option zilla:window 8192 option zilla:transmission "duplex" +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .generationId(1) + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .partition(1, 1, 0) + .build() + .build()} +write zilla:data.empty +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-retained") + .partition(0) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .build() + .build()} +write zilla:data.empty +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(0) + .producerEpoch(0) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(1) + .producerEpoch(1) + .build() + .build()} + +connected + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(1, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-retained") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 2, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client") + .build() + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# session expiry cancellation signal for client +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write advise zilla:flush + + accepted read zilla:begin.ext ${kafka:beginEx() @@ -48,6 +371,34 @@ read zilla:data.ext ${kafka:matchDataEx() read "message1" +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .packetId(1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + + accepted read zilla:begin.ext ${kafka:beginEx() @@ -62,12 +413,31 @@ read zilla:begin.ext ${kafka:beginEx() connected +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .build() + .build()} + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .partitionId(0) + .build() + .build()} + read zilla:data.ext ${kafka:matchDataEx() .typeId(zilla:id("kafka")) .merged() .produce() .deferred(0) - .partition(-1, -1) + .producerId(1) + .producerEpoch(1) + .partition(-1, 1) .key("sensor/one") .header("zilla:filter", "sensor") .header("zilla:filter", "one") diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.init.producer.abort/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.init.producer.abort/client.rpt new file mode 100644 index 0000000000..04c278665f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.init.producer.abort/client.rpt @@ -0,0 +1,225 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_MIGRATE_SIGNAL + + +connect await SENT_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER + +write zilla:data.empty +write flush + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} + +write close + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +read notify RECEIVED_PARTITION_METADATA + +write close + + +connect await RECEIVED_PARTITION_METADATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .partition(1, 1, 0) + .build() + .build()} +read zilla:data.empty + +write close +read closed + + +connect await RECEIVED_PARTITION_METADATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-retained") + .partition(0) + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .build() + .build()} +read zilla:data.empty +read notify RECEIVED_INITIAL_OFFSETS + +write close +read closed + + +connect await RECEIVED_INITIAL_OFFSETS + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(0) + .producerEpoch(0) + .build() + .build()} + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(1) + .producerEpoch(1) + .build() + .build()} + +connected + +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.init.producer.abort/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.init.producer.abort/server.rpt new file mode 100644 index 0000000000..4ffd107949 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.init.producer.abort/server.rpt @@ -0,0 +1,215 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .generationId(1) + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .partition(1, 1, 0) + .build() + .build()} +write zilla:data.empty +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-retained") + .partition(0) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .build() + .build()} +write zilla:data.empty +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(0) + .producerEpoch(0) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(1) + .producerEpoch(1) + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.meta.abort/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.meta.abort/client.rpt new file mode 100644 index 0000000000..f4bde1cd79 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.meta.abort/client.rpt @@ -0,0 +1,106 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_MIGRATE_SIGNAL + + +connect await SENT_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER + +write zilla:data.empty +write flush + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} +connected + +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.meta.abort/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.meta.abort/server.rpt new file mode 100644 index 0000000000..493b3738dd --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.meta.abort/server.rpt @@ -0,0 +1,101 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .generationId(1) + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.commit.abort.phase1/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.commit.abort.phase1/client.rpt new file mode 100644 index 0000000000..b3f7e0318f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.commit.abort.phase1/client.rpt @@ -0,0 +1,401 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_MIGRATE_SIGNAL + + +connect await SENT_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER + +write zilla:data.empty +write flush + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} + +write close + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +read notify RECEIVED_PARTITION_METADATA + +write close + + +connect await RECEIVED_PARTITION_METADATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .partition(1, 1, 0) + .build() + .build()} +read zilla:data.empty + +write close +read closed + + +connect await RECEIVED_PARTITION_METADATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-retained") + .partition(0) + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .build() + .build()} +read zilla:data.empty +read notify RECEIVED_INITIAL_OFFSETS + +write close +read closed + + +connect await RECEIVED_INITIAL_OFFSETS + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(0) + .producerEpoch(0) + .build() + .build()} + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(1) + .producerEpoch(1) + .build() + .build()} +read notify RECEIVED_PRODUCER + +connected + +write close +read closed + + +connect await RECEIVED_PRODUCER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(1, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-retained") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write notify SENT_INITIAL_OFFSET_COMMIT + + +connect await SENT_INITIAL_OFFSET_COMMIT + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client") + .build() + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read advised zilla:flush +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +read notify PUBLISH_CONNECTED +read aborted + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("IN_SYNC_REPLICAS") + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .partitionId(0) + .build() + .build()} diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.commit.abort.phase1/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.commit.abort.phase1/server.rpt new file mode 100644 index 0000000000..53f90137a7 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.commit.abort.phase1/server.rpt @@ -0,0 +1,376 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .generationId(1) + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .partition(1, 1, 0) + .build() + .build()} +write zilla:data.empty +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-retained") + .partition(0) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .build() + .build()} +write zilla:data.empty +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(0) + .producerEpoch(0) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(1) + .producerEpoch(1) + .build() + .build()} + +connected + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(1, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-retained") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client") + .build() + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# session expiry cancellation signal for client +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write advise zilla:flush + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +write await PUBLISH_CONNECTED +write abort + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("IN_SYNC_REPLICAS") + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .build() + .build()} + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .partitionId(0) + .build() + .build()} diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.commit.abort.phase2/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.commit.abort.phase2/client.rpt new file mode 100644 index 0000000000..78ea08a153 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.commit.abort.phase2/client.rpt @@ -0,0 +1,305 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_MIGRATE_SIGNAL + + +connect await SENT_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER + +write zilla:data.empty +write flush + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} + +write close + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +read notify RECEIVED_PARTITION_METADATA + +write close + + +connect await RECEIVED_PARTITION_METADATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .partition(1, 1, 0) + .build() + .build()} +read zilla:data.empty + +write close +read closed + + +connect await RECEIVED_PARTITION_METADATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-retained") + .partition(0) + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .build() + .build()} +read zilla:data.empty +read notify RECEIVED_INITIAL_OFFSETS + +write close +read closed + + +connect await RECEIVED_INITIAL_OFFSETS + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(0) + .producerEpoch(0) + .build() + .build()} + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(1) + .producerEpoch(1) + .build() + .build()} +read notify RECEIVED_PRODUCER + +connected + +write close +read closed + + +connect await RECEIVED_PRODUCER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +read notify RECEIVED_SESSION_CONNECTED +read aborted + +connect await RECEIVED_PRODUCER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client") + .build() + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.commit.abort.phase2/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.commit.abort.phase2/server.rpt new file mode 100644 index 0000000000..4a617c4eee --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.commit.abort.phase2/server.rpt @@ -0,0 +1,288 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .generationId(1) + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .partition(1, 1, 0) + .build() + .build()} +write zilla:data.empty +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-retained") + .partition(0) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .build() + .build()} +write zilla:data.empty +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(0) + .producerEpoch(0) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(1) + .producerEpoch(1) + .build() + .build()} + +connected + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +write await RECEIVED_SESSION_CONNECTED +write abort + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client") + .build() + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected +# session expiry cancellation signal for client +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client") + .delay(1000) + .expireAt(-1) + .build() + .build()} diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.fetch.abort/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.fetch.abort/client.rpt new file mode 100644 index 0000000000..dd927f9cf7 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.fetch.abort/client.rpt @@ -0,0 +1,159 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_MIGRATE_SIGNAL + + +connect await SENT_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER + +write zilla:data.empty +write flush + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} + +write close + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +read notify RECEIVED_PARTITION_METADATA + +write close + + +connect await RECEIVED_PARTITION_METADATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} +connected + +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.fetch.abort/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.fetch.abort/server.rpt new file mode 100644 index 0000000000..c39e68b720 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.offset.fetch.abort/server.rpt @@ -0,0 +1,153 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .generationId(1) + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.recovery/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.recovery/client.rpt new file mode 100644 index 0000000000..e2979e9453 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.recovery/client.rpt @@ -0,0 +1,299 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_MIGRATE_SIGNAL + + +connect await SENT_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER + +write zilla:data.empty +write flush + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} + +write close + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +read notify RECEIVED_PARTITION_METADATA + +write close + + +connect await RECEIVED_PARTITION_METADATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 100, 0, mqtt_kafka:publishMetadata() + .producer(12345, 3) + .packetId(1) + .build()) + .partition(1, 70, 0, mqtt_kafka:publishMetadata() + .producer(12345, 3) + .packetId(2) + .build()) + .build() + .build()} +read zilla:data.empty + +write close +read closed + + + +connect await RECEIVED_PARTITION_METADATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-retained") + .partition(0) + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 10, 0, mqtt_kafka:publishMetadata() + .producer(12345, 3) + .packetId(3) + .build()) + .build() + .build()} +read zilla:data.empty +read notify RECEIVED_INITIAL_OFFSETS + +write close +read closed + + +connect await RECEIVED_INITIAL_OFFSETS + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 101, mqtt_kafka:publishMetadata() + .producer(12345, 3) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty + + +connect await RECEIVED_INITIAL_OFFSETS + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client") + .build() + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read advised zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.recovery/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.recovery/server.rpt new file mode 100644 index 0000000000..094ff1596e --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.recovery/server.rpt @@ -0,0 +1,286 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .generationId(1) + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 100, 0, mqtt_kafka:publishMetadata() + .producer(12345, 3) + .packetId(1) + .build()) + .partition(1, 70, 0, mqtt_kafka:publishMetadata() + .producer(12345, 3) + .packetId(2) + .build()) + .build() + .build()} +write zilla:data.empty +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-retained") + .partition(0) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 10, 0, mqtt_kafka:publishMetadata() + .producer(12345, 3) + .packetId(3) + .build()) + .build() + .build()} +write zilla:data.empty +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 101, mqtt_kafka:publishMetadata() + .producer(12345, 3) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client") + .build() + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# session expiry cancellation signal for client +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write advise zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.retained/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.retained/client.rpt new file mode 100644 index 0000000000..14d00efe7f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.retained/client.rpt @@ -0,0 +1,529 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_MIGRATE_SIGNAL + + +connect await SENT_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER + +write zilla:data.empty +write flush + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} + +write close + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +read notify RECEIVED_PARTITION_METADATA + +write close + + +connect await RECEIVED_PARTITION_METADATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .partition(1, 1, 0) + .build() + .build()} +read zilla:data.empty + +write close +read closed + + + +connect await RECEIVED_PARTITION_METADATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-retained") + .partition(0) + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .build() + .build()} +read zilla:data.empty +read notify RECEIVED_INITIAL_OFFSETS + +write close +read closed + + +connect await RECEIVED_INITIAL_OFFSETS + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(0) + .producerEpoch(0) + .build() + .build()} + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(1) + .producerEpoch(1) + .build() + .build()} +read notify RECEIVED_PRODUCER + +connected + +write close +read closed + + +connect await RECEIVED_PRODUCER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(1, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-retained") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write notify SENT_INITIAL_OFFSET_COMMIT + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 2, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-retained") + .progress(0, 2, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write flush + + +connect await SENT_INITIAL_OFFSET_COMMIT + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client") + .build() + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read advised zilla:flush +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .packetId(1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-retained") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .packetId(1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write flush + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("IN_SYNC_REPLICAS") + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .partitionId(0) + .build() + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .producerId(1) + .producerEpoch(1) + .partition(-1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:qos", "2") + .build() + .build()} +write "message" +write flush + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-retained") + .partition(-1, -2) + .ackMode("IN_SYNC_REPLICAS") + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .partitionId(0) + .build() + .build()} + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .producerId(1) + .producerEpoch(1) + .partition(-1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:qos", "2") + .build() + .build()} +write "message" +write flush + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.retained/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.retained/server.rpt new file mode 100644 index 0000000000..65183792c4 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2.retained/server.rpt @@ -0,0 +1,495 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .generationId(1) + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .partition(1, 1, 0) + .build() + .build()} +write zilla:data.empty +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-retained") + .partition(0) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .build() + .build()} +write zilla:data.empty +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(0) + .producerEpoch(0) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(1) + .producerEpoch(1) + .build() + .build()} + +connected + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(1, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-retained") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 2, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-retained") + .progress(0, 2, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client") + .build() + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# session expiry cancellation signal for client +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write advise zilla:flush + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .packetId(1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-retained") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .packetId(1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-messages") + .partition(-1, -2) + .ackMode("IN_SYNC_REPLICAS") + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .build() + .build()} + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .partitionId(0) + .build() + .build()} + + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .producerId(1) + .producerEpoch(1) + .partition(-1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:qos", "2") + .build() + .build()} +read "message" + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_ONLY") + .topic("mqtt-retained") + .partition(-1, -2) + .ackMode("IN_SYNC_REPLICAS") + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .build() + .build()} + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .partitionId(0) + .build() + .build()} + + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .producerId(1) + .producerEpoch(1) + .partition(-1, 1) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:qos", "2") + .build() + .build()} +read "message" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2/client.rpt index c6e3b10966..28f0bd1ed5 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2/client.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2/client.rpt @@ -17,6 +17,415 @@ connect "zilla://streams/kafka0" option zilla:window 8192 option zilla:transmission "duplex" +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +write zilla:data.empty +write flush +write notify SENT_MIGRATE_SIGNAL + + +connect await SENT_MIGRATE_SIGNAL + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +read advised zilla:flush ${kafka:matchFlushEx() + .typeId(zilla:id("kafka")) + .group() + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +read notify RECEIVED_LEADER + +write zilla:data.empty +write flush + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} + +write close + + +connect await RECEIVED_LEADER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +read notify RECEIVED_PARTITION_METADATA + +write close + + +connect await RECEIVED_PARTITION_METADATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .partition(1, 1, 0) + .build() + .build()} +read zilla:data.empty + +write close +read closed + + +connect await RECEIVED_PARTITION_METADATA + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-retained") + .partition(0) + .build() + .build()} +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .build() + .build()} +read zilla:data.empty +read notify RECEIVED_INITIAL_OFFSETS + +write close +read closed + + +connect await RECEIVED_INITIAL_OFFSETS + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(0) + .producerEpoch(0) + .build() + .build()} + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(1) + .producerEpoch(1) + .build() + .build()} +read notify RECEIVED_PRODUCER + +connected + +write close +read closed + + +connect await RECEIVED_PRODUCER + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(1, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-retained") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write notify SENT_INITIAL_OFFSET_COMMIT + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 2, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 3, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write flush + + +connect await SENT_INITIAL_OFFSET_COMMIT + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client") + .build() + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +write ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client") + .delay(1000) + .expireAt(-1) + .build() + .build()} +write flush + +read advised zilla:flush +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .packetId(1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write flush + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 2, mqtt_kafka:publishMetadata() + .producer(1, 1) + .packetId(1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +write zilla:data.empty +write flush + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/kafka0" + option zilla:window 8192 + option zilla:transmission "duplex" + write zilla:begin.ext ${kafka:beginEx() .typeId(zilla:id("kafka")) .merged() @@ -29,12 +438,31 @@ write zilla:begin.ext ${kafka:beginEx() connected +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .build() + .build()} + +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .partitionId(0) + .build() + .build()} + write zilla:data.ext ${kafka:dataEx() .typeId(zilla:id("kafka")) .merged() .produce() .deferred(0) - .partition(-1, -1) + .producerId(1) + .producerEpoch(1) + .partition(-1, 1) .key("sensor/one") .header("zilla:filter", "sensor") .header("zilla:filter", "one") @@ -45,3 +473,23 @@ write zilla:data.ext ${kafka:dataEx() write "message" write flush +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .producerId(1) + .producerEpoch(1) + .partition(-1, 2) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:qos", "2") + .build() + .build()} +write "message2" +write flush + + + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2/server.rpt index 53377dd9f2..3171df0c04 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2/server.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.qos2/server.rpt @@ -17,6 +17,386 @@ accept "zilla://streams/kafka0" option zilla:window 8192 option zilla:transmission "duplex" +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#migrate") + .hashKey("client") + .header("sender-id", "sender-1") + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .timeout(1000) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .group() + .groupId("client-session") + .protocol("highlander") + .instanceId("zilla") + .host("localhost") + .port(9092) + .timeout(1000) + .build() + .build()} + +connected + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .group() + .generationId(1) + .leaderId("consumer-1") + .memberId("consumer-1") + .members("consumer-1") + .build() + .build()} +write flush + +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-messages") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .partition(1, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .meta() + .topic("mqtt-retained") + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .meta() + .partition(0, -2) + .build() + .build()} +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-messages") + .partition(0) + .partition(1) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .partition(1, 1, 0) + .build() + .build()} +write zilla:data.empty +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .groupId("client-session") + .host("localhost") + .port(9092) + .topic("mqtt-retained") + .partition(0) + .build() + .build()} + +connected + +write zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetFetch() + .partition(0, 1, 0) + .build() + .build()} +write zilla:data.empty +write flush + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(0) + .producerEpoch(0) + .build() + .build()} + +write zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .initProducerId() + .producerId(1) + .producerEpoch(1) + .build() + .build()} + +connected + +read closed +write close + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(1, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-retained") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + +#Triggered by PUBREL +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 2, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + +#Triggered by PUBREL +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 3, mqtt_kafka:publishMetadata() + .producer(1, 1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + + +accepted + +read zilla:begin.ext ${kafka:matchBeginEx() + .typeId(zilla:id("kafka")) + .merged() + .capabilities("PRODUCE_AND_FETCH") + .topic("mqtt-sessions") + .groupId("mqtt-clients") + .filter() + .key("client") + .build() + .filter() + .key("client#migrate") + .headerNot("sender-id", "sender-1") + .build() + .build() + .build()} + +connected + +# session expiry cancellation signal for client +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +read zilla:data.null + +# session expire later signal for client +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .partition(-1, -1) + .key("client#expiry-signal") + .hashKey("client") + .header("type", "expiry-signal") + .build() + .build()} +read ${mqtt:sessionSignal() + .expiry() + .instanceId("zilla-1") + .clientId("client") + .delay(1000) + .expireAt(-1) + .build() + .build()} + +write advise zilla:flush + + +accepted + +read zilla:begin.ext ${kafka:beginEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .groupId("client-session") + .memberId("consumer-1") + .instanceId("zilla") + .build() + .build()} + +connected + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 1, mqtt_kafka:publishMetadata() + .producer(1, 1) + .packetId(1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + +read zilla:data.ext ${kafka:dataEx() + .typeId(zilla:id("kafka")) + .offsetCommit() + .topic("mqtt-messages") + .progress(0, 2, mqtt_kafka:publishMetadata() + .producer(1, 1) + .packetId(1) + .build()) + .generationId(1) + .leaderEpoch(0) + .build() + .build()} +read zilla:data.empty + + accepted read zilla:begin.ext ${kafka:beginEx() @@ -31,12 +411,31 @@ read zilla:begin.ext ${kafka:beginEx() connected +read advised zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .build() + .build()} + +write advise zilla:flush ${kafka:flushEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .hashKey("sensor/one") + .partitionId(0) + .build() + .build()} + read zilla:data.ext ${kafka:matchDataEx() .typeId(zilla:id("kafka")) .merged() .produce() .deferred(0) - .partition(-1, -1) + .producerId(1) + .producerEpoch(1) + .partition(-1, 1) .key("sensor/one") .header("zilla:filter", "sensor") .header("zilla:filter", "one") @@ -45,3 +444,22 @@ read zilla:data.ext ${kafka:matchDataEx() .build() .build()} read "message" + +read zilla:data.ext ${kafka:matchDataEx() + .typeId(zilla:id("kafka")) + .merged() + .produce() + .deferred(0) + .producerId(1) + .producerEpoch(1) + .partition(-1, 2) + .key("sensor/one") + .header("zilla:filter", "sensor") + .header("zilla:filter", "one") + .header("zilla:local", "client") + .header("zilla:qos", "2") + .build() + .build()} +read "message2" + + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.flush/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.flush/client.rpt deleted file mode 100644 index e5d9d4cd82..0000000000 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.flush/client.rpt +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt-messages") - .partition(-1, -2) - .ackMode("NONE") - .build() - .build()} - -connected - -write notify MESSAGES_DONE - - -connect await MESSAGES_DONE - "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt-retained") - .partition(-1, -2) - .ackMode("NONE") - .build() - .build()} - -connected - -read advised zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.flush/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.flush/server.rpt deleted file mode 100644 index dd3fd10a58..0000000000 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.retained.server.sent.flush/server.rpt +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt-messages") - .partition(-1, -2) - .ackMode("NONE") - .build() - .build()} - -connected - - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt-retained") - .partition(-1, -2) - .ackMode("NONE") - .build() - .build()} - -connected - -write advise zilla:flush - diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/client.rpt deleted file mode 100644 index 612ba69b23..0000000000 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/client.rpt +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -connect "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -write zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt-messages") - .partition(-1, -2) - .ackMode("NONE") - .build() - .build()} - -connected - -read advised zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/server.rpt deleted file mode 100644 index 0ec69c9a88..0000000000 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/publish.server.sent.flush/server.rpt +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/kafka0" - option zilla:window 8192 - option zilla:transmission "duplex" - -accepted - -read zilla:begin.ext ${kafka:beginEx() - .typeId(zilla:id("kafka")) - .merged() - .capabilities("PRODUCE_ONLY") - .topic("mqtt-messages") - .partition(-1, -2) - .ackMode("NONE") - .build() - .build()} - -connected - -write advise zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard.mixed.qos/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard.mixed.qos/client.rpt index b2659a5bab..db7deb6ca0 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard.mixed.qos/client.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard.mixed.qos/client.rpt @@ -225,7 +225,7 @@ write advise zilla:flush ${kafka:flushEx() .merged() .consumer() .progress(0, 3, - mqtt:metadata() + mqtt_kafka:subscribeMetadata() .metadata(2) .build()) .correlationId(2) diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard.mixed.qos/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard.mixed.qos/server.rpt index 45df409a42..3cdb43bffd 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard.mixed.qos/server.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.overlapping.wildcard.mixed.qos/server.rpt @@ -229,7 +229,7 @@ read advised zilla:flush ${kafka:matchFlushEx() .merged() .consumer() .progress(0, 3, - mqtt:metadata() + mqtt_kafka:subscribeMetadata() .metadata(2) .build()) .correlationId(2) diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.qos2/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.qos2/client.rpt index bb39860052..a69d804085 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.qos2/client.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.qos2/client.rpt @@ -137,7 +137,7 @@ write advise zilla:flush ${kafka:flushEx() .merged() .consumer() .progress(0, 3, - mqtt:metadata() + mqtt_kafka:subscribeMetadata() .metadata(1) .build()) .correlationId(1) diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.qos2/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.qos2/server.rpt index 9ca39d5ab8..5fa79e6863 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.qos2/server.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.message.qos2/server.rpt @@ -137,7 +137,7 @@ read advised zilla:flush ${kafka:matchFlushEx() .merged() .consumer() .progress(0, 3, - mqtt:metadata() + mqtt_kafka:subscribeMetadata() .metadata(1) .build()) .correlationId(1) diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.messages.mixture.qos/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.messages.mixture.qos/client.rpt index 4619492645..9a163c068a 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.messages.mixture.qos/client.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.messages.mixture.qos/client.rpt @@ -189,7 +189,7 @@ write advise zilla:flush ${kafka:flushEx() .merged() .consumer() .progress(0, 5, - mqtt:metadata() + mqtt_kafka:subscribeMetadata() .metadata(2) .build()) .correlationId(2) diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.messages.mixture.qos/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.messages.mixture.qos/server.rpt index 781188782c..9170ccb85b 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.messages.mixture.qos/server.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.receive.messages.mixture.qos/server.rpt @@ -195,7 +195,7 @@ read advised zilla:flush ${kafka:matchFlushEx() .merged() .consumer() .progress(0, 5, - mqtt:metadata() + mqtt_kafka:subscribeMetadata() .metadata(2) .build()) .correlationId(2) diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.incomplete.message/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.incomplete.message/client.rpt index 91ab9353d8..6ea03c6f8e 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.incomplete.message/client.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.incomplete.message/client.rpt @@ -141,7 +141,7 @@ write advise zilla:flush ${kafka:flushEx() .merged() .consumer() .progress(0, 3, - mqtt:metadata() + mqtt_kafka:subscribeMetadata() .metadata(1) .build()) .correlationId(1) @@ -249,7 +249,7 @@ read zilla:begin.ext ${kafka:matchBeginEx() .merged() .capabilities("FETCH_ONLY") .topic("mqtt-messages") - .partition(0, 2, 3, 3, mqtt:metadata() + .partition(0, 2, 3, 3, mqtt_kafka:subscribeMetadata() .metadata(1) .build()) .build() diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.incomplete.message/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.incomplete.message/server.rpt index adf5fdc077..fef08595d9 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.incomplete.message/server.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.incomplete.message/server.rpt @@ -141,7 +141,7 @@ read advised zilla:flush ${kafka:matchFlushEx() .merged() .consumer() .progress(0, 3, - mqtt:metadata() + mqtt_kafka:subscribeMetadata() .metadata(1) .build()) .correlationId(1) @@ -239,7 +239,7 @@ write zilla:begin.ext ${kafka:beginEx() .merged() .capabilities("FETCH_ONLY") .topic("mqtt-messages") - .partition(0, 2, 3, 3, mqtt:metadata() + .partition(0, 2, 3, 3, mqtt_kafka:subscribeMetadata() .metadata(1) .build()) .build() diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.unreceived.message/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.unreceived.message/client.rpt index 899fb9fceb..13394d3897 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.unreceived.message/client.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.unreceived.message/client.rpt @@ -267,7 +267,7 @@ write advise zilla:flush ${kafka:flushEx() .merged() .consumer() .progress(0, 3, - mqtt:metadata() + mqtt_kafka:subscribeMetadata() .metadata(2) .build()) .correlationId(2) diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.unreceived.message/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.unreceived.message/server.rpt index 8b0140d779..fef2858068 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.unreceived.message/server.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.reconnect.replay.qos2.unreceived.message/server.rpt @@ -259,7 +259,7 @@ read advised zilla:flush ${kafka:matchFlushEx() .merged() .consumer() .progress(0, 3, - mqtt:metadata() + mqtt_kafka:subscribeMetadata() .metadata(2) .build()) .correlationId(2) diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.replay.retained.message.qos2/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.replay.retained.message.qos2/client.rpt index e836f5fc39..4e6f38e92b 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.replay.retained.message.qos2/client.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.replay.retained.message.qos2/client.rpt @@ -217,7 +217,7 @@ write advise zilla:flush ${kafka:flushEx() .merged() .consumer() .progress(0, 3, - mqtt:metadata() + mqtt_kafka:subscribeMetadata() .metadata(1) .build()) .correlationId(1) diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.replay.retained.message.qos2/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.replay.retained.message.qos2/server.rpt index 01b6627d94..b96ddb2bf4 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.replay.retained.message.qos2/server.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/kafka/subscribe.replay.retained.message.qos2/server.rpt @@ -211,7 +211,7 @@ read advised zilla:flush ${kafka:matchFlushEx() .merged() .consumer() .progress(0, 3, - mqtt:metadata() + mqtt_kafka:subscribeMetadata() .metadata(1) .build()) .correlationId(1) diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.mixture.qos/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.mixture.qos/client.rpt index 9081f46d80..b69e3f718e 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.mixture.qos/client.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.mixture.qos/client.rpt @@ -17,6 +17,54 @@ connect "zilla://streams/mqtt0" option zilla:window 8192 option zilla:transmission "duplex" +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(1) + .publishQosMax(2) + .capabilities("REDIRECT") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .subscribeQosMax(2) + .capabilities("RETAIN", "SUBSCRIPTION_IDS", "WILDCARD") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + +write await SENT_DATA_TWO +# Triggered by PUBREL +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +read advised zilla:flush ${mqtt:matchFlushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .publish() @@ -38,7 +86,8 @@ write "message1" write flush -connect "zilla://streams/mqtt0" +connect await RECEIVED_SESSION_STATE + "zilla://streams/mqtt0" option zilla:window 8192 option zilla:transmission "duplex" @@ -57,13 +106,16 @@ write zilla:data.ext ${mqtt:dataEx() .typeId(zilla:id("mqtt")) .publish() .qos("EXACTLY_ONCE") + .packetId(1) .build() .build()} write "message2" write flush +write notify SENT_DATA_TWO -connect "zilla://streams/mqtt0" +connect await SENT_DATA_TWO + "zilla://streams/mqtt0" option zilla:window 8192 option zilla:transmission "duplex" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.mixture.qos/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.mixture.qos/server.rpt index 01739ace31..770df0be77 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.mixture.qos/server.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.mixture.qos/server.rpt @@ -19,6 +19,49 @@ accept "zilla://streams/mqtt0" accepted +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(1) + .publishQosMax(2) + .capabilities("REDIRECT") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .subscribeQosMax(2) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + + +accepted + read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .publish() @@ -56,6 +99,7 @@ read zilla:data.ext ${mqtt:matchDataEx() .typeId(zilla:id("mqtt")) .publish() .qos("EXACTLY_ONCE") + .packetId(1) .build() .build()} read "message2" diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.flush/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.abort/client.rpt similarity index 56% rename from specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.flush/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.abort/client.rpt index e62fd29994..4bb6c96bfa 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.flush/client.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.abort/client.rpt @@ -14,18 +14,18 @@ # connect "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" + option zilla:window 8192 + option zilla:transmission "duplex" write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .flags("RETAIN") - .build() - .build()} + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(1) + .publishQosMax(2) + .capabilities("REDIRECT") + .clientId("client") + .build() + .build()} -connected - -read advised zilla:flush +connect aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.abort/server.rpt similarity index 62% rename from specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/client.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.abort/server.rpt index cd81e9e0f4..b4ed4e9e30 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/client.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.abort/server.rpt @@ -13,18 +13,8 @@ # specific language governing permissions and limitations under the License. # -connect "zilla://streams/mqtt0" +accept "zilla://streams/mqtt0" option zilla:window 8192 option zilla:transmission "duplex" -write zilla:begin.ext ${mqtt:beginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .build() - .build()} - -connected - -read advised zilla:flush +rejected diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.offset.commit.abort.phase1/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.offset.commit.abort.phase1/client.rpt new file mode 100644 index 0000000000..72055eab6e --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.offset.commit.abort.phase1/client.rpt @@ -0,0 +1,63 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(1) + .publishQosMax(2) + .capabilities("REDIRECT") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .subscribeQosMax(2) + .capabilities("RETAIN", "SUBSCRIPTION_IDS", "WILDCARD") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .qos(2) + .build() + .build()} + +connected +read notify PUBLISH_CONNECTED +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.offset.commit.abort.phase1/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.offset.commit.abort.phase1/server.rpt new file mode 100644 index 0000000000..46a062b407 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.offset.commit.abort.phase1/server.rpt @@ -0,0 +1,61 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(1) + .publishQosMax(2) + .capabilities("REDIRECT") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .subscribeQosMax(2) + .capabilities("RETAIN", "SUBSCRIPTION_IDS", "WILDCARD") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .qos(2) + .build() + .build()} + +connected + +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.offset.commit.abort.phase2/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.offset.commit.abort.phase2/client.rpt new file mode 100644 index 0000000000..d41271d752 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.offset.commit.abort.phase2/client.rpt @@ -0,0 +1,44 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(1) + .publishQosMax(2) + .capabilities("REDIRECT") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .subscribeQosMax(2) + .capabilities("RETAIN", "SUBSCRIPTION_IDS", "WILDCARD") + .clientId("client") + .build() + .build()} + +connected +read notify RECEIVED_SESSION_CONNECTED + +read aborted diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.offset.commit.abort.phase2/server.rpt similarity index 50% rename from specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/server.rpt rename to specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.offset.commit.abort.phase2/server.rpt index 4fae513f0c..30e1bbe368 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.server.sent.flush/server.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.offset.commit.abort.phase2/server.rpt @@ -14,18 +14,32 @@ # accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" + option zilla:window 8192 + option zilla:transmission "duplex" + accepted -read zilla:begin.ext ${mqtt:matchBeginEx() +read zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(1) + .publishQosMax(2) + .capabilities("REDIRECT") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) - .publish() + .session() + .expiry(1) + .subscribeQosMax(2) + .capabilities("RETAIN", "SUBSCRIPTION_IDS", "WILDCARD") .clientId("client") - .topic("sensor/one") .build() .build()} connected -write advise zilla:flush +write abort diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.recovery/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.recovery/client.rpt new file mode 100644 index 0000000000..eb207d9b9a --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.recovery/client.rpt @@ -0,0 +1,61 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(1) + .publishQosMax(2) + .capabilities("REDIRECT") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .subscribeQosMax(2) + .capabilities("RETAIN", "SUBSCRIPTION_IDS", "WILDCARD") + .clientId("client") + .packetId(1) + .packetId(2) + .packetId(3) + .build() + .build()} + +connected + +read zilla:data.empty + +# Triggered by PUBREL +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.recovery/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.recovery/server.rpt new file mode 100644 index 0000000000..43882d38cd --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.recovery/server.rpt @@ -0,0 +1,64 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(1) + .publishQosMax(2) + .capabilities("REDIRECT") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .subscribeQosMax(2) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") + .clientId("client") + .packetId(1) + .packetId(2) + .packetId(3) + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.retained/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.retained/client.rpt new file mode 100644 index 0000000000..82f9e3ae6b --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.retained/client.rpt @@ -0,0 +1,93 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +connect "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(1) + .publishQosMax(2) + .capabilities("REDIRECT") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .subscribeQosMax(2) + .capabilities("RETAIN", "SUBSCRIPTION_IDS", "WILDCARD") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + +write await SENT_DATA_ONE +# Triggered by PUBREL +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .qos(2) + .build() + .build()} + +connected + +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .qos("EXACTLY_ONCE") + .flags("RETAIN") + .packetId(1) + .build() + .build()} +write "message" +write flush +write notify SENT_DATA_ONE + + + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.retained/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.retained/server.rpt new file mode 100644 index 0000000000..aeb5a33408 --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2.retained/server.rpt @@ -0,0 +1,87 @@ +# +# Copyright 2021-2023 Aklivity Inc +# +# Licensed under the Aklivity Community License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of the +# License at +# +# https://www.aklivity.io/aklivity-community-license/ +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +accept "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(1) + .publishQosMax(2) + .capabilities("REDIRECT") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .subscribeQosMax(2) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .publish() + .clientId("client") + .topic("sensor/one") + .flags("RETAIN") + .qos(2) + .build() + .build()} + +connected + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .qos("EXACTLY_ONCE") + .flags("RETAIN") + .packetId(1) + .build() + .build()} +read "message" + + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2/client.rpt index bb98405e3a..e73e50b548 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2/client.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2/client.rpt @@ -13,11 +13,76 @@ # specific language governing permissions and limitations under the License. # - connect "zilla://streams/mqtt0" option zilla:window 8192 option zilla:transmission "duplex" +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(1) + .publishQosMax(2) + .capabilities("REDIRECT") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .subscribeQosMax(2) + .capabilities("RETAIN", "SUBSCRIPTION_IDS", "WILDCARD") + .clientId("client") + .build() + .build()} + +connected + +read zilla:data.empty +read notify RECEIVED_SESSION_STATE + +# Triggered by PUBREL +write await SENT_DATA_ONE +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +read advised zilla:flush ${mqtt:matchFlushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} +read notify RECEIVED_FLUSH + +write await SENT_DATA_TWO +# Triggered by PUBREL +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +read advised zilla:flush ${mqtt:matchFlushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + + + +connect await RECEIVED_SESSION_STATE + "zilla://streams/mqtt0" + option zilla:window 8192 + option zilla:transmission "duplex" + write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .publish() @@ -33,7 +98,21 @@ write zilla:data.ext ${mqtt:dataEx() .typeId(zilla:id("mqtt")) .publish() .qos("EXACTLY_ONCE") + .packetId(1) .build() .build()} write "message" write flush +write notify SENT_DATA_ONE + +write await RECEIVED_FLUSH +write zilla:data.ext ${mqtt:dataEx() + .typeId(zilla:id("mqtt")) + .publish() + .qos("EXACTLY_ONCE") + .packetId(1) + .build() + .build()} +write "message2" +write flush +write notify SENT_DATA_TWO diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2/server.rpt index fbb4196b8c..c161fc4087 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2/server.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.qos2/server.rpt @@ -19,6 +19,63 @@ accept "zilla://streams/mqtt0" accepted +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .expiry(1) + .publishQosMax(2) + .capabilities("REDIRECT") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .expiry(1) + .subscribeQosMax(2) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") + .clientId("client") + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + + +accepted + read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .publish() @@ -34,6 +91,17 @@ read zilla:data.ext ${mqtt:matchDataEx() .typeId(zilla:id("mqtt")) .publish() .qos("EXACTLY_ONCE") + .packetId(1) .build() .build()} read "message" + +read zilla:data.ext ${mqtt:matchDataEx() + .typeId(zilla:id("mqtt")) + .publish() + .qos("EXACTLY_ONCE") + .packetId(1) + .build() + .build()} +read "message2" + diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.flush/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.flush/server.rpt deleted file mode 100644 index 0d654c898a..0000000000 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/publish.retained.server.sent.flush/server.rpt +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright 2021-2023 Aklivity Inc -# -# Licensed under the Aklivity Community License (the "License"); you may not use -# this file except in compliance with the License. You may obtain a copy of the -# License at -# -# https://www.aklivity.io/aklivity-community-license/ -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. -# - -accept "zilla://streams/mqtt0" - option zilla:window 8192 - option zilla:transmission "duplex" -accepted - -read zilla:begin.ext ${mqtt:matchBeginEx() - .typeId(zilla:id("mqtt")) - .publish() - .clientId("client") - .topic("sensor/one") - .flags("RETAIN") - .build() - .build()} - -connected - -write advise zilla:flush diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe/client.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe/client.rpt index fb15fa41ce..a1d1b43209 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe/client.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .expiry(1) - .qosMax(2) + .subscribeQosMax(2) .capabilities("RETAIN", "SUBSCRIPTION_IDS", "WILDCARD") .clientId("client-1") .build() diff --git a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe/server.rpt b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe/server.rpt index b49dd97da5..fd0f073269 100644 --- a/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe/server.rpt +++ b/specs/binding-mqtt-kafka.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/mqtt/session.subscribe/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .expiry(1) - .qosMax(2) + .subscribeQosMax(2) .capabilities("RETAIN", "SUBSCRIPTION_IDS", "WILDCARD") .clientId("client-1") .build() diff --git a/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/internal/MqttKafkaFunctionsTest.java b/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/internal/MqttKafkaFunctionsTest.java new file mode 100644 index 0000000000..d8a121a61f --- /dev/null +++ b/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/internal/MqttKafkaFunctionsTest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2021-2023 Aklivity Inc + * + * Licensed under the Aklivity Community License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of the + * License at + * + * https://www.aklivity.io/aklivity-community-license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package io.aklivity.zilla.specs.binding.mqtt.kafka.internal; + +import static org.junit.Assert.assertEquals; + +import java.util.function.IntConsumer; + +import org.agrona.BitUtil; +import org.agrona.DirectBuffer; +import org.agrona.collections.IntArrayList; +import org.agrona.concurrent.UnsafeBuffer; +import org.junit.Test; + +import io.aklivity.zilla.specs.binding.mqtt.kafka.internal.types.MqttPublishOffsetMetadataFW; +import io.aklivity.zilla.specs.binding.mqtt.kafka.internal.types.MqttSubscribeOffsetMetadataFW; + +public class MqttKafkaFunctionsTest +{ + @Test + public void shouldGetMapper() + { + MqttKafkaFunctions.Mapper mapper = new MqttKafkaFunctions.Mapper(); + assertEquals("mqtt_kafka", mapper.getPrefixName()); + } + @Test + public void shouldEncodeMqttOffsetMetadata() + { + final String state = MqttKafkaFunctions.subscribeMetadata() + .metadata(1) + .metadata(2) + .build(); + + final IntArrayList metadataList = new IntArrayList(); + UnsafeBuffer buffer = new UnsafeBuffer(BitUtil.fromHex(state)); + MqttSubscribeOffsetMetadataFW offsetMetadata = new MqttSubscribeOffsetMetadataFW().wrap(buffer, 0, buffer.capacity()); + offsetMetadata.packetIds().forEachRemaining((IntConsumer) metadataList::add); + + assertEquals(1, offsetMetadata.version()); + assertEquals(1, (int) metadataList.get(0)); + assertEquals(2, (int) metadataList.get(1)); + } + + @Test + public void shouldEncodeMqttPublishOffsetMetadata() + { + final String state = MqttKafkaFunctions.publishMetadata() + .producer(1L, (short) 1) + .packetId(1) + .build(); + + DirectBuffer buffer = new UnsafeBuffer(BitUtil.fromHex(state)); + MqttPublishOffsetMetadataFW offsetMetadata = new MqttPublishOffsetMetadataFW().wrap(buffer, 0, buffer.capacity()); + + assertEquals(1, offsetMetadata.version()); + assertEquals(1, offsetMetadata.packetIds().nextInt()); + assertEquals(1, offsetMetadata.producerId()); + assertEquals(1, offsetMetadata.producerEpoch()); + } +} diff --git a/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/KafkaIT.java b/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/KafkaIT.java index 97a896ad9f..ec7de4d86e 100644 --- a/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/KafkaIT.java +++ b/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/KafkaIT.java @@ -62,15 +62,6 @@ public void shouldPublishReceiveServerSentAbort() throws Exception k3po.finish(); } - @Test - @Specification({ - "${kafka}/publish.server.sent.flush/client", - "${kafka}/publish.server.sent.flush/server"}) - public void shouldPublishReceiveServerSentFlush() throws Exception - { - k3po.finish(); - } - @Test @Specification({ "${kafka}/publish.server.sent.reset/client", @@ -98,15 +89,6 @@ public void shouldPublishReceiveServerSentRetainedAbort() throws Exception k3po.finish(); } - @Test - @Specification({ - "${kafka}/publish.retained.server.sent.flush/client", - "${kafka}/publish.retained.server.sent.flush/server"}) - public void shouldPublishReceiveServerSentRetainedFlush() throws Exception - { - k3po.finish(); - } - @Test @Specification({ "${kafka}/publish.retained.server.sent.reset/client", @@ -863,6 +845,75 @@ public void shouldPublishQoS2Message() throws Exception k3po.finish(); } + @Test + @Specification({ + "${kafka}/publish.qos2.retained/client", + "${kafka}/publish.qos2.retained/server"}) + public void shouldPublishQoS2MessageRetained() throws Exception + { + k3po.start(); + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.qos2.recovery/client", + "${kafka}/publish.qos2.recovery/server"}) + public void shouldPublishQoS2MessageDuringRecovery() throws Exception + { + k3po.start(); + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.qos2.meta.abort/client", + "${kafka}/publish.qos2.meta.abort/server"}) + public void shouldSessionReceiveQos2MetaSentAbort() throws Exception + { + k3po.start(); + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.qos2.offset.fetch.abort/client", + "${kafka}/publish.qos2.offset.fetch.abort/server"}) + public void shouldSessionReceiveQos2OffsetFetchSentAbort() throws Exception + { + k3po.start(); + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.qos2.init.producer.abort/client", + "${kafka}/publish.qos2.init.producer.abort/server"}) + public void shouldSessionReceiveQos2InitProducerSentAbort() throws Exception + { + k3po.start(); + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.qos2.offset.commit.abort.phase1/client", + "${kafka}/publish.qos2.offset.commit.abort.phase1/server"}) + public void shouldPublishReceiveQos2OffsetCommitSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${kafka}/publish.qos2.offset.commit.abort.phase2/client", + "${kafka}/publish.qos2.offset.commit.abort.phase2/server"}) + public void shouldSessionReceiveQos2OffsetCommitSentAbort() throws Exception + { + k3po.start(); + k3po.finish(); + } + @Test @Specification({ "${kafka}/publish.mixture.qos/client", diff --git a/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/MqttIT.java b/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/MqttIT.java index 132d0b034e..973a4d0661 100644 --- a/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/MqttIT.java +++ b/specs/binding-mqtt-kafka.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/kafka/streams/MqttIT.java @@ -62,15 +62,6 @@ public void shouldPublishReceiveServerSentAbort() throws Exception k3po.finish(); } - @Test - @Specification({ - "${mqtt}/publish.server.sent.flush/client", - "${mqtt}/publish.server.sent.flush/server"}) - public void shouldPublishReceiveServerSentFlush() throws Exception - { - k3po.finish(); - } - @Test @Specification({ "${mqtt}/publish.server.sent.reset/client", @@ -233,15 +224,6 @@ public void shouldSubscribeReceiveServerSentAbort() throws Exception k3po.finish(); } - @Test - @Specification({ - "${mqtt}/subscribe.server.sent.flush/client", - "${mqtt}/subscribe.server.sent.flush/server"}) - public void shouldSubscribeReceiveServerSentFlush() throws Exception - { - k3po.finish(); - } - @Test @Specification({ "${mqtt}/subscribe.server.sent.reset/client", @@ -687,6 +669,55 @@ public void shouldPublishQoS2Message() throws Exception k3po.finish(); } + @Test + @Specification({ + "${mqtt}/publish.qos2.retained/client", + "${mqtt}/publish.qos2.retained/server"}) + public void shouldPublishQoS2MessageRetained() throws Exception + { + k3po.start(); + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.qos2.recovery/client", + "${mqtt}/publish.qos2.recovery/server"}) + public void shouldPublishQoS2MessageDuringRecovery() throws Exception + { + k3po.start(); + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.qos2.abort/client", + "${mqtt}/publish.qos2.abort/server"}) + public void shouldSessionReceiveQos2Abort() throws Exception + { + k3po.start(); + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.qos2.offset.commit.abort.phase1/client", + "${mqtt}/publish.qos2.offset.commit.abort.phase1/server"}) + public void shouldPublishReceiveQos2OffsetCommitSentAbort() throws Exception + { + k3po.finish(); + } + + @Test + @Specification({ + "${mqtt}/publish.qos2.offset.commit.abort.phase2/client", + "${mqtt}/publish.qos2.offset.commit.abort.phase2/server"}) + public void shouldSessionReceiveQos2OffsetCommitAbort() throws Exception + { + k3po.start(); + k3po.finish(); + } + @Test @Specification({ "${mqtt}/publish.mixture.qos/client", diff --git a/specs/binding-mqtt.spec/src/main/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctions.java b/specs/binding-mqtt.spec/src/main/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctions.java index d3913cc7c3..42d726c4e7 100644 --- a/specs/binding-mqtt.spec/src/main/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctions.java +++ b/specs/binding-mqtt.spec/src/main/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctions.java @@ -19,11 +19,13 @@ import static java.nio.charset.StandardCharsets.UTF_8; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; +import java.util.PrimitiveIterator; import java.util.concurrent.ThreadLocalRandom; import java.util.function.Predicate; -import org.agrona.BitUtil; import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; import org.agrona.concurrent.UnsafeBuffer; @@ -53,7 +55,6 @@ import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttDataExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttExtensionKind; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttFlushExFW; -import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttOffsetMetadataFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttOffsetStateFlags; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttPublishBeginExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttPublishDataExFW; @@ -62,6 +63,7 @@ import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttSessionBeginExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttSessionDataExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttSessionDataKind; +import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttSessionFlushExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttSubscribeBeginExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttSubscribeDataExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttSubscribeFlushExFW; @@ -111,21 +113,21 @@ public static MqttFlushExBuilder flushEx() } @Function - public static MqttResetExBuilder resetEx() + public static MqttFlushExMatcherBuilder matchFlushEx() { - return new MqttResetExBuilder(); + return new MqttFlushExMatcherBuilder(); } @Function - public static MqttSessionStateBuilder session() + public static MqttResetExBuilder resetEx() { - return new MqttSessionStateBuilder(); + return new MqttResetExBuilder(); } @Function - public static MqttOffsetMetadataBuilder metadata() + public static MqttSessionStateBuilder session() { - return new MqttOffsetMetadataBuilder(); + return new MqttSessionStateBuilder(); } @Function @@ -224,6 +226,13 @@ public MqttSessionBeginExBuilder clientId( return this; } + public MqttSessionBeginExBuilder packetId( + int packetId) + { + sessionBeginExRW.appendPacketIds((short) packetId); + return this; + } + public MqttSessionBeginExBuilder expiry( int expiry) { @@ -231,10 +240,17 @@ public MqttSessionBeginExBuilder expiry( return this; } - public MqttSessionBeginExBuilder qosMax( - int qosMax) + public MqttSessionBeginExBuilder subscribeQosMax( + int subscribeQosMax) + { + sessionBeginExRW.subscribeQosMax(subscribeQosMax); + return this; + } + + public MqttSessionBeginExBuilder publishQosMax( + int publishQosMax) { - sessionBeginExRW.qosMax(qosMax); + sessionBeginExRW.publishQosMax(publishQosMax); return this; } @@ -570,6 +586,13 @@ public MqttPublishDataExBuilder flags( return this; } + public MqttPublishDataExBuilder packetId( + int packetId) + { + publishDataExRW.packetId(packetId); + return this; + } + public MqttPublishDataExBuilder expiryInterval( int expiryInterval) { @@ -680,6 +703,13 @@ public MqttFlushExBuilder typeId( return this; } + public MqttSessionFlushExBuilder session() + { + flushExRW.kind(MqttExtensionKind.SESSION.value()); + + return new MqttSessionFlushExBuilder(); + } + public MqttSubscribeFlushExBuilder subscribe() { flushExRW.kind(MqttExtensionKind.SUBSCRIBE.value()); @@ -687,13 +717,37 @@ public MqttSubscribeFlushExBuilder subscribe() return new MqttSubscribeFlushExBuilder(); } + public final class MqttSessionFlushExBuilder + { + private final MqttSessionFlushExFW.Builder sessionFlushExRW = new MqttSessionFlushExFW.Builder(); + + private MqttSessionFlushExBuilder() + { + sessionFlushExRW.wrap(writeBuffer, MqttFlushExFW.FIELD_OFFSET_SESSION, writeBuffer.capacity()); + } + + public MqttSessionFlushExBuilder packetId( + int packetId) + { + sessionFlushExRW.packetId(packetId); + return this; + } + + public MqttFlushExBuilder build() + { + final MqttSessionFlushExFW sessionFlushEx = sessionFlushExRW.build(); + flushExRO.wrap(writeBuffer, 0, sessionFlushEx.limit()); + return MqttFlushExBuilder.this; + } + } + public final class MqttSubscribeFlushExBuilder { private final MqttSubscribeFlushExFW.Builder subscribeFlushExRW = new MqttSubscribeFlushExFW.Builder(); private MqttSubscribeFlushExBuilder() { - subscribeFlushExRW.wrap(writeBuffer, MqttBeginExFW.FIELD_OFFSET_PUBLISH, writeBuffer.capacity()); + subscribeFlushExRW.wrap(writeBuffer, MqttFlushExFW.FIELD_OFFSET_SUBSCRIBE, writeBuffer.capacity()); } public MqttSubscribeFlushExBuilder packetId( @@ -860,34 +914,6 @@ public byte[] build() } } - public static final class MqttOffsetMetadataBuilder - { - private final MqttOffsetMetadataFW.Builder offsetMetadataRW = new MqttOffsetMetadataFW.Builder(); - - byte version = 1; - - - private MqttOffsetMetadataBuilder() - { - MutableDirectBuffer writeBuffer = new UnsafeBuffer(new byte[1024 * 8]); - offsetMetadataRW.wrap(writeBuffer, 0, writeBuffer.capacity()); - offsetMetadataRW.version(version); - } - - public MqttOffsetMetadataBuilder metadata( - int packetId) - { - offsetMetadataRW.appendPacketIds((short) packetId); - return this; - } - - public String build() - { - final MqttOffsetMetadataFW offsetMetadata = offsetMetadataRW.build(); - return BitUtil.toHex(offsetMetadata.buffer().byteArray(), offsetMetadata.offset(), offsetMetadata.limit()); - } - } - public static final class MqttWillMessageBuilder { private final MqttWillMessageFW.Builder willMessageRW = new MqttWillMessageFW.Builder(); @@ -1434,14 +1460,17 @@ private boolean matchFilters( public final class MqttSessionBeginExMatcherBuilder { private String16FW clientId; + private List packetIds; private Integer expiry; private Integer flags; private Integer capabilities; - private Integer qosMax; + private Integer subscribeQosMax; + private int publishQosMax; private Integer packetSizeMax; private MqttSessionBeginExMatcherBuilder() { + packetIds = new ArrayList<>(); } public MqttSessionBeginExMatcherBuilder clientId( @@ -1458,10 +1487,24 @@ public MqttSessionBeginExMatcherBuilder expiry( return this; } - public MqttSessionBeginExMatcherBuilder qosMax( - int qosMax) + public MqttSessionBeginExMatcherBuilder packetId( + int packetId) { - this.qosMax = qosMax; + this.packetIds.add(packetId); + return this; + } + + public MqttSessionBeginExMatcherBuilder subscribeQosMax( + int subscribeQosMax) + { + this.subscribeQosMax = subscribeQosMax; + return this; + } + + public MqttSessionBeginExMatcherBuilder publishQosMax( + int publishQosMax) + { + this.publishQosMax = publishQosMax; return this; } @@ -1501,8 +1544,9 @@ private boolean match( final MqttSessionBeginExFW sessionBeginEx = beginEx.session(); return matchFlags(sessionBeginEx) && matchClientId(sessionBeginEx) && + matchPacketIds(sessionBeginEx) && matchExpiry(sessionBeginEx) && - matchQosMax(sessionBeginEx) && + matchSubscribeQosMax(sessionBeginEx) && matchPacketSizeMax(sessionBeginEx) && matchCapabilities(sessionBeginEx); } @@ -1513,10 +1557,23 @@ private boolean matchClientId( return clientId == null || clientId.equals(sessionBeginEx.clientId()); } - private boolean matchQosMax( + private boolean matchPacketIds( + final MqttSessionBeginExFW sessionBeginEx) + { + final PrimitiveIterator.OfInt ids = sessionBeginEx.packetIds(); + + boolean match = packetIds == null || packetIds.isEmpty(); + while (!match && ids.hasNext()) + { + match = packetIds.contains(ids.nextInt()); + } + return match; + } + + private boolean matchSubscribeQosMax( final MqttSessionBeginExFW sessionBeginEx) { - return qosMax == null || qosMax == sessionBeginEx.qosMax(); + return subscribeQosMax == null || subscribeQosMax == sessionBeginEx.subscribeQosMax(); } private boolean matchPacketSizeMax( @@ -1853,6 +1910,7 @@ public final class MqttPublishDataExMatcherBuilder private final DirectBuffer correlationRO = new UnsafeBuffer(0, 0); private Integer qos; private Integer flags; + private Integer packetId; private Integer expiryInterval = -1; private String16FW contentType; private MqttPayloadFormatFW format; @@ -1887,6 +1945,13 @@ public MqttPublishDataExMatcherBuilder flags( return this; } + public MqttPublishDataExMatcherBuilder packetId( + int packetId) + { + this.packetId = packetId; + return this; + } + public MqttPublishDataExMatcherBuilder expiryInterval( int expiryInterval) { @@ -1967,6 +2032,7 @@ private boolean match( return matchDeferred(publishDataEx) && matchQos(publishDataEx) && matchFlags(publishDataEx) && + matchPacketId(publishDataEx) && matchExpiryInterval(publishDataEx) && matchContentType(publishDataEx) && matchFormat(publishDataEx) && @@ -1993,6 +2059,12 @@ private boolean matchFlags( return flags == null || flags == data.flags(); } + private boolean matchPacketId( + final MqttPublishDataExFW data) + { + return packetId == null || packetId == data.packetId(); + } + private boolean matchExpiryInterval( final MqttPublishDataExFW data) { @@ -2031,6 +2103,113 @@ private boolean matchUserProperties( } } + public static final class MqttFlushExMatcherBuilder + { + private final DirectBuffer bufferRO = new UnsafeBuffer(); + + private final MqttFlushExFW flushExRo = new MqttFlushExFW(); + + private Integer typeId; + private Integer kind; + private Predicate caseMatcher; + + public MqttSessionFlushExMatcherBuilder session() + { + final MqttSessionFlushExMatcherBuilder matcherBuilder = new MqttSessionFlushExMatcherBuilder(); + + this.kind = MqttExtensionKind.SESSION.value(); + this.caseMatcher = matcherBuilder::match; + return matcherBuilder; + } + + public MqttFlushExMatcherBuilder typeId( + int typeId) + { + this.typeId = typeId; + return this; + } + + public BytesMatcher build() + { + return typeId != null || kind != null ? this::match : buf -> null; + } + + private MqttFlushExFW match( + ByteBuffer byteBuf) throws Exception + { + if (!byteBuf.hasRemaining()) + { + return null; + } + + bufferRO.wrap(byteBuf); + final MqttFlushExFW flushEx = flushExRo.tryWrap(bufferRO, byteBuf.position(), byteBuf.capacity()); + + if (flushEx != null && + matchTypeId(flushEx) && + matchKind(flushEx) && + matchCase(flushEx)) + { + byteBuf.position(byteBuf.position() + flushEx.sizeof()); + return flushEx; + } + + throw new Exception(flushEx.toString()); + } + + private boolean matchTypeId( + final MqttFlushExFW flushEx) + { + return typeId == null || typeId == flushEx.typeId(); + } + + private boolean matchKind( + final MqttFlushExFW flushEx) + { + return kind == null || kind == flushEx.kind(); + } + + private boolean matchCase( + final MqttFlushExFW flushEx) throws Exception + { + return caseMatcher == null || caseMatcher.test(flushEx); + } + + public final class MqttSessionFlushExMatcherBuilder + { + private Integer packetId; + + private MqttSessionFlushExMatcherBuilder() + { + } + + public MqttSessionFlushExMatcherBuilder packetId( + int packetId) + { + this.packetId = packetId; + return this; + } + + public MqttFlushExMatcherBuilder build() + { + return MqttFlushExMatcherBuilder.this; + } + + private boolean match( + MqttFlushExFW flushEx) + { + final MqttSessionFlushExFW sessionFlushEx = flushEx.session(); + return matchPacketId(sessionFlushEx); + } + + private boolean matchPacketId( + final MqttSessionFlushExFW flush) + { + return packetId == null || packetId == flush.packetId(); + } + } + } + public static class Mapper extends FunctionMapperSpi.Reflective { public Mapper() diff --git a/specs/binding-mqtt.spec/src/main/resources/META-INF/zilla/mqtt.idl b/specs/binding-mqtt.spec/src/main/resources/META-INF/zilla/mqtt.idl index 8cb6978488..26730b7747 100644 --- a/specs/binding-mqtt.spec/src/main/resources/META-INF/zilla/mqtt.idl +++ b/specs/binding-mqtt.spec/src/main/resources/META-INF/zilla/mqtt.idl @@ -156,10 +156,13 @@ scope mqtt { uint8 flags = 0; int32 expiry = 0; - uint16 qosMax = 0; + uint16 subscribeQosMax = 0; + uint16 publishQosMax = 0; uint32 packetSizeMax = 0; uint8 capabilities = 0; string16 clientId; + int8 length; + int16[length] packetIds = null; } struct MqttSubscribeBeginEx @@ -205,6 +208,7 @@ scope mqtt int32 deferred = 0; // INIT only (TODO: move to DATA frame) uint8 qos = 0; uint8 flags = 0; + uint16 packetId = 0; int32 expiryInterval = -1; string16 contentType = null; MqttPayloadFormat format = NONE; @@ -235,6 +239,12 @@ scope mqtt union MqttFlushEx switch (uint8) extends core::stream::Extension { case 1: mqtt::stream::MqttSubscribeFlushEx subscribe; + case 2: mqtt::stream::MqttSessionFlushEx session; + } + + struct MqttSessionFlushEx + { + uint16 packetId = 0; } struct MqttSubscribeFlushEx @@ -251,11 +261,5 @@ scope mqtt INCOMPLETE(1) } - struct MqttOffsetMetadata - { - uint8 version = 1; - uint8 length; - int16[length] packetIds; - } } } diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/client.rpt index b771dafd37..6364266fa4 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/server.rpt index b5555172b2..26e83a2ab5 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/client.sent.abort/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.delegate.connack.properties/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.delegate.connack.properties/client.rpt index 88889bceaa..c40045ddeb 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.delegate.connack.properties/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.delegate.connack.properties/client.rpt @@ -31,7 +31,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .session() .flags("CLEAN_START") .expiry(0) - .qosMax(0) + .subscribeQosMax(0) .packetSizeMax(50) .clientId("client-1") .build() diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.delegate.connack.properties/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.delegate.connack.properties/server.rpt index 12aed590e7..dfdbce6c48 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.delegate.connack.properties/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.delegate.connack.properties/server.rpt @@ -33,7 +33,7 @@ write zilla:begin.ext ${mqtt:beginEx() .session() .flags("CLEAN_START") .expiry(0) - .qosMax(0) + .subscribeQosMax(0) .packetSizeMax(50) .clientId("client-1") .build() diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/client.rpt index ed7f767334..dd1f786658 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(50) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/server.rpt index 315bdcb778..0ad5bd74ac 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.max.packet.size.exceeded/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(50) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.maximum.qos.0/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.maximum.qos.0/client.rpt index c8ed292659..aab12b50c1 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.maximum.qos.0/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.maximum.qos.0/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(0) + .subscribeQosMax(0) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.maximum.qos.0/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.maximum.qos.0/server.rpt index 7492f9ab3e..3a405bdfc9 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.maximum.qos.0/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.maximum.qos.0/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(0) + .subscribeQosMax(0) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.disconnect/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.disconnect/client.rpt index 365e9bb357..6d28a51db8 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.disconnect/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.disconnect/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.disconnect/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.disconnect/server.rpt index e3b9ad7f5f..61743454bb 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.disconnect/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.non.successful.disconnect/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.reject.will.retain.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.reject.will.retain.not.supported/client.rpt index 4902ad1d9b..0c064accae 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.reject.will.retain.not.supported/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.reject.will.retain.not.supported/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.reject.will.retain.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.reject.will.retain.not.supported/server.rpt index bac2170456..d5ea02814f 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.reject.will.retain.not.supported/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.reject.will.retain.not.supported/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.retain.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.retain.not.supported/client.rpt index dc21bb3d5d..ec6e3a4ef7 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.retain.not.supported/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.retain.not.supported/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.retain.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.retain.not.supported/server.rpt index f94abcde9e..417c798e8a 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.retain.not.supported/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/connect.retain.not.supported/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/disconnect.after.subscribe.and.publish/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/disconnect.after.subscribe.and.publish/client.rpt index 152b4defb9..bff7b12332 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/disconnect.after.subscribe.and.publish/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/disconnect.after.subscribe.and.publish/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/disconnect.after.subscribe.and.publish/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/disconnect.after.subscribe.and.publish/server.rpt index 9efec7dc01..27c0e9894a 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/disconnect.after.subscribe.and.publish/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/disconnect.after.subscribe.and.publish/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.10k/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.10k/client.rpt index 609e09c1ec..ee3aedb394 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.10k/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.10k/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.10k/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.10k/server.rpt index a7718f5940..ede4b66df7 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.10k/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.10k/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/client.rpt index 9aff694e50..e4095349c7 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/server.rpt index bda65ca1bd..b2aa6b4baa 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.message/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/client.rpt index f72e494334..135c2b1627 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/server.rpt index c4e8bd3cbf..3fe24c4d94 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.empty.retained.message/server.rpt @@ -33,7 +33,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/client.rpt index bd3c03ccb5..3e0da6e53e 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/server.rpt index 1985238c24..43a600bab2 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.message.with.topic.alias/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/client.rpt index 78c686fb6e..e01510fff9 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/server.rpt index 5a00d9a593..a978b46735 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.distinct/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/client.rpt index 17b4d208ce..d75da00da8 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/server.rpt index af8fb2059f..8e3d8d2955 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.invalid.scope/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -87,7 +87,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client2") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/client.rpt index 8d8a2ff12c..0b815f902c 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/server.rpt index dbe9ebc13d..2c6bdfc015 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.repeated/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/client.rpt index db91f65323..c8da04d36f 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/server.rpt index 2f9653d000..d7021f1b9d 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.messages.with.topic.alias.replaced/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.mixture.qos/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.mixture.qos/client.rpt index 5b4629bd7b..61890af08e 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.mixture.qos/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.mixture.qos/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -42,6 +42,20 @@ connected read zilla:data.empty read notify RECEIVED_SESSION_STATE +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + connect await RECEIVED_SESSION_STATE "zilla://streams/app0" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.mixture.qos/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.mixture.qos/server.rpt index 3b23dfdc5b..fb46b4ceb8 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.mixture.qos/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.mixture.qos/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -44,6 +44,21 @@ connected write zilla:data.empty write flush +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + + accepted read zilla:begin.ext ${mqtt:matchBeginEx() diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.clients/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.clients/client.rpt index f7fca6e853..8aa78bb727 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.clients/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.clients/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client-1") @@ -89,7 +89,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client-2") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.clients/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.clients/server.rpt index e7dddbbc99..7f30cac1d1 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.clients/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.clients/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client-1") @@ -59,7 +59,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client-2") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages.timeout/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages.timeout/client.rpt index e74dacf5a2..1ebe11fb55 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages.timeout/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages.timeout/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages.timeout/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages.timeout/server.rpt index 5a04de02e6..cf35fd4e73 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages.timeout/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages.timeout/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/client.rpt index 5006c59363..4ce978cd51 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/server.rpt index 14fc69b797..0f5527bd63 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.multiple.messages/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.properties/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.properties/client.rpt index f15914b23e..3e3389fa33 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.properties/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.properties/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.properties/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.properties/server.rpt index 946782638d..4ee206b05f 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.properties/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.one.message.properties/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos1.dup.after.puback/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos1.dup.after.puback/client.rpt index 901bfc458c..fc1613e1fc 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos1.dup.after.puback/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos1.dup.after.puback/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos1.dup.after.puback/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos1.dup.after.puback/server.rpt index 710c97ed02..951caddb35 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos1.dup.after.puback/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos1.dup.after.puback/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.ack.with.reasoncode/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.ack.with.reasoncode/client.rpt index 5b56e99d4f..7c5d6cf006 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.ack.with.reasoncode/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.ack.with.reasoncode/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -42,6 +42,20 @@ connected read zilla:data.empty read notify RECEIVED_SESSION_STATE +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + connect await RECEIVED_SESSION_STATE "zilla://streams/app0" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.ack.with.reasoncode/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.ack.with.reasoncode/server.rpt index 1e5d66822a..d45a074fbc 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.ack.with.reasoncode/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.ack.with.reasoncode/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -44,6 +44,21 @@ connected write zilla:data.empty write flush +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + + accepted read zilla:begin.ext ${mqtt:matchBeginEx() diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.no.dupicate.before.pubrel/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.no.dupicate.before.pubrel/client.rpt index 5b56e99d4f..7c5d6cf006 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.no.dupicate.before.pubrel/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.no.dupicate.before.pubrel/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -42,6 +42,20 @@ connected read zilla:data.empty read notify RECEIVED_SESSION_STATE +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + connect await RECEIVED_SESSION_STATE "zilla://streams/app0" diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.no.dupicate.before.pubrel/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.no.dupicate.before.pubrel/server.rpt index 8f8700feb0..474b3e7e64 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.no.dupicate.before.pubrel/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.no.dupicate.before.pubrel/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -44,6 +44,21 @@ connected write zilla:data.empty write flush +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + + accepted read zilla:begin.ext ${mqtt:matchBeginEx() diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.recovery/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.recovery/client.rpt new file mode 100644 index 0000000000..bdeea89b10 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.recovery/client.rpt @@ -0,0 +1,58 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .subscribeQosMax(2) + .capabilities("RETAIN", "SUBSCRIPTION_IDS", "WILDCARD", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .packetId(1) + .packetId(2) + .packetId(3) + .build() + .build()} + +connected + +read zilla:data.empty + +# Triggered by PUBREL +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.recovery/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.recovery/server.rpt new file mode 100644 index 0000000000..754c2746d2 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.qos2.recovery/server.rpt @@ -0,0 +1,63 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/app0" + option zilla:window 8192 + option zilla:transmission "duplex" + +accepted + +read zilla:begin.ext ${mqtt:matchBeginEx() + .typeId(zilla:id("mqtt")) + .session() + .flags("CLEAN_START") + .clientId("client") + .build() + .build()} + +write zilla:begin.ext ${mqtt:beginEx() + .typeId(zilla:id("mqtt")) + .session() + .subscribeQosMax(2) + .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") + .clientId("client") + .packetId(1) + .packetId(2) + .packetId(3) + .build() + .build()} + +connected + +write zilla:data.empty +write flush + +read advised zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + +write advise zilla:flush ${mqtt:flushEx() + .typeId(zilla:id("mqtt")) + .session() + .packetId(1) + .build() + .build()} + + + diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.large.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.large.message/client.rpt index 0bb0fb4f0a..0f2c175c72 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.large.message/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.large.message/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.large.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.large.message/server.rpt index c7bed4e1ce..afb88e0716 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.large.message/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.large.message/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.qos.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.qos.not.supported/client.rpt index df76616097..57aa676b9d 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.qos.not.supported/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.qos.not.supported/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(0) + .subscribeQosMax(0) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.qos.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.qos.not.supported/server.rpt index 58cb238a7b..544de8fc3b 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.qos.not.supported/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.qos.not.supported/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(0) + .subscribeQosMax(0) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.retain.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.retain.not.supported/client.rpt index c7fbd6eb15..e91bb67055 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.retain.not.supported/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.retain.not.supported/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities(WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.retain.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.retain.not.supported/server.rpt index 6a569d5c82..75b2922373 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.retain.not.supported/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.reject.retain.not.supported/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/client.rpt index 9212801e9c..af4572e6ae 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/server.rpt index 5b3acac928..4e9f74acdb 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.retained/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.subscribe.batched/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.subscribe.batched/client.rpt index 03703f0489..174476d2d5 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.subscribe.batched/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.subscribe.batched/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.subscribe.batched/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.subscribe.batched/server.rpt index e98bd7250e..53f718055e 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.subscribe.batched/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.subscribe.batched/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.unroutable/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.unroutable/client.rpt index 5d145d66d2..c320d8da63 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.unroutable/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.unroutable/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.unroutable/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.unroutable/server.rpt index 3740651d71..7da3fc82e9 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.unroutable/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.unroutable/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.valid.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.valid.message/client.rpt index 92ba7e6735..ee091b154c 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.valid.message/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.valid.message/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.valid.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.valid.message/server.rpt index d07e0738d8..5d56222518 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.valid.message/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.valid.message/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/client.rpt index 7375f857b6..1ec36e0807 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/server.rpt index 462f3d08af..c4c13f0315 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.distinct/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/client.rpt index c0d527d820..1b08738955 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/server.rpt index 84b66de991..e53051d4bb 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.properties.repeated/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/client.rpt index c52c4f3dea..6965c126ab 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/server.rpt index d3925f6b6e..c7581f5668 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/publish.with.user.property/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("755452d5-e2ef-4113-b9c6-2f53de96fd76") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/client.rpt index c3f946b238..12238e3d1e 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -94,7 +94,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/server.rpt index a258abfbfc..0e92c5b8aa 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.abort.reconnect.non.clean.start/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -89,7 +89,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/client.rpt index 665d70433e..5510810418 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -95,7 +95,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/server.rpt index e5d9fa5a7d..3c74c7e45b 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.client.takeover/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -93,7 +93,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.abort/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.abort/client.rpt index d3980ce8ec..706fe66a81 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.abort/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.abort/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.abort/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.abort/server.rpt index 62685691f2..76ca3601f9 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.abort/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.abort/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.authorization/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.authorization/client.rpt index fdb49465b2..4a9638e8da 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.authorization/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.authorization/client.rpt @@ -31,7 +31,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.authorization/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.authorization/server.rpt index bd2eb8ff17..5dd753719d 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.authorization/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.authorization/server.rpt @@ -33,7 +33,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.override.session.expiry/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.override.session.expiry/client.rpt index 30750fea4a..1d9ca21058 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.override.session.expiry/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.override.session.expiry/client.rpt @@ -31,7 +31,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .session() .flags("CLEAN_START") .expiry(30) - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client-1") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.override.session.expiry/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.override.session.expiry/server.rpt index 1357014205..5596eb6ee0 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.override.session.expiry/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.override.session.expiry/server.rpt @@ -33,7 +33,7 @@ write zilla:begin.ext ${mqtt:beginEx() .session() .flags("CLEAN_START") .expiry(30) - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client-1") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.redirect.support/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.redirect.support/client.rpt index 5d5d85aa20..346b2b59d3 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.redirect.support/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.redirect.support/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS", "REDIRECT") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.redirect.support/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.redirect.support/server.rpt index 04f0dfd5ba..f34fba7b7f 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.redirect.support/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.redirect.support/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS", "REDIRECT") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/client.rpt index 66bf8e17ec..b515e8cc74 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("one") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/server.rpt index d6679679de..447a459379 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect.with.session.expiry/server.rpt @@ -33,7 +33,7 @@ write zilla:begin.ext ${mqtt:beginEx() .session() .flags("CLEAN_START") .expiry(1) - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("one") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect/client.rpt index a8cb8971ee..d4e95f8d07 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect/server.rpt index 62685691f2..76ca3601f9 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.connect/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/client.rpt index cdfbf8a24c..a084768629 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -99,7 +99,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/server.rpt index 991300b37e..7d5cd23034 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.exists.clean.start/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -93,7 +93,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.after.connack/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.after.connack/client.rpt index 6b7b0ceec6..d758fcb964 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.after.connack/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.after.connack/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.after.connack/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.after.connack/server.rpt index ec97e6429e..98bb0363f3 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.after.connack/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.after.connack/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.before.connack/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.before.connack/client.rpt index e4e3a14673..738bd0d94d 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.before.connack/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.before.connack/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.before.connack/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.before.connack/server.rpt index 20e60a236f..36f807ed77 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.before.connack/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.invalid.session.timeout.before.connack/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.publish/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.publish/client.rpt index 39b659f0e0..3763d572a6 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.publish/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.publish/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.publish/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.publish/server.rpt index c8af42e786..73b79fb79b 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.publish/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.publish/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.after.connack/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.after.connack/client.rpt index 08ea0b183e..e96d972a90 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.after.connack/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.after.connack/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.after.connack/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.after.connack/server.rpt index 4e3e92d69f..38607b3e67 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.after.connack/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.after.connack/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.before.connack/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.before.connack/client.rpt index 90137a930e..9819844bca 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.before.connack/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.before.connack/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.before.connack/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.before.connack/server.rpt index c14f65f6a6..517aedb68e 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.before.connack/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.redirect.before.connack/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.sent.abort/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.sent.abort/client.rpt index 2ebe37fed5..ff262c1ac9 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.sent.abort/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.sent.abort/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.sent.abort/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.sent.abort/server.rpt index 8fcf49a343..5e795bd2bb 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.sent.abort/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.server.sent.abort/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.multiple.isolated/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.multiple.isolated/client.rpt index 389b218e61..05fbfda3d0 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.multiple.isolated/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.multiple.isolated/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.multiple.isolated/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.multiple.isolated/server.rpt index c6c5002735..1d03c4dbbd 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.multiple.isolated/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.multiple.isolated/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.publish.routing/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.publish.routing/client.rpt index d41cdfa57d..b29fabab6b 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.publish.routing/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.publish.routing/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.publish.routing/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.publish.routing/server.rpt index 985adbda51..57f1238b19 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.publish.routing/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.publish.routing/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/client.rpt index 6e5c555867..d937db9857 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/server.rpt index d4b61821c8..2784d15424 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe.via.session.state/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/client.rpt index 50208fb289..bfe3e5967c 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/server.rpt index 17011ced85..614473660a 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.subscribe/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/client.rpt index d1bee0322d..1d2eeb3cc2 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/server.rpt index fc39b40d0c..f8a2ed3549 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe.deferred/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/client.rpt index 5cc4d09b24..47f831e755 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/server.rpt index 3c5d0b4ff6..2f7e60007a 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.after.subscribe/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/client.rpt index b6130c77ac..c2a4f7ec48 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/server.rpt index d2c62d1ad3..68d9488e9e 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.unsubscribe.via.session.state/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.10k/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.10k/client.rpt index 4a152d86dc..45dd0d19f3 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.10k/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.10k/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("WILL", "CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("one") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.10k/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.10k/server.rpt index 223664f487..5a880179c4 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.10k/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.10k/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("WILL", "CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("one") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.abort/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.abort/client.rpt index 2facc6a8a7..a9abc78bf6 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.abort/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.abort/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("WILL", "CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("one") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.abort/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.abort/server.rpt index af34a7f078..5e421d77c5 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.abort/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.abort/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("WILL", "CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("one") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/client.rpt index b12bdaf584..2fc07513ff 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("WILL", "CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("one") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/server.rpt index 0623c3adfa..3f2a2bc32b 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.normal.disconnect/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("WILL", "CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("one") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/client.rpt index 49a8c2b24c..1b2fd00874 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/client.rpt @@ -46,7 +46,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("WILL", "CLEAN_START") - .qosMax(0) + .subscribeQosMax(0) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") .clientId("one") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/server.rpt index a189ab5691..21def7c9b1 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/session.will.message.retain/server.rpt @@ -48,7 +48,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("WILL", "CLEAN_START") - .qosMax(0) + .subscribeQosMax(0) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") .clientId("one") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/client.rpt index 2b7df6d001..872fca805e 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/server.rpt index 68efdb3ecf..9052346f06 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.get.retained.as.published/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt index 4bdff3a5f6..feb314aed0 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt index 639fd94f52..7b1d2cb205 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.receive.response.topic.and.correlation.data/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/client.rpt index 345092dba3..b65ba0d319 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/server.rpt index c71af4e41d..36eb537daf 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message.user.properties.unaltered/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/client.rpt index e667b900af..d0b232f0e6 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/server.rpt index da2b521046..c71a476fe2 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.one.message/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/client.rpt index c0bc2759ca..cb77b476c5 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/server.rpt index cddcae8682..160afffa8a 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.publish.no.local/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/client.rpt index ea318306af..5d57863666 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/client.rpt @@ -31,7 +31,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client-1") @@ -91,7 +91,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client-2") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/server.rpt index 755712b684..f7e3a2ac38 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.publish.retained.no.replay/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client-1") @@ -82,7 +82,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client-2") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/client.rpt index 0c193373c8..9c0502ce98 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/client.rpt @@ -31,7 +31,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client1") @@ -91,7 +91,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client2") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/server.rpt index 2c5e931635..4020f80cfc 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.qos0.replay.retained.no.packet.id/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client1") @@ -82,7 +82,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client2") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard.mixed.qos/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard.mixed.qos/client.rpt index 0f18d42f0c..800eb6a018 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard.mixed.qos/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard.mixed.qos/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard.mixed.qos/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard.mixed.qos/server.rpt index 03f34496ea..ce3e3fbb98 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard.mixed.qos/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard.mixed.qos/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/client.rpt index 57b9d982c7..c7b6da24a5 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/server.rpt index 960ab1b1e1..f29007652c 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.overlapping.wildcard/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos1/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos1/client.rpt index bdb0c80613..0aa2419763 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos1/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos1/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos1/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos1/server.rpt index f54a65c0b8..f61539f25a 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos1/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos1/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos2/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos2/client.rpt index 16e7377343..2b3db0347b 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos2/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos2/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos2/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos2/server.rpt index 4d757bf89e..30597f6e5d 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos2/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos0.published.qos2/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1.published.qos2/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1.published.qos2/client.rpt index 76b277efeb..b595b01da0 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1.published.qos2/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1.published.qos2/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1.published.qos2/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1.published.qos2/server.rpt index f3faaab253..9d2e1f587e 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1.published.qos2/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1.published.qos2/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1/client.rpt index 38fe077bf3..bffd7e51f4 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1/server.rpt index c7059330d5..689832c23c 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos1/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos2/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos2/client.rpt index f2ead70a57..5948168442 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos2/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos2/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos2/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos2/server.rpt index 2a0712e505..84124b3024 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos2/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.qos2/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/client.rpt index b61bc0f9f4..787b2fb4a8 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/server.rpt index 2ce1853bdb..6f716cf77c 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message.wildcard/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/client.rpt index e98a052a22..faea365a10 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/server.rpt index a9e75a71ef..7739bfae9d 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.message/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.mixture.qos/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.mixture.qos/client.rpt index 4ae46c8f26..46afb2d16c 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.mixture.qos/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.mixture.qos/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.mixture.qos/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.mixture.qos/server.rpt index 6f080adc52..15205cf5ed 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.mixture.qos/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.mixture.qos/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.topic.alias.repeated/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.topic.alias.repeated/client.rpt index 23f8c0df6a..7ef648bd5f 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.topic.alias.repeated/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.topic.alias.repeated/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.topic.alias.repeated/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.topic.alias.repeated/server.rpt index d91fcf9c07..a0f6aa0b3e 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.topic.alias.repeated/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.receive.messages.topic.alias.repeated/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.publish.no.subscription/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.publish.no.subscription/client.rpt index 9606660cb6..403a6e7a25 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.publish.no.subscription/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.publish.no.subscription/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.publish.no.subscription/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.publish.no.subscription/server.rpt index be569d49e7..cd91e9b8aa 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.publish.no.subscription/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.publish.no.subscription/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos1.unacked.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos1.unacked.message/client.rpt index 470a1c9ac3..5b9ad149cc 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos1.unacked.message/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos1.unacked.message/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -127,7 +127,7 @@ write zilla:begin.ext ${mqtt:beginEx() read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos1.unacked.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos1.unacked.message/server.rpt index 043cc582c7..651f17b6c6 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos1.unacked.message/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos1.unacked.message/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -118,7 +118,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.incomplete.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.incomplete.message/client.rpt index 78558f2300..f31fe43584 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.incomplete.message/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.incomplete.message/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -155,7 +155,7 @@ write zilla:begin.ext ${mqtt:beginEx() read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.incomplete.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.incomplete.message/server.rpt index 95a23a20d3..26780e4619 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.incomplete.message/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.incomplete.message/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -143,7 +143,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.unreceived.message/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.unreceived.message/client.rpt index 65994cc20c..dcecdc7da5 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.unreceived.message/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.unreceived.message/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -146,7 +146,7 @@ write zilla:begin.ext ${mqtt:beginEx() read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.unreceived.message/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.unreceived.message/server.rpt index 77a5fdd975..8f812311d1 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.unreceived.message/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reconnect.replay.qos2.unreceived.message/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") @@ -134,7 +134,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.shared.subscriptions.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.shared.subscriptions.not.supported/client.rpt index 23f920f17a..502e0151bf 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.shared.subscriptions.not.supported/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.shared.subscriptions.not.supported/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.shared.subscriptions.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.shared.subscriptions.not.supported/server.rpt index 3167305bbe..bc9e682451 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.shared.subscriptions.not.supported/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.shared.subscriptions.not.supported/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.subscription.ids.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.subscription.ids.not.supported/client.rpt index 4a57d637db..707ad620fb 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.subscription.ids.not.supported/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.subscription.ids.not.supported/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.subscription.ids.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.subscription.ids.not.supported/server.rpt index dbb15859eb..52b3a8ace6 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.subscription.ids.not.supported/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.subscription.ids.not.supported/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.wildcard.subscriptions.not.supported/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.wildcard.subscriptions.not.supported/client.rpt index b3ba629994..d9cee97b78 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.wildcard.subscriptions.not.supported/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.wildcard.subscriptions.not.supported/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.wildcard.subscriptions.not.supported/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.wildcard.subscriptions.not.supported/server.rpt index fffe14919d..b5d041e6a6 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.wildcard.subscriptions.not.supported/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.reject.wildcard.subscriptions.not.supported/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1.v4/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1.v4/client.rpt index 78f539ab4c..1aacd9180b 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1.v4/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1.v4/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1.v4/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1.v4/server.rpt index 90a55c5b9a..ce5d89ac72 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1.v4/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1.v4/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1/client.rpt index a43531b2f4..78c5e58c4f 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1/server.rpt index f443af16c4..21dafd084b 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos1/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2.v4/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2.v4/client.rpt index cb17fffa99..ac1479c5ca 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2.v4/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2.v4/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2.v4/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2.v4/server.rpt index 69081b70c3..e39b71bfb4 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2.v4/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2.v4/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2/client.rpt index dcb5b0e6aa..f36bbedf63 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2/server.rpt index ccd38c90da..a96406d0c2 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.replay.retained.message.qos2/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/client.rpt index fda2157214..5b18f30548 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/server.rpt index c2e06f5318..93abfceef8 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.retain.as.published/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/client.rpt index b951e2bb3a..6c12edcbba 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/server.rpt index cc1cd82e72..c1d3e835c9 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.multi.level.wildcard/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt index 1490553b89..c15989b169 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt index 282d76ed86..b46a12553f 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.and.multi.level.wildcard/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/client.rpt index 7c1e2dfd88..03c0811b59 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/server.rpt index 2466432741..4ac4e900e5 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.exact/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/client.rpt index f335981ee2..ee7d7777ca 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/server.rpt index bf02ff67e7..ed5194aaa6 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.single.level.wildcard/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/client.rpt index 16b2c4eb6a..6f704f0c80 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/server.rpt index aa8d721d09..7077b12957 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filter.two.single.level.wildcard/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/client.rpt index e278ab0b80..afd5bd3a8c 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/server.rpt index 9c08aa337f..c4e4b38be2 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.both.exact/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt index 0097dac0d8..50fc6e9339 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt index 3e9fdd654e..7f0628afb0 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.aggregated.exact.and.wildcard/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/client.rpt index 7acbbffd8c..8c5f5a7a3a 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/server.rpt index 52fc4d003f..a5462a8520 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.disjoint.wildcards/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/client.rpt index db6e337a9e..a0a9bba262 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/server.rpt index 60a9dd2299..464d8e3a18 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.exact/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/client.rpt index 38baf06562..3e6743dbc4 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/server.rpt index b4443804fb..44a700fe23 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.both.wildcard/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt index 2a9725217a..05484623c7 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt index 9e67c51a43..cf1f5a0200 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.isolated.exact.and.wildcard/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.non.successful/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.non.successful/client.rpt index 80715eb608..08f2000cc3 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.non.successful/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.non.successful/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.non.successful/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.non.successful/server.rpt index a895e567ba..83c2080681 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.non.successful/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.non.successful/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/client.rpt index de67a971f1..bed9a5becb 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/server.rpt index 55a060d9f6..048aedf5e3 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.topic.filters.overlapping.wildcards/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.unroutable/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.unroutable/client.rpt index e2bd0f7a94..b55f589b79 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.unroutable/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.unroutable/client.rpt @@ -29,7 +29,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.unroutable/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.unroutable/server.rpt index ab045dc44b..b5ba625e7e 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.unroutable/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/subscribe.unroutable/server.rpt @@ -31,7 +31,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/client.rpt index aa530f336d..7a56c44233 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/server.rpt index 6ac847b2ef..bbce97e4c3 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.after.subscribe/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/client.rpt index 71995c567e..ab43377785 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/server.rpt index bdaa42e5c4..8417c7e658 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.aggregated.topic.filters.both.exact/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/client.rpt index 59f3936622..42b63bb4bb 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/server.rpt index 44d9254d3e..07399f3a0e 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.publish.unfragmented/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/client.rpt index 084eaf6b68..6ba9da3bb0 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/server.rpt index 5227e3d6b5..b94f10e6b6 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filter.single/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filters.non.successful/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filters.non.successful/client.rpt index dee38fef29..1e0bc70078 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filters.non.successful/client.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filters.non.successful/client.rpt @@ -30,7 +30,7 @@ read zilla:begin.ext ${mqtt:matchBeginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filters.non.successful/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filters.non.successful/server.rpt index 78a6d6f6b7..8623dc2504 100644 --- a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filters.non.successful/server.rpt +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/application/unsubscribe.topic.filters.non.successful/server.rpt @@ -32,7 +32,7 @@ write zilla:begin.ext ${mqtt:beginEx() .typeId(zilla:id("mqtt")) .session() .flags("CLEAN_START") - .qosMax(2) + .subscribeQosMax(2) .packetSizeMax(66560) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS", "SHARED_SUBSCRIPTIONS") .clientId("client") diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/v5/publish.qos2.recovery/client.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/v5/publish.qos2.recovery/client.rpt new file mode 100644 index 0000000000..207794b986 --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/v5/publish.qos2.recovery/client.rpt @@ -0,0 +1,45 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +connect "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +connected + +write [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +read [0x20 0x03] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x00] # properties + +write [0x62 0x04] # PUBREL + [0x00 0x01] # packet id = 1 + [0x00] # reason code + [0x00] # properties + +read [0x70 0x03] # PUBCOMP + [0x00 0x01] # packet id = 1 + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/v5/publish.qos2.recovery/server.rpt b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/v5/publish.qos2.recovery/server.rpt new file mode 100644 index 0000000000..83feb8fe4f --- /dev/null +++ b/specs/binding-mqtt.spec/src/main/scripts/io/aklivity/zilla/specs/binding/mqtt/streams/network/v5/publish.qos2.recovery/server.rpt @@ -0,0 +1,46 @@ +# +# Copyright 2021-2023 Aklivity Inc. +# +# Aklivity licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +accept "zilla://streams/net0" + option zilla:window 8192 + option zilla:transmission "duplex" + option zilla:byteorder "network" + +accepted +connected + +read [0x10 0x18] # CONNECT + [0x00 0x04] "MQTT" # protocol name + [0x05] # protocol version + [0x02] # flags = clean start + [0x00 0x3c] # keep alive = 60s + [0x05] # properties + [0x27] 66560 # maximum packet size = 66560 + [0x00 0x06] "client" # client id + +write [0x20 0x03] # CONNACK + [0x00] # flags = none + [0x00] # reason code + [0x00] # properties = none + +read [0x62 0x04] # PUBREL + [0x00 0x01] # packet id = 1 + [0x00] # reason code + [0x00] # properties + +write [0x70 0x03] # PUBCOMP + [0x00 0x01] # packet id = 1 + [0x00] # reason code diff --git a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctionsTest.java b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctionsTest.java index 1fbdbd3129..ca08c29173 100644 --- a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctionsTest.java +++ b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/internal/MqttFunctionsTest.java @@ -23,11 +23,8 @@ import java.nio.ByteBuffer; import java.util.Objects; -import java.util.function.IntConsumer; -import org.agrona.BitUtil; import org.agrona.DirectBuffer; -import org.agrona.collections.IntArrayList; import org.agrona.concurrent.UnsafeBuffer; import org.junit.Test; import org.kaazing.k3po.lang.el.BytesMatcher; @@ -40,7 +37,6 @@ import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttBeginExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttDataExFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttFlushExFW; -import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttOffsetMetadataFW; import io.aklivity.zilla.specs.binding.mqtt.internal.types.stream.MqttResetExFW; public class MqttFunctionsTest @@ -68,10 +64,12 @@ public void shouldEncodeMqttSessionBeginExt() .session() .flags("WILL", "CLEAN_START") .expiry(30) - .qosMax(1) + .subscribeQosMax(1) + .publishQosMax(1) .packetSizeMax(100) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") .clientId("client") + .packetId(1) .build() .build(); @@ -81,10 +79,12 @@ public void shouldEncodeMqttSessionBeginExt() assertEquals(2, mqttBeginEx.kind()); assertEquals("client", mqttBeginEx.session().clientId().asString()); assertEquals(30, mqttBeginEx.session().expiry()); - assertEquals(1, mqttBeginEx.session().qosMax()); + assertEquals(1, mqttBeginEx.session().subscribeQosMax()); + assertEquals(1, mqttBeginEx.session().publishQosMax()); assertEquals(100, mqttBeginEx.session().packetSizeMax()); assertEquals(7, mqttBeginEx.session().capabilities()); assertEquals(6, mqttBeginEx.session().flags()); + assertEquals(1, mqttBeginEx.session().packetIds().nextInt()); } @Test @@ -298,10 +298,12 @@ public void shouldMatchSessionBeginExtension() throws Exception .session() .flags("CLEAN_START") .expiry(10) - .qosMax(1) + .subscribeQosMax(1) + .publishQosMax(1) .packetSizeMax(100) .capabilities("RETAIN", "WILDCARD", "SUBSCRIPTION_IDS") .clientId("client") + .packetId(1) .build() .build(); @@ -313,10 +315,12 @@ public void shouldMatchSessionBeginExtension() throws Exception .session(s -> s .flags(2) .expiry(10) - .qosMax(1) + .subscribeQosMax(1) + .publishQosMax(1) .packetSizeMax(100) .capabilities(7) - .clientId("client")) + .clientId("client") + .appendPacketIds((short) 1)) .build(); assertNotNull(matcher.match(byteBuf)); @@ -799,6 +803,7 @@ public void shouldMatchPublishDataExtension() throws Exception .deferred(100) .qos("AT_MOST_ONCE") .flags("RETAIN") + .packetId(1) .expiryInterval(20) .contentType("message") .format("TEXT") @@ -818,6 +823,7 @@ public void shouldMatchPublishDataExtension() throws Exception p.deferred(100); p.qos(0); p.flags(1); + p.packetId(1); p.expiryInterval(20); p.contentType("message"); p.format(f -> f.set(MqttPayloadFormat.TEXT)); @@ -895,6 +901,7 @@ public void shouldEncodeMqttPublishDataEx() .typeId(0) .publish() .deferred(100) + .packetId(1) .expiryInterval(15) .contentType("message") .format("TEXT") @@ -909,6 +916,7 @@ public void shouldEncodeMqttPublishDataEx() assertEquals(0, mqttPublishDataEx.typeId()); assertEquals(100, mqttPublishDataEx.publish().deferred()); + assertEquals(1, mqttPublishDataEx.publish().packetId()); assertEquals(15, mqttPublishDataEx.publish().expiryInterval()); assertEquals("message", mqttPublishDataEx.publish().contentType().asString()); assertEquals("TEXT", mqttPublishDataEx.publish().format().toString()); @@ -1197,6 +1205,43 @@ public void shouldEncodeMqttSubscribeFlushExOffsetCommit() assertEquals(1, mqttFlushEx.subscribe().state()); } + @Test + public void shouldEncodeMqttSessionFlushEx() + { + final byte[] array = MqttFunctions.flushEx() + .typeId(0) + .session() + .packetId(1) + .build() + .build(); + + DirectBuffer buffer = new UnsafeBuffer(array); + MqttFlushExFW mqttFlushEx = new MqttFlushExFW().wrap(buffer, 0, buffer.capacity()); + + assertEquals(0, mqttFlushEx.typeId()); + assertEquals(1, mqttFlushEx.session().packetId()); + } + + @Test + public void shouldMatchMqttPublishFlushEx() throws Exception + { + BytesMatcher matcher = MqttFunctions.matchFlushEx() + .session() + .packetId(1) + .build() + .build(); + + ByteBuffer byteBuf = ByteBuffer.allocate(1024); + + new MqttFlushExFW.Builder() + .wrap(new UnsafeBuffer(byteBuf), 0, byteBuf.capacity()) + .typeId(0x00) + .session(p -> p.packetId(1)) + .build(); + + assertNotNull(matcher.match(byteBuf)); + } + @Test public void shouldEncodeMqttSubscribeFlushExChangeFilter() { @@ -1244,6 +1289,8 @@ public void shouldEncodeMqttSessionState() .subscription("sensor/one", 1, "AT_LEAST_ONCE", "SEND_RETAINED") .subscriptionWithReasonCode("sensor/two", 1, 0) .subscription("sensor/three", 1, "EXACTLY_ONCE", "SEND_RETAINED") + .subscription("sensor/four", 1) + .subscription("sensor/five") .build(); DirectBuffer buffer = new UnsafeBuffer(array); @@ -1270,24 +1317,15 @@ public void shouldEncodeMqttSessionState() 1 == f.subscriptionId() && 2 == f.qos() && 0b0001 == f.flags())); - } - @Test - public void shouldEncodeMqttOffsetMetadata() - { - final String state = MqttFunctions.metadata() - .metadata(1) - .metadata(2) - .build(); - - final IntArrayList metadataList = new IntArrayList(); - UnsafeBuffer buffer = new UnsafeBuffer(BitUtil.fromHex(state)); - MqttOffsetMetadataFW offsetMetadata = new MqttOffsetMetadataFW().wrap(buffer, 0, buffer.capacity()); - offsetMetadata.packetIds().forEachRemaining((IntConsumer) metadataList::add); + assertNotNull(sessionState.subscriptions() + .matchFirst(f -> + "sensor/four".equals(f.pattern().asString()) && + 1 == f.subscriptionId())); - assertEquals(1, offsetMetadata.version()); - assertEquals(1, (int) metadataList.get(0)); - assertEquals(2, (int) metadataList.get(1)); + assertNotNull(sessionState.subscriptions() + .matchFirst(f -> + "sensor/five".equals(f.pattern().asString()))); } @Test diff --git a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/PublishIT.java b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/PublishIT.java index ee228dbeb5..4e170660ec 100644 --- a/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/PublishIT.java +++ b/specs/binding-mqtt.spec/src/test/java/io/aklivity/zilla/specs/binding/mqtt/streams/application/PublishIT.java @@ -226,6 +226,15 @@ public void shouldPublishQoS2MessageAckWithReasoncode() throws Exception k3po.finish(); } + @Test + @Specification({ + "${app}/publish.qos2.recovery/client", + "${app}/publish.qos2.recovery/server"}) + public void shouldReleaseQos2PacketIdDuringRecovery() throws Exception + { + k3po.finish(); + } + @Test @Specification({ "${app}/publish.mixture.qos/client",