Skip to content

Commit

Permalink
Add alpha version of load-simulator
Browse files Browse the repository at this point in the history
Add SWAGGER.md to protect newbie
  • Loading branch information
YuikoSempai committed May 11, 2024
1 parent f49a30e commit d644ff7
Show file tree
Hide file tree
Showing 8 changed files with 321 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ An IoT service with mobile client and microservices arhitecture.

# Content

- [Technical task](./doc/technical-task.md)
- [Technical task](./doc/technical-task.md)
- [Swagger](doc/SWAGGER.md)
105 changes: 105 additions & 0 deletions doc/SWAGGER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Swagger Mosquitto(mqtt)

[ConnectionTask](../common/src/main/kotlin/org/vivlaniv/nexohub/ConnectionTask.kt)

## $user/fetch/devices

### /in

Check failure on line 7 in doc/SWAGGER.md

View workflow job for this annotation

GitHub Actions / lint

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### /in"]
FetchSavedDevicesTask
```json lines

Check failure on line 9 in doc/SWAGGER.md

View workflow job for this annotation

GitHub Actions / lint

Fenced code blocks should be surrounded by blank lines [Context: "```json lines"]
{
"id": String
}
```

Check failure on line 13 in doc/SWAGGER.md

View workflow job for this annotation

GitHub Actions / lint

Fenced code blocks should be surrounded by blank lines [Context: "```"]
### /out

Check failure on line 14 in doc/SWAGGER.md

View workflow job for this annotation

GitHub Actions / lint

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Above] [Context: "### /out"]

Check failure on line 14 in doc/SWAGGER.md

View workflow job for this annotation

GitHub Actions / lint

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### /out"]
FetchSavedDevicesTaskResult
```json lines

Check failure on line 16 in doc/SWAGGER.md

View workflow job for this annotation

GitHub Actions / lint

Fenced code blocks should be surrounded by blank lines [Context: "```json lines"]
{
"tid": String,
"code": Int,
"errorMessage": String?,
"devices": List<SavedDevice>?
}
```

## $user/property

### /in

Check failure on line 27 in doc/SWAGGER.md

View workflow job for this annotation

GitHub Actions / lint

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### /in"]

Check failure on line 27 in doc/SWAGGER.md

View workflow job for this annotation

GitHub Actions / lint

Multiple headings with the same content [Context: "### /in"]
PutDevicePropertyTask
```json lines

Check failure on line 29 in doc/SWAGGER.md

View workflow job for this annotation

GitHub Actions / lint

Fenced code blocks should be surrounded by blank lines [Context: "```json lines"]
{
"id": String,
"device": String,
"property": String,
"value": Int
}
```
### /out
PutDevicePropertyTaskResult
```json lines
{
"tid": String,
"code": Int,
"errorMessage": String?,
"device": String,
}
```

## $user/fetch/props
### /in
FetchDevicesPropertiesTask
```json lines
{
"id": String,
"include": List<String>?,
}
```
### /out
FetchDevicesPropertiesTaskResult
```json lines
{
"tid": String,
"code": Int,
"errorMessage": String?,
"properties": Map<String, List<PropertyInfo>>?
}
```

## $user/save
### /in
SaveDeviceTask
```json lines
{
"id": String,
"device": String,
"room": String?,
"alias": String?
}
```
### /out
SaveDeviceTaskResult
```json lines
{
"tid": String,
"code": Int,
"errorMessage": String?
}
```

## $user/search

### /in
SearchDevicesTask
```json lines
{
"id": String
}
```
### /out
SearchDevicesTaskResult
```json lines
{
"tid": String,
"devices": List<DeviceInfo>
}
```
21 changes: 21 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
version: "3.9"
# TODO:: add mosquito
services:
redis:
image: redis:latest
restart: always
ports:
- "6379:6379"
environment:
- REDIS_PASSWORD=my-password
- REDIS_PORT=6379
- REDIS_DATABASES=16

postgres:
image: postgres:13.3
environment:
POSTGRES_DB: "postgres"
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "postgres"
ports:
- "5432:5432"
24 changes: 24 additions & 0 deletions load-simulator/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
plugins {
alias(libs.plugins.jetbrainsKotlinJvm)
alias(libs.plugins.kotlinSerialization)
}

group = "org.vivlaniv.nexohub"

dependencies {
testImplementation("org.jetbrains.kotlin:kotlin-test")
implementation(project(":common"))
implementation(project(":log-service"))
implementation(libs.redisson)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.serialization.json)
implementation(libs.org.eclipse.paho.client.mqttv3)
testImplementation(libs.junit.jupiter.api)
testRuntimeOnly(libs.junit.jupiter.engine)

implementation("org.apache.commons:commons-lang3:3.0")
}

tasks.getByName<Test>("test") {
useJUnitPlatform()
}
49 changes: 49 additions & 0 deletions load-simulator/src/main/kotlin/org/vivlaniv/nexohub/Main.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.vivlaniv.nexohub

import org.apache.commons.lang3.RandomStringUtils
import org.eclipse.paho.client.mqttv3.MqttClient
import org.eclipse.paho.client.mqttv3.MqttConnectOptions
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence
import org.slf4j.LoggerFactory
import java.util.*

// Цель: каждому пользователю создать устройство, после чего получить его в списке

fun main() {
val log = LoggerFactory.getLogger("load-simulator")
log.info("Load-simulator service started")
log.info("Load-simulator service started")

val prop = Properties().also {
it.load(ClassLoader.getSystemResourceAsStream("application.properties"))
}
val mqttUrl = prop.getProperty("mqtt.url", "tcp://localhost:1883")
val usersCount = prop.getProperty("app.users.count", "10").toInt()

val mqttConfig = MqttConnectOptions()
mqttConfig.isAutomaticReconnect = true
mqttConfig.isCleanSession = true
mqttConfig.connectionTimeout = 10
val mqttClient = MqttClient(mqttUrl, MqttClient.generateClientId(), MemoryPersistence())
mqttClient.connect(mqttConfig)
val adapter = MqttClientAdapter(mqttClient, log)
log.info("Configuration is done")

log.info("Start generate load")

val usernamesList = generateUsernames(usersCount)
log.info("Users for load test: $usernamesList")
// TODO:: add several scenarios and users
val user = "user"
log.info("Start scenario for username: $user")
scenario(adapter, user)
}

fun generateUsernames(usersCount: Int): List<String> {
val randomList = List(usersCount) { RandomStringUtils.randomAlphabetic(usersCount) }
return randomList
}

fun scenario(adapter: MqttClientAdapter, username: String) {
adapter.startScenario(username)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package org.vivlaniv.nexohub

import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import org.eclipse.paho.client.mqttv3.MqttClient
import org.slf4j.Logger

class MqttClientAdapter(
private val mqttClient: MqttClient,
private val logger: Logger
) {
private fun sendFetchSavedDevicesTask(user: String) {
val task = FetchSavedDevicesTask()
mqttClient.publish("$user/fetch/devices/in", Json.encodeToString(task).encodeToByteArray(), 2, false)
}

private fun getFetchSavedDevicesTaskResult(user: String) {
mqttClient.subscribe("$user/fetch/devices/out") { _, msg ->
println("got fetch saved devices task for $user: $msg")
val result = Json.decodeFromString<FetchSavedDevicesTaskResult>(msg.payload.decodeToString())
if (result.errorMessage == null) {
for (device in result.devices!!) {
logger.info("Got device for $user: ${device.type}")
}
} else {
logger.error(result.errorMessage)
}
}
}

private fun sendPutDevicePropertyTask(user: String, device: String, property: String, value: Int) {
val task = PutDevicePropertyTask(
device = device,
property = property,
value = value
)
mqttClient.publish("$user/property/in", Json.encodeToString(task).encodeToByteArray(), 2, false)
}

private fun getPutDevicePropertyTaskResult(user: String) {
mqttClient.subscribe("$user/property/out") { _, msg ->
println("got put device property task for $user: $msg")
}
}

private fun sendFetchDevicesPropertiesTask(user: String, include: List<String>?) {
val task = FetchDevicesPropertiesTask(include = include)
mqttClient.publish("$user/fetch/props/in", Json.encodeToString(task).encodeToByteArray(), 2, false)
}

private fun getFetchDevicesPropertiesTaskResult(user: String) {
mqttClient.subscribe("$user/fetch/props/out") { _, msg ->
println("got fetch devices properties task for $user: $msg")
}
}

private fun sendSaveDeviceTask(user: String, device: String, room: String?, alias: String?) {
val task = SaveDeviceTask(
device = device,
room = room,
alias = alias
)
mqttClient.publish("$user/save/in", Json.encodeToString(task).encodeToByteArray(), 2, false)
}

private fun getSaveDeviceTaskResult(user: String) {
mqttClient.subscribe("user/save/out") { topic, msg ->
println("got save device task for $user: $msg")

mqttClient.unsubscribe(topic)
}
}

private fun sendSearchDevicesTask(user: String) {
val task = SearchDevicesTask()
mqttClient.publish("$user/search/in", Json.encodeToString(task).encodeToByteArray(), 2, false)
}


private fun getSearchDevicesTaskResult(user: String) {
mqttClient.subscribe("$user/search/out") { topic, msg ->
println("got search devices task for $user: $msg")
val result = Json.decodeFromString<SearchDevicesTaskResult>(msg.payload.decodeToString())
if (result.errorMessage == null) {
for (device in result.devices!!) {
logger.info("Send save device task")
sendSaveDeviceTask(user, device.id, "Kronverksky Prospekt 49", "home")
mqttClient.unsubscribe(topic)
}
} else {
logger.error(result.errorMessage)
}
}
}

fun startScenario(user: String) {
getSearchDevicesTaskResult(user)
getSaveDeviceTaskResult(user)
sendSearchDevicesTask(user)
getFetchSavedDevicesTaskResult(user)
sendFetchSavedDevicesTask(user)
}
}
Empty file.
17 changes: 17 additions & 0 deletions load-simulator/src/main/resources/logback.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<configuration>
<variable resource="app.properties"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="LOG-SERVICE" class="org.vivlaniv.nexohub.LogServiceAppender">
<redisUrl>${redis.url:-redis://localhost:6379}</redisUrl>
<logsTopic>${topic.logs:-logs}</logsTopic>
<serviceName>load-simulator</serviceName>
</appender>
<root level="info">
<appender-ref ref="STDOUT"/>
<appender-ref ref="LOG-SERVICE"/>
</root>
</configuration>

0 comments on commit d644ff7

Please sign in to comment.