mirror of
https://github.com/valitydev/wb-list-manager.git
synced 2024-11-06 01:35:17 +00:00
Add logic fir check lists
This commit is contained in:
parent
7ac69e6f6e
commit
90f227a7ce
80
.gitignore
vendored
80
.gitignore
vendored
@ -1,42 +1,56 @@
|
|||||||
# Created by .ignore support plugin (hsz.mobi)
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
### JetBrains template
|
.eunit
|
||||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
|
deps
|
||||||
|
*.o
|
||||||
*.DS_Store
|
*.beam
|
||||||
|
*.plt
|
||||||
*.iml
|
erl_crash.dump
|
||||||
|
ebin/*.beam
|
||||||
## Directory-based project format:
|
rel/example_project
|
||||||
.idea/
|
.concrete/DEV_MODE
|
||||||
# if you remove the above rule, at least ignore the following:
|
.rebar
|
||||||
|
target/
|
||||||
|
pom.xml.tag
|
||||||
|
pom.xml.releaseBackup
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
pom.xml.next
|
||||||
|
release.properties
|
||||||
|
dependency-reduced-pom.xml
|
||||||
|
buildNumber.properties
|
||||||
|
.mvn/timing.properties
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
# User-specific stuff:
|
# User-specific stuff:
|
||||||
# .idea/workspace.xml
|
.idea/
|
||||||
# .idea/tasks.xml
|
.idea/workspace.xml
|
||||||
# .idea/dictionaries
|
.idea/tasks.xml
|
||||||
|
.idea/dictionaries
|
||||||
|
.idea/vcs.xml
|
||||||
|
.idea/jsLibraryMappings.xml
|
||||||
|
|
||||||
# Sensitive or high-churn files:
|
# Sensitive or high-churn files:
|
||||||
# .idea/dataSources.ids
|
.idea/dataSources.ids
|
||||||
# .idea/dataSources.xml
|
.idea/dataSources.xml
|
||||||
# .idea/sqlDataSources.xml
|
.idea/dataSources.local.xml
|
||||||
# .idea/dynamic.xml
|
.idea/sqlDataSources.xml
|
||||||
# .idea/uiDesigner.xml
|
.idea/dynamic.xml
|
||||||
|
.idea/uiDesigner.xml
|
||||||
|
|
||||||
# Gradle:
|
# Gradle:
|
||||||
# .idea/gradle.xml
|
.idea/gradle.xml
|
||||||
# .idea/libraries
|
.idea/libraries
|
||||||
|
|
||||||
# Mongo Explorer plugin:
|
# Mongo Explorer plugin:
|
||||||
# .idea/mongoSettings.xml
|
.idea/mongoSettings.xml
|
||||||
|
|
||||||
## File-based project format:
|
|
||||||
*.ipr
|
|
||||||
*.iws
|
*.iws
|
||||||
|
*.ipr
|
||||||
|
*.iml
|
||||||
|
|
||||||
## Plugin-specific files:
|
|
||||||
|
|
||||||
# IntelliJ
|
# IntelliJ
|
||||||
out/
|
/out/
|
||||||
|
|
||||||
# mpeltonen/sbt-idea plugin
|
# mpeltonen/sbt-idea plugin
|
||||||
.idea_modules/
|
.idea_modules/
|
||||||
@ -48,9 +62,17 @@ atlassian-ide-plugin.xml
|
|||||||
com_crashlytics_export_strings.xml
|
com_crashlytics_export_strings.xml
|
||||||
crashlytics.properties
|
crashlytics.properties
|
||||||
crashlytics-build.properties
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
*.class
|
||||||
|
|
||||||
# Target folder
|
# Mobile Tools for Java (J2ME)
|
||||||
target
|
.mtj.tmp/
|
||||||
|
|
||||||
# Target ant folder
|
# Package Files #
|
||||||
build
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.ear
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
env.list
|
||||||
|
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[submodule "build_utils"]
|
||||||
|
path = build_utils
|
||||||
|
url = git@github.com:rbkmoney/build_utils.git
|
||||||
|
branch = master
|
16
Jenkinsfile
vendored
Normal file
16
Jenkinsfile
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#!groovy
|
||||||
|
build('wb-list-manager', 'java-maven') {
|
||||||
|
checkoutRepo()
|
||||||
|
loadBuildUtils()
|
||||||
|
|
||||||
|
def javaServicePipeline
|
||||||
|
runStage('load JavaService pipeline') {
|
||||||
|
javaServicePipeline = load("build_utils/jenkins_lib/pipeJavaService.groovy")
|
||||||
|
}
|
||||||
|
|
||||||
|
def serviceName = env.REPO_NAME
|
||||||
|
def mvnArgs = '-DjvmArgs="-Xmx256m"'
|
||||||
|
def useJava11 = true
|
||||||
|
|
||||||
|
javaServicePipeline(serviceName, useJava11, mvnArgs)
|
||||||
|
}
|
1
build_utils
Submodule
1
build_utils
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 269686d735abef363f9f40a1bf4e1b7c751f3722
|
190
pom.xml
Normal file
190
pom.xml
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.rbkmoney</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>2.1.1.RELEASE</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>wb-list-manager</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>wb-list-manager</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<java.version>11</java.version>
|
||||||
|
<server.port>8022</server.port>
|
||||||
|
<exposed.ports>${server.port}</exposed.ports>
|
||||||
|
<dockerfile.base.service.tag>81f57f9ef5e5854c27659c9f56f59cdb2b7c43e5</dockerfile.base.service.tag>
|
||||||
|
<shared.resources.version>0.3.2</shared.resources.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.rbkmoney</groupId>
|
||||||
|
<artifactId>shared-resources</artifactId>
|
||||||
|
<version>${shared.resources.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
<artifactId>javax.servlet-api</artifactId>
|
||||||
|
<version>4.0.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.rbkmoney.woody</groupId>
|
||||||
|
<artifactId>woody-thrift</artifactId>
|
||||||
|
<version>1.1.15</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.rbkmoney</groupId>
|
||||||
|
<artifactId>spring-boot-starter-metrics-statsd</artifactId>
|
||||||
|
<version>1.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.4</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.testcontainers</groupId>
|
||||||
|
<artifactId>testcontainers</artifactId>
|
||||||
|
<version>1.10.5</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.basho.riak</groupId>
|
||||||
|
<artifactId>riak-client</artifactId>
|
||||||
|
<version>2.1.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--kafka-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.kafka</groupId>
|
||||||
|
<artifactId>kafka-clients</artifactId>
|
||||||
|
<version>2.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.kafka</groupId>
|
||||||
|
<artifactId>spring-kafka</artifactId>
|
||||||
|
<version>2.2.2.RELEASE</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.kafka</groupId>
|
||||||
|
<artifactId>kafka-clients</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.testcontainers</groupId>
|
||||||
|
<artifactId>kafka</artifactId>
|
||||||
|
<version>1.10.2</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.rbkmoney</groupId>
|
||||||
|
<artifactId>wb-list-proto</artifactId>
|
||||||
|
<version>1.8-36aed97</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>${project.build.directory}/maven-shared-archive-resources</directory>
|
||||||
|
<targetPath>${project.build.directory}</targetPath>
|
||||||
|
<includes>
|
||||||
|
<include>Dockerfile</include>
|
||||||
|
</includes>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
<resource>
|
||||||
|
<directory>${project.build.directory}/maven-shared-archive-resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
<excludes>
|
||||||
|
<exclude>Dockerfile</exclude>
|
||||||
|
</excludes>
|
||||||
|
</resource>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<version>2.1.1.RELEASE</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-remote-resources-plugin</artifactId>
|
||||||
|
<version>1.6.0</version>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.shared</groupId>
|
||||||
|
<artifactId>maven-filtering</artifactId>
|
||||||
|
<version>1.3</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<configuration>
|
||||||
|
<resourceBundles>
|
||||||
|
<resourceBundle>com.rbkmoney:shared-resources:${shared.resources.version}</resourceBundle>
|
||||||
|
</resourceBundles>
|
||||||
|
<attachToMain>false</attachToMain>
|
||||||
|
<attachToTest>false</attachToTest>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>process</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<!-- Sonar-JaCoCo integration plugin -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.jacoco</groupId>
|
||||||
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
|
<version>0.8.2</version>
|
||||||
|
<configuration>
|
||||||
|
<destFile>${sonar.jacoco.reportPath}</destFile>
|
||||||
|
<append>true</append>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>agent</id>
|
||||||
|
<goals>
|
||||||
|
<goal>prepare-agent</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||||
|
|
||||||
|
@ServletComponentScan
|
||||||
|
@SpringBootApplication
|
||||||
|
public class WbListManagerApplication extends SpringApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(WbListManagerApplication.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager.config;
|
||||||
|
|
||||||
|
import org.apache.kafka.clients.consumer.ConsumerConfig;
|
||||||
|
import org.apache.kafka.common.serialization.StringDeserializer;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
|
||||||
|
import org.springframework.kafka.config.KafkaListenerContainerFactory;
|
||||||
|
import org.springframework.kafka.core.ConsumerFactory;
|
||||||
|
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
|
||||||
|
import org.springframework.kafka.listener.ConcurrentMessageListenerContainer;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class KafkaConfig {
|
||||||
|
|
||||||
|
private static final String GROUP_ID = "CommandListener";
|
||||||
|
private static final String EARLIEST = "earliest";
|
||||||
|
|
||||||
|
@Value("${kafka.bootstrap.servers}")
|
||||||
|
private String bootstrapServers;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Map<String, Object> consumerConfigs() {
|
||||||
|
Map<String, Object> props = new HashMap<>();
|
||||||
|
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
|
||||||
|
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
|
||||||
|
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
|
||||||
|
props.put(ConsumerConfig.GROUP_ID_CONFIG, GROUP_ID);
|
||||||
|
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, EARLIEST);
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ConsumerFactory<String, String> consumerFactory() {
|
||||||
|
return new DefaultKafkaConsumerFactory<>(consumerConfigs());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<String, String>> kafkaListenerContainerFactory() {
|
||||||
|
ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
|
||||||
|
factory.setConsumerFactory(consumerFactory());
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager.config;
|
||||||
|
|
||||||
|
import com.rbkmoney.damsel.wb_list.WbListServiceSrv;
|
||||||
|
import com.rbkmoney.wb.list.manager.handler.WbListServiceHandler;
|
||||||
|
import com.rbkmoney.wb.list.manager.repository.ListRepository;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class ResourceConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public WbListServiceSrv.Iface fraudInspectorHandler(ListRepository listRepository) {
|
||||||
|
return new WbListServiceHandler(listRepository);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager.config;
|
||||||
|
|
||||||
|
import com.basho.riak.client.api.RiakClient;
|
||||||
|
import com.basho.riak.client.core.RiakCluster;
|
||||||
|
import com.basho.riak.client.core.RiakNode;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class RiakConfig {
|
||||||
|
|
||||||
|
@Value("${riak.port}")
|
||||||
|
public int riakPort;
|
||||||
|
|
||||||
|
@Value("${riak.address}")
|
||||||
|
public String riakAddress;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RiakCluster riakCluster() {
|
||||||
|
RiakNode node = new RiakNode.Builder()
|
||||||
|
.withRemoteAddress(riakAddress)
|
||||||
|
.withRemotePort(riakPort)
|
||||||
|
.build();
|
||||||
|
RiakCluster cluster = new RiakCluster.Builder(node)
|
||||||
|
.build();
|
||||||
|
cluster.start();
|
||||||
|
return cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RiakClient riakClient() {
|
||||||
|
return new RiakClient(riakCluster());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager.exception;
|
||||||
|
|
||||||
|
public class RiakExecutionException extends RuntimeException {
|
||||||
|
|
||||||
|
public RiakExecutionException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public RiakExecutionException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RiakExecutionException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RiakExecutionException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RiakExecutionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||||
|
super(message, cause, enableSuppression, writableStackTrace);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager.handler;
|
||||||
|
|
||||||
|
import com.rbkmoney.damsel.wb_list.ListNotFound;
|
||||||
|
import com.rbkmoney.damsel.wb_list.WbListServiceSrv;
|
||||||
|
import com.rbkmoney.wb.list.manager.exception.RiakExecutionException;
|
||||||
|
import com.rbkmoney.wb.list.manager.repository.ListRepository;
|
||||||
|
import com.rbkmoney.wb.list.manager.utils.KeyGenerator;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.thrift.TException;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class WbListServiceHandler implements WbListServiceSrv.Iface {
|
||||||
|
|
||||||
|
private final ListRepository listRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isExist(String partyId, String shopId, String listName, String value) throws ListNotFound, TException {
|
||||||
|
String bucket = KeyGenerator.generateBucket(partyId, shopId);
|
||||||
|
String key = KeyGenerator.generateKey(listName, value);
|
||||||
|
try {
|
||||||
|
return listRepository.get(bucket, key).isPresent();
|
||||||
|
} catch (RiakExecutionException e) {
|
||||||
|
throw new TException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager.listener;
|
||||||
|
|
||||||
|
import com.rbkmoney.wb.list.manager.model.Row;
|
||||||
|
import com.rbkmoney.wb.list.manager.repository.ListRepository;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.kafka.annotation.KafkaListener;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class WbListListener {
|
||||||
|
|
||||||
|
private final ListRepository listRepository;
|
||||||
|
|
||||||
|
@KafkaListener(topics = "${kafka.wblist.topic}", containerFactory = "kafkaListenerContainerFactory")
|
||||||
|
public void listen(Row row) {
|
||||||
|
log.info("TemplateListener ruleTemplate: {}", row);
|
||||||
|
listRepository.create(row);
|
||||||
|
}
|
||||||
|
}
|
17
src/main/java/com/rbkmoney/wb/list/manager/model/Row.java
Normal file
17
src/main/java/com/rbkmoney/wb/list/manager/model/Row.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager.model;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class Row {
|
||||||
|
|
||||||
|
private String bucketName;
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager.repository;
|
||||||
|
|
||||||
|
import com.rbkmoney.wb.list.manager.model.Row;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface CrudRepository<T, K> {
|
||||||
|
|
||||||
|
void create(T row);
|
||||||
|
|
||||||
|
void remove(T row);
|
||||||
|
|
||||||
|
Optional<Row> get(String bucket, K key);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager.repository;
|
||||||
|
|
||||||
|
import com.basho.riak.client.api.RiakClient;
|
||||||
|
import com.basho.riak.client.api.cap.Quorum;
|
||||||
|
import com.basho.riak.client.api.commands.kv.DeleteValue;
|
||||||
|
import com.basho.riak.client.api.commands.kv.FetchValue;
|
||||||
|
import com.basho.riak.client.api.commands.kv.StoreValue;
|
||||||
|
import com.basho.riak.client.core.query.Location;
|
||||||
|
import com.basho.riak.client.core.query.Namespace;
|
||||||
|
import com.basho.riak.client.core.query.RiakObject;
|
||||||
|
import com.basho.riak.client.core.util.BinaryValue;
|
||||||
|
import com.rbkmoney.wb.list.manager.exception.RiakExecutionException;
|
||||||
|
import com.rbkmoney.wb.list.manager.model.Row;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ListRepository implements CrudRepository<Row, String> {
|
||||||
|
|
||||||
|
private static final String TEXT_PLAIN = "text/plain";
|
||||||
|
private final RiakClient client;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create(Row row) {
|
||||||
|
try {
|
||||||
|
RiakObject quoteObject = new RiakObject()
|
||||||
|
.setContentType(TEXT_PLAIN)
|
||||||
|
.setValue(BinaryValue.create(row.getValue()));
|
||||||
|
Location quoteObjectLocation = createLocation(row.getBucketName(), row.getKey());
|
||||||
|
StoreValue storeOp = new StoreValue.Builder(quoteObject)
|
||||||
|
.withOption(StoreValue.Option.W, Quorum.oneQuorum())
|
||||||
|
.withLocation(quoteObjectLocation)
|
||||||
|
.build();
|
||||||
|
client.execute(storeOp);
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
log.error("Exception in ListRepository when create e: ", e);
|
||||||
|
throw new RiakExecutionException();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error("InterruptedException in ListRepository when get e: ", e);
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw new RiakExecutionException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(Row row) {
|
||||||
|
try {
|
||||||
|
Location quoteObjectLocation = createLocation(row.getBucketName(), row.getKey());
|
||||||
|
DeleteValue delete = new DeleteValue.Builder(quoteObjectLocation).build();
|
||||||
|
client.execute(delete);
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
log.error("Exception in ListRepository when remove e: ", e);
|
||||||
|
throw new RiakExecutionException(e);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error("InterruptedException in ListRepository when get e: ", e);
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw new RiakExecutionException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Row> get(String bucket, String key) {
|
||||||
|
try {
|
||||||
|
Location quoteObjectLocation = createLocation(bucket, key);
|
||||||
|
FetchValue fetch = new FetchValue.Builder(quoteObjectLocation)
|
||||||
|
.withOption(FetchValue.Option.R, new Quorum(3))
|
||||||
|
.build();
|
||||||
|
FetchValue.Response response = client.execute(fetch);
|
||||||
|
RiakObject obj = response.getValue(RiakObject.class);
|
||||||
|
return Optional.of(new Row(bucket, key, obj.getValue().toString()));
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
log.error("Exception in ListRepository when get e: ", e);
|
||||||
|
throw new RiakExecutionException(e);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error("InterruptedException in ListRepository when get e: ", e);
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw new RiakExecutionException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Location createLocation(String bucketName, String key) {
|
||||||
|
Namespace quotesBucket = new Namespace(bucketName);
|
||||||
|
return new Location(quotesBucket, key);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager.resource;
|
||||||
|
|
||||||
|
import com.rbkmoney.damsel.wb_list.WbListServiceSrv;
|
||||||
|
import com.rbkmoney.woody.thrift.impl.http.THServiceBuilder;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import javax.servlet.*;
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@WebServlet("/v1/wb_list")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class FraudInspectorServlet extends GenericServlet {
|
||||||
|
|
||||||
|
private Servlet thriftServlet;
|
||||||
|
|
||||||
|
private final WbListServiceSrv.Iface fraudInspectorHandler;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(ServletConfig config) throws ServletException {
|
||||||
|
super.init(config);
|
||||||
|
thriftServlet = new THServiceBuilder()
|
||||||
|
.build(WbListServiceSrv.Iface.class, fraudInspectorHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
|
||||||
|
thriftServlet.service(req, res);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager.serializer;
|
||||||
|
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.apache.kafka.common.errors.SerializationException;
|
||||||
|
import org.apache.kafka.common.serialization.Deserializer;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class JsonPOJODeserializer<T> implements Deserializer<T> {
|
||||||
|
private ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
private Class<T> tClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor needed by Kafka
|
||||||
|
*/
|
||||||
|
public JsonPOJODeserializer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void configure(Map<String, ?> props, boolean isKey) {
|
||||||
|
tClass = (Class<T>) props.get("JsonPOJOClass");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T deserialize(String topic, byte[] bytes) {
|
||||||
|
if (bytes == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
T data;
|
||||||
|
try {
|
||||||
|
data = objectMapper.readValue(bytes, tClass);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SerializationException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager.serializer;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.apache.kafka.common.errors.SerializationException;
|
||||||
|
import org.apache.kafka.common.serialization.Serializer;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class JsonPOJOSerializer<T> implements Serializer<T> {
|
||||||
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor needed by Kafka
|
||||||
|
*/
|
||||||
|
public JsonPOJOSerializer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(Map<String, ?> props, boolean isKey) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] serialize(String topic, T data) {
|
||||||
|
if (data == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return objectMapper.writeValueAsBytes(data);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SerializationException("Error serializing JSON message", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager.utils;
|
||||||
|
|
||||||
|
public class KeyGenerator {
|
||||||
|
|
||||||
|
public static final String DELIMITER = "_";
|
||||||
|
|
||||||
|
public static String generateBucket(String partyId, String shopId) {
|
||||||
|
return generateKeySecondField(partyId, shopId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generateKey(String type, String key) {
|
||||||
|
return generateKeySecondField(type, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String generateKeySecondField(String first, String second) {
|
||||||
|
return first + DELIMITER + second;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
16
src/main/resources/application.yml
Normal file
16
src/main/resources/application.yml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
server.port: @server.port@
|
||||||
|
management.security.flag: false
|
||||||
|
spring.application.name: @project.name@
|
||||||
|
info.version: @project.version@
|
||||||
|
info.stage: dev
|
||||||
|
|
||||||
|
management.metrics.export.statsd:
|
||||||
|
flavor: etsy
|
||||||
|
|
||||||
|
riak:
|
||||||
|
address: localhost
|
||||||
|
port: 8087
|
||||||
|
|
||||||
|
kafka:
|
||||||
|
bootstrap.servers: "localhost:9092"
|
||||||
|
wblist.topic: "wblist"
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager;
|
||||||
|
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.util.TestPropertyValues;
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.testcontainers.containers.KafkaContainer;
|
||||||
|
|
||||||
|
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(webEnvironment = RANDOM_PORT)
|
||||||
|
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
|
||||||
|
@ContextConfiguration(initializers = KafkaAbstractTest.Initializer.class)
|
||||||
|
public abstract class KafkaAbstractTest {
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static KafkaContainer kafka = new KafkaContainer("5.0.1").withEmbeddedZookeeper();
|
||||||
|
|
||||||
|
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||||
|
@Override
|
||||||
|
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
|
||||||
|
TestPropertyValues
|
||||||
|
.of("kafka.bootstrap.servers=" + kafka.getBootstrapServers())
|
||||||
|
.applyTo(configurableApplicationContext.getEnvironment());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager;
|
||||||
|
|
||||||
|
import com.basho.riak.client.api.RiakClient;
|
||||||
|
import com.basho.riak.client.api.commands.kv.FetchValue;
|
||||||
|
import com.basho.riak.client.core.query.Location;
|
||||||
|
import com.basho.riak.client.core.query.Namespace;
|
||||||
|
import com.basho.riak.client.core.query.RiakObject;
|
||||||
|
import com.rbkmoney.wb.list.manager.config.KafkaConfig;
|
||||||
|
import com.rbkmoney.wb.list.manager.model.Row;
|
||||||
|
import com.rbkmoney.wb.list.manager.repository.ListRepository;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.util.TestPropertyValues;
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.FilterType;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.testcontainers.containers.GenericContainer;
|
||||||
|
import org.testcontainers.containers.wait.strategy.WaitAllStrategy;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(webEnvironment = RANDOM_PORT)
|
||||||
|
@ContextConfiguration(classes = WbListManagerApplication.class, initializers = WbListManagerApplicationTest.Initializer.class)
|
||||||
|
public class WbListManagerApplicationTest extends KafkaAbstractTest {
|
||||||
|
|
||||||
|
public static final String TYPE = "type";
|
||||||
|
public static final String BUCKET_NAME = "bucketName";
|
||||||
|
public static final String VALUE = "value";
|
||||||
|
public static final String KEY = "key";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ListRepository listRepository;
|
||||||
|
@Autowired
|
||||||
|
private RiakClient client;
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static GenericContainer riak = new GenericContainer("basho/riak-kv")
|
||||||
|
.waitingFor(new WaitAllStrategy());
|
||||||
|
|
||||||
|
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||||
|
@Override
|
||||||
|
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
|
||||||
|
TestPropertyValues
|
||||||
|
.of("riak.port=" + riak.getMappedPort(8087))
|
||||||
|
.applyTo(configurableApplicationContext.getEnvironment());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init() throws InterruptedException {
|
||||||
|
riak.start();
|
||||||
|
// TODO add cycle for up check
|
||||||
|
Thread.sleep(8000L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void contextLoads() throws ExecutionException, InterruptedException {
|
||||||
|
Row row = new Row();
|
||||||
|
row.setKey(KEY);
|
||||||
|
row.setBucketName(BUCKET_NAME);
|
||||||
|
row.setValue(VALUE);
|
||||||
|
listRepository.create(row);
|
||||||
|
|
||||||
|
Namespace ns = new Namespace(BUCKET_NAME);
|
||||||
|
Location location = new Location(ns, KEY);
|
||||||
|
FetchValue fv = new FetchValue.Builder(location).build();
|
||||||
|
FetchValue.Response response = client.execute(fv);
|
||||||
|
RiakObject obj = response.getValue(RiakObject.class);
|
||||||
|
|
||||||
|
String result = obj.getValue().toString();
|
||||||
|
Assert.assertEquals(VALUE, result);
|
||||||
|
|
||||||
|
Optional<Row> resultGet = listRepository.get(BUCKET_NAME, KEY);
|
||||||
|
Assert.assertFalse(resultGet.isEmpty());
|
||||||
|
Assert.assertEquals(VALUE, resultGet.get().getValue());
|
||||||
|
|
||||||
|
listRepository.remove(row);
|
||||||
|
response = client.execute(fv);
|
||||||
|
obj = response.getValue(RiakObject.class);
|
||||||
|
Assert.assertNull(obj);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.rbkmoney.wb.list.manager.handler;
|
||||||
|
|
||||||
|
import com.rbkmoney.wb.list.manager.model.Row;
|
||||||
|
import com.rbkmoney.wb.list.manager.repository.ListRepository;
|
||||||
|
import org.apache.thrift.TException;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
|
||||||
|
public class WbListServiceHandlerTest {
|
||||||
|
|
||||||
|
public static final String VALUE = "value";
|
||||||
|
WbListServiceHandler wbListServiceHandler;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
ListRepository listRepository;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
wbListServiceHandler = new WbListServiceHandler(listRepository);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isExist() throws TException {
|
||||||
|
Row value = new Row();
|
||||||
|
value.setValue(VALUE);
|
||||||
|
Mockito.when(listRepository.get(anyString(), anyString())).thenReturn(Optional.of(value));
|
||||||
|
boolean exist = wbListServiceHandler.isExist("partyId", "shopId", "listName", "value");
|
||||||
|
Assert.assertTrue(exist);
|
||||||
|
|
||||||
|
Mockito.when(listRepository.get(anyString(), anyString())).thenReturn(Optional.empty());
|
||||||
|
exist = wbListServiceHandler.isExist("partyId", "shopId", "listName", "value");
|
||||||
|
Assert.assertFalse(exist);
|
||||||
|
}
|
||||||
|
}
|
2
src/test/resources/app/start.sh
Normal file
2
src/test/resources/app/start.sh
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
riak-admin bucket-type create type
|
||||||
|
riak-admin bucket-type activate type
|
10
src/test/resources/logback-test.xml
Normal file
10
src/test/resources/logback-test.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
|
||||||
|
|
||||||
|
<root level="warn">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
</root>
|
||||||
|
<logger name="com.rbkmoney.woody" level="ALL"/>
|
||||||
|
</configuration>
|
Loading…
Reference in New Issue
Block a user