create docker-compose
This commit is contained in:
parent
da55d49316
commit
02ed372d99
3
docker-compose/chats.env
Normal file
3
docker-compose/chats.env
Normal file
@ -0,0 +1,3 @@
|
||||
QUARKUS_DATASOURCE_REACTIVE_URL=vertx-reactive:postgresql://database:5432/volvox
|
||||
QUARKUS_DATASOURCE_USERNAME=volvox
|
||||
QUARKUS_DATASOURCE_PASSWORD=volvox
|
3
docker-compose/database.env
Normal file
3
docker-compose/database.env
Normal file
@ -0,0 +1,3 @@
|
||||
POSTGRES_USER=volvox
|
||||
POSTGRES_PASSWORD=volvox
|
||||
POSTGRES_DB=volvox
|
98
docker-compose/docker-compose.yml
Normal file
98
docker-compose/docker-compose.yml
Normal file
@ -0,0 +1,98 @@
|
||||
version: "1.0.0"
|
||||
services:
|
||||
chats:
|
||||
build:
|
||||
context: ../service-chats
|
||||
dockerfile: src/main/docker/Dockerfile.jvm
|
||||
container_name: service-chats
|
||||
env_file: chats.env
|
||||
ports:
|
||||
- 8282:8282
|
||||
links:
|
||||
- database
|
||||
- elastic
|
||||
td:
|
||||
build:
|
||||
context: ../service-td
|
||||
dockerfile: src/main/docker/Dockerfile.jvm
|
||||
container_name: service-td
|
||||
env_file: td.env
|
||||
ports:
|
||||
- 8283:8283
|
||||
links: []
|
||||
database:
|
||||
image: postgres
|
||||
container_name: postgres01
|
||||
env_file: database.env
|
||||
ports:
|
||||
- 5432:5432
|
||||
volumes:
|
||||
- database_data:/var/lib/postgresql/data/
|
||||
es01:
|
||||
image: docker.elastic.co/elasticsearch/elasticsearch:7.15.2
|
||||
container_name: es01
|
||||
environment:
|
||||
- node.name=es01
|
||||
- cluster.name=es-docker-cluster
|
||||
- discovery.seed_hosts=es02,es03
|
||||
- cluster.initial_master_nodes=es01,es02,es03
|
||||
- bootstrap.memory_lock=true
|
||||
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
|
||||
ulimits:
|
||||
memlock:
|
||||
soft: -1
|
||||
hard: -1
|
||||
volumes:
|
||||
- data01:/usr/share/elasticsearch/data
|
||||
ports:
|
||||
- 9200:9200
|
||||
networks:
|
||||
- elastic
|
||||
es02:
|
||||
image: docker.elastic.co/elasticsearch/elasticsearch:7.15.2
|
||||
container_name: es02
|
||||
environment:
|
||||
- node.name=es02
|
||||
- cluster.name=es-docker-cluster
|
||||
- discovery.seed_hosts=es01,es03
|
||||
- cluster.initial_master_nodes=es01,es02,es03
|
||||
- bootstrap.memory_lock=true
|
||||
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
|
||||
ulimits:
|
||||
memlock:
|
||||
soft: -1
|
||||
hard: -1
|
||||
volumes:
|
||||
- data02:/usr/share/elasticsearch/data
|
||||
networks:
|
||||
- elastic
|
||||
es03:
|
||||
image: docker.elastic.co/elasticsearch/elasticsearch:7.15.2
|
||||
container_name: es03
|
||||
environment:
|
||||
- node.name=es03
|
||||
- cluster.name=es-docker-cluster
|
||||
- discovery.seed_hosts=es01,es02
|
||||
- cluster.initial_master_nodes=es01,es02,es03
|
||||
- bootstrap.memory_lock=true
|
||||
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
|
||||
ulimits:
|
||||
memlock:
|
||||
soft: -1
|
||||
hard: -1
|
||||
volumes:
|
||||
- data03:/usr/share/elasticsearch/data
|
||||
networks:
|
||||
- elastic
|
||||
volumes:
|
||||
database_data:
|
||||
driver: local
|
||||
data01:
|
||||
driver: local
|
||||
data02:
|
||||
driver: local
|
||||
data03:
|
||||
driver: local
|
||||
networks:
|
||||
elastic:
|
||||
driver: bridge
|
0
docker-compose/td.env
Normal file
0
docker-compose/td.env
Normal file
1
pom.xml
1
pom.xml
@ -33,6 +33,7 @@
|
||||
<id>complete</id>
|
||||
<modules>
|
||||
<module>service-td</module>
|
||||
<module>service-chats</module>
|
||||
</modules>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
@ -8,13 +8,13 @@
|
||||
<properties>
|
||||
<compiler-plugin.version>3.8.1</compiler-plugin.version>
|
||||
<maven.compiler.parameters>true</maven.compiler.parameters>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
|
||||
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
|
||||
<quarkus.platform.version>2.4.1.Final</quarkus.platform.version>
|
||||
<quarkus.platform.version>2.5.0.Final</quarkus.platform.version>
|
||||
<surefire-plugin.version>3.0.0-M5</surefire-plugin.version>
|
||||
<elasticsearch-reactive.version>0.2.0</elasticsearch-reactive.version>
|
||||
</properties>
|
||||
@ -145,6 +145,9 @@
|
||||
<systemPropertyVariables>
|
||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||
<maven.home>${maven.home}</maven.home>
|
||||
<junit.jupiter.execution.parallel.enabled>false</junit.jupiter.execution.parallel.enabled>
|
||||
<forkCount>1</forkCount>
|
||||
<reuseForks>false</reuseForks>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
@ -21,7 +21,7 @@
|
||||
# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/service-chats-jvm
|
||||
#
|
||||
###
|
||||
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4
|
||||
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.5
|
||||
|
||||
ARG JAVA_PACKAGE=java-11-openjdk-headless
|
||||
ARG RUN_JAVA_VERSION=1.3.8
|
||||
|
@ -21,7 +21,7 @@
|
||||
# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/service-chats-legacy-jar
|
||||
#
|
||||
###
|
||||
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4
|
||||
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.5
|
||||
|
||||
ARG JAVA_PACKAGE=java-11-openjdk-headless
|
||||
ARG RUN_JAVA_VERSION=1.3.8
|
||||
|
@ -14,7 +14,7 @@
|
||||
# docker run -i --rm -p 8080:8080 quarkus/service-chats
|
||||
#
|
||||
###
|
||||
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4
|
||||
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.5
|
||||
WORKDIR /work/
|
||||
RUN chown 1001 /work \
|
||||
&& chmod "g+rwX" /work \
|
||||
|
@ -30,8 +30,8 @@ public class Chat extends PanacheEntityBase {
|
||||
@Positive(message = "id is not positive")
|
||||
@Max(message = "id is too big", value = ChatId.MASK)
|
||||
@Column(nullable = false, unique = true)
|
||||
@JsonSerialize(using = ChatIdJsonSerializer.class)
|
||||
@JsonDeserialize(using = ChatIdJsonDeserializer.class)
|
||||
@JsonSerialize(using = ChatIdLongJsonSerializer.class)
|
||||
@JsonDeserialize(using = ChatIdLongJsonDeserializer.class)
|
||||
public Long id;
|
||||
|
||||
/**
|
||||
|
@ -1,116 +1,215 @@
|
||||
package io.volvox.chats;
|
||||
|
||||
public record ChatId(Type type, long subId) {
|
||||
import java.util.Objects;
|
||||
|
||||
public static final int SUB_ID_MASK_BYTES = 52;
|
||||
public static final int TYPE_MASK_BYTES = 2;
|
||||
public final class ChatId {
|
||||
private final Type type;
|
||||
private final long subId;
|
||||
|
||||
public static final long SUB_ID_MASK = 0b001111111111111111111111111111111111111111111111111111L;
|
||||
public static final long TYPE_MASK = 0b11L << SUB_ID_MASK_BYTES;
|
||||
public static final long MASK = SUB_ID_MASK | TYPE_MASK;
|
||||
public static final int TYPE_PRIVATE_INT = 0b00;
|
||||
public static final int TYPE_BASIC_INT = 0b01;
|
||||
public static final int TYPE_SUPER_INT = 0b10;
|
||||
public static final int TYPE_SECRET_INT = 0b11;
|
||||
public static final long TYPE_PRIVATE_LONG = 0;
|
||||
public static final long TYPE_BASIC_LONG = 0b01L << SUB_ID_MASK_BYTES & TYPE_MASK;
|
||||
public static final long TYPE_SUPER_LONG = 0b10L << SUB_ID_MASK_BYTES & TYPE_MASK;
|
||||
public static final long TYPE_SECRET_LONG = 0b11L << SUB_ID_MASK_BYTES & TYPE_MASK;
|
||||
public ChatId(Type type, long subId) {
|
||||
if ((subId & SUB_ID_MASK) != subId) {
|
||||
throw new IllegalArgumentException("subId is too big");
|
||||
}
|
||||
this.type = type;
|
||||
this.subId = subId;
|
||||
}
|
||||
|
||||
public ChatId {
|
||||
if ((subId & SUB_ID_MASK) != subId) {
|
||||
throw new IllegalArgumentException("subId is too big");
|
||||
}
|
||||
}
|
||||
public Type type() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static ChatId fromLong(long id) {
|
||||
return new ChatId(getType(id), getIdLong(id));
|
||||
}
|
||||
public long subId() {
|
||||
return subId;
|
||||
}
|
||||
|
||||
private static Type getType(long id) {
|
||||
return switch ((int) ((id & TYPE_MASK) >> SUB_ID_MASK_BYTES)) {
|
||||
case TYPE_SUPER_INT -> Type.SUPER;
|
||||
case TYPE_BASIC_INT -> Type.BASIC;
|
||||
case TYPE_PRIVATE_INT -> Type.PRIVATE;
|
||||
case TYPE_SECRET_INT -> Type.SECRET;
|
||||
default -> throw new IllegalArgumentException("Invalid id type: " + id);
|
||||
};
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || obj.getClass() != this.getClass()) {
|
||||
return false;
|
||||
}
|
||||
var that = (ChatId) obj;
|
||||
return Objects.equals(this.type, that.type) &&
|
||||
this.subId == that.subId;
|
||||
}
|
||||
|
||||
private static long getIdLong(long id) {
|
||||
return id & SUB_ID_MASK;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(type, subId);
|
||||
}
|
||||
|
||||
public long toLong() {
|
||||
return switch (type) {
|
||||
case SUPER -> TYPE_SUPER_LONG;
|
||||
case BASIC -> TYPE_BASIC_LONG;
|
||||
case PRIVATE -> TYPE_PRIVATE_LONG;
|
||||
case SECRET -> TYPE_SECRET_LONG;
|
||||
} | (subId & SUB_ID_MASK);
|
||||
}
|
||||
public static final int SUB_ID_MASK_BYTES = 52;
|
||||
public static final int TYPE_MASK_BYTES = 2;
|
||||
|
||||
public enum Type {
|
||||
PRIVATE,
|
||||
BASIC,
|
||||
SUPER,
|
||||
SECRET
|
||||
}
|
||||
public static final long SUB_ID_MASK = 0b001111111111111111111111111111111111111111111111111111L;
|
||||
public static final long TYPE_MASK = 0b11L << SUB_ID_MASK_BYTES;
|
||||
public static final long MASK = SUB_ID_MASK | TYPE_MASK;
|
||||
public static final int TYPE_PRIVATE_INT = 0b00;
|
||||
public static final int TYPE_BASIC_INT = 0b01;
|
||||
public static final int TYPE_SUPER_INT = 0b10;
|
||||
public static final int TYPE_SECRET_INT = 0b11;
|
||||
public static final long TYPE_PRIVATE_LONG = 0;
|
||||
public static final long TYPE_BASIC_LONG = 0b01L << SUB_ID_MASK_BYTES & TYPE_MASK;
|
||||
public static final long TYPE_SUPER_LONG = 0b10L << SUB_ID_MASK_BYTES & TYPE_MASK;
|
||||
public static final long TYPE_SECRET_LONG = 0b11L << SUB_ID_MASK_BYTES & TYPE_MASK;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(this);
|
||||
}
|
||||
public static ChatId fromLong(long id) {
|
||||
return new ChatId(getType(id), getIdLong(id));
|
||||
}
|
||||
|
||||
public static String toString(ChatId chatId) {
|
||||
return Long.toUnsignedString(chatId.subId) + "-" + switch (chatId.type) {
|
||||
case SUPER -> 's';
|
||||
case BASIC -> 'b';
|
||||
case PRIVATE -> 'u';
|
||||
case SECRET -> 'd';
|
||||
};
|
||||
}
|
||||
private static Type getType(long id) {
|
||||
switch ((int) ((id & TYPE_MASK) >> SUB_ID_MASK_BYTES)) {
|
||||
case TYPE_SUPER_INT:
|
||||
return Type.SUPER;
|
||||
case TYPE_BASIC_INT:
|
||||
return Type.BASIC;
|
||||
case TYPE_PRIVATE_INT:
|
||||
return Type.PRIVATE;
|
||||
case TYPE_SECRET_INT:
|
||||
return Type.SECRET;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid id type: " + id);
|
||||
}
|
||||
}
|
||||
|
||||
public static String toString(long chatId) {
|
||||
return Long.toUnsignedString(getIdLong(chatId)) + "-" + switch (getType(chatId)) {
|
||||
case SUPER -> 's';
|
||||
case BASIC -> 'b';
|
||||
case PRIVATE -> 'u';
|
||||
case SECRET -> 'd';
|
||||
};
|
||||
}
|
||||
private static long getIdLong(long id) {
|
||||
return id & SUB_ID_MASK;
|
||||
}
|
||||
|
||||
public static ChatId fromString(String chatId) {
|
||||
var parts = chatId.split("-", 2);
|
||||
if (parts.length != 2) {
|
||||
throw new IllegalArgumentException("Malformed chat id");
|
||||
}
|
||||
if (parts[1].length() != 1) {
|
||||
throw new IllegalArgumentException("Chat type is too long");
|
||||
}
|
||||
return new ChatId(switch(parts[1].charAt(0)) {
|
||||
case 's' -> Type.SUPER;
|
||||
case 'b' -> Type.BASIC;
|
||||
case 'u' -> Type.PRIVATE;
|
||||
case 'd' -> Type.SECRET;
|
||||
default -> throw new IllegalStateException("Unexpected value: " + parts[1].charAt(0));
|
||||
}, Long.parseUnsignedLong(parts[0]) & SUB_ID_MASK);
|
||||
}
|
||||
public long toLong() {
|
||||
long result;
|
||||
switch (type) {
|
||||
case SUPER:
|
||||
result = TYPE_SUPER_LONG;
|
||||
break;
|
||||
case BASIC:
|
||||
result = TYPE_BASIC_LONG;
|
||||
break;
|
||||
case PRIVATE:
|
||||
result = TYPE_PRIVATE_LONG;
|
||||
break;
|
||||
case SECRET:
|
||||
result = TYPE_SECRET_LONG;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected value: " + type);
|
||||
}
|
||||
result |= (subId & SUB_ID_MASK);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Long stringToLong(String chatId) {
|
||||
var parts = chatId.split("-", 2);
|
||||
if (parts.length != 2) {
|
||||
throw new IllegalArgumentException("Malformed chat id");
|
||||
}
|
||||
if (parts[1].length() != 1) {
|
||||
throw new IllegalArgumentException("Chat type is too long");
|
||||
}
|
||||
return switch(parts[1].charAt(0)) {
|
||||
case 's' -> TYPE_SUPER_LONG;
|
||||
case 'b' -> TYPE_BASIC_LONG;
|
||||
case 'u' -> TYPE_PRIVATE_LONG;
|
||||
case 'd' -> TYPE_SECRET_LONG;
|
||||
default -> throw new IllegalStateException("Unexpected value: " + parts[1].charAt(0));
|
||||
} | (Long.parseUnsignedLong(parts[0]) & SUB_ID_MASK);
|
||||
}
|
||||
public enum Type {
|
||||
PRIVATE,
|
||||
BASIC,
|
||||
SUPER,
|
||||
SECRET
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(this);
|
||||
}
|
||||
|
||||
public static String toString(ChatId chatId) {
|
||||
char suffix;
|
||||
switch (chatId.type) {
|
||||
case SUPER:
|
||||
suffix = 's';
|
||||
break;
|
||||
case BASIC:
|
||||
suffix = 'b';
|
||||
break;
|
||||
case PRIVATE:
|
||||
suffix = 'u';
|
||||
break;
|
||||
case SECRET:
|
||||
suffix = 'd';
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected value: " + chatId.type);
|
||||
}
|
||||
return Long.toUnsignedString(chatId.subId) + "-" + suffix;
|
||||
}
|
||||
|
||||
public static String toString(long chatId) {
|
||||
char suffix;
|
||||
switch (getType(chatId)) {
|
||||
case SUPER:
|
||||
suffix = 's';
|
||||
break;
|
||||
case BASIC:
|
||||
suffix = 'b';
|
||||
break;
|
||||
case PRIVATE:
|
||||
suffix = 'u';
|
||||
break;
|
||||
case SECRET:
|
||||
suffix = 'd';
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected value: " + chatId);
|
||||
}
|
||||
return Long.toUnsignedString(getIdLong(chatId)) + "-" + suffix;
|
||||
}
|
||||
|
||||
public static ChatId fromString(String chatId) {
|
||||
var parts = chatId.split("-", 2);
|
||||
if (parts.length != 2) {
|
||||
throw new IllegalArgumentException("Malformed chat id");
|
||||
}
|
||||
if (parts[1].length() != 1) {
|
||||
throw new IllegalArgumentException("Chat type is too long");
|
||||
}
|
||||
|
||||
Type type;
|
||||
switch (parts[1].charAt(0)) {
|
||||
case 's':
|
||||
type = Type.SUPER;
|
||||
break;
|
||||
case 'b':
|
||||
type = Type.BASIC;
|
||||
break;
|
||||
case 'u':
|
||||
type = Type.PRIVATE;
|
||||
break;
|
||||
case 'd':
|
||||
type = Type.SECRET;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected value: " + parts[1].charAt(0));
|
||||
}
|
||||
|
||||
return new ChatId(type, Long.parseUnsignedLong(parts[0]) & SUB_ID_MASK);
|
||||
}
|
||||
|
||||
public static Long stringToLong(String chatId) {
|
||||
var parts = chatId.split("-", 2);
|
||||
if (parts.length != 2) {
|
||||
throw new IllegalArgumentException("Malformed chat id");
|
||||
}
|
||||
if (parts[1].length() != 1) {
|
||||
throw new IllegalArgumentException("Chat type is too long");
|
||||
}
|
||||
long result;
|
||||
switch (parts[1].charAt(0)) {
|
||||
case 's':
|
||||
result = TYPE_SUPER_LONG;
|
||||
break;
|
||||
case 'b':
|
||||
result = TYPE_BASIC_LONG;
|
||||
break;
|
||||
case 'u':
|
||||
result = TYPE_PRIVATE_LONG;
|
||||
break;
|
||||
case 'd':
|
||||
result = TYPE_SECRET_LONG;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected value: " + parts[1].charAt(0));
|
||||
}
|
||||
result |= (Long.parseUnsignedLong(parts[0]) & SUB_ID_MASK);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ChatIdJsonDeserializer extends JsonDeserializer<Long> {
|
||||
public class ChatIdJsonDeserializer extends JsonDeserializer<ChatId> {
|
||||
|
||||
@Override
|
||||
public Long deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
||||
public ChatId deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
||||
var id = p.readValueAs(String.class);
|
||||
return ChatId.stringToLong(id);
|
||||
return ChatId.fromString(id);
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,10 @@ import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ChatIdJsonSerializer extends JsonSerializer<Long> {
|
||||
public class ChatIdJsonSerializer extends JsonSerializer<ChatId> {
|
||||
|
||||
@Override
|
||||
public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
public void serialize(ChatId value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
gen.writeString(ChatId.toString(value));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
package io.volvox.chats;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ChatIdLongJsonDeserializer extends JsonDeserializer<Long> {
|
||||
|
||||
@Override
|
||||
public Long deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
||||
var id = p.readValueAs(String.class);
|
||||
return ChatId.stringToLong(id);
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package io.volvox.chats;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ChatIdLongJsonSerializer extends JsonSerializer<Long> {
|
||||
|
||||
@Override
|
||||
public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
gen.writeString(ChatId.toString(value));
|
||||
}
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
package io.volvox.chats;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize.Typing;
|
||||
import io.smallrye.mutiny.Multi;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import java.net.URI;
|
||||
@ -20,6 +23,8 @@ import javax.ws.rs.core.Response;
|
||||
@ApplicationScoped
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@JsonSerialize(using = ChatIdLongJsonSerializer.class, as = ChatId.class, typing = Typing.STATIC)
|
||||
@JsonDeserialize(using = ChatIdLongJsonDeserializer.class, as = ChatId.class)
|
||||
public class ChatResource {
|
||||
|
||||
@Inject
|
||||
@ -32,8 +37,8 @@ public class ChatResource {
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
public Uni<Chat> get(@PathParam("id") Long id) {
|
||||
return chatService.get(id);
|
||||
public Uni<Chat> get(@PathParam("id") ChatId id) {
|
||||
return chatService.get(id.toLong());
|
||||
}
|
||||
|
||||
@POST
|
||||
@ -44,14 +49,14 @@ public class ChatResource {
|
||||
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
public Uni<Chat> update(@PathParam("id") Long id, Chat chat) {
|
||||
return chatService.update(id, chat);
|
||||
public Uni<Chat> update(@PathParam("id") ChatId id, Chat chat) {
|
||||
return chatService.update(id.toLong(), chat);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
public Uni<Void> delete(@PathParam("id") Long id) {
|
||||
return chatService.delete(id);
|
||||
public Uni<Void> delete(@PathParam("id") ChatId id) {
|
||||
return chatService.delete(id.toLong());
|
||||
}
|
||||
|
||||
@GET
|
||||
|
@ -2,16 +2,18 @@ quarkus.http.port=8282
|
||||
# we don't need SSL here, let's disable it to have a more compact native executable
|
||||
quarkus.ssl.native=false
|
||||
|
||||
%prod.quarkus.datasource.db-kind=postgresql
|
||||
%prod.quarkus.datasource.username=quarkus_test
|
||||
%prod.quarkus.datasource.password=quarkus_test
|
||||
quarkus.datasource.db-kind=postgresql
|
||||
%dev.quarkus.datasource.username=quarkus_test
|
||||
%dev.quarkus.datasource.password=quarkus_test
|
||||
%prod.quarkus.datasource.username=volvox
|
||||
%prod.quarkus.datasource.password=volvox
|
||||
|
||||
quarkus.hibernate-orm.database.generation=drop-and-create
|
||||
quarkus.hibernate-orm.log.sql=true
|
||||
quarkus.hibernate-orm.sql-load-script=import.sql
|
||||
quarkus.hibernate-orm.database.generation=update
|
||||
%dev.quarkus.datasource.devservices.enabled=true
|
||||
%dev.quarkus.datasource.devservices.image-name=postgres
|
||||
|
||||
# Reactive config
|
||||
%prod.quarkus.datasource.reactive.url=vertx-reactive:postgresql://localhost/quarkus_test
|
||||
quarkus.vertx.prefer-native-transport=true
|
||||
%prod.quarkus.datasource.reactive.url=vertx-reactive:postgresql://database/volvox-chats
|
||||
|
||||
quarkus.elasticsearch.health.enabled=false
|
||||
quarkus.elasticsearch.reactive.health.enabled=true
|
||||
quarkus.elasticsearch.hosts=searchengine:9200
|
||||
|
@ -41,7 +41,7 @@ public class ChatsEndpointTest {
|
||||
.when()
|
||||
.body("{\"name\" : \"Telegram Official\"}")
|
||||
.contentType("application/json")
|
||||
.put("/chats/777000")
|
||||
.put("/chats/777000-u")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.body(
|
||||
@ -62,7 +62,7 @@ public class ChatsEndpointTest {
|
||||
//Delete Telegram:
|
||||
given()
|
||||
.when()
|
||||
.delete("/chats/777000")
|
||||
.delete("/chats/777000-u")
|
||||
.then()
|
||||
.statusCode(204);
|
||||
|
||||
@ -101,7 +101,7 @@ public class ChatsEndpointTest {
|
||||
public void testEntityNotFoundForDelete() {
|
||||
given()
|
||||
.when()
|
||||
.delete("/chats/777123")
|
||||
.delete("/chats/777123-u")
|
||||
.then()
|
||||
.statusCode(404)
|
||||
.body(emptyString());
|
||||
@ -113,7 +113,7 @@ public class ChatsEndpointTest {
|
||||
.when()
|
||||
.body("{\"id\": \"777234-u\", \"name\" : \"Juan\"}")
|
||||
.contentType("application/json")
|
||||
.put("/chats/777234")
|
||||
.put("/chats/777234-u")
|
||||
.then()
|
||||
.statusCode(200);
|
||||
}
|
||||
@ -124,7 +124,7 @@ public class ChatsEndpointTest {
|
||||
.when()
|
||||
.body("{\"name\" : \"Juan\"}")
|
||||
.contentType("application/json")
|
||||
.put("/chats/777234")
|
||||
.put("/chats/777234-u")
|
||||
.then()
|
||||
.statusCode(500);
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
package io.volvox.chats;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusIntegrationTest;
|
||||
|
||||
@QuarkusIntegrationTest
|
||||
public class ChatsEndpointTestIT extends ChatsEndpointTest {
|
||||
|
||||
// Execute the same tests but in native mode.
|
||||
}
|
@ -1,12 +1,17 @@
|
||||
package io.volvox.chats;
|
||||
|
||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||
import io.quarkus.logging.Log;
|
||||
import io.reactiverse.elasticsearch.client.mutiny.RestHighLevelClient;
|
||||
import io.smallrye.mutiny.Multi;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.inject.Inject;
|
||||
import org.elasticsearch.ElasticsearchStatusException;
|
||||
import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest;
|
||||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.flush.FlushRequest;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
||||
@ -14,6 +19,7 @@ import org.elasticsearch.action.update.UpdateRequest;
|
||||
import org.elasticsearch.action.update.UpdateResponse;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.indices.CreateIndexRequest;
|
||||
import org.elasticsearch.common.collect.List;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
@ -24,14 +30,29 @@ public class ChatsServiceWarmup {
|
||||
@Inject
|
||||
RestHighLevelClient restHighLevelClient;
|
||||
|
||||
|
||||
public void warmup() {
|
||||
try {
|
||||
resetDb();
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
createIndices();
|
||||
chatService.listAll().onItem().transformToUni(this::updateIndex).merge().select().last().toUni().await()
|
||||
chatService.listAll().onItem().transformToUni(this::updateIndex).merge().collect().last().await()
|
||||
.indefinitely();
|
||||
|
||||
restHighLevelClient.indices().flushAsyncAndAwait(new FlushRequest("chats"), RequestOptions.DEFAULT);
|
||||
restHighLevelClient.indices().flushAsyncAndAwait(new FlushRequest("chats").force(true).waitIfOngoing(true), RequestOptions.DEFAULT);
|
||||
restHighLevelClient.indices().refreshAsyncAndAwait(new RefreshRequest("chats"), RequestOptions.DEFAULT);
|
||||
restHighLevelClient.indices().clearCacheAsyncAndAwait(new ClearIndicesCacheRequest("chats"), RequestOptions.DEFAULT);
|
||||
}
|
||||
|
||||
private void resetDb() throws IOException {
|
||||
var db = new String(Objects
|
||||
.requireNonNull(ChatsServiceWarmup.class.getResourceAsStream("/import.sql"), "Cannot find import.sql")
|
||||
.readAllBytes());
|
||||
Panache.getSession().flatMap(sess -> Multi.createFrom().iterable(List.of(db.split("\n")))
|
||||
.filter(s -> !s.isBlank() && !s.startsWith("#"))
|
||||
.onItem().transformToUni(query -> sess.createNativeQuery(query).executeUpdate()).merge().collect().last()).await()
|
||||
.indefinitely();
|
||||
}
|
||||
|
||||
private void createIndices() {
|
||||
|
@ -1,3 +1,5 @@
|
||||
TRUNCATE chat, chat_name, chat_username CASCADE;
|
||||
|
||||
INSERT INTO chat(id, status, name, username) VALUES (9007199256673076, 1, 'My Supergroup', 'mysupergroup');
|
||||
INSERT INTO chat_name(chat_id, id, time, name) VALUES (9007199256673076, 12345000, current_timestamp, 'My Supergroup');
|
||||
INSERT INTO chat_username(chat_id, id, time, username) VALUES (9007199256673076, 12345001, current_timestamp, 'mysupergroup');
|
@ -8,13 +8,13 @@
|
||||
<properties>
|
||||
<compiler-plugin.version>3.8.1</compiler-plugin.version>
|
||||
<maven.compiler.parameters>true</maven.compiler.parameters>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
|
||||
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
|
||||
<quarkus.platform.version>2.4.1.Final</quarkus.platform.version>
|
||||
<quarkus.platform.version>2.5.0.Final</quarkus.platform.version>
|
||||
<surefire-plugin.version>3.0.0-M5</surefire-plugin.version>
|
||||
<volvox.tdlight.version>2.7.9.2</volvox.tdlight.version>
|
||||
<volvox.tdlight.natives.version>4.0.183</volvox.tdlight.natives.version>
|
||||
@ -87,6 +87,11 @@
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>it.tdlight</groupId>
|
||||
|
@ -72,7 +72,8 @@ public class TdEventBusClient implements TdClient {
|
||||
@ConsumeEvent(value = "td.send", codec = TdObjectCodec.class)
|
||||
public void onSendRequest(Message<TdObjectCodec.TdObject> msg) {
|
||||
this.send(msg.body().getObject()).subscribe().with(message -> msg.reply(message, SEND_OPTS), ex -> {
|
||||
if (ex instanceof TelegramException tdException) {
|
||||
if (ex instanceof TelegramException) {
|
||||
TelegramException tdException = (TelegramException) ex;
|
||||
msg.fail(tdException.getCode(), tdException.getMessage());
|
||||
} else {
|
||||
msg.fail(500, ex.toString());
|
||||
|
@ -46,9 +46,14 @@ public class TdService {
|
||||
}
|
||||
|
||||
void shutdown(@Observes ShutdownEvent event) {
|
||||
clients.forEach((uuid, client) -> client.dispose());
|
||||
disposeAll();
|
||||
}
|
||||
|
||||
public void disposeAll() {
|
||||
clients.forEach((uuid, client) -> client.dispose());
|
||||
clients.clear();
|
||||
}
|
||||
|
||||
public Optional<TdClient> get(String uuid) {
|
||||
if (uuid == null) return Optional.empty();
|
||||
return Optional.ofNullable(clients.get(uuid));
|
||||
|
@ -1,18 +1,22 @@
|
||||
package io.volvox.td;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.text.IsEmptyString.emptyOrNullString;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import java.util.Set;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import javax.inject.Inject;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@QuarkusTest
|
||||
public class TdResourceTest {
|
||||
|
||||
@Inject TdService tdService;
|
||||
|
||||
@Test
|
||||
public void testEmptyList() {
|
||||
given()
|
||||
@ -50,18 +54,22 @@ public class TdResourceTest {
|
||||
.body()
|
||||
.asString();
|
||||
|
||||
var expectedBodyElems = Set.of(sessionId1, sessionId2);
|
||||
var bodyElems = given()
|
||||
.when().get("/td/list")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.body()
|
||||
.asString()
|
||||
.split("\n");
|
||||
|
||||
var bodyElems = Set.of(given()
|
||||
.when().get("/td/list")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.body()
|
||||
.asString()
|
||||
.split("\n"));
|
||||
|
||||
Assertions.assertEquals(expectedBodyElems, bodyElems);
|
||||
assertThat(bodyElems).containsExactlyInAnyOrder(sessionId1, sessionId2);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
@AfterEach
|
||||
public void resetTdServices() {
|
||||
tdService.disposeAll();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user