Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public class ClientOffsetCommitIT
.directory("target/zilla-itests")
.countersBufferCapacity(8192)
.configurationRoot("io/aklivity/zilla/specs/binding/kafka/config")
.configure("zilla.binding.kafka.client.connection.pool", "false")
.configure("zilla.binding.kafka.client.api.versions", "false")
.external("net0")
.clean();

Expand Down Expand Up @@ -87,4 +89,54 @@ public void shouldHandleOffsetCommitError() throws Exception
{
k3po.finish();
}

@Test
@Configuration("client.yaml")
@Specification({
"${app}/bare.commit/client",
"${net}/bare.commit/server"})
public void shouldCommitBareOffset() throws Exception
{
k3po.finish();
}

@Test
@Configuration("client.yaml")
@Specification({
"${app}/reset.offsets.dead/client",
"${net}/reset.offsets.dead/server"})
public void shouldResetOffsetsForDeadGroup() throws Exception
{
k3po.finish();
}

@Test
@Configuration("client.yaml")
@Specification({
"${app}/find.then.describe/client",
"${net}/find.then.describe/server"})
public void shouldChainFindCoordinatorThenDescribeGroups() throws Exception
{
k3po.finish();
}

@Test
@Configuration("client.yaml")
@Specification({
"${app}/find.coordinator.only/client",
"${net}/find.coordinator.only/server"})
public void shouldFindCoordinatorOnly() throws Exception
{
k3po.finish();
}

@Test
@Configuration("client.yaml")
@Specification({
"${app}/find.then.describe.no.wait/client",
"${net}/find.then.describe/server"})
public void shouldChainFindCoordinatorThenDescribeGroupsNoWait() throws Exception
{
k3po.finish();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9041,16 +9041,23 @@ private void advanceToOffsetCommit(
traceId, authorization, affinity, kafkaBeginEx);
}

/**
* Only the reply of the stage currently in flight closes the MCP reply; the previous stage's
* reply END arrives after {@link #advanceToOffsetCommit} has already opened the next stream.
*/
private void onKafkaEnd(
EndFW end)
{
final long traceId = end.traceId();

state = McpKafkaState.closedReply(state);

if (stage == STAGE_OFFSET_COMMIT && mcpBegun)
if (end.streamId() == kafkaReplyId)
{
peer.doMcpEnd(traceId);
state = McpKafkaState.closedReply(state);

if (stage == STAGE_OFFSET_COMMIT && mcpBegun)
{
peer.doMcpEnd(traceId);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,16 @@ public void shouldResetOffsetsCoordinatorNotFound() throws Exception
k3po.finish();
}

@Test
@Configuration("client.reset.offsets.yaml")
@Specification({
"${mcp}/reset.offsets.dead/client",
"${kafka}/reset.offsets.dead/server"})
public void shouldResetOffsetsForDeadGroup() throws Exception
{
k3po.finish();
}

@Test
@Configuration("client.describe.consumer.group.lag.yaml")
@Specification({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#
# Copyright 2021-2026 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 "half-duplex"

write zilla:begin.ext ${kafka:beginEx()
.typeId(zilla:id("kafka"))
.offsetCommit()
.groupId("orders-analytics")
.memberId("")
.instanceId("")
.host("broker1.example.com")
.port(9092)
.build()
.build()}

connected

write zilla:data.ext ${kafka:dataEx()
.typeId(zilla:id("kafka"))
.offsetCommit()
.topic("orders")
.progress(0, 100, "")
.generationId(-1)
.leaderEpoch(-1)
.build()
.build()}

write zilla:data.empty
write flush
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#
# Copyright 2021-2026 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 "half-duplex"
option zilla:byteorder "network"

write zilla:begin.ext ${kafka:beginEx()
.typeId(zilla:id("kafka"))
.apiRequest()
.length(12)
.api(10)
.version(3)
.clientId("zilla")
.build()
.build()}

connected

write [0x00] # request header tagged fields
[0x09] "my-group" # group id (key)
[0x00] # key type (group)
[0x00] # tagged fields

read zilla:begin.ext ${kafka:matchBeginEx()
.typeId(zilla:id("kafka"))
.apiResponse()
.length(25)
.version(3)
.build()
.build()}

read [0x00] # tagged fields
0 # throttle time ms
0s # error code
[0x00] # message (null)
1 # node id
[0x08] "broker1" # host
9092 # port
[0x00] # tagged fields

write close
read closed
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#
# Copyright 2021-2026 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.
#

# Mirrors McpKafkaProxyFactory's KafkaApiResetOffsetsClient: it ends the
# FindCoordinator stream and opens the DescribeGroups stream in the same
# synchronous call, without waiting for the END to be acknowledged first.

connect "zilla://streams/app0"
option zilla:window 8192
option zilla:transmission "half-duplex"
option zilla:byteorder "network"

write zilla:begin.ext ${kafka:beginEx()
.typeId(zilla:id("kafka"))
.apiRequest()
.length(12)
.api(10)
.version(3)
.clientId("zilla")
.build()
.build()}

connected

write [0x00] # request header tagged fields
[0x09] "my-group" # group id (key)
[0x00] # key type (group)
[0x00] # tagged fields

read zilla:begin.ext ${kafka:matchBeginEx()
.typeId(zilla:id("kafka"))
.apiResponse()
.length(25)
.version(3)
.build()
.build()}

read [0x00] # tagged fields
0 # throttle time ms
0s # error code
[0x00] # message (null)
1 # node id
[0x08] "broker1" # host
9092 # port
[0x00] # tagged fields

write close

connect "zilla://streams/app0"
option zilla:window 8192
option zilla:transmission "half-duplex"
option zilla:byteorder "network"

write zilla:begin.ext ${kafka:beginEx()
.typeId(zilla:id("kafka"))
.apiRequest()
.length(13)
.api(15)
.version(5)
.clientId("zilla")
.build()
.build()}

connected

write [0x00] # request header tagged fields
[0x02] # group count
[0x09] "my-group" # group id
[0x00] # include authorized operations
[0x00] # tagged fields

read zilla:begin.ext ${kafka:matchBeginEx()
.typeId(zilla:id("kafka"))
.apiResponse()
.length(31)
.version(5)
.build()
.build()}

read [0x00] # tagged fields
0 # throttle time ms
[0x02] # groups
0s # error code
[0x09] "my-group" # group id
[0x05] "Dead" # group state (never had members)
[0x01] # protocol type (empty)
[0x01] # protocol data (empty)
[0x01] # members (none)
[0xff 0xff 0xff 0xff] # authorized operations (-1)
[0x00] # group tagged fields
[0x00] # tagged fields

write close
read closed
Loading
Loading