release: v2.0.4 (#217)

* perf(routes): batch cross-IATA and hash route search (#216)

One search fired a /routes/cross request per IATA pair (138k on 2026-10-08). Route search now takes an optional iatas list and runs a fixed number of index-backed queries. /info advertises built-in minimum client versions.

* chore: bump version to 2.0.4
This commit is contained in:
MrAlders0n authored and GitHub committed 2026-10-09 22:17:23 -04:00
1 parent 768889243c
commit 9bbf8efee5
37 files changed
+1625 -591

No files matched your search

+62 -22
View File
@@ -899,14 +899,14 @@ const docTemplate = `{
},
"/info": {
"get": {
"description": "minAppVersion is null when the server sets no requirement.",
"description": "minAppVersion (BEACON Mobile) and minWebVersion (Beacon Web) are null when the\nserver sets no requirement. Each is the higher of the built-in floor and config.",
"produces": [
"application/json"
],
"tags": [
"Info"
],
"summary": "Server info and minimum mobile app version",
"summary": "Server info and minimum client versions",
"responses": {
"200": {
"description": "OK",
@@ -2201,6 +2201,7 @@ const docTemplate = `{
},
"/routes/cross": {
"get": {
"description": "Pass iatas (comma-separated, optional; omitted searches every IATA) or the\nsingle directed pair fromIata/toIata, not both.",
"produces": [
"application/json"
],
@@ -2211,31 +2212,35 @@ const docTemplate = `{
"parameters": [
{
"type": "string",
"description": "Source node hash prefix (hex)",
"description": "Source node hash prefix (hex, 1-4 bytes)",
"name": "fromHash",
"in": "query",
"required": true
},
{
"type": "string",
"description": "Source IATA code",
"name": "fromIata",
"in": "query",
"required": true
},
{
"type": "string",
"description": "Destination node hash prefix (hex)",
"description": "Destination node hash prefix (hex, 1-4 bytes)",
"name": "toHash",
"in": "query",
"required": true
},
{
"type": "string",
"description": "Destination IATA code",
"description": "Comma-separated IATA codes to search (2-100)",
"name": "iatas",
"in": "query"
},
{
"type": "string",
"description": "Source IATA code (with toIata)",
"name": "fromIata",
"in": "query"
},
{
"type": "string",
"description": "Destination IATA code (with fromIata)",
"name": "toIata",
"in": "query",
"required": true
"in": "query"
}
],
"responses": {
@@ -2259,12 +2264,19 @@ const docTemplate = `{
"schema": {
"$ref": "#/definitions/internal_api_handlers.APIError"
}
},
"503": {
"description": "Service Unavailable",
"schema": {
"$ref": "#/definitions/internal_api_handlers.APIError"
}
}
}
}
},
"/routes/search": {
"get": {
"description": "Routes within one IATA that run from the source hash to the destination hash,\ntrimmed to that span. iatas is optional (omitted searches every IATA); the single\niata is still accepted. At most 500, shortest first.",
"produces": [
"application/json"
],
@@ -2275,21 +2287,26 @@ const docTemplate = `{
"parameters": [
{
"type": "string",
"description": "IATA code to search within",
"name": "iata",
"in": "query",
"required": true
"description": "Comma-separated IATA codes to search (max 100)",
"name": "iatas",
"in": "query"
},
{
"type": "string",
"description": "Source node hash prefix (hex)",
"description": "Single IATA code (when iatas is omitted)",
"name": "iata",
"in": "query"
},
{
"type": "string",
"description": "Source node hash prefix (hex, 1-4 bytes)",
"name": "from",
"in": "query",
"required": true
},
{
"type": "string",
"description": "Destination node hash prefix (hex)",
"description": "Destination node hash prefix (hex, 1-4 bytes)",
"name": "to",
"in": "query",
"required": true
@@ -2316,6 +2333,12 @@ const docTemplate = `{
"schema": {
"$ref": "#/definitions/internal_api_handlers.APIError"
}
},
"503": {
"description": "Service Unavailable",
"schema": {
"$ref": "#/definitions/internal_api_handlers.APIError"
}
}
}
}
@@ -3662,6 +3685,9 @@ const docTemplate = `{
},
"mobile": {
"$ref": "#/definitions/github_com_MeshCore-Beacon_beacon-server_internal_api.AdminMobileConfig"
},
"web": {
"$ref": "#/definitions/github_com_MeshCore-Beacon_beacon-server_internal_api.AdminWebConfig"
}
}
},
@@ -3678,7 +3704,16 @@ const docTemplate = `{
"type": "object",
"properties": {
"min_app_version": {
"description": "empty means no requirement",
"description": "effective floor; empty means no requirement",
"type": "string"
}
}
},
"github_com_MeshCore-Beacon_beacon-server_internal_api.AdminWebConfig": {
"type": "object",
"properties": {
"min_web_version": {
"description": "effective floor; empty means no requirement",
"type": "string"
}
}
@@ -3987,6 +4022,11 @@ const docTemplate = `{
"type": "string",
"example": "0.1.1"
},
"minWebVersion": {
"description": "MinWebVersion is the oldest allowed Beacon Web version (X.Y.Z); null means no requirement.",
"type": "string",
"example": "2.0.3"
},
"serverVersion": {
"type": "string",
"example": "2.0.2"
@@ -6086,7 +6126,7 @@ const docTemplate = `{
// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = &swag.Spec{
Version: "2.0.3",
Version: "2.0.4",
Host: "localhost:8080",
BasePath: "/api/v1",
Schemes: []string{"http", "https"},
+62 -22
View File
@@ -15,7 +15,7 @@
"license": {
"name": "AGPL-3-or-later"
},
"version": "2.0.3"
"version": "2.0.4"
},
"host": "localhost:8080",
"basePath": "/api/v1",
@@ -897,14 +897,14 @@
},
"/info": {
"get": {
"description": "minAppVersion is null when the server sets no requirement.",
"description": "minAppVersion (BEACON Mobile) and minWebVersion (Beacon Web) are null when the\nserver sets no requirement. Each is the higher of the built-in floor and config.",
"produces": [
"application/json"
],
"tags": [
"Info"
],
"summary": "Server info and minimum mobile app version",
"summary": "Server info and minimum client versions",
"responses": {
"200": {
"description": "OK",
@@ -2199,6 +2199,7 @@
},
"/routes/cross": {
"get": {
"description": "Pass iatas (comma-separated, optional; omitted searches every IATA) or the\nsingle directed pair fromIata/toIata, not both.",
"produces": [
"application/json"
],
@@ -2209,31 +2210,35 @@
"parameters": [
{
"type": "string",
"description": "Source node hash prefix (hex)",
"description": "Source node hash prefix (hex, 1-4 bytes)",
"name": "fromHash",
"in": "query",
"required": true
},
{
"type": "string",
"description": "Source IATA code",
"name": "fromIata",
"in": "query",
"required": true
},
{
"type": "string",
"description": "Destination node hash prefix (hex)",
"description": "Destination node hash prefix (hex, 1-4 bytes)",
"name": "toHash",
"in": "query",
"required": true
},
{
"type": "string",
"description": "Destination IATA code",
"description": "Comma-separated IATA codes to search (2-100)",
"name": "iatas",
"in": "query"
},
{
"type": "string",
"description": "Source IATA code (with toIata)",
"name": "fromIata",
"in": "query"
},
{
"type": "string",
"description": "Destination IATA code (with fromIata)",
"name": "toIata",
"in": "query",
"required": true
"in": "query"
}
],
"responses": {
@@ -2257,12 +2262,19 @@
"schema": {
"$ref": "#/definitions/internal_api_handlers.APIError"
}
},
"503": {
"description": "Service Unavailable",
"schema": {
"$ref": "#/definitions/internal_api_handlers.APIError"
}
}
}
}
},
"/routes/search": {
"get": {
"description": "Routes within one IATA that run from the source hash to the destination hash,\ntrimmed to that span. iatas is optional (omitted searches every IATA); the single\niata is still accepted. At most 500, shortest first.",
"produces": [
"application/json"
],
@@ -2273,21 +2285,26 @@
"parameters": [
{
"type": "string",
"description": "IATA code to search within",
"name": "iata",
"in": "query",
"required": true
"description": "Comma-separated IATA codes to search (max 100)",
"name": "iatas",
"in": "query"
},
{
"type": "string",
"description": "Source node hash prefix (hex)",
"description": "Single IATA code (when iatas is omitted)",
"name": "iata",
"in": "query"
},
{
"type": "string",
"description": "Source node hash prefix (hex, 1-4 bytes)",
"name": "from",
"in": "query",
"required": true
},
{
"type": "string",
"description": "Destination node hash prefix (hex)",
"description": "Destination node hash prefix (hex, 1-4 bytes)",
"name": "to",
"in": "query",
"required": true
@@ -2314,6 +2331,12 @@
"schema": {
"$ref": "#/definitions/internal_api_handlers.APIError"
}
},
"503": {
"description": "Service Unavailable",
"schema": {
"$ref": "#/definitions/internal_api_handlers.APIError"
}
}
}
}
@@ -3660,6 +3683,9 @@
},
"mobile": {
"$ref": "#/definitions/github_com_MeshCore-Beacon_beacon-server_internal_api.AdminMobileConfig"
},
"web": {
"$ref": "#/definitions/github_com_MeshCore-Beacon_beacon-server_internal_api.AdminWebConfig"
}
}
},
@@ -3676,7 +3702,16 @@
"type": "object",
"properties": {
"min_app_version": {
"description": "empty means no requirement",
"description": "effective floor; empty means no requirement",
"type": "string"
}
}
},
"github_com_MeshCore-Beacon_beacon-server_internal_api.AdminWebConfig": {
"type": "object",
"properties": {
"min_web_version": {
"description": "effective floor; empty means no requirement",
"type": "string"
}
}
@@ -3985,6 +4020,11 @@
"type": "string",
"example": "0.1.1"
},
"minWebVersion": {
"description": "MinWebVersion is the oldest allowed Beacon Web version (X.Y.Z); null means no requirement.",
"type": "string",
"example": "2.0.3"
},
"serverVersion": {
"type": "string",
"example": "2.0.2"
+52 -17
View File
@@ -54,6 +54,8 @@ definitions:
$ref: '#/definitions/github_com_MeshCore-Beacon_beacon-server_internal_api.AdminIngestConfig'
mobile:
$ref: '#/definitions/github_com_MeshCore-Beacon_beacon-server_internal_api.AdminMobileConfig'
web:
$ref: '#/definitions/github_com_MeshCore-Beacon_beacon-server_internal_api.AdminWebConfig'
type: object
github_com_MeshCore-Beacon_beacon-server_internal_api.AdminIngestConfig:
properties:
@@ -66,7 +68,13 @@ definitions:
github_com_MeshCore-Beacon_beacon-server_internal_api.AdminMobileConfig:
properties:
min_app_version:
description: empty means no requirement
description: effective floor; empty means no requirement
type: string
type: object
github_com_MeshCore-Beacon_beacon-server_internal_api.AdminWebConfig:
properties:
min_web_version:
description: effective floor; empty means no requirement
type: string
type: object
github_com_MeshCore-Beacon_beacon-server_internal_api.AdvertObservation:
@@ -279,6 +287,11 @@ definitions:
means no requirement.
example: 0.1.1
type: string
minWebVersion:
description: MinWebVersion is the oldest allowed Beacon Web version (X.Y.Z);
null means no requirement.
example: 2.0.3
type: string
serverVersion:
example: 2.0.2
type: string
@@ -1727,7 +1740,7 @@ info:
name: AGPL-3-or-later
termsOfService: https://github.com/MeshCore-Beacon/beacon-server
title: MeshCore Beacon API
version: 2.0.3
version: 2.0.4
paths:
/admin/accounts:
get:
@@ -2322,7 +2335,9 @@ paths:
- IATAs
/info:
get:
description: minAppVersion is null when the server sets no requirement.
description: |-
minAppVersion (BEACON Mobile) and minWebVersion (Beacon Web) are null when the
server sets no requirement. Each is the higher of the built-in floor and config.
produces:
- application/json
responses:
@@ -2330,7 +2345,7 @@ paths:
description: OK
schema:
$ref: '#/definitions/github_com_MeshCore-Beacon_beacon-server_internal_api.Info'
summary: Server info and minimum mobile app version
summary: Server info and minimum client versions
tags:
- Info
/messages:
@@ -3275,26 +3290,31 @@ paths:
- Routes
/routes/cross:
get:
description: |-
Pass iatas (comma-separated, optional; omitted searches every IATA) or the
single directed pair fromIata/toIata, not both.
parameters:
- description: Source node hash prefix (hex)
- description: Source node hash prefix (hex, 1-4 bytes)
in: query
name: fromHash
required: true
type: string
- description: Source IATA code
in: query
name: fromIata
required: true
type: string
- description: Destination node hash prefix (hex)
- description: Destination node hash prefix (hex, 1-4 bytes)
in: query
name: toHash
required: true
type: string
- description: Destination IATA code
- description: Comma-separated IATA codes to search (2-100)
in: query
name: iatas
type: string
- description: Source IATA code (with toIata)
in: query
name: fromIata
type: string
- description: Destination IATA code (with fromIata)
in: query
name: toIata
required: true
type: string
produces:
- application/json
@@ -3313,23 +3333,34 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/internal_api_handlers.APIError'
"503":
description: Service Unavailable
schema:
$ref: '#/definitions/internal_api_handlers.APIError'
summary: Search for routes that cross IATA boundaries
tags:
- Routes
/routes/search:
get:
description: |-
Routes within one IATA that run from the source hash to the destination hash,
trimmed to that span. iatas is optional (omitted searches every IATA); the single
iata is still accepted. At most 500, shortest first.
parameters:
- description: IATA code to search within
- description: Comma-separated IATA codes to search (max 100)
in: query
name: iatas
type: string
- description: Single IATA code (when iatas is omitted)
in: query
name: iata
required: true
type: string
- description: Source node hash prefix (hex)
- description: Source node hash prefix (hex, 1-4 bytes)
in: query
name: from
required: true
type: string
- description: Destination node hash prefix (hex)
- description: Destination node hash prefix (hex, 1-4 bytes)
in: query
name: to
required: true
@@ -3351,6 +3382,10 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/internal_api_handlers.APIError'
"503":
description: Service Unavailable
schema:
$ref: '#/definitions/internal_api_handlers.APIError'
summary: Search known routes by source and destination hash
tags:
- Routes