Files
msgexchange-v2/src/main/kotlin/com/gzzn/omms/msgexchange/ingress/FlightQueryController.kt
T
windyboyandCursor f45a0ac898 fix(acm2-107): finalize /all/flights contract and FLTR JSON payload
Close Q21 into C-11 and emit day-schedule FLTR-shaped JSON for Redis, schd, and query responses.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-23 11:23:37 +08:00

54 lines
2.4 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.gzzn.omms.msgexchange.ingress
import com.fasterxml.jackson.databind.ObjectMapper
import com.gzzn.omms.msgexchange.processing.FlightProjectionPort
import io.micronaut.http.HttpResponse
import io.micronaut.http.HttpStatus
import io.micronaut.http.MediaType
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.annotation.Produces
/**
* `GET /all/flights`:从 Redis 查询投影读当前全部动态航班,不含共享航班(`US-12`、`C-11`)。
*
* 数据只从投影来,不回落 PG:查询与网页客户端必须读同一份,不然两边会看到不同的航班
* (`INV-11`)。投影读不出来就返回错误——空列表会被前端当成"现在没有航班"`US-12` AC2)。
*
* 成功:裸 JSON 数组、不套旧系统的 `ResponseDto`;失败:503 加错误对象(`C-11`)。
* 数组元素与 `KAFKA:schd` 同形,都是日计划 `FLTR` 转成的 JSON`C-9`、`C-11`)。
*/
@Controller("/all/flights")
class FlightQueryController(
private val projection: FlightProjectionPort,
private val mapper: ObjectMapper,
) {
private val log = org.slf4j.LoggerFactory.getLogger(FlightQueryController::class.java)
@Get
@Produces(MediaType.APPLICATION_JSON)
fun all(): HttpResponse<String> =
try {
HttpResponse.ok(mapper.writeValueAsString(nonSharedFlights()))
} catch (e: Exception) {
// 读投影失败(Redis 不可用、未接通、载荷读不动)一律报错:这里没有可信的兜底数据源
val reason = e.message ?: e.javaClass.simpleName
log.error("GET /all/flights unavailable reason={}", reason, e)
HttpResponse.status<String>(HttpStatus.SERVICE_UNAVAILABLE)
.body(mapper.writeValueAsString(mapOf("error" to PROJECTION_UNAVAILABLE, "reason" to reason)))
}
/**
* 共享航班由 `MAID`(主航班 FLID)非空标识,随主航班下发,不单独出现在列表里
* `US-06` AC2 的主/共享关系,见 docs/implementation.md「航班域」)。
*/
private fun nonSharedFlights(): List<com.fasterxml.jackson.databind.JsonNode> =
projection.readAll()
.map { mapper.readTree(it) }
.filter { it.path("MAID").asText("").isBlank() }
private companion object {
private const val PROJECTION_UNAVAILABLE = "FLIGHT_PROJECTION_UNAVAILABLE"
}
}