From feabe74942a3d09eca2e1264eb48fd6ef7c0f125 Mon Sep 17 00:00:00 2001 From: John Ahlroos Date: Sun, 10 Jun 2018 09:12:16 +0300 Subject: [PATCH] Allow to select between in-memory ledger and mongo ledger --- .../LedgerUpdateTransactionHandler.groovy | 2 +- .../dbt/modules/DBTExecutorModule.groovy | 4 + .../dbt/modules/DBTLedgerModule.groovy | 3 +- .../com/devsoap/dbt/modules/DBTModule.groovy | 42 ++++++++++ .../dbt/services/InMemoryLedgerService.groovy | 61 ++++++++++++++ .../devsoap/dbt/services/LedgerService.groovy | 67 ++------------- .../dbt/services/MongoLedgerService.groovy | 82 +++++++++++++++++++ dbt-test/src/ratpack/Ratpack.groovy | 14 ++-- docker-executor/src/ratpack/Ratpack.groovy | 7 +- docker-ledger/src/ratpack/Ratpack.groovy | 8 +- 10 files changed, 212 insertions(+), 78 deletions(-) create mode 100644 dbt-core/src/main/groovy/com/devsoap/dbt/modules/DBTModule.groovy create mode 100644 dbt-core/src/main/groovy/com/devsoap/dbt/services/InMemoryLedgerService.groovy create mode 100644 dbt-core/src/main/groovy/com/devsoap/dbt/services/MongoLedgerService.groovy diff --git a/dbt-core/src/main/groovy/com/devsoap/dbt/handlers/LedgerUpdateTransactionHandler.groovy b/dbt-core/src/main/groovy/com/devsoap/dbt/handlers/LedgerUpdateTransactionHandler.groovy index f8f0d07..11e2682 100644 --- a/dbt-core/src/main/groovy/com/devsoap/dbt/handlers/LedgerUpdateTransactionHandler.groovy +++ b/dbt-core/src/main/groovy/com/devsoap/dbt/handlers/LedgerUpdateTransactionHandler.groovy @@ -19,9 +19,9 @@ import com.devsoap.dbt.config.DBTConfig import com.devsoap.dbt.data.BlockTransaction import com.devsoap.dbt.data.Query import com.devsoap.dbt.services.LedgerService +import com.devsoap.dbt.services.MongoLedgerService import com.fasterxml.jackson.databind.ObjectMapper import groovy.util.logging.Slf4j -import ratpack.exec.Promise import ratpack.handling.Context import ratpack.handling.Handler import ratpack.http.HttpMethod diff --git a/dbt-core/src/main/groovy/com/devsoap/dbt/modules/DBTExecutorModule.groovy b/dbt-core/src/main/groovy/com/devsoap/dbt/modules/DBTExecutorModule.groovy index 378718e..2f120b4 100644 --- a/dbt-core/src/main/groovy/com/devsoap/dbt/modules/DBTExecutorModule.groovy +++ b/dbt-core/src/main/groovy/com/devsoap/dbt/modules/DBTExecutorModule.groovy @@ -7,6 +7,8 @@ import com.google.inject.multibindings.Multibinder import ratpack.handling.HandlerDecorator import ratpack.server.ServerConfig +import javax.sql.DataSource + class DBTExecutorModule extends DBTModule { @Override @@ -16,6 +18,8 @@ class DBTExecutorModule extends DBTModule { bind(ExecutorChainAction) bind(ExecutorHandler) + requireBinding(DataSource) + Multibinder.newSetBinder(binder(), HandlerDecorator).addBinding() .toInstance(HandlerDecorator.prependHandlers(ExecutorChainAction)) } diff --git a/dbt-core/src/main/groovy/com/devsoap/dbt/modules/DBTLedgerModule.groovy b/dbt-core/src/main/groovy/com/devsoap/dbt/modules/DBTLedgerModule.groovy index 02cacf9..d34347b 100644 --- a/dbt-core/src/main/groovy/com/devsoap/dbt/modules/DBTLedgerModule.groovy +++ b/dbt-core/src/main/groovy/com/devsoap/dbt/modules/DBTLedgerModule.groovy @@ -20,7 +20,8 @@ class DBTLedgerModule extends DBTModule { bind(LedgerGetTransactionHandler) bind(LedgerListTransactionsHandler) bind(LedgerUpdateTransactionHandler) - bind(LedgerService) + + requireBinding(LedgerService) Multibinder.newSetBinder(binder(), HandlerDecorator).addBinding() .toInstance(HandlerDecorator.prependHandlers(LedgerChainAction)) diff --git a/dbt-core/src/main/groovy/com/devsoap/dbt/modules/DBTModule.groovy b/dbt-core/src/main/groovy/com/devsoap/dbt/modules/DBTModule.groovy new file mode 100644 index 0000000..06272ff --- /dev/null +++ b/dbt-core/src/main/groovy/com/devsoap/dbt/modules/DBTModule.groovy @@ -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 { + + @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) + } +} \ No newline at end of file diff --git a/dbt-core/src/main/groovy/com/devsoap/dbt/services/InMemoryLedgerService.groovy b/dbt-core/src/main/groovy/com/devsoap/dbt/services/InMemoryLedgerService.groovy new file mode 100644 index 0000000..1820710 --- /dev/null +++ b/dbt-core/src/main/groovy/com/devsoap/dbt/services/InMemoryLedgerService.groovy @@ -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> fetchTransaction(String transactionId) { + Promise.value(Optional.ofNullable(data.transactions.find {it.id == transactionId})) + } + + @Override + Promise> allTransactions() { + log.info("Found ${data.transactions.size()} transactions") + Promise.value(data.transactions) + } + + @Override + Promise newTransaction(BlockTransaction transaction) { + log.info("Adding new transaction $transaction.id") + data.transactions.add(transaction) + Promise.value(transaction.id) + } + + @Override + Promise 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 transactions = [] + } +} diff --git a/dbt-core/src/main/groovy/com/devsoap/dbt/services/LedgerService.groovy b/dbt-core/src/main/groovy/com/devsoap/dbt/services/LedgerService.groovy index 149521b..d47d0c7 100644 --- a/dbt-core/src/main/groovy/com/devsoap/dbt/services/LedgerService.groovy +++ b/dbt-core/src/main/groovy/com/devsoap/dbt/services/LedgerService.groovy @@ -15,72 +15,17 @@ */ 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.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.service.Service -import javax.inject.Inject +interface LedgerService extends Service { -@Slf4j -class LedgerService implements Service { + Promise> fetchTransaction(String transactionId) - private final String dbUrl - private DB db - private final ObjectMapper mapper + Promise> allTransactions() - @Inject - LedgerService(DBTConfig config, ObjectMapper mapper) { - dbUrl = config.ledger.databaseUrl - this.mapper = mapper - } + Promise newTransaction(BlockTransaction transaction) - Promise> fetchTransaction(String transactionId) { - BlockTransaction transaction = transactions.findOne(['id':transactionId])?.findAll { it.key != '_id' } as BlockTransaction - Promise.value(Optional.ofNullable(transaction)) - } - - Promise> allTransactions() { - def cursor = transactions.find() - log.info("Found ${cursor.size()} transactions") - - Promise.value(cursor.collect {it.findAll { it.key != '_id' } as BlockTransaction}) - } - - Promise newTransaction(BlockTransaction transaction) { - log.info("Adding new transaction $transaction.id") - transactions << JSON.parse(mapper.writeValueAsString(transaction)) - Promise.value(transaction.id) - } - - Promise 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 - } -} + Promise updateTransaction(BlockTransaction transaction) +} \ No newline at end of file diff --git a/dbt-core/src/main/groovy/com/devsoap/dbt/services/MongoLedgerService.groovy b/dbt-core/src/main/groovy/com/devsoap/dbt/services/MongoLedgerService.groovy new file mode 100644 index 0000000..d5475ed --- /dev/null +++ b/dbt-core/src/main/groovy/com/devsoap/dbt/services/MongoLedgerService.groovy @@ -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> fetchTransaction(String transactionId) { + BlockTransaction transaction = transactions.findOne(['id':transactionId])?.findAll { it.key != '_id' } as BlockTransaction + Promise.value(Optional.ofNullable(transaction)) + } + + @Override + Promise> allTransactions() { + def cursor = transactions.find() + log.info("Found ${cursor.size()} transactions") + Promise.value(cursor.collect {it.findAll { it.key != '_id' } as BlockTransaction}) + } + + @Override + Promise newTransaction(BlockTransaction transaction) { + log.info("Adding new transaction $transaction.id") + transactions << JSON.parse(mapper.writeValueAsString(transaction)) + Promise.value(transaction.id) + } + + @Override + Promise 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 + } +} diff --git a/dbt-test/src/ratpack/Ratpack.groovy b/dbt-test/src/ratpack/Ratpack.groovy index aba07fb..4ce078b 100644 --- a/dbt-test/src/ratpack/Ratpack.groovy +++ b/dbt-test/src/ratpack/Ratpack.groovy @@ -17,6 +17,8 @@ import com.devsoap.dbt.config.DBTConfig import com.devsoap.dbt.modules.DBTExecutorModule 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.h2.jdbcx.JdbcDataSource import ratpack.service.Service @@ -35,16 +37,14 @@ ratpack { bindings { - module (DBTLedgerModule) { - it.executor.remoteUrl = 'http://localhost:8888/executor' - } - - module (DBTExecutorModule) { - it.ledger.remoteUrl = 'http://localhost:8888/ledger' - } + // Configure Ledger + bind(LedgerService, InMemoryLedgerService) + module (DBTLedgerModule) + // Configure executor bindInstance(DataSource, new JdbcDataSource(url: 'jdbc:h2:mem:dbtdb;DB_CLOSE_DELAY=-1', user: '')) bind FlywayMigrationService + module (DBTExecutorModule) } } diff --git a/docker-executor/src/ratpack/Ratpack.groovy b/docker-executor/src/ratpack/Ratpack.groovy index 442b6e6..fb34871 100644 --- a/docker-executor/src/ratpack/Ratpack.groovy +++ b/docker-executor/src/ratpack/Ratpack.groovy @@ -1,4 +1,6 @@ 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.slf4j.LoggerFactory @@ -16,9 +18,6 @@ ratpack { bindings { bindInstance(DataSource, new JdbcDataSource(url: 'jdbc:h2:mem:dbtdb;DB_CLOSE_DELAY=-1', user: '')) - module (DBTExecutorModule) { config -> - log.info "Executor available at $config.executor.remoteUrl" - log.info "Ledger available at $config.ledger.remoteUrl" - } + module (DBTExecutorModule) } } diff --git a/docker-ledger/src/ratpack/Ratpack.groovy b/docker-ledger/src/ratpack/Ratpack.groovy index a0a6f03..e157454 100644 --- a/docker-ledger/src/ratpack/Ratpack.groovy +++ b/docker-ledger/src/ratpack/Ratpack.groovy @@ -1,4 +1,6 @@ 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.MongoClientURI import org.slf4j.LoggerFactory @@ -14,9 +16,7 @@ ratpack { } bindings { - module (DBTLedgerModule) { config -> - log.info("Using Mongo database at $config.ledger.databaseUrl") - bindInstance(MongoClient, new MongoClient(new MongoClientURI(config.ledger.databaseUrl))) - } + bind(LedgerService, MongoLedgerService) + module (DBTLedgerModule) } }