mirror of
https://github.com/corda/corda.git
synced 2025-06-21 08:40:03 +00:00
Add RPC deduplication to client and server
This commit is contained in:
@ -19,6 +19,7 @@ import org.apache.activemq.artemis.api.core.SimpleString
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import rx.Observable
|
||||
@ -127,7 +128,7 @@ class RPCStabilityTests {
|
||||
rpcDriver {
|
||||
fun startAndCloseServer(broker: RpcBrokerHandle) {
|
||||
startRpcServerWithBrokerRunning(
|
||||
configuration = RPCServerConfiguration.default.copy(consumerPoolSize = 1, producerPoolBound = 1),
|
||||
configuration = RPCServerConfiguration.default,
|
||||
ops = DummyOps,
|
||||
brokerHandle = broker
|
||||
).rpcServer.close()
|
||||
@ -148,7 +149,7 @@ class RPCStabilityTests {
|
||||
@Test
|
||||
fun `rpc client close doesnt leak broker resources`() {
|
||||
rpcDriver {
|
||||
val server = startRpcServer(configuration = RPCServerConfiguration.default.copy(consumerPoolSize = 1, producerPoolBound = 1), ops = DummyOps).get()
|
||||
val server = startRpcServer(configuration = RPCServerConfiguration.default, ops = DummyOps).get()
|
||||
RPCClient<RPCOps>(server.broker.hostAndPort!!).start(RPCOps::class.java, rpcTestUser.username, rpcTestUser.password).close()
|
||||
val initial = server.broker.getStats()
|
||||
repeat(100) {
|
||||
@ -337,11 +338,12 @@ class RPCStabilityTests {
|
||||
val request = RPCApi.ClientToServer.RpcRequest(
|
||||
clientAddress = SimpleString(myQueue),
|
||||
methodName = SlowConsumerRPCOps::streamAtInterval.name,
|
||||
serialisedArguments = listOf(10.millis, 123456).serialize(context = SerializationDefaults.RPC_SERVER_CONTEXT).bytes,
|
||||
serialisedArguments = listOf(10.millis, 123456).serialize(context = SerializationDefaults.RPC_SERVER_CONTEXT),
|
||||
replyId = Trace.InvocationId.newInstance(),
|
||||
sessionId = Trace.SessionId.newInstance()
|
||||
)
|
||||
request.writeToClientMessage(message)
|
||||
message.putLongProperty(RPCApi.DEDUPLICATION_SEQUENCE_NUMBER_FIELD_NAME, 0)
|
||||
producer.send(message)
|
||||
session.commit()
|
||||
|
||||
@ -350,6 +352,46 @@ class RPCStabilityTests {
|
||||
}
|
||||
}
|
||||
|
||||
interface StreamOps : RPCOps {
|
||||
fun stream(streamInterval: Duration): Observable<Long>
|
||||
}
|
||||
class StreamOpsImpl : StreamOps {
|
||||
override val protocolVersion = 0
|
||||
override fun stream(streamInterval: Duration): Observable<Long> {
|
||||
return Observable.interval(streamInterval.toNanos(), TimeUnit.NANOSECONDS)
|
||||
}
|
||||
}
|
||||
@Ignore("This is flaky as sometimes artemis delivers out of order messages after the kick")
|
||||
@Test
|
||||
fun `deduplication on the client side`() {
|
||||
rpcDriver {
|
||||
val server = startRpcServer(ops = StreamOpsImpl()).getOrThrow()
|
||||
val proxy = startRpcClient<StreamOps>(
|
||||
server.broker.hostAndPort!!,
|
||||
configuration = RPCClientConfiguration.default.copy(
|
||||
connectionRetryInterval = 1.days // switch off failover
|
||||
)
|
||||
).getOrThrow()
|
||||
// Find the internal address of the client
|
||||
val clientAddress = server.broker.serverControl.addressNames.find { it.startsWith(RPCApi.RPC_CLIENT_QUEUE_NAME_PREFIX) }
|
||||
val events = ArrayList<Long>()
|
||||
// Start streaming an incrementing value 2000 times per second from the server.
|
||||
val subscription = proxy.stream(streamInterval = Duration.ofNanos(500_000)).subscribe {
|
||||
events.add(it)
|
||||
}
|
||||
// These sleeps are *fine*, the invariant should hold regardless of any delays
|
||||
Thread.sleep(50)
|
||||
// Kick the client. This seems to trigger redelivery of (presumably non-acked) messages.
|
||||
server.broker.serverControl.closeConsumerConnectionsForAddress(clientAddress)
|
||||
Thread.sleep(50)
|
||||
subscription.unsubscribe()
|
||||
for (i in 0 until events.size) {
|
||||
require(events[i] == i.toLong()) {
|
||||
"Events not incremental, possible duplicate, ${events[i]} != ${i.toLong()}\nExpected: ${(0..i).toList()}\nGot : $events\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun RPCDriverDSL.pollUntilClientNumber(server: RpcServerHandle, expected: Int) {
|
||||
|
Reference in New Issue
Block a user