create docker-compose

This commit is contained in:
Andrea Cavalli 2021-12-01 14:23:42 +01:00
parent da55d49316
commit 02ed372d99
25 changed files with 441 additions and 165 deletions

3
docker-compose/chats.env Normal file
View File

@ -0,0 +1,3 @@
QUARKUS_DATASOURCE_REACTIVE_URL=vertx-reactive:postgresql://database:5432/volvox
QUARKUS_DATASOURCE_USERNAME=volvox
QUARKUS_DATASOURCE_PASSWORD=volvox

View File

@ -0,0 +1,3 @@
POSTGRES_USER=volvox
POSTGRES_PASSWORD=volvox
POSTGRES_DB=volvox

View 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
View File

View File

@ -33,6 +33,7 @@
<id>complete</id>
<modules>
<module>service-td</module>
<module>service-chats</module>
</modules>
</profile>
</profiles>

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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 \

View File

@ -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;
/**

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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.
}

View File

@ -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() {

View File

@ -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');

View File

@ -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>

View File

@ -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());

View File

@ -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));

View File

@ -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();
}
}