Merge pull request #74 from p2p-org/debug-null-nativecall-result

trying to find null in response
This commit is contained in:
a10zn8
2022-12-09 18:01:50 +04:00
committed by GitHub
9 changed files with 45 additions and 40 deletions

View File

@@ -116,7 +116,7 @@ abstract class BaseHandler(
// If Proxy is configured to preserve original order it means that a client expect responses at exact same position // If Proxy is configured to preserve original order it means that a client expect responses at exact same position
// as requests even if a request completely failed for a some reason. It's very unlikely situation, but still possible // as requests even if a request completely failed for a some reason. It's very unlikely situation, but still possible
// At this case, if we found a gap in responses, we put a default response with an error // At this case, if we found a gap in responses, we put a default response with an error
?: NativeCall.CallResult(id, null, null, NativeCall.CallError(id, "No response", null), null, null) ?: NativeCall.CallResult(id, null, null, NativeCall.CallError(id, "No response", null), null, null, null)
} }
} }
.flatMapMany { .flatMapMany {

View File

@@ -181,7 +181,7 @@ class WebsocketHandler(
} }
Mono.just(response) Mono.just(response)
.map { Global.objectMapper.writeValueAsString(it) } .map { Global.objectMapper.writeValueAsString(it) }
.doOnNext { eventHandler.onResponse(NativeCall.CallResult.ok(0, null, it.toByteArray(), null, null)) } .doOnNext { eventHandler.onResponse(NativeCall.CallResult.ok(0, null, it.toByteArray(), null, null, null)) }
.doFinally { eventHandler.close() } .doFinally { eventHandler.close() }
} else { } else {
val eventHandler: AccessHandlerHttp.RequestHandler = eventHandlerFactory.call() val eventHandler: AccessHandlerHttp.RequestHandler = eventHandlerFactory.call()

View File

@@ -25,7 +25,7 @@ import reactor.core.publisher.Mono
* Composition of multiple readers. * Composition of multiple readers.
* Reader returns first value returned by any of the source readers by checking one by one until one of them returns a non-empty result. * Reader returns first value returned by any of the source readers by checking one by one until one of them returns a non-empty result.
*/ */
class CompoundReader<K, D>( class CompoundReader<K, D> (
private vararg val readers: Reader<K, D> private vararg val readers: Reader<K, D>
) : Reader<K, D> { ) : Reader<K, D> {

View File

@@ -98,7 +98,7 @@ open class NativeCall(
val error = it.getError() val error = it.getError()
Mono.just( Mono.just(
CallResult(error.id, 0, null, error, null, null) CallResult(error.id, 0, null, error, null, null, null)
) )
} }
} }
@@ -119,6 +119,9 @@ open class NativeCall(
result.setErrorMessage(error.message).setErrorCode(error.id) result.setErrorMessage(error.message).setErrorCode(error.id)
} }
} else { } else {
if (it.result == null || it.result.isEmpty()) {
log.warn("Empty result on building response, method ${it.ctx?.payload?.method}, params ${it.ctx?.payload?.params}")
}
result.payload = ByteString.copyFrom(it.result) result.payload = ByteString.copyFrom(it.result)
} }
if (it.nonce != null && it.signature != null) { if (it.nonce != null && it.signature != null) {
@@ -275,9 +278,9 @@ open class NativeCall(
.map { .map {
validateResult(it, "local", ctx) validateResult(it, "local", ctx)
if (ctx.nonce != null) { if (ctx.nonce != null) {
CallResult.ok(ctx.id, ctx.nonce, it, signer.sign(ctx.nonce, it, ctx.upstream.getId()), ctx.upstream.getId()) CallResult.ok(ctx.id, ctx.nonce, it, signer.sign(ctx.nonce, it, ctx.upstream.getId()), ctx.upstream.getId(), ctx)
} else { } else {
CallResult.ok(ctx.id, null, it, null, ctx.upstream.getId()) CallResult.ok(ctx.id, null, it, null, ctx.upstream.getId(), ctx)
} }
} }
}.switchIfEmpty( }.switchIfEmpty(
@@ -285,9 +288,9 @@ open class NativeCall(
) )
.onErrorResume { .onErrorResume {
if (it is CallFailure) { if (it is CallFailure) {
Mono.just(CallResult.fail(it.id, ctx.nonce, it.reason)) Mono.just(CallResult.fail(it.id, ctx.nonce, it.reason, ctx))
} else { } else {
Mono.just(CallResult.fail(ctx.id, ctx.nonce, it)) Mono.just(CallResult.fail(ctx.id, ctx.nonce, it, ctx))
} }
} }
} }
@@ -309,13 +312,13 @@ open class NativeCall(
.map { .map {
val bytes = ctx.resultDecorator.processResult(it) val bytes = ctx.resultDecorator.processResult(it)
validateResult(bytes, "remote", ctx) validateResult(bytes, "remote", ctx)
CallResult.ok(ctx.id, ctx.nonce, bytes, it.signature, ctx.upstream.getId()) CallResult.ok(ctx.id, ctx.nonce, bytes, it.signature, ctx.upstream.getId(), ctx)
} }
.onErrorResume { t -> .onErrorResume { t ->
val failure = when (t) { val failure = when (t) {
is CallFailure -> CallResult.fail(t.id, ctx.nonce, t.reason) is CallFailure -> CallResult.fail(t.id, ctx.nonce, t.reason, ctx)
is JsonRpcException -> CallResult.fail(ctx.id, ctx.nonce, t.error.code, t.error.message) is JsonRpcException -> CallResult.fail(ctx.id, ctx.nonce, t.error.code, t.error.message, ctx)
else -> CallResult.fail(ctx.id, ctx.nonce, t) else -> CallResult.fail(ctx.id, ctx.nonce, t, ctx)
} }
Mono.just(failure) Mono.just(failure)
} }
@@ -326,7 +329,8 @@ open class NativeCall(
ctx.id, ctx.id,
ctx.nonce, ctx.nonce,
1, 1,
errorMessage(attempts, ctx.payload.method) errorMessage(attempts, ctx.payload.method),
ctx
).also { ).also {
countFailure(attempts, ctx) countFailure(attempts, ctx)
} }
@@ -503,19 +507,20 @@ open class NativeCall(
val result: ByteArray?, val result: ByteArray?,
val error: CallError?, val error: CallError?,
val signature: ResponseSigner.Signature?, val signature: ResponseSigner.Signature?,
val upstreamId: String? val upstreamId: String?,
val ctx: ValidCallContext<ParsedCallDetails>?
) { ) {
companion object { companion object {
fun ok(id: Int, nonce: Long?, result: ByteArray, signature: ResponseSigner.Signature?, upstreamId: String?): CallResult { fun ok(id: Int, nonce: Long?, result: ByteArray, signature: ResponseSigner.Signature?, upstreamId: String?, ctx: ValidCallContext<ParsedCallDetails>?): CallResult {
return CallResult(id, nonce, result, null, signature, upstreamId) return CallResult(id, nonce, result, null, signature, upstreamId, ctx)
} }
fun fail(id: Int, nonce: Long?, errorCore: Int, errorMessage: String): CallResult { fun fail(id: Int, nonce: Long?, errorCore: Int, errorMessage: String, ctx: ValidCallContext<ParsedCallDetails>?): CallResult {
return CallResult(id, nonce, null, CallError(errorCore, errorMessage, null), null, null) return CallResult(id, nonce, null, CallError(errorCore, errorMessage, null), null, null, ctx)
} }
fun fail(id: Int, nonce: Long?, error: Throwable): CallResult { fun fail(id: Int, nonce: Long?, error: Throwable, ctx: ValidCallContext<ParsedCallDetails>?): CallResult {
return CallResult(id, nonce, null, CallError.from(error), null, null) return CallResult(id, nonce, null, CallError.from(error), null, null, ctx)
} }
} }

View File

@@ -62,7 +62,7 @@ class BaseHandlerSpec extends Specification {
def call = new ProxyCall(ProxyCall.RpcType.SINGLE) def call = new ProxyCall(ProxyCall.RpcType.SINGLE)
call.items.add(request) call.items.add(request)
call.ids[0] = 5 call.ids[0] = 5
def response = new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, null) def response = new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, null, null)
when: when:
def act = Flux.from(handler.execute(Chain.ETHEREUM, call, requestHandler, false)) def act = Flux.from(handler.execute(Chain.ETHEREUM, call, requestHandler, false))
.collectList() .collectList()
@@ -85,7 +85,7 @@ class BaseHandlerSpec extends Specification {
def call = new ProxyCall(ProxyCall.RpcType.BATCH) def call = new ProxyCall(ProxyCall.RpcType.BATCH)
call.items.add(request) call.items.add(request)
call.ids[0] = 5 call.ids[0] = 5
def response = new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, null) def response = new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, null, null)
when: when:
def act = Flux.from(handler.execute(Chain.ETHEREUM, call, requestHandler, false)) def act = Flux.from(handler.execute(Chain.ETHEREUM, call, requestHandler, false))
.collectList() .collectList()
@@ -116,8 +116,8 @@ class BaseHandlerSpec extends Specification {
call.items.add(request2) call.items.add(request2)
call.ids[1] = 6 call.ids[1] = 6
def response = [ def response = [
new NativeCall.CallResult(1, null, '{"foo": 2}'.bytes, null, null, null), new NativeCall.CallResult(1, null, '{"foo": 2}'.bytes, null, null, null, null),
new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, null) new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, null, null)
] ]
when: when:
def act = Flux.from(handler.execute(Chain.ETHEREUM, call, requestHandler, true)) def act = Flux.from(handler.execute(Chain.ETHEREUM, call, requestHandler, true))
@@ -149,8 +149,8 @@ class BaseHandlerSpec extends Specification {
call.items.add(request2) call.items.add(request2)
call.ids[1] = 6 call.ids[1] = 6
def response = [ def response = [
new NativeCall.CallResult(1, null, '{"foo": 2}'.bytes, null, null, null), new NativeCall.CallResult(1, null, '{"foo": 2}'.bytes, null, null, null, null),
new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, null) new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, null, null)
] ]
when: when:
def act = Flux.from(handler.execute(Chain.ETHEREUM, call, requestHandler, true)) def act = Flux.from(handler.execute(Chain.ETHEREUM, call, requestHandler, true))
@@ -189,8 +189,8 @@ class BaseHandlerSpec extends Specification {
// note there is only 2 responses // note there is only 2 responses
def response = [ def response = [
new NativeCall.CallResult(1, null, '{"foo": 2}'.bytes, null, null, null), new NativeCall.CallResult(1, null, '{"foo": 2}'.bytes, null, null, null, null),
new NativeCall.CallResult(2, null, '{"foo": 3}'.bytes, null, null, null) new NativeCall.CallResult(2, null, '{"foo": 3}'.bytes, null, null, null, null)
] ]
when: when:
def act = Flux.from(handler.execute(Chain.ETHEREUM, call, requestHandler, true)) def act = Flux.from(handler.execute(Chain.ETHEREUM, call, requestHandler, true))

View File

@@ -43,7 +43,7 @@ class HttpHandlerSpec extends Specification {
.setMethod("test_test") .setMethod("test_test")
.setPayload(ByteString.copyFromUtf8("[]")) .setPayload(ByteString.copyFromUtf8("[]"))
.build() .build()
def respItem = new NativeCall.CallResult(1, null, "100".bytes, null, null, null) def respItem = new NativeCall.CallResult(1, null, "100".bytes, null, null, null, null)
def req = BlockchainOuterClass.NativeCallRequest.newBuilder() def req = BlockchainOuterClass.NativeCallRequest.newBuilder()
.setChain(Common.ChainRef.CHAIN_ETHEREUM) .setChain(Common.ChainRef.CHAIN_ETHEREUM)
.addItems(reqItem) .addItems(reqItem)
@@ -129,7 +129,7 @@ class HttpHandlerSpec extends Specification {
def act = handler.execute(Chain.ETHEREUM, call, new AccessHandlerHttp.NoOpHandler(), false) def act = handler.execute(Chain.ETHEREUM, call, new AccessHandlerHttp.NoOpHandler(), false)
then: then:
1 * nativeCall.nativeCallResult(_) >> Flux.just(new NativeCall.CallResult(1, null, "".bytes, null, null, null)) 1 * nativeCall.nativeCallResult(_) >> Flux.just(new NativeCall.CallResult(1, null, "".bytes, null, null, null, null))
StepVerifier.create(act) StepVerifier.create(act)
.expectNext("hello") .expectNext("hello")
.expectComplete() .expectComplete()

View File

@@ -85,7 +85,7 @@ class WebsocketHandlerSpec extends Specification {
def "Respond to a single call"() { def "Respond to a single call"() {
setup: setup:
def response = new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, "test") def response = new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, "test", null)
def nativeCall = Mock(NativeCall) { def nativeCall = Mock(NativeCall) {
1 * it.nativeCallResult(_) >> Flux.fromIterable([response]) 1 * it.nativeCallResult(_) >> Flux.fromIterable([response])

View File

@@ -85,7 +85,7 @@ class WriteRpcJsonSpec extends Specification {
def call = new ProxyCall(ProxyCall.RpcType.SINGLE) def call = new ProxyCall(ProxyCall.RpcType.SINGLE)
call.ids[1] = 105 call.ids[1] = 105
def data = [ def data = [
new NativeCall.CallResult(1, null, '"0x98dbb1"'.bytes, null, null, null) new NativeCall.CallResult(1, null, '"0x98dbb1"'.bytes, null, null, null, null)
] ]
when: when:
def act = writer.toJson(call, data[0]) def act = writer.toJson(call, data[0])
@@ -98,7 +98,7 @@ class WriteRpcJsonSpec extends Specification {
def call = new ProxyCall(ProxyCall.RpcType.SINGLE) def call = new ProxyCall(ProxyCall.RpcType.SINGLE)
call.ids[1] = 1 call.ids[1] = 1
def data = [ def data = [
new NativeCall.CallResult(1, null, null, new NativeCall.CallError(1, "Internal Error", null), null, null) new NativeCall.CallResult(1, null, null, new NativeCall.CallError(1, "Internal Error", null), null, null, null)
] ]
when: when:
def act = writer.toJson(call, data[0]) def act = writer.toJson(call, data[0])
@@ -111,7 +111,7 @@ class WriteRpcJsonSpec extends Specification {
def call = new ProxyCall(ProxyCall.RpcType.SINGLE) def call = new ProxyCall(ProxyCall.RpcType.SINGLE)
call.ids[1] = "aaa" call.ids[1] = "aaa"
def data = [ def data = [
new NativeCall.CallResult(1, null, '"0x98dbb1"'.bytes, null, null, null) new NativeCall.CallResult(1, null, '"0x98dbb1"'.bytes, null, null, null, null)
] ]
when: when:
def act = writer.toJson(call, data[0]) def act = writer.toJson(call, data[0])
@@ -126,9 +126,9 @@ class WriteRpcJsonSpec extends Specification {
call.ids[2] = 11 call.ids[2] = 11
call.ids[3] = 15 call.ids[3] = 15
def data = [ def data = [
new NativeCall.CallResult(1, null, '"0x98dbb1"'.bytes, null, null, null), new NativeCall.CallResult(1, null, '"0x98dbb1"'.bytes, null, null, null, null),
new NativeCall.CallResult(2, null, null, new NativeCall.CallError(2, "oops", null), null, null), new NativeCall.CallResult(2, null, null, new NativeCall.CallError(2, "oops", null), null, null, null),
new NativeCall.CallResult(3, null, '{"hash": "0x2484f459dc"}'.bytes, null, null, null), new NativeCall.CallResult(3, null, '{"hash": "0x2484f459dc"}'.bytes, null, null, null, null),
] ]
when: when:
def act = Flux.fromIterable(data) def act = Flux.fromIterable(data)
@@ -154,7 +154,7 @@ class WriteRpcJsonSpec extends Specification {
def call = new ProxyCall(ProxyCall.RpcType.SINGLE) def call = new ProxyCall(ProxyCall.RpcType.SINGLE)
call.ids[1] = 10 call.ids[1] = 10
def data = [ def data = [
new NativeCall.CallResult(1, null, '"0x1"'.bytes, null, null, null), new NativeCall.CallResult(1, null, '"0x1"'.bytes, null, null, null, null),
] ]
when: when:
def act = Flux.fromIterable(data) def act = Flux.fromIterable(data)

View File

@@ -193,7 +193,7 @@ class NativeCallSpec extends Specification {
when: when:
def resp = nativeCall.buildResponse( def resp = nativeCall.buildResponse(
new NativeCall.CallResult(1561, 10, objectMapper.writeValueAsBytes(json), null, null, null) new NativeCall.CallResult(1561, 10, objectMapper.writeValueAsBytes(json), null, null, null, null)
) )
then: then:
resp.id == 1561 resp.id == 1561
@@ -208,7 +208,7 @@ class NativeCallSpec extends Specification {
when: when:
def resp = nativeCall.buildResponse( def resp = nativeCall.buildResponse(
new NativeCall.CallResult(1561, 10, objectMapper.writeValueAsBytes(json), null, new ResponseSigner.Signature("sig1".bytes, "test", 100), "test") new NativeCall.CallResult(1561, 10, objectMapper.writeValueAsBytes(json), null, new ResponseSigner.Signature("sig1".bytes, "test", 100), "test", null)
) )
then: then:
resp.id == 1561 resp.id == 1561