This is an automated email from the ASF dual-hosted git repository.
toulmean pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-tuweni.git
The following commit(s) were added to refs/heads/main by this push:
new b7e5e7c Add caching to app
new 761b3e8 Merge pull request #330 from atoulme/add_caching_to_app
b7e5e7c is described below
commit b7e5e7c636b647ba9a71cbe8a5d948e3d3b05956
Author: Antoine Toulme <[email protected]>
AuthorDate: Fri Jul 30 22:17:12 2021 -0700
Add caching to app
---
jsonrpc-app/build.gradle | 3 ++
.../org/apache/tuweni/jsonrpc/app/JSONRPCApp.kt | 52 +++++++++++++++++++++-
.../org/apache/tuweni/jsonrpc/app/JSONRPCConfig.kt | 8 ++++
3 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/jsonrpc-app/build.gradle b/jsonrpc-app/build.gradle
index 9c1037f..61441fd 100644
--- a/jsonrpc-app/build.gradle
+++ b/jsonrpc-app/build.gradle
@@ -21,6 +21,7 @@ dependencies {
implementation project(':concurrent')
implementation project(':eth')
implementation project(':jsonrpc')
+ implementation project(':kv')
implementation project(':metrics')
implementation project(':net')
implementation project(':units')
@@ -40,6 +41,8 @@ dependencies {
implementation 'io.opentelemetry:opentelemetry-sdk-metrics'
implementation 'javax.servlet:javax.servlet-api'
implementation 'org.bouncycastle:bcprov-jdk15on'
+ implementation 'org.infinispan:infinispan-core'
+ implementation 'org.infinispan:infinispan-cachestore-rocksdb'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core'
implementation 'org.slf4j:slf4j-api'
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
diff --git
a/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCApp.kt
b/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCApp.kt
index 2cc0453..3d10d92 100644
--- a/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCApp.kt
+++ b/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCApp.kt
@@ -16,20 +16,36 @@
*/
package org.apache.tuweni.jsonrpc.app
+import com.fasterxml.jackson.databind.ObjectMapper
import io.vertx.core.Vertx
import io.vertx.core.VertxOptions
import io.vertx.tracing.opentelemetry.OpenTelemetryOptions
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.runBlocking
import org.apache.tuweni.eth.internalError
+import org.apache.tuweni.bytes.Bytes
+import org.apache.tuweni.eth.JSONRPCResponse
import org.apache.tuweni.jsonrpc.JSONRPCClient
import org.apache.tuweni.jsonrpc.JSONRPCServer
+import org.apache.tuweni.jsonrpc.methods.CachingHandler
import org.apache.tuweni.jsonrpc.methods.MeteredHandler
import org.apache.tuweni.jsonrpc.methods.MethodAllowListHandler
+import org.apache.tuweni.jsonrpc.methods.ThrottlingHandler
+import org.apache.tuweni.kv.InfinispanKeyValueStore
import org.apache.tuweni.metrics.MetricsService
import org.apache.tuweni.net.ip.IPRangeChecker
import org.apache.tuweni.net.tls.VertxTrustOptions
import org.bouncycastle.jce.provider.BouncyCastleProvider
+import org.infinispan.Cache
+import org.infinispan.commons.dataconversion.MediaType
+import org.infinispan.commons.io.ByteBuffer
+import org.infinispan.commons.io.ByteBufferImpl
+import org.infinispan.commons.marshall.AbstractMarshaller
+import org.infinispan.configuration.cache.ConfigurationBuilder
+import org.infinispan.configuration.global.GlobalConfigurationBuilder
+import org.infinispan.manager.DefaultCacheManager
+import org.infinispan.marshall.persistence.PersistenceMarshaller
+import
org.infinispan.persistence.rocksdb.configuration.RocksDBStoreConfigurationBuilder
import org.slf4j.LoggerFactory
import java.nio.file.Paths
import java.security.Security
@@ -93,7 +109,26 @@ class JSONRPCApplication(
val successCounter = meter.longCounterBuilder("success").build()
val failureCounter = meter.longCounterBuilder("failure").build()
- val handler = MeteredHandler(successCounter, failureCounter,
allowListHandler::handleRequest)
+ val nextHandler = if (config.cacheEnabled()) {
+
+ val builder =
GlobalConfigurationBuilder().serialization().marshaller(PersistenceMarshaller())
+ val manager = DefaultCacheManager(builder.build())
+ val cache: Cache<String, JSONRPCResponse> = manager.createCache(
+ "responses",
+
ConfigurationBuilder().persistence().addStore(RocksDBStoreConfigurationBuilder::class.java)
+ .location(config.cacheStoragePath()).build()
+ )
+
+ val cachingHandler =
+ CachingHandler(config.cachedMethods(), InfinispanKeyValueStore(cache),
allowListHandler::handleRequest)
+ cachingHandler::handleRequest
+ } else {
+ allowListHandler::handleRequest
+ }
+
+ val throttlingHandler = ThrottlingHandler(config.maxConcurrentRequests(),
nextHandler)
+
+ val handler = MeteredHandler(successCounter, failureCounter,
throttlingHandler::handleRequest)
val server = JSONRPCServer(
vertx, config.port(), config.networkInterface(),
config.ssl(),
@@ -126,3 +161,18 @@ class JSONRPCApplication(
}
}
}
+
+class PersistenceMarshaller : AbstractMarshaller() {
+
+ companion object {
+ val mapper = ObjectMapper()
+ }
+
+ override fun objectFromByteBuffer(buf: ByteArray?, offset: Int, length: Int)
= mapper.readValue(Bytes.wrap(buf!!, offset, length).toArrayUnsafe(),
JSONRPCResponse::class.java)
+
+ override fun objectToBuffer(o: Any?, estimatedSize: Int): ByteBuffer =
ByteBufferImpl.create(mapper.writeValueAsBytes(o))
+
+ override fun isMarshallable(o: Any?): Boolean = o is JSONRPCResponse
+
+ override fun mediaType(): MediaType = MediaType.APPLICATION_OCTET_STREAM
+}
diff --git
a/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCConfig.kt
b/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCConfig.kt
index 8cd38d8..49c1705 100644
--- a/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCConfig.kt
+++ b/jsonrpc-app/src/main/kotlin/org/apache/tuweni/jsonrpc/app/JSONRPCConfig.kt
@@ -52,6 +52,10 @@ class JSONRPCConfig(val filePath: Path) {
.addBoolean("endpointBasicAuthEnabled", false, "Enable basic
authentication for the endpoint", null)
.addString("endpointBasicAuthUsername", "", "Basic authentication
username for the endpoint", null)
.addString("endpointBasicAuthPassword", "", "Basic authentication
password for the endpoint", null)
+ .addListOfString("cachedMethods", Collections.emptyList(), "Cached
JSON-RPC methods", null)
+ .addBoolean("cacheEnabled", false, "Enable caching", null)
+ .addString("cacheStoragePath", "", "Location of cache storage", null)
+ .addInteger("maxConcurrentRequests", 30, "Maximum concurrent requests",
null)
.toSchema()
}
@@ -81,4 +85,8 @@ class JSONRPCConfig(val filePath: Path) {
fun endpointBasicAuthEnabled() =
config.getBoolean("endpointBasicAuthEnabled")
fun endpointBasicAuthUsername() =
config.getString("endpointBasicAuthUsername")
fun endpointBasicAuthPassword() =
config.getString("endpointBasicAuthPassword")
+ fun cachedMethods() = config.getListOfString("cachedMethods")
+ fun cacheEnabled() = config.getBoolean("cacheEnabled")
+ fun cacheStoragePath() = config.getString("cacheStoragePath")
+ fun maxConcurrentRequests() = config.getInteger("maxConcurrentRequests")
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]