Skip to content

Commit

Permalink
Remover Spring Boot (#622)
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagohm authored Oct 9, 2024
2 parents 3be0ea6 + 18c114d commit aafe107
Show file tree
Hide file tree
Showing 169 changed files with 2,450 additions and 2,145 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
run: chmod +x gradlew

- name: Build
run: ./gradlew --no-daemon :api:bootJar
run: ./gradlew --no-daemon :api:shadowJar

- name: Upload Artifact
uses: actions/upload-artifact@v4
Expand Down
12 changes: 3 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
.PHONY: api desktop bootRun build install
.PHONY: api desktop build install

ifeq ($(OS),Windows_NT)
api:
gradlew.bat api:bootJar
gradlew.bat api:shadowJar

desktop:
cd desktop && npm run electron:build

bootRun:
gradlew.bat api:bootRun --args='--server.port=7000'
else
api:
./gradlew api:bootJar
./gradlew api:shadowJar

desktop:
cd desktop && npm run electron:build:deb

bootRun:
./gradlew api:bootRun --args='--server.port=7000'

install:
sudo dpkg -i desktop/release/nebulosa_0.1.0_amd64.deb
endif
Expand Down
2 changes: 1 addition & 1 deletion api/Main.run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
value="nebulosa.api.MainKt"/>
<module name="nebulosa.api.main"/>
<option name="PROGRAM_PARAMETERS"
value="--server.port=7000 --spring.jpa.show-sql=true --logging.level.nebulosa=DEBUG"/>
value="--port=7000"/>
<shortenClasspath name="NONE"/>
<method v="2">
<option name="Gradle.BeforeRunTask"
Expand Down
33 changes: 12 additions & 21 deletions api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import org.springframework.boot.gradle.tasks.bundling.BootJar
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

plugins {
kotlin("jvm")
id("org.springframework.boot") version "3.3.3"
id("io.spring.dependency-management") version "1.1.6"
kotlin("plugin.spring")
kotlin("kapt")
id("io.objectbox")
id("com.gradleup.shadow")
}

dependencies {
Expand Down Expand Up @@ -38,30 +36,23 @@ dependencies {
implementation(libs.eventbus)
implementation(libs.okhttp)
implementation(libs.oshi)
implementation("org.springframework.boot:spring-boot-starter")
implementation("org.springframework.boot:spring-boot-starter-web") {
exclude(module = "spring-boot-starter-tomcat")
}
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-websocket") {
exclude(module = "spring-boot-starter-tomcat")
}
implementation("org.springframework.boot:spring-boot-starter-undertow")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
annotationProcessor("org.springframework:spring-context-indexer:6.1.12")
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
implementation(libs.javalin)
implementation(libs.koin)
implementation(libs.airline)

testImplementation(project(":nebulosa-astrobin-api"))
testImplementation(project(":nebulosa-skycatalog-stellarium"))
testImplementation(project(":nebulosa-test"))
}

tasks.withType<BootJar> {
archiveFileName = "api.jar"
destinationDirectory = file("$rootDir/desktop")
tasks.withType<ShadowJar> {
isZip64 = true

archiveFileName.set("api.jar")
destinationDirectory.set(file("../desktop"))

manifest {
attributes["Start-Class"] = "nebulosa.api.MainKt"
attributes["Main-Class"] = "nebulosa.api.MainKt"
}
}

Expand Down
47 changes: 12 additions & 35 deletions api/src/main/kotlin/nebulosa/api/Main.kt
Original file line number Diff line number Diff line change
@@ -1,57 +1,34 @@
package nebulosa.api

import com.github.rvesse.airline.SingleCommand
import com.sun.jna.Platform
import nebulosa.time.SystemClock
import org.springframework.boot.runApplication
import java.nio.file.Path
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.*
import javax.swing.filechooser.FileSystemView
import kotlin.io.path.Path
import kotlin.io.path.createDirectories
import kotlin.io.path.deleteIfExists
import kotlin.io.path.exists
import kotlin.io.path.listDirectoryEntries

const val APP_DIR_KEY = "app.dir"

fun initAppDirectory(): Path {
val appPath = when {
Platform.isLinux() -> Path.of(System.getProperty("user.home"), ".nebulosa")
Platform.isWindows() -> Path.of(FileSystemView.getFileSystemView().defaultDirectory.path, "Nebulosa")
Platform.isLinux() -> Path(System.getProperty("user.home"), ".nebulosa")
Platform.isWindows() -> Path(FileSystemView.getFileSystemView().defaultDirectory.path, "Nebulosa")
else -> throw IllegalStateException("unsupported operating system")
}

appPath.createDirectories()
System.setProperty("app.dir", "$appPath")
return appPath
}

private fun Path.clearLogIfPastDays(days: Long = 7L) {
if (exists()) {
val pastDays = LocalDate.now(SystemClock).minusDays(days)

for (entry in listDirectoryEntries("nebulosa-*.log")) {
val logDate = entry.fileName.toString()
.replace("nebulosa-", "")
.replace(".log", "")
.let { runCatching { LocalDate.parse(it, DateTimeFormatter.ISO_LOCAL_DATE) }.getOrNull() }
?: continue

if (pastDays.isAfter(logDate)) {
entry.deleteIfExists()
}
}
}
.createDirectories()
.also { System.setProperty(APP_DIR_KEY, "$it") }
}

fun main(args: Array<String>) {
with(initAppDirectory()) {
Path.of("$this", "logs").createDirectories().clearLogIfPastDays()
Path.of("$this", "data").createDirectories().also { System.setProperty("DATA_PATH", "$it") }
}
initAppDirectory()

// Sets default locale to en_US.
Locale.setDefault(Locale.ENGLISH)

// Run the Spring Boot application.
runApplication<Nebulosa>(*args)
val parser = SingleCommand.singleCommand(Nebulosa::class.java)
val nebulosa = parser.parse(*args)
nebulosa.run()
}
77 changes: 69 additions & 8 deletions api/src/main/kotlin/nebulosa/api/Nebulosa.kt
Original file line number Diff line number Diff line change
@@ -1,20 +1,81 @@
package nebulosa.api

import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.module.kotlin.jsonMapper
import com.github.rvesse.airline.annotations.Command
import com.github.rvesse.airline.annotations.Option
import io.javalin.Javalin
import io.javalin.json.JavalinJackson
import nebulosa.api.atlas.Location
import nebulosa.api.beans.modules.DeviceModule
import nebulosa.api.inject.*
import nebulosa.json.PathModule
import nebulosa.log.loggerFor
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent
import org.springframework.context.event.EventListener
import org.koin.core.context.startKoin
import java.util.concurrent.ConcurrentHashMap

@SpringBootApplication
class Nebulosa {
@Command(name = "nebulosa")
class Nebulosa : Runnable, AutoCloseable {

@EventListener
private fun onServletWebServerInitializedEvent(event: ServletWebServerInitializedEvent) {
LOG.info("server is started at port: ${event.webServer.port}")
@Option(name = ["-h", "--host"])
private var host = "0.0.0.0"

@Option(name = ["-p", "--port"])
private var port = 0

private lateinit var app: Javalin

override fun run() {
// Run the server.
app = Javalin.create { config ->
config.showJavalinBanner = false
// JACKSON
config.jsonMapper(JavalinJackson(OBJECT_MAPPER))
// CORS
config.bundledPlugins.enableCors { cors ->
cors.addRule {
it.anyHost()
it.exposeHeader("X-Image-Info")
}
}
}.start(host, port)

koinApp.modules(appModule(app))
koinApp.modules(objectMapperModule(OBJECT_MAPPER))
koinApp.modules(servicesModule())
koinApp.modules(controllersModule())
startKoin(koinApp)

LOG.info("server is started at port: {}", app.port())
}

override fun close() {
app.stop()
}

private data object LocationConverter : (String) -> Location? {

private val CACHED_LOCATION = ConcurrentHashMap<String, Location>(4)

override fun invoke(value: String): Location? {
return if (value.isBlank()) null
else CACHED_LOCATION.computeIfAbsent(value) { OBJECT_MAPPER.readValue(value, Location::class.java) }
}
}

companion object {

@JvmStatic private val LOG = loggerFor<Nebulosa>()

@JvmStatic private val OBJECT_MAPPER = jsonMapper {
addModule(JavaTimeModule())
addModule(PathModule())
addModule(DeviceModule())
disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,59 +1,72 @@
package nebulosa.api.alignment.polar

import nebulosa.api.alignment.polar.darv.DARVEvent
import io.javalin.Javalin
import io.javalin.http.Context
import io.javalin.http.bodyAsClass
import nebulosa.api.alignment.polar.darv.DARVStartRequest
import nebulosa.api.alignment.polar.tppa.TPPAEvent
import nebulosa.api.alignment.polar.tppa.TPPAStartRequest
import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.guider.GuideOutput
import nebulosa.indi.device.mount.Mount
import org.springframework.web.bind.annotation.*
import nebulosa.api.connection.ConnectionService
import nebulosa.api.javalin.notNull
import nebulosa.api.javalin.valid

@RestController
@RequestMapping("polar-alignment")
class PolarAlignmentController(
app: Javalin,
private val polarAlignmentService: PolarAlignmentService,
private val connectionService: ConnectionService,
) {

@PutMapping("darv/{camera}/{guideOutput}/start")
fun darvStart(
camera: Camera, guideOutput: GuideOutput,
@RequestBody body: DARVStartRequest,
) = polarAlignmentService.darvStart(camera, guideOutput, body)
init {
app.put("polar-alignment/darv/{camera}/{guideOutput}/start", ::darvStart)
app.put("polar-alignment/darv/{camera}/stop", ::darvStop)
app.get("polar-alignment/darv/{camera}/status", ::darvStatus)
app.put("polar-alignment/tppa/{camera}/{mount}/start", ::tppaStart)
app.put("polar-alignment/tppa/{camera}/stop", ::tppaStop)
app.put("polar-alignment/tppa/{camera}/pause", ::tppaPause)
app.put("polar-alignment/tppa/{camera}/unpause", ::tppaUnpause)
app.get("polar-alignment/tppa/{camera}/status", ::tppaStatus)
}

private fun darvStart(ctx: Context) {
val camera = connectionService.camera(ctx.pathParam("camera")).notNull()
val guideOutput = connectionService.guideOutput(ctx.pathParam("guideOutput")).notNull()
val body = ctx.bodyAsClass<DARVStartRequest>().valid()
polarAlignmentService.darvStart(camera, guideOutput, body)
}

@PutMapping("darv/{camera}/stop")
fun darvStop(camera: Camera) {
private fun darvStop(ctx: Context) {
val camera = connectionService.camera(ctx.pathParam("camera")) ?: return
polarAlignmentService.darvStop(camera)
}

@GetMapping("darv/{camera}/status")
fun darvStatus(camera: Camera): DARVEvent? {
return polarAlignmentService.darvStatus(camera)
private fun darvStatus(ctx: Context) {
val camera = connectionService.camera(ctx.pathParam("camera")).notNull()
polarAlignmentService.darvStatus(camera)?.also(ctx::json)
}

@PutMapping("tppa/{camera}/{mount}/start")
fun tppaStart(
camera: Camera, mount: Mount,
@RequestBody body: TPPAStartRequest,
) = polarAlignmentService.tppaStart(camera, mount, body)
private fun tppaStart(ctx: Context) {
val camera = connectionService.camera(ctx.pathParam("camera")).notNull()
val mount = connectionService.mount(ctx.pathParam("mount")).notNull()
val body = ctx.bodyAsClass<TPPAStartRequest>().valid()
polarAlignmentService.tppaStart(camera, mount, body)
}

@PutMapping("tppa/{camera}/stop")
fun tppaStop(camera: Camera) {
private fun tppaStop(ctx: Context) {
val camera = connectionService.camera(ctx.pathParam("camera")) ?: return
polarAlignmentService.tppaStop(camera)
}

@PutMapping("tppa/{camera}/pause")
fun tppaPause(camera: Camera) {
private fun tppaPause(ctx: Context) {
val camera = connectionService.camera(ctx.pathParam("camera")) ?: return
polarAlignmentService.tppaPause(camera)
}

@PutMapping("tppa/{camera}/unpause")
fun tppaUnpause(camera: Camera) {
private fun tppaUnpause(ctx: Context) {
val camera = connectionService.camera(ctx.pathParam("camera")) ?: return
polarAlignmentService.tppaUnpause(camera)
}

@GetMapping("tppa/{camera}/status")
fun tppaStatus(camera: Camera): TPPAEvent? {
return polarAlignmentService.tppaStatus(camera)
private fun tppaStatus(ctx: Context) {
val camera = connectionService.camera(ctx.pathParam("camera")).notNull()
polarAlignmentService.tppaStatus(camera)?.also(ctx::json)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import nebulosa.api.alignment.polar.tppa.TPPAStartRequest
import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.guider.GuideOutput
import nebulosa.indi.device.mount.Mount
import org.springframework.stereotype.Service

@Service
class PolarAlignmentService(
private val darvExecutor: DARVExecutor,
private val tppaExecutor: TPPAExecutor,
Expand Down
Loading

0 comments on commit aafe107

Please sign in to comment.