1

Allow to select between in-memory ledger and mongo ledger

This commit is contained in:
2018-06-10 09:12:16 +03:00
parent 0f24c37ac5
commit feabe74942
10 changed files with 212 additions and 78 deletions

View File

@@ -19,9 +19,9 @@ import com.devsoap.dbt.config.DBTConfig
import com.devsoap.dbt.data.BlockTransaction import com.devsoap.dbt.data.BlockTransaction
import com.devsoap.dbt.data.Query import com.devsoap.dbt.data.Query
import com.devsoap.dbt.services.LedgerService import com.devsoap.dbt.services.LedgerService
import com.devsoap.dbt.services.MongoLedgerService
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import groovy.util.logging.Slf4j import groovy.util.logging.Slf4j
import ratpack.exec.Promise
import ratpack.handling.Context import ratpack.handling.Context
import ratpack.handling.Handler import ratpack.handling.Handler
import ratpack.http.HttpMethod import ratpack.http.HttpMethod

View File

@@ -7,6 +7,8 @@ import com.google.inject.multibindings.Multibinder
import ratpack.handling.HandlerDecorator import ratpack.handling.HandlerDecorator
import ratpack.server.ServerConfig import ratpack.server.ServerConfig
import javax.sql.DataSource
class DBTExecutorModule extends DBTModule { class DBTExecutorModule extends DBTModule {
@Override @Override
@@ -16,6 +18,8 @@ class DBTExecutorModule extends DBTModule {
bind(ExecutorChainAction) bind(ExecutorChainAction)
bind(ExecutorHandler) bind(ExecutorHandler)
requireBinding(DataSource)
Multibinder.newSetBinder(binder(), HandlerDecorator).addBinding() Multibinder.newSetBinder(binder(), HandlerDecorator).addBinding()
.toInstance(HandlerDecorator.prependHandlers(ExecutorChainAction)) .toInstance(HandlerDecorator.prependHandlers(ExecutorChainAction))
} }

View File

@@ -20,7 +20,8 @@ class DBTLedgerModule extends DBTModule {
bind(LedgerGetTransactionHandler) bind(LedgerGetTransactionHandler)
bind(LedgerListTransactionsHandler) bind(LedgerListTransactionsHandler)
bind(LedgerUpdateTransactionHandler) bind(LedgerUpdateTransactionHandler)
bind(LedgerService)
requireBinding(LedgerService)
Multibinder.newSetBinder(binder(), HandlerDecorator).addBinding() Multibinder.newSetBinder(binder(), HandlerDecorator).addBinding()
.toInstance(HandlerDecorator.prependHandlers(LedgerChainAction)) .toInstance(HandlerDecorator.prependHandlers(LedgerChainAction))

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2018 Devsoap Inc.
*
* Licensed 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.
*/
package com.devsoap.dbt.modules
import com.devsoap.dbt.config.DBTConfig
import com.devsoap.dbt.handlers.ConfigInfoHandler
import com.devsoap.dbt.handlers.JsonSchemaHandler
import com.devsoap.dbt.services.TransactionManagerService
import com.fasterxml.jackson.databind.ObjectMapper
import groovy.util.logging.Slf4j
import ratpack.guice.ConfigurableModule
import ratpack.server.ServerConfig
@Slf4j
class DBTModule extends ConfigurableModule<DBTConfig> {
@Override
protected void configure() {
bind(ObjectMapper)
bind(TransactionManagerService)
bind(ConfigInfoHandler)
bind(JsonSchemaHandler)
}
@Override
protected DBTConfig createConfig(ServerConfig serverConfig) {
(DBTConfig) serverConfig.getAsConfigObject('/dbt', DBTConfig)?.getObject() ?: super.createConfig(serverConfig)
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2018 Devsoap Inc.
*
* Licensed 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.
*/
package com.devsoap.dbt.services
import com.devsoap.dbt.data.BlockTransaction
import groovy.util.logging.Slf4j
import ratpack.exec.Promise
@Slf4j
class InMemoryLedgerService implements LedgerService {
private static final LedgerData data = new LedgerData()
InMemoryLedgerService() {
log.warn('Using in-memory ledger service which will not store the ledger between restarts. Please consider ' +
'using the Mongo ledger service instead.')
}
@Override
Promise<Optional<BlockTransaction>> fetchTransaction(String transactionId) {
Promise.value(Optional.ofNullable(data.transactions.find {it.id == transactionId}))
}
@Override
Promise<List<BlockTransaction>> allTransactions() {
log.info("Found ${data.transactions.size()} transactions")
Promise.value(data.transactions)
}
@Override
Promise<String> newTransaction(BlockTransaction transaction) {
log.info("Adding new transaction $transaction.id")
data.transactions.add(transaction)
Promise.value(transaction.id)
}
@Override
Promise<String> updateTransaction(BlockTransaction transaction) {
log.info("Updating transaction $transaction.id")
data.transactions.removeAll {it.id == transaction.id}
data.transactions.add(transaction)
Promise.value(transaction.id)
}
private static class LedgerData {
final List<BlockTransaction> transactions = []
}
}

View File

@@ -15,72 +15,17 @@
*/ */
package com.devsoap.dbt.services package com.devsoap.dbt.services
import com.devsoap.dbt.config.DBTConfig
import com.devsoap.dbt.data.BlockTransaction import com.devsoap.dbt.data.BlockTransaction
import com.fasterxml.jackson.databind.ObjectMapper
import com.gmongo.GMongo
import com.mongodb.BasicDBObject
import com.mongodb.BasicDBObjectBuilder
import com.mongodb.DB
import com.mongodb.DBCollection
import com.mongodb.DBCursor
import com.mongodb.DBObject
import com.mongodb.MongoURI
import com.mongodb.util.JSON
import groovy.util.logging.Slf4j
import ratpack.exec.Promise import ratpack.exec.Promise
import ratpack.service.Service import ratpack.service.Service
import javax.inject.Inject interface LedgerService extends Service {
@Slf4j Promise<Optional<BlockTransaction>> fetchTransaction(String transactionId)
class LedgerService implements Service {
private final String dbUrl Promise<List<BlockTransaction>> allTransactions()
private DB db
private final ObjectMapper mapper
@Inject Promise<String> newTransaction(BlockTransaction transaction)
LedgerService(DBTConfig config, ObjectMapper mapper) {
dbUrl = config.ledger.databaseUrl
this.mapper = mapper
}
Promise<Optional<BlockTransaction>> fetchTransaction(String transactionId) { Promise<String> updateTransaction(BlockTransaction transaction)
BlockTransaction transaction = transactions.findOne(['id':transactionId])?.findAll { it.key != '_id' } as BlockTransaction
Promise.value(Optional.ofNullable(transaction))
}
Promise<List<BlockTransaction>> allTransactions() {
def cursor = transactions.find()
log.info("Found ${cursor.size()} transactions")
Promise.value(cursor.collect {it.findAll { it.key != '_id' } as BlockTransaction})
}
Promise<String> newTransaction(BlockTransaction transaction) {
log.info("Adding new transaction $transaction.id")
transactions << JSON.parse(mapper.writeValueAsString(transaction))
Promise.value(transaction.id)
}
Promise<String> updateTransaction(BlockTransaction transaction) {
log.info("Updating transaction $transaction.id")
transactions.findAndModify(
['id':transaction.id] as BasicDBObject,
JSON.parse(mapper.writeValueAsString(transaction)) as DBObject
)
Promise.value(transaction.id)
}
private DBCollection getTransactions() {
database.getCollection('transactions')
}
private DB getDatabase() {
if(!db) {
db = new GMongo(new MongoURI(dbUrl)).getDB('dbt')
}
db
}
} }

View File

@@ -0,0 +1,82 @@
/*
* Copyright 2018 Devsoap Inc.
*
* Licensed 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.
*/
package com.devsoap.dbt.services
import com.devsoap.dbt.config.DBTConfig
import com.devsoap.dbt.data.BlockTransaction
import com.fasterxml.jackson.databind.ObjectMapper
import com.gmongo.GMongo
import com.mongodb.*
import com.mongodb.util.JSON
import groovy.util.logging.Slf4j
import ratpack.exec.Promise
import javax.inject.Inject
@Slf4j
class MongoLedgerService implements LedgerService {
private final String dbUrl
private DB db
private final ObjectMapper mapper
@Inject
MongoLedgerService(DBTConfig config, ObjectMapper mapper) {
dbUrl = config.ledger.databaseUrl
this.mapper = mapper
}
@Override
Promise<Optional<BlockTransaction>> fetchTransaction(String transactionId) {
BlockTransaction transaction = transactions.findOne(['id':transactionId])?.findAll { it.key != '_id' } as BlockTransaction
Promise.value(Optional.ofNullable(transaction))
}
@Override
Promise<List<BlockTransaction>> allTransactions() {
def cursor = transactions.find()
log.info("Found ${cursor.size()} transactions")
Promise.value(cursor.collect {it.findAll { it.key != '_id' } as BlockTransaction})
}
@Override
Promise<String> newTransaction(BlockTransaction transaction) {
log.info("Adding new transaction $transaction.id")
transactions << JSON.parse(mapper.writeValueAsString(transaction))
Promise.value(transaction.id)
}
@Override
Promise<String> updateTransaction(BlockTransaction transaction) {
log.info("Updating transaction $transaction.id")
transactions.findAndModify(
['id':transaction.id] as BasicDBObject,
JSON.parse(mapper.writeValueAsString(transaction)) as DBObject
)
Promise.value(transaction.id)
}
private DBCollection getTransactions() {
database.getCollection('transactions')
}
private DB getDatabase() {
if(!db) {
db = new GMongo(new MongoURI(dbUrl)).getDB('dbt')
}
db
}
}

View File

@@ -17,6 +17,8 @@
import com.devsoap.dbt.config.DBTConfig import com.devsoap.dbt.config.DBTConfig
import com.devsoap.dbt.modules.DBTExecutorModule import com.devsoap.dbt.modules.DBTExecutorModule
import com.devsoap.dbt.modules.DBTLedgerModule import com.devsoap.dbt.modules.DBTLedgerModule
import com.devsoap.dbt.services.InMemoryLedgerService
import com.devsoap.dbt.services.LedgerService
import org.flywaydb.core.Flyway import org.flywaydb.core.Flyway
import org.h2.jdbcx.JdbcDataSource import org.h2.jdbcx.JdbcDataSource
import ratpack.service.Service import ratpack.service.Service
@@ -35,16 +37,14 @@ ratpack {
bindings { bindings {
module (DBTLedgerModule) { // Configure Ledger
it.executor.remoteUrl = 'http://localhost:8888/executor' bind(LedgerService, InMemoryLedgerService)
} module (DBTLedgerModule)
module (DBTExecutorModule) {
it.ledger.remoteUrl = 'http://localhost:8888/ledger'
}
// Configure executor
bindInstance(DataSource, new JdbcDataSource(url: 'jdbc:h2:mem:dbtdb;DB_CLOSE_DELAY=-1', user: '')) bindInstance(DataSource, new JdbcDataSource(url: 'jdbc:h2:mem:dbtdb;DB_CLOSE_DELAY=-1', user: ''))
bind FlywayMigrationService bind FlywayMigrationService
module (DBTExecutorModule)
} }
} }

View File

@@ -1,4 +1,6 @@
import com.devsoap.dbt.modules.DBTExecutorModule import com.devsoap.dbt.modules.DBTExecutorModule
import com.devsoap.dbt.services.LedgerService
import com.devsoap.dbt.services.MongoLedgerService
import org.h2.jdbcx.JdbcDataSource import org.h2.jdbcx.JdbcDataSource
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
@@ -16,9 +18,6 @@ ratpack {
bindings { bindings {
bindInstance(DataSource, new JdbcDataSource(url: 'jdbc:h2:mem:dbtdb;DB_CLOSE_DELAY=-1', user: '')) bindInstance(DataSource, new JdbcDataSource(url: 'jdbc:h2:mem:dbtdb;DB_CLOSE_DELAY=-1', user: ''))
module (DBTExecutorModule) { config -> module (DBTExecutorModule)
log.info "Executor available at $config.executor.remoteUrl"
log.info "Ledger available at $config.ledger.remoteUrl"
}
} }
} }

View File

@@ -1,4 +1,6 @@
import com.devsoap.dbt.modules.DBTLedgerModule import com.devsoap.dbt.modules.DBTLedgerModule
import com.devsoap.dbt.services.LedgerService
import com.devsoap.dbt.services.MongoLedgerService
import com.mongodb.MongoClient import com.mongodb.MongoClient
import com.mongodb.MongoClientURI import com.mongodb.MongoClientURI
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
@@ -14,9 +16,7 @@ ratpack {
} }
bindings { bindings {
module (DBTLedgerModule) { config -> bind(LedgerService, MongoLedgerService)
log.info("Using Mongo database at $config.ledger.databaseUrl") module (DBTLedgerModule)
bindInstance(MongoClient, new MongoClient(new MongoClientURI(config.ledger.databaseUrl)))
}
} }
} }